车辆运动模型中LQR代码实现

一、前言

最近看到关于架构和算法两者关系的一个描述,我觉得非常认同,分享给大家。

1、好架构起到两个作用:合理的分解功能、合理的适配算法;
2、好的架构是好的功能的必要条件,不是充分条件,一味追求架构的完美是不可取的,并且不存在完美的架构,只存在合适的架构;
3、好的架构可以一定层度上提升算法的能力,但功能开发不能将重心全放在框架上,应该追求框架+算法的适配,从而实现 1+1 > 2 。

**我的理解是这样的:**架构的设计一定要结合功能、硬件、人力、成本、时间等多种因素,在此基础上尽量去满足算法的低耦合、高内聚。

二、LQR跟踪效果视频

说明:LQR跟踪比较依赖路径的平滑度(路径曲率的变化)

LQR路径跟踪

三、车辆运动学模型的详细推导

上一篇文章中(LQR原理及其在路径跟踪的应用,http://t.csdnimg.cn/4YDos),有人私信问关于车辆运动学模型的推导过程,这里我进行更详细的推导
在这里插入图片描述
在这里插入图片描述
到这里就应该没什么问题了吧?再通过向前欧拉法离散化,套公式即可求解;

四、差速模型的详细推导

其一:为了举一反三,所有对差速模型也进行了推导;
其二:即使控制对象是车辆模型,也可以先使用差速模型先进行计算得到v,w,然后根据车辆的模型二次解算得到速度和转向角。
在这里插入图片描述

五、具体代码实现

注意事项:
1、使用lqr跟踪一段轨迹,轨迹中的v,w不知道的情况下可以给0,但那么lqr中的调节矩阵R就应该尽量的小;
2、轨迹中的yaw尽量保证突变较小(没有前置轨迹平滑的基础可以简单用均值滤波),否则lqr无法收敛,跟踪效果很差;
3、以差速模型计算得到v,w ,可以再车辆的模型二次解算得到速度和转向角。

/**
 * lqr_controler.hpp
 * @brief  lqr控制器 构建的是一个差速机器人模型
 * @author MCE
 * @date 2024-5-9
 */
#ifndef LQR_CONTROLER
#define LQR_CONTROLER
#include <math.h>
#include <Eigen/Dense>
#include <iostream>
#include "utils.hpp"
namespace lqr_control {
using namespace std;
using namespace Eigen;
using namespace lqr_control;

class LQRControler {
public:
    LQRControler(){};
    /**
     * @brief lqr 初始化
     * @return void
     */
    void init();

    /**
     * @brief lqr 控制器 输出 v, w
     * @param robot_state 机器人状态
     * @param front_point 预瞄点
     * @param v 以引用的方式输出v
     * @param w 以引用的方式输出w
     * @return void
     */
    void lqrControl(const state& robot_state, const state& front_point, float& v, float& w);

private:
    MatrixXf A;
    MatrixXf B;
    MatrixXf Q;
    MatrixXf R;

    // P矩阵最多迭代次数
    int n;
    // 离散化控制周期
    float dt;
    // P容许误差
    float eps;

    /**
     * @brief 黎卡迪计算方程
     * @return MatrixXf P矩阵
     */
    MatrixXf calRicatti();

    /**
     * @brief 计算AB 矩阵
     * @return void
     */
    void calAB(const state& front_point);
};
} // namespace lqr_control
#endif
/**
 * lqr_controler.cpp
 * @brief  lqr控制器
 * @author MCE
 * @date 2024-5-9
 */
#include "../include/lqr_controler.hpp"

namespace lqr_control {

void LQRControler::init() {
    A.resize(3, 3);
    A.setZero();
    B.resize(3, 2);
    B.setZero();

    Q.resize(3, 3);
    Q << 1.0, 0.0, 0.0,
         0.0, 1.0, 0.0, 
         0.0, 0.0, 1.0; 
    R.resize(2, 2);
    R << 0.001, 0.0, 
         0.0, 0.001; 

    n = 100;
    dt = 0.02;
    eps = 1.0e-4;
}

void LQRControler::calAB(const state& front_point) {
    A << 1.0, 0.0, -front_point.linear_vel * dt * sin(front_point.yaw), 0.0, 1.0, front_point.linear_vel * dt * cos(front_point.yaw), 0.0, 0.0, 1.0;
    B << dt * cos(front_point.yaw), 0.0, dt * sin(front_point.yaw), 0.0, 0.0, dt;
}

// 离散时间Riccati方程求解函数
MatrixXf LQRControler::calRicatti() {
    MatrixXf P = Q;
    for (int i = 0; i < n; ++i) {
        MatrixXf P_next = A.transpose() * P * A - A.transpose() * P * B * (R + B.transpose() * P * B).inverse() * B.transpose() * P * A + Q;
        if ((P_next - P).norm() < eps) {
            P = P_next;
            break;
        }
        P = P_next;
    }
    return P;
}

void LQRControler::lqrControl(const state& robot_state, const state& front_point, float& v, float& w) {
    MatrixXf X(3, 1);
    X << robot_state.x - front_point.x, robot_state.y - front_point.y, angleNormalize(robot_state.yaw - front_point.yaw);
    calAB(front_point);
    MatrixXf P = calRicatti();
    MatrixXf K = -(R + B.transpose() * P * B).inverse() * B.transpose() * P * A;
    MatrixXf U = K * X;
    v = U(0, 0);
    w = U(1, 0);
}
} // namespace lqr_control

欢迎大家讨论、交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/614892.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

贝壳面试:MySQL联合索引,最左匹配原则是什么?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 1.谈谈你对MySQL联合索引的认识&#xff1f; 2.在MySQ…

【强训笔记】day20

NO.1 思路&#xff1a;先判断能对砍几个回合&#xff0c;取最小值&#xff0c;因为回合数是整数&#xff0c;所以可能存在都大于0的情况&#xff0c;再判断一下如果都存活就再对砍一次&#xff0c;直到一家存活或者都死亡。 代码实现&#xff1a; #include<iostream>u…

即插即用篇 | YOLOv8 引入多光谱通道注意力 | 频率领域中的通道注意力网络

本改进已集成到 YOLOv8-Magic 框架。 注意力机制,尤其是通道注意力,在计算机视觉领域取得了巨大成功。许多工作聚焦于如何设计高效的通道注意力机制,同时忽略了一个基本问题,即通道注意力机制使用标量来表示通道,这很困难,因为会造成大量信息的丢失。在这项工作中,我们从…

OGG几何内核开发-BRepAlgoAPI_Fuse与BRep_Builder.MakeCompound比较

最近在与同事讨论BRepAlgoAPI_Fuse与BRep_Builder.MakeCompound有什么区别。 一、从直觉上来说&#xff0c;BRepAlgoAPI_Fuse会对两个实体相交处理&#xff0c;相交的部分会重新的生成相关的曲面。而BRep_Builder.MakeCompound仅仅是把两个实体组合成一个新的实体&#xff0c;…

【一支射频电缆的诞生】GORE 戈尔

工具连接&#xff1a; https://microwave-cablebuilder.gore.com/ 控制参数&#xff1a; 连接器&#xff1a; 欣赏

Ubuntu18.04--虚拟机配置Samba并从Windows登录

前言&#xff1a; 本文记录我自己在Windows上安装 Virtualbox &#xff0c;并在Virtualbox中安装 Ubuntu-18.04 虚拟机&#xff0c;在Ubuntu-18.04虚拟机里安装配置Smaba服务器&#xff0c;从 Windows 宿主系统上访问虚拟机共享samba目录的配置命令。 引用: N/A 正文 虚拟…

《Python编程从入门到实践》day25

# 昨日知识点回顾 如何创建多行外星人 碰撞结束游戏 创建game_stats.py跟踪统计信息 # 今日知识点学习 第14章 记分 14.1 添加Play按钮 14.1.1 创建Button类 import pygame.font# button.py class Button:def __init__(self, ai_game, msg):"""初始化按钮…

【GESP】2023年12月图形化二级 -- 小杨报数

小杨报数 【题目描述】 小杨需要从 1 1 1到 N N N报数。在报数过程中&#xff0c;小杨希望跳过 M M M的倍数。例如&#xff0c;如果 N 5 N5 N5&#xff0c; M 2 M2 M2&#xff0c;那么小杨就需要依次报出 1 1 1&#xff0c; 3 3 3&#xff0c; 5 5 5。 默认小猫角色和白色背…

zblog中用户中心-邀请码注册插件的导出功能补充

自己加了一个导出未使用的邀请码功能&#xff0c;可惜我不是入驻作者&#xff0c;没有权限发布&#xff0c;之前被一条大河拒了&#xff0c;他说我抄他代码&#xff0c;不给我过审还冷嘲热讽&#xff0c;我一气之下&#xff0c;就没继续申请了&#xff0c;话说我是专业搞java开…

Unity引擎是什么?有哪些优点

大家好&#xff0c;我是咕噜土豆&#xff0c;很高兴又和大家见面了。今天我们一起来了解一下Unity引擎和它有哪些优点。 首先带大家了解什么是Unity引擎 Unity引擎是一款由Unity Technologies开发的跨平台游戏开发引擎&#xff0c;广泛用于创建2D和3D游戏以及其他交互式内容&…

ADS1220芯片利用自身温度传感器测试自身温度

一、简介 ADS1220 内部集成了一个精密温度传感器&#xff0c;通过将寄存器的TS位置1可使能温度传感器模式。 在温度传感器模式下&#xff0c; 配置寄存器 0 的设置不产生任何影响&#xff0c;该器件使用内部基准进行测量&#xff0c;与所选基准电压源无关。 温度读数过程与模拟…

SELECT SUM用法和ZMM008入货登记号大于可入仓量

select sum 用法示例 入货登记号大于可入仓量 之前错误的写法

德国Dürr杜尔机器人维修技巧分析

在工业生产中&#xff0c;杜尔工业机器人因其高效、精准和稳定性而备受青睐。然而&#xff0c;即便是最精良的设备&#xff0c;也难免会出现Drr机械手故障。 一、传感器故障 1. 视觉传感器故障&#xff1a;可能导致机器人无法正确识别目标物&#xff0c;影响工作效率。解决方法…

27.哀家要长脑子了!---栈与队列

1.739. 每日温度 - 力扣&#xff08;LeetCode&#xff09; 用单调栈的方法做&#xff1a; 从左到右遍历数组&#xff1a; 栈中存放的是下标&#xff0c;每个温度在原数组中的下标&#xff0c;从大到小排列&#xff0c;因为这样才能确保的是最近一天的升高温度 如果栈为空&am…

【Ubuntu 安装erlang】

apt-get 安装 apt-get install erlang或 源码安装 git clone https://github.com/erlang/otp.git cd otp git checkout maint-25 # current latest stable version ./configure make make install安装完后&#xff0c;验证是否成功 # 命令行输入 erl

JavaSE基础小知识Ⅱ(很容易错!!!)

1. 变量被final修饰后不能再指向其他对象&#xff0c;但可以重写 如果是引用变量被final修饰&#xff0c;那么的确如此&#xff1b; 基本变量不能重写 2. 下列代码的输出结果是&#xff1f; public class Test {static {int x 5; }static int x,y; public static void ma…

Ansible playbook

playbook playbook介绍 playbooks是ansible用于配置&#xff0c;部署&#xff0c;和管理被控节点的剧本。通过playbooks的详细描述&#xff0c;执行其中的tasks&#xff0c;可以让远端主机达到预期的状态。playbooks是由一个或多个”play”组成的列表。 当对一台机器做环境初…

【免费】在线识别通用验证码接口

模块优势价格5元1000次&#xff0c;每天免费100次api文档支持 使用量小的完全够用了 <?phpfunction Post_base64($base64_str){$url http://api.95man.com:8888/api/Http/Recog?Taken41******QK&imgtype1&len0 ; $fields array( ImgBase64>$base64_str); $ch…

MySQL系列之索引

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

为啥我说英语能决定程序员的天花板?

看到知乎有这样的一个问题&#xff0c;作为程序员的你&#xff0c;大学最后悔没有好好学哪门课&#xff1f; 很多人回答《软件工程》、《线性代数》、《微积分》等&#xff0c;各种都有。。 但我觉得&#xff0c;这些课都很重要&#xff0c;但没学好不妨碍自学。 其实对程序…