当前位置: 首页 > news >正文

基于动力学的MPC控制器设计盲点解析

文章目录

    • Apollo MPC控制器的设计架构
    • 误差模型和离散化
    • 预测模型推导
    • 目标函数和约束设计
    • 优化求解
    • 优化OSQP求解器
    • 参考文献

Apollo MPC控制器的设计架构

误差模型和离散化

状态变量和控制变量

1、Apollo MPC控制器中状态变量主要有如下6个

  matrix_state_ = Matrix::Zero(basic_state_size_, 1);// State matrix update;matrix_state_(0, 0) = debug->lateral_error();matrix_state_(1, 0) = debug->lateral_error_rate();matrix_state_(2, 0) = debug->heading_error();matrix_state_(3, 0) = debug->heading_error_rate();matrix_state_(4, 0) = debug->station_error();matrix_state_(5, 0) = debug->speed_error();

状态变量计算:

控制变量有两个:

其中\delta _{_{f}} 为前轮转角,a为加速度补偿

  Eigen::MatrixXd control_matrix(controls_, 1);control_matrix << 0, 0;

在代码中控制量的计算和输出

// 解mpc,输出一个vector,control内有10个control_matrix
SolveLinearMPC(matrix_ad_, matrix_bd_, matrix_cd_, matrix_q_updated_,matrix_r_updated_, lower_bound, upper_bound, matrix_state_, reference,mpc_eps_, mpc_max_iteration_, &control)
// 已知,mpc仅取第一组解为当前时刻最优控制解,即control[0]
// steer_single_direction_max_degree_ --- the maximum turn of steer
// control中第一个矩阵中的第一个值用于计算方向盘转角
double steer_angle_feedback = control[0](0, 0) * 180 / M_PI *steer_transmission_ratio_ /steer_single_direction_max_degree_ * 100;double steer_angle = steer_angle_feedback + steer_angle_feedforwardterm_updated_ +steer_angle_ff_compensation + steer_angle_feedback_augment;// control中第一个矩阵中的第二个值control[0](1, 0),用于计算加速度 = 加速度补偿 + 期望加速度 + 坡度加速度补偿
debug->set_acceleration_cmd_closeloop(control[0](1, 0));
double acceleration_cmd = control[0](1, 0) + debug->acceleration_reference() + control_conf_.enable_slope_offset() * debug->slope_offset_compensation();

动力学误差模型

代码实现:

// 初始化矩阵
Status MPCController::Init(const ControlConf *control_conf) {...// Matrix init operations.matrix_a_ = Matrix::Zero(basic_state_size_, basic_state_size_);matrix_ad_ = Matrix::Zero(basic_state_size_, basic_state_size_);...// TODO(QiL): expand the model to accomendate more combined states.matrix_a_coeff_ = Matrix::Zero(basic_state_size_, basic_state_size_);...matrix_b_ = Matrix::Zero(basic_state_size_, controls_);matrix_bd_ = Matrix::Zero(basic_state_size_, controls_);...matrix_bd_ = matrix_b_ * ts_;matrix_c_ = Matrix::Zero(basic_state_size_, 1);...matrix_cd_ = Matrix::Zero(basic_state_size_, 1);...}// 更新矩阵
void MPCController::UpdateMatrix(SimpleMPCDebug *debug) {const double v = VehicleStateProvider::instance()->linear_velocity();matrix_a_(1, 1) = matrix_a_coeff_(1, 1) / v;matrix_a_(1, 3) = matrix_a_coeff_(1, 3) / v;matrix_a_(3, 1) = matrix_a_coeff_(3, 1) / v;matrix_a_(3, 3) = matrix_a_coeff_(3, 3) / v;Matrix matrix_i = Matrix::Identity(matrix_a_.cols(), matrix_a_.cols());matrix_ad_ = (matrix_i + ts_ * 0.5 * matrix_a_) *(matrix_i - ts_ * 0.5 * matrix_a_).inverse();matrix_c_(1, 0) = (lr_ * cr_ - lf_ * cf_) / mass_ / v - v;matrix_c_(3, 0) = -(lf_ * lf_ * cf_ + lr_ * lr_ * cr_) / iz_ / v;matrix_cd_ = matrix_c_ * debug->heading_error_rate() * ts_;
}// 求解MPC
// discrete linear predictive control solver, with control format
// x(i + 1) = A * x(i) + B * u (i) + C
bool SolveLinearMPC(const Matrix &matrix_a, const Matrix &matrix_b,const Matrix &matrix_c, const Matrix &matrix_q,const Matrix &matrix_r, const Matrix &matrix_lower,const Matrix &matrix_upper,const Matrix &matrix_initial_state,const std::vector<Matrix> &reference, const double eps,const int max_iter, std::vector<Matrix> *control) 

apollo使用的是双线性变换离散法的方法:

  matrix_ad_ = (matrix_i + ts_ * 0.5 * matrix_a_) *(matrix_i - ts_ * 0.5 * matrix_a_).inverse();matrix_bd_ = matrix_b_ * ts_;matrix_cd_ = matrix_c_ * debug->heading_error_rate() * ts_;

补充:

Apollo采用的中点欧拉法和向前欧拉法的结合:

预测模型推导

为什么不用上述推导出的离散化的状态空间方程来推导我们的预测模型,以此来设计MPC控制器?

主要考虑在设计目标函数的时候,想将我们的控制增量设计到我们的目标函数中去,而非直接使用控制量,控制增量为代价,能有效改善控制的平滑性

此处我们需要注意的是:

  • 控制步长为Nc,因此当预测步长为k+Nc+1时,此时预测状态y(k+Nc+1)的最后一项也只写到k+Nc-1。因为到k+Nc时刻及以后的控制量有两种处理策略第一种就是控制步长Nc之后的预测控制量保持不变;第二种就是Nc之后的预测控制量全部置零。我们此处达到控制步长之后的控制量全置零;
  • 最终推导出的系统的预测模型Y, 其可以根据系统当前的状态量,以及施加一个未来一段时间Nc序列的控制增量,我们就可以知道系统未来(Np步)的表现是什么样子的(系统输出),即y(k+1)~y(k+Np);

目标函数和约束设计

设计目标:

  • 希望我们的路径跟踪误差在预测时域内尽可能趋于0,也即希望目标函数的第一项的几个状态量尽可能趋于0,这样我们的车辆才能更好的跟随规划路径;
  • 其次,我们希望目标函数的第二项控制增量的代价越小越好,也即希望前后两帧的控制量变化越小越好,这样控制的效果越平滑,对应前轮转角和加速度变化越平滑;
  • 目标函数最后一项引入松弛因子(在程序中是一个具体的数值),其主要作用就是改善优化问题的可行解,提高求解效率;

在MPC控制规律中,将控制序列中的第一个参数作为控制量,输入给被控系统。

对于车辆控制来说,就是找到一组合适的控制量,如u = [\delta _{f},a]其中\delta _{_{f}} 为前轮转角,a为刹车/油门系数,使车辆沿参考轨迹行驶,且误差最小、控制最平稳、舒适度最高等。因此在设计目标函数的时候可以考虑以下几点:

1、设计代价函数时候,一般设计为二次型的样式,为的是避免在预测时域内,误差忽正忽负,导致误差相互抵消;

2、考虑的代价主要有如下:

  • 横向误差:指实际轨迹点与参考轨迹点间的距离;
  • 航向误差:车辆当前航向与参考轨迹点航向的偏差;
  • 速度误差:车辆当前速度与规划轨期望车速的偏差;
  • 刹车/油门调节量:目的是为了保证刹车/油门变化的平稳性;

3、约束条件:

  • 最大前轮转角
  • 最大前轮转角变化量
  • 最大刹车/油门调节量
  • 最大方向盘转角
  • 最大车速
  • 最大加速度等

此处关于控制增量的约束,比如说,我们的前轮转角打30°需要2s,则1s需要打15°,然而我们的控制周期T=0.05s,则控制周期我们需要下发的转角最大为0.75°,也即我们下发转角的最大速率不超过0.75°/T。

关于软约束,也即代价函数,使其值越小越好。

优化求解

滚动优化求解的目的是为了求最优控制解,是一种在线优化,它每一时刻都会针对当前误差重新计算控制量,通过使某一或某些性能指标达到最优来实现控制作用。因此,滚动优化可能不会得到全局最优解,但是却能对每一时刻的状态进行最及时的响应,达到局部最优。

第一步:目标函数如何转化为标准二次型

注意:

目标函数化简后的每一项其实都是一个具体的数,第三项表示具体数的转置等于其自身。因此合并第二项和第三项,二者实质相等。其次化成二次型后,G属于已知项,且Q也是已知项,故二次型的最后一项其实不影响最终的优化求解最小值问题,因此放在最后一项,且求解过程可以忽略

第二步:约束的转化

u(k)^{*}作为此时的控制量输入给系统,直到下一个控制时刻,系统根据新的状态信息预测下一时段内的输出,然后通过优化得到一组新的控制序列。如此反复,直至完成整个控制过程。

OSQP求解器

带参构造函数MpcOsqp 求解

输入矩阵Ad,Bd,Q,R,初始状态阵X0,控制量上下边界,状态量上下边界,参考状态(0矩阵),最大迭代次数mpc_max_iteration_,预测时域周期数horizon_,求解精度mpc_eps_,用输入参数去初始化类对象的数据成员

MpcOsqp::MpcOsqp(const Eigen::MatrixXd &matrix_a,const Eigen::MatrixXd &matrix_b,const Eigen::MatrixXd &matrix_q,const Eigen::MatrixXd &matrix_r,const Eigen::MatrixXd &matrix_initial_x,const Eigen::MatrixXd &matrix_u_lower,const Eigen::MatrixXd &matrix_u_upper,const Eigen::MatrixXd &matrix_x_lower,const Eigen::MatrixXd &matrix_x_upper,const Eigen::MatrixXd &matrix_x_ref, const int max_iter,const int horizon, const double eps_abs): matrix_a_(matrix_a),matrix_b_(matrix_b),matrix_q_(matrix_q),matrix_r_(matrix_r),matrix_initial_x_(matrix_initial_x),matrix_u_lower_(matrix_u_lower),matrix_u_upper_(matrix_u_upper),matrix_x_lower_(matrix_x_lower),matrix_x_upper_(matrix_x_upper),matrix_x_ref_(matrix_x_ref),max_iteration_(max_iter),horizon_(horizon),eps_abs_(eps_abs) {state_dim_ = matrix_b.rows();control_dim_ = matrix_b.cols();ADEBUG << "state_dim" << state_dim_;ADEBUG << "control_dim_" << control_dim_;num_param_ = state_dim_ * (horizon_ + 1) + control_dim_ * horizon_;
}

OSQP求解结果输出:

 std::vector<double> control_cmd(controls_, 0);apollo::common::math::MpcOsqp mpc_osqp(matrix_ad_, matrix_bd_, matrix_q_updated_, matrix_r_updated_,matrix_state_, lower_bound, upper_bound, lower_state_bound,upper_state_bound, reference_state, mpc_max_iteration_, horizon_,mpc_eps_);
//取控制序列的第一个作为输出的控制量if (!mpc_osqp.Solve(&control_cmd)) {AERROR << "MPC OSQP solver failed";} else {ADEBUG << "MPC OSQP problem solved! ";control[0](0, 0) = control_cmd.at(0);control[0](1, 0) = control_cmd.at(1);}//第一个元素前轮反馈转角steer_angle_feedback = Wheel2SteerPct(control[0](0, 0));//第二个元素加速度补偿acc_feedback = control[0](1, 0);

参考文献

本文针对运动学MPC控制器进行回顾总结,详细可以参考下述文献。

1、【基础】自动驾驶控制算法第五讲 连续方程的离散化与离散LQR原理_哔哩哔哩_bilibili

2、基于MPC轨迹跟踪~理论篇上_哔哩哔哩_bilibili

3、Apollo代码学习(六)—模型预测控制(MPC)_apollo mpc-CSDN博客

相关文章:

基于动力学的MPC控制器设计盲点解析

文章目录 Apollo MPC控制器的设计架构误差模型和离散化预测模型推导目标函数和约束设计优化求解优化OSQP求解器参考文献 Apollo MPC控制器的设计架构 误差模型和离散化 状态变量和控制变量 1、Apollo MPC控制器中状态变量主要有如下6个 matrix_state_ Matrix::Zero(basic_stat…...

Java重要面试名词整理(十六):SpringBoot

由于SpringBoot和Spring、SpringMVC重合度较高&#xff0c;更多详细内容请参考https://blog.csdn.net/weixin_73195042/article/details/144632385 本文着重于SpringBoot的启动流程 文章目录 概念启动流程底层分析构造SpringApplication对象run(String... args)方法SpringBoo…...

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;对于一些基础能力较弱的群体来说K8S控制面板操作存在一定的难度&#xff0c;此时kubesphere可以有效的解决这类难题。以下是部署kubesphere的操作步骤&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存储目录 yum -y install nfs-server e…...

算法-查找缺失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums &#xff0c;找出 [0, n] 这个范围内没有出现在数组中的那个数。 示例 1&#xff1a; 输入&#xff1a;nums [3,0,1] 输出&#xff1a;2 解释&#xff1a;n 3&#xff0c;因为有 3 个数字&#xff0c;所以所有的数字都在范围 [0,3…...

antd-vue - - - - - a-date-picker限制选择范围

antd-vue - - - - - a-date-picker限制选择范围 1. 效果展示2. 代码展示 1. 效果展示 如图&#xff1a;限制选择范围为 今年 & 去年 的 月份. 2. 代码展示 <template><a-date-picker:disabledDate"disabledDate"picker"month"/> &l…...

计算机网络练习题

学习这么多啦&#xff0c;那就简单写几个选择题巩固一下吧&#xff01; 1. 在IPv4分组各字段中&#xff0c;以下最适合携带隐藏信息的是&#xff08;D&#xff09; A、源IP地址 B、版本 C、TTL D、标识 2. OSI 参考模型中&#xff0c;数据链路层的主要功能是&#xff08;…...

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…...

STM32-笔记18-呼吸灯

1、实验目的 使用定时器 4 通道 3 生成 PWM 波控制 LED1 &#xff0c;实现呼吸灯效果。 频率&#xff1a;2kHz&#xff0c;PSC71&#xff0c;ARR499 利用定时器溢出公式 周期等于频率的倒数。故Tout 1/2KHZ&#xff1b;Ft 72MHZ PSC71&#xff08;喜欢设置成Ft的倍数&…...

Vue3 + ElementPlus动态合并数据相同的单元格(超级详细版)

最近的新项目有个需求需要合并单元列表。ElementPlus 的 Table 提供了合并行或列的方法&#xff0c;可以参考一下https://element-plus.org/zh-CN/component/table.html 但项目中&#xff0c;后台数据返回格式和指定合并是动态且没有规律的&#xff0c;Element 的示例过于简单&…...

【JavaWeb后端学习笔记】MySQL的数据控制语言(Data Control Language,DCL)

MySQL DCL 1、管理用户2、控制权限 DCL英文全称是Data Control Language&#xff08;数据控制语言&#xff09;&#xff0c;用来管理数据库用户、控制数据库访问权限。 1、管理用户 管理用户的操作都需要在MySQL自带的 mysql 数据库中进行。 -- 查询用户 -- 需要先切换到MyS…...

libvirt学习

文章目录 libvirt 简介节点、Hypervisor和域libvirt 安装和配置libvirt的XML配置文件libvirt APIMain libvirt APIsError handlingSpecial specific APIs 建立到Hypervisor的连接libvirt API使用编译libvirt工具virshvirt-clonevirt-dfvirt-imagevirt-installvirt-topvirt-what…...

STM32-笔记19-串口打印功能

复制项目文件夹03-流水灯&#xff0c;重命名为19-串口打印功能 打开项目 在主函数中&#xff0c;添加头文件、和串口初始化函数&#xff08;设置波特率&#xff09;和输出函数&#xff0c;如图所示&#xff1a; 软件部分就设置好了 下面是硬件部分 接线&#xff1a;使用USB…...

概率论与数理统计

概率论占比更多&#xff0c;三分之二左右 数理统计会少一些 事件之间的概率 ab互斥&#xff0c;不是ab独立 古典概型吃高中基础&#xff0c;考的不会很多 条件概率公式&#xff0c;要记 公式不要全记&#xff0c;很多有名称的公式是通过基础公式转换而来的 目的在于解决一…...

统信系统设置代理的问题

统信系统设置代理的问题 问题表现方式一方式二 问题表现 统信系统下有系统代理和应用代理两个代理。设置系统代理时&#xff0c;git不能经过代理拉取代码。但是设置应用代理时&#xff0c;可以用git通过代理拉代码。 这是系统代理&#xff0c;在这里设置 ip 端口&#xff0c;…...

TCP 为什么采用三次握手和四次挥手以及 TCP 和 UDP 的区别

1. TCP 为什么采用三次握手和四次挥手 采用三次握手的原因&#xff1a; 确认双方的收发能力。第一次握手&#xff0c;客户端发送 SYN 报文&#xff0c;告诉服务器自身具备发送数据的能力&#xff0c;第二次握手&#xff0c;服务器回应 SYN ACK 报文&#xff0c;表名自己既能…...

springboot配置并使用RestTemplate

目录 一、RestTemplate配置 1、将RestTemplate初始化为Bean 2、使用HttpClient作为RestTemplate客户端 &#xff08;1&#xff09;引入HttpClient依赖 &#xff08;2&#xff09;修改RestTemplate配置类 3、设置拦截器 &#xff08;1&#xff09;新增拦截器类 &#xf…...

人工智能-Python网络编程-TCP

1 TCP-概念版 服务端 import socket ​ # 1 创建服务端套接字对象 # socket.AF_INET IPV4 # socket.SOCK_STREAM TCP # socket.SOCK_DGRAM UDP tcp_server_socket socket.socket(socket.AF_INET, socket.SOCK_STREAM) ​ # 2 绑定端口号 tcp_server_socket.bind((192.…...

【Java回顾】Day3 继承|Override/Ovverload|多态|抽象类|封装|接口|枚举

学习资料 菜鸟教程 https://www.runoob.com/java/java-interfaces.html 继承|Override/Ovverload|多态|抽象类|封装|接口|枚举 继承 创建分等级层次的类&#xff0c;子类继承父类的特征、行为、方法 class 父类{ } class 子类 extends 父类{ super(); }一些性质 Java 不支持…...

SpringMVC(四)响应

目录 数据处理及跳转 1. 结果跳转方式 ①.ModelAndView ②.ServletAPI 1、通过HttpServletResponse进行输出 2、通过HttpServletResponse实现请求转发 3、通过HttpServletResponse实现重定向 ③.SpringMVC 1.直接输出 2.请求转发 3.重定向 2.ResponseBody响应json数…...

vim 的基础使用

目录 一&#xff1a;vim 介绍二&#xff1a;vim 特点三&#xff1a;vim 配置四&#xff1a;vim 使用1、vim 语法格式2、vim 普通模式&#xff08;1&#xff09;保存退出&#xff08;2&#xff09;光标跳转&#xff08;3&#xff09;文本删除&#xff08;4&#xff09;文本查找&…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)

本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢&#xff0c;连接红外测温传感器&#xff0c;可实时精准捕捉宠物体温变化&#xff0c;以便及时发现健康异常&#xff1b;水位检测传感器时刻监测饮用水余量&#xff0c;防止宠物…...