Apollo代码学习—模型预测控制

  • 前言
  • 模型预测控制
    • 预测模型
      • 线性化
      • 单车模型
    • 滚动优化
    • 反馈矫正
  • 总结

前言

非专业选手,此篇博文内容基于书本和网络资源整理,可能理解的较为狭隘,起点较低,就事论事。如发现有纰漏,请指正,非常感谢!!!

查看Apollo中关于MPC_controller的代码可以发现,它的主体集成了横纵向控制,在计算控制命令时,计算了横纵向误差:

ComputeLongitudinalErrors(&trajectory_analyzer_, debug);ComputeLateralErrors(com.x(), com.y(),VehicleStateProvider::instance()->heading(),VehicleStateProvider::instance()->linear_velocity(),VehicleStateProvider::instance()->angular_velocity(),trajectory_analyzer_, debug);

下文将从MPC原理入手,结合横纵向控制进行分析。

模型预测控制

可以先结合官方的教学视频对MPC进行一个简单的了解:模型预测控制。

根据维基百科,模型预测控制是一种先进的过程控制方法,在满足一定约束条件的前提下,被用来实现过程控制,它的实现依赖于过程的动态模型(通常为线性模型)。在控制时域(一段有限时间)内,它主要针对当前时刻进行优化,但也考虑未来时刻,求取当前时刻的最优控制解,然后反复优化,从而实现整个时域的优化求解。

也就是说,模型预测控制实际上是一种时间相关的,利用系统当前状态和当前的控制量,来实现对系统未来状态的控制。而系统未来的状态是不定的,因此在控制过程中要不断根据系统状态对未来的控制量作出调整。而且相较于经典的的PID控制,它具有优化和预测的能力,也就是说,模型预测控制是一种致力于将更长时间跨度、甚至于无穷时间的最优化控制问题,分解为若干个更短时间跨度,或者有限时间跨度的最优化控制问题,并且在一定程度上仍然追求最优解1

可以通过下图对模型预测控制进行一个简单的理解:

图1 模型预测控制原理 (图片来源:无人驾驶车辆模型预测控制)

图1中,k轴为当前状态,左侧为过去状态,右侧为将来状态。可结合无人驾驶车辆模型预测控制2第3.1.2节来理解此图。

模型预测控制在实现上有三个要素:

  1. 预测模型,是模型预测控制的基础,用来预测系统未来的输出;
  2. 滚动优化,一种在线优化,用于优化短时间内的控制输入,以尽可能减小预测模型输出与参考值的差距;
  3. 反馈矫正,在新的采样时刻,基于被控对象的实际输出,对预测模型的输出进行矫正,然后进行新的优化,以防模型失配或外界干扰导致的控制输出与期望差距过大。

下面从三要素入手对模型预测控制进行分析。

预测模型

无论是运动学模型,还是动力学模型,所搭建的均为非线性系统,而线性模型预测控制较非线性模型预测控制有更好的实时性,且更易于分析和计算。对于无人车来说,实时性显然很重要,因此,需要将非线性系统转化为线性系统,而非线性系统的线性化的方法大体可分为精确线性化和近似线性化,多采用近似的线性化方法。

线性化

此部分内容主要参考《无人驾驶车辆模型预测控制》23.3.2节,本人对对线性化、离散化等问题也理解的不深,不理解的可以自行查找一些其他的文章。

非线性系统线性化的方法有很多种,大致分为:

图2 线性化方法

下面以泰勒展开的方法为例,结合《无人驾驶车辆模型预测控制》23.3.2节非线性系统线性化方法,展示一种存在参考系统的线性化方法。存在参考系统的线性化方法假设参考系统已经在规划轨迹上完全跑通,得出每个时刻上相应的状态量XrX_rXr​和控制量UrU_rUr​,然后通过处理参考系统与当前系统的偏差,利用模型预测控制器来跟踪期望路径。

假设车辆参考系统在任意时刻的状态和控制量满足如下方程:
(1)X˙r=f(Xr,Ur)\dot{X}_r=f(X_r, U_r) \tag{1}X˙r​=f(Xr​,Ur​)(1)
在任意点(Xr,Ur)(X_r, U_r)(Xr​,Ur​)处泰勒展开,只保留一阶项,忽略高阶项,有:
(2)X˙=f(Xr,Ur)+∂f∂X(X−Xr)+∂f∂U(U−Ur)\dot{X}=f(X_r, U_r)+\frac{\partial f}{\partial X}(X - X_r)+\frac{\partial f}{\partial U}(U - U_r) \tag{2}X˙=f(Xr​,Ur​)+∂X∂f​(X−Xr​)+∂U∂f​(U−Ur​)(2)
公式2与公式1相减可得:
(3)X~˙=A(t)X~+B(t)U~\dot{\widetilde{X}}=A(t)\widetilde{X}+B(t)\widetilde{U} \tag{3}X˙=A(t)X+B(t)U(3)
其中,X~˙=X˙−X˙r\dot{\widetilde{X}}=\dot{X}-\dot{X}_rX˙=X˙−X˙r​,X~=X−Xr\widetilde{X}=X-X_rX=X−Xr​,U~=U−Ur\widetilde{U}=U-U_rU=U−Ur​,A(t)A(t)A(t)为f(X,U)f(X, U)f(X,U)对XXX的雅克比矩阵,B(t)B(t)B(t)为f(X,U)f(X, U)f(X,U)对UUU的雅克比矩阵。
此时,通过雅克比矩阵,将非线性系统近似转化为一个连续的线性系统,但并不适于模型预测控制器的设计,然后对其离散化处理可得,
(4)X~˙(k)=X~(k+1)−X~(k)T=A(k)X~(k)+B(k)U~(k)\dot{\widetilde{X}}(k)=\frac{\widetilde{X}(k+1)-\widetilde{X}(k)}{T}=A(k)\widetilde{X}(k)+B(k)\widetilde{U}(k) \tag{4}X˙(k)=TX(k+1)−X(k)​=A(k)X(k)+B(k)U(k)(4)
得到线性化时变模型:
(5)X~(k+1)=A~(k)X~(k)+B~(k)U~(k)\widetilde{X}(k+1)=\widetilde{A}(k)\widetilde{X}(k)+\widetilde{B}(k)\widetilde{U}(k) \tag{5}X(k+1)=A(k)X(k)+B(k)U(k)(5)
其中:A~(t)=I+TA(t),B~(t)=TB(t),I\widetilde{A}(t)=I+TA(t) ,\widetilde{B}(t)=TB(t),IA(t)=I+TA(t),B(t)=TB(t),I为单位矩阵。

至此,得到一个非线性系统在任意一参考点线性化后的线性系统,该系统是设计模型预测控制算法的基础。

以运动学模型中的式1.15为例,低速情况下的车辆运动学模型可表达为:
(6)[x˙y˙ψ˙]=[cos⁡ψsin⁡ψtan⁡δf/l]v\begin{bmatrix} \dot{x} \\ \dot{y} \\ \dot\psi \end{bmatrix}= \begin{bmatrix} \cos\psi \\ \sin\psi \\ \tan{\delta_f}/l \end{bmatrix}v \tag{6}⎣⎡​x˙y˙​ψ˙​​⎦⎤​=⎣⎡​cosψsinψtanδf​/l​⎦⎤​v(6)
其状态变量和控制变量分别为:
X=[xyψ],U=[vδf]X= \begin{bmatrix} x \\ y \\ \psi \end{bmatrix}, U= \begin{bmatrix} v\\ \delta_f \end{bmatrix}X=⎣⎡​xyψ​⎦⎤​,U=[vδf​​]
对应的雅克比矩阵:
(7)A=[00−vsin⁡ψ00vcos⁡ψ000],B=[cos⁡ψ0sin⁡ψ0tan⁡δflvlcos⁡2δf]A= \begin{bmatrix} 0 & 0 & -v\sin{\psi} \\ 0 & 0 & v\cos{\psi} \\ 0 & 0 & 0 \end{bmatrix}, B= \begin{bmatrix} \cos{\psi} & 0\\ \sin{\psi} & 0\\ \frac{\tan{\delta_f}}{l} & \frac{v}{l\cos^2{\delta_f}} \end{bmatrix} \tag{7} A=⎣⎡​000​000​−vsinψvcosψ0​⎦⎤​,B=⎣⎡​cosψsinψltanδf​​​00lcos2δf​v​​⎦⎤​(7)
其线性时变模型为:
X~˙=A~X~+B~U~\dot{\widetilde{X}}=\widetilde{A}\widetilde{X}+\widetilde{B}\widetilde{U}X˙=AX+BU
其中,
(8)X~=[x−x0y−y0ψ−ψ0],U~=[v−v0δf−δf0],A~=I+TA=[10−vsin⁡ψT01vcos⁡ψT001],B~=TB=[cos⁡ψT0sin⁡ψT0tan⁡δfTlvTlcos⁡2δf]\widetilde{X}= \begin{bmatrix} x-x_0 \\ y-y_0 \\ \psi-\psi_0 \end{bmatrix}, \widetilde{U}= \begin{bmatrix} v-v_0 \\ \delta_f-\delta_{f0} \end{bmatrix},\\ \widetilde{A}=I+TA= \begin{bmatrix} 1 & 0 & -v\sin{\psi}T \\ 0 & 1 & v\cos{\psi}T \\ 0 & 0 & 1 \end{bmatrix}, \widetilde{B}=TB= \begin{bmatrix} \cos{\psi}T & 0\\ \sin{\psi}T & 0\\ \frac{\tan{\delta_f}T}{l} & \frac{vT}{l\cos^2{\delta_f}} \end{bmatrix} \tag{8}X=⎣⎡​x−x0​y−y0​ψ−ψ0​​⎦⎤​,U=[v−v0​δf​−δf0​​],A=I+TA=⎣⎡​100​010​−vsinψTvcosψT1​⎦⎤​,B=TB=⎣⎡​cosψTsinψTltanδf​T​​00lcos2δf​vT​​⎦⎤​(8)

单车模型

预测模型仍以单车模型为主,结合运动学模型和动力学模型对车辆运动状态进行分析。

图3 单车模型

根据化代码可知,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();

matrix_state_=[lateral_errorlateral_error_rateheading_errorheading_error_ratestation_errorspeed_error]matrix\_state\_= \begin{bmatrix} lateral\_error\\ lateral\_error\_rate\\ heading\_error\\ heading\_error\_rate\\ station\_error\\ speed\_error\\ \end{bmatrix}matrix_state_=⎣⎢⎢⎢⎢⎢⎢⎡​lateral_errorlateral_error_rateheading_errorheading_error_ratestation_errorspeed_error​⎦⎥⎥⎥⎥⎥⎥⎤​
它们的计算请参考上一篇Apollo代码学习(五)—横纵向控制:
{matrix_state_(0,0)=dy∗cos⁡φ−dx∗sin⁡φmatrix_state_(1,0)=Vx∗sin⁡Δφ=Vx∗sin⁡e2matrix_state_(2,0)=φ−φdesmatrix_state_(3,0)=φ˙−φ˙desmatrix_state_(4,0)=−(dx∗cos⁡φdes+dy∗sin⁡φdes)matrix_state_(5,0)=Vdes−V∗cos⁡Δφ/k\begin{cases} matrix\_state\_(0, 0)=dy*\cos{\varphi}-dx*\sin{\varphi}\\ matrix\_state\_(1, 0)=V_x*\sin{\Delta\varphi} =V_x*\sin{e_2}\\ matrix\_state\_(2, 0)=\varphi-\varphi_{des}\\ matrix\_state\_(3, 0)=\dot{\varphi}-\dot{\varphi}_{des}\\ matrix\_state\_(4, 0)=-(dx*\cos{\varphi_{des}} + dy*\sin{\varphi_{des}})\\ matrix\_state\_(5, 0)=V_{des} - V*\cos{\Delta\varphi}/k\\ \end{cases}⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧​matrix_state_(0,0)=dy∗cosφ−dx∗sinφmatrix_state_(1,0)=Vx​∗sinΔφ=Vx​∗sine2​matrix_state_(2,0)=φ−φdes​matrix_state_(3,0)=φ˙​−φ˙​des​matrix_state_(4,0)=−(dx∗cosφdes​+dy∗sinφdes​)matrix_state_(5,0)=Vdes​−V∗cosΔφ/k​
控制变量有2个:

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

并结合代码去分析control_matrixcontrol\_matrixcontrol_matrix内包含的变量:

// 解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]
// 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_;
// control中第一个矩阵中的第二个值用于计算加速度
debug->set_acceleration_cmd_closeloop(control[0](1, 0));
double acceleration_cmd = control[0](1, 0) + debug->acceleration_reference();

可得
control_matrix=[δfa]control\_matrix= \begin{bmatrix} \delta_f \\ a \end{bmatrix} control_matrix=[δf​a​]
其中,δf\delta_fδf​为前轮转角,aaa为加速度补偿。
结合方向盘控制的动力学模型:
(9)ddt[e1e˙1e2e˙2]=[01000−2Caf+2CarmVx2Caf+2Carm−2Cafℓf+2CarℓrmVx00010−2Cafℓf−2CarℓrIzVx2Cafℓf−2CarℓrIz−2Cafℓf2+2Carℓr2IzVx][e1e˙1e2e˙2]+[02Cαfm02CαfℓfIz]δf+[0−2Cafℓf−2CarℓrmVx−Vx0−2Cafℓf2+2Carℓr2IzVx]φ˙\frac{d}{dt} \begin{bmatrix} e_1 \\ \dot{e}_1 \\ e_2 \\ \dot{e}_2 \end{bmatrix}= \begin{bmatrix} 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; -\frac{2C_{af}+2C_{ar}}{mV_x} &amp; \frac{2C_{af}+2C_{ar}}{m} &amp; \frac{-2C_{af}\ell_f+2C_{ar}\ell_r}{mV_x}\\ 0 &amp; 0 &amp; 0 &amp; 1 \\ 0 &amp; -\frac{2C_{af}\ell_f-2C_{ar}\ell_r}{I_zV_x} &amp; \frac{2C_{af}\ell_f-2C_{ar}\ell_r}{I_z} &amp; -\frac{2C_{af}\ell_f^2+2C_{ar}\ell_r^2}{I_zV_x} \end{bmatrix} \begin{bmatrix} e_1 \\ \dot{e}_1 \\ e_2 \\ \dot{e}_2 \end{bmatrix} \\ +\begin{bmatrix} 0 \\ \frac{2C_{\alpha f}}{m} \\ 0 \\ \frac{2C_{\alpha f}\ell_f}{I_z} \end{bmatrix}\delta_f+ \begin{bmatrix} 0 \\ -\frac{2C_{af}\ell_f-2C_{ar}\ell_r}{mV_x} -V_x\\ 0 \\ -\frac{2C_{af}\ell_f^2+2C_{ar}\ell_r^2}{I_zV_x} \end{bmatrix}\dot{\varphi} \tag{9} dtd​⎣⎢⎢⎡​e1​e˙1​e2​e˙2​​⎦⎥⎥⎤​=⎣⎢⎢⎢⎡​0000​1−mVx​2Caf​+2Car​​0−Iz​Vx​2Caf​ℓf​−2Car​ℓr​​​0m2Caf​+2Car​​0Iz​2Caf​ℓf​−2Car​ℓr​​​0mVx​−2Caf​ℓf​+2Car​ℓr​​1−Iz​Vx​2Caf​ℓf2​+2Car​ℓr2​​​⎦⎥⎥⎥⎤​⎣⎢⎢⎡​e1​e˙1​e2​e˙2​​⎦⎥⎥⎤​+⎣⎢⎢⎡​0m2Cαf​​0Iz​2Cαf​ℓf​​​⎦⎥⎥⎤​δf​+⎣⎢⎢⎢⎡​0−mVx​2Caf​ℓf​−2Car​ℓr​​−Vx​0−Iz​Vx​2Caf​ℓf2​+2Car​ℓr2​​​⎦⎥⎥⎥⎤​φ˙​(9)
和mpc_controller.cc、mpc_slover.cc中的代码注释,

// 初始化矩阵
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) 

可得MPC控制模型:
(10)ddt[lateral_errorlateral_error_rateheading_errorheading_error_ratestation_errorspeed_error]=[0100000−Cf+CrmVCf+CrmCrℓr−CfℓfmV000001000Crℓr−CfℓfIzVCfℓf−CrℓrIz−Crℓr2+Cfℓf2IzV00000001000000][lateral_errorlateral_error_rateheading_errorheading_errorratestation_errorspeed_error]+[00Cfm000CfℓfIz0000−1][δfa]+[0Crℓr−CfℓfmV−V0−Crℓr2+Cfℓf2IzV01]φ˙\frac{d}{dt} \begin{bmatrix} lateral\_error\\ lateral\_error\_rate\\ heading\_error\\ heading\_error\_rate\\ station\_error\\ speed\_error\\ \end{bmatrix}= \begin{bmatrix} 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0\\ 0 &amp; -\frac{C_f+C_r}{mV} &amp; \frac{C_f+C_r}{m} &amp; \frac{C_r\ell_r-C_f\ell_f}{mV} &amp; 0 &amp; 0\\ 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0\\ 0 &amp; \frac{C_r\ell_r-C_f\ell_f}{I_zV} &amp; \frac{C_f\ell_f-C_r\ell_r}{I_z} &amp; -\frac{C_r\ell_r^2+C_f\ell_f^2}{I_zV} &amp; 0 &amp; 0\\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1\\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \end{bmatrix} \begin{bmatrix} lateral\_error\\ lateral\_error\_rate\\ heading\_error\\ heading\_error_rate\\ station\_error\\ speed\_error\\ \end{bmatrix} \\ +\begin{bmatrix} 0 &amp; 0\\ \frac{C_f}{m} &amp; 0\\ 0 &amp; 0\\ \frac{C_f\ell_f}{I_z} &amp; 0\\ 0 &amp; 0\\ 0 &amp; -1 \end{bmatrix} \begin{bmatrix} \delta_f \\ a \end{bmatrix}+ \begin{bmatrix} 0\\ \frac{C_r\ell_r-C_f\ell_f}{mV}-V\\ 0\\ -\frac{C_r\ell_r^2+C_f\ell_f^2}{I_zV}\\ 0\\ 1 \end{bmatrix} \dot{\varphi} \tag{10}dtd​⎣⎢⎢⎢⎢⎢⎢⎡​lateral_errorlateral_error_rateheading_errorheading_error_ratestation_errorspeed_error​⎦⎥⎥⎥⎥⎥⎥⎤​=⎣⎢⎢⎢⎢⎢⎢⎢⎡​000000​1−mVCf​+Cr​​0Iz​VCr​ℓr​−Cf​ℓf​​00​0mCf​+Cr​​0Iz​Cf​ℓf​−Cr​ℓr​​00​0mVCr​ℓr​−Cf​ℓf​​1−Iz​VCr​ℓr2​+Cf​ℓf2​​00​000000​000010​⎦⎥⎥⎥⎥⎥⎥⎥⎤​⎣⎢⎢⎢⎢⎢⎢⎡​lateral_errorlateral_error_rateheading_errorheading_errorr​atestation_errorspeed_error​⎦⎥⎥⎥⎥⎥⎥⎤​+⎣⎢⎢⎢⎢⎢⎢⎡​0mCf​​0Iz​Cf​ℓf​​00​00000−1​⎦⎥⎥⎥⎥⎥⎥⎤​[δf​a​]+⎣⎢⎢⎢⎢⎢⎢⎢⎡​0mVCr​ℓr​−Cf​ℓf​​−V0−Iz​VCr​ℓr2​+Cf​ℓf2​​01​⎦⎥⎥⎥⎥⎥⎥⎥⎤​φ˙​(10)

其中,Cf,CrC_f,C_rCf​,Cr​分别为前/后轮转弯刚度,ℓf,ℓr\ell_f,\ell_rℓf​,ℓr​分别为前悬/后悬长度,mmm为车身质量,VVV为车速,IzI_zIz​为车辆绕zzz轴转动的转动惯量,φ˙\dot{\varphi}φ˙​为转向速度。
对应的状态矩阵、控制矩阵、扰动矩阵等如下:
(11)A=[0100000−Cf+CrmVCf+CrmCrℓr−CfℓfmV000001000Crℓr−CfℓfIzVCfℓf−CrℓrIz−Crℓr2+Cfℓf2IzV00000001000000],B=[00Cfm000CfℓfIz0000−1],C=[0Crℓr−CfℓfmV−V0−Crℓr2+Cfℓf2IzV01]A=\begin{bmatrix} 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0\\ 0 &amp; -\frac{C_f+C_r}{mV} &amp; \frac{C_f+C_r}{m} &amp; \frac{C_r\ell_r-C_f\ell_f}{mV} &amp; 0 &amp; 0\\ 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0\\ 0 &amp; \frac{C_r\ell_r-C_f\ell_f}{I_zV} &amp; \frac{C_f\ell_f-C_r\ell_r}{I_z} &amp; -\frac{C_r\ell_r^2+C_f\ell_f^2}{I_zV} &amp; 0 &amp; 0\\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1\\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \end{bmatrix},\\ B=\begin{bmatrix} 0 &amp; 0\\ \frac{C_f}{m} &amp; 0\\ 0 &amp; 0\\ \frac{C_f\ell_f}{I_z} &amp; 0\\ 0 &amp; 0\\ 0 &amp; -1 \end{bmatrix}, C=\begin{bmatrix} 0\\ \frac{C_r\ell_r-C_f\ell_f}{mV}-V\\ 0\\ -\frac{C_r\ell_r^2+C_f\ell_f^2}{I_zV}\\ 0\\ 1 \end{bmatrix} \tag{11}A=⎣⎢⎢⎢⎢⎢⎢⎢⎡​000000​1−mVCf​+Cr​​0Iz​VCr​ℓr​−Cf​ℓf​​00​0mCf​+Cr​​0Iz​Cf​ℓf​−Cr​ℓr​​00​0mVCr​ℓr​−Cf​ℓf​​1−Iz​VCr​ℓr2​+Cf​ℓf2​​00​000000​000010​⎦⎥⎥⎥⎥⎥⎥⎥⎤​,B=⎣⎢⎢⎢⎢⎢⎢⎡​0mCf​​0Iz​Cf​ℓf​​00​00000−1​⎦⎥⎥⎥⎥⎥⎥⎤​,C=⎣⎢⎢⎢⎢⎢⎢⎢⎡​0mVCr​ℓr​−Cf​ℓf​​−V0−Iz​VCr​ℓr2​+Cf​ℓf2​​01​⎦⎥⎥⎥⎥⎥⎥⎥⎤​(11)
对应的线性化系数应为(欧拉映射离散法):
A~=I+TA,B~=TB,C~=TC\widetilde{A}=I+TA,\widetilde{B}=TB,\widetilde{C}=TCA=I+TA,B=TB,C=TC
但代码中实际线性化系数为(双线性变换离散法):

  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_;

(12)A~=(I+TA/2)(I−TA/2)−1,B~=TB,C~=TC∗heading_error_rate\widetilde{A}=(I+TA/2)(I-TA/2)^{-1},\widetilde{B}=TB,\widetilde{C}=TC*heading\_error\_rate \tag{12}A=(I+TA/2)(I−TA/2)−1,B=TB,C=TC∗heading_error_rate(12)
对于C~\widetilde{C}C的形式不同,个人认为是由于heading_error_rateheading\_error\_rateheading_error_rate是计算横向误差之后才有的,无法直接获取,在矩阵更新的时候才将heading_error_rateheading\_error\_rateheading_error_rate作为系数更新到矩阵中,也就是公式10中的φ˙\dot{\varphi}φ˙​,其实对于C~\widetilde{C}C来说,仍是C~=TC\widetilde{C}=TCC=TC的形式。A~\widetilde{A}A的形式不一样,是因为此处采用了双线性变换离散法。感谢博友LLCCCJJ的友情提示。 关于连续系统离散化的方法可参考:连续系统离散化方法。

最终得到形如公式13的离散线性模型:
(13)x(k+1)=Ax(k)+Bu(k)+Cx(k+1)=Ax(k)+Bu(k)+C\tag{13}x(k+1)=Ax(k)+Bu(k)+C(13)
系统的输出方程为:y(k)=Dx(k)y(k)=Dx(k)y(k)=Dx(k)。
则在预测时域内有状态变量方程和输出变量方程如下:
(14)x(k)=Akx(0)+∑i=0k−1AiBu(k−1−i)+∑i=0k−1AiCx(k)=A^kx(0)+\sum_{i=0}^{k-1}A^iBu(k-1-i)+\sum_{i=0}^{k-1}A^iC \tag{14}x(k)=Akx(0)+i=0∑k−1​AiBu(k−1−i)+i=0∑k−1​AiC(14)
(15)y(k)=DAkx(0)+∑i=0k−1DAiBu(k−1−i)+∑i=0k−1DAiCy(k)=DA^kx(0)+\sum_{i=0}^{k-1}DA^iBu(k-1-i)+\sum_{i=0}^{k-1}DA^iC \tag{15}y(k)=DAkx(0)+i=0∑k−1​DAiBu(k−1−i)+i=0∑k−1​DAiC(15)
假设
(16)ξ(k∣t)=[x(k∣t)u(k−1∣t)]\xi(k|t)= \begin{bmatrix} x(k|t)\\ u(k-1|t) \end{bmatrix} \tag{16}ξ(k∣t)=[x(k∣t)u(k−1∣t)​](16)
可得到新的状态空间表达式:
(17)ξ(k+1∣t)=A~ξ(k∣t)+B~Δu(k∣t)+C~η(k∣t)=D~ξ(k∣t)\begin{matrix} \xi(k+1|t)=\widetilde{A}\xi(k|t)+\widetilde{B}\Delta u(k|t)+\widetilde{C} \\ \eta(k|t)=\widetilde{D}\xi(k|t) \end{matrix}\tag{17}ξ(k+1∣t)=Aξ(k∣t)+BΔu(k∣t)+Cη(k∣t)=Dξ(k∣t)​(17)
其中,
(18)A~=[AB0I],B~=[BI],C~=[C0],D~=[D0]\begin{matrix} \widetilde{A}= \begin{bmatrix} A &amp; B \\ 0 &amp; I \end{bmatrix}, \widetilde{B}= \begin{bmatrix} B \\ I \end{bmatrix}, \widetilde{C}= \begin{bmatrix} C \\ 0 \end{bmatrix}, \widetilde{D}=[D\ \ \ 0] \end{matrix}\tag{18}A=[A0​BI​],B=[BI​],C=[C0​],D=[D   0]​(18)
可将公式16、公式18代入公式17,验证公式18的由来。
则在预测时域内的状态变量和输出变量可用如下算式计算:
(19)ξ(k+Np∣t)=A~tNpξ(t∣t)+A~tNp−1B~tΔu(t∣t)+A~tNp−1C~t+⋯+B~tΔu(t+Np−1∣t)+C~tη(k+Np∣t)=D~tA~tNpξ(t∣t)+D~tA~tNp−1B~tΔu(t∣t)+D~tA~tNp−1C~t+⋯+D~tB~tΔu(t+Np−1∣t)+D~tC~t\begin{matrix} \xi(k+N_p|t)=\widetilde{A}_t^{N_p}\xi(t|t)+\widetilde{A}_t^{N_p-1}\widetilde{B}_t\Delta u(t|t)+\widetilde{A}_t^{N_p-1}\widetilde{C}_t+\cdots +\widetilde{B}_t\Delta u(t+N_p-1|t)+\widetilde{C}_t \\ \eta(k+N_p|t)=\widetilde{D}_t\widetilde{A}_t^{N_p}\xi(t|t)+\widetilde{D}_t\widetilde{A}_t^{N_p-1}\widetilde{B}_t\Delta u(t|t)+\widetilde{D}_t\widetilde{A}_t^{N_p-1}\widetilde{C}_t+\cdots +\widetilde{D}_t\widetilde{B}_t\Delta u(t+N_p-1|t)+\widetilde{D}_t\widetilde{C}_t \end{matrix} \tag{19}ξ(k+Np​∣t)=AtNp​​ξ(t∣t)+AtNp​−1​Bt​Δu(t∣t)+AtNp​−1​Ct​+⋯+Bt​Δu(t+Np​−1∣t)+Ct​η(k+Np​∣t)=Dt​AtNp​​ξ(t∣t)+Dt​AtNp​−1​Bt​Δu(t∣t)+Dt​AtNp​−1​Ct​+⋯+Dt​Bt​Δu(t+Np​−1∣t)+Dt​Ct​​(19)
将系统未来时刻的状态和输出以矩阵形式表达为:
(20)X(t)=Ψtξ(t∣t)+ΦtΔU(t∣t)+ΥtY(t)=D~tX(t)\begin{matrix} X(t)=\Psi_t\xi(t|t)+\Phi_t\Delta U(t|t)+\Upsilon_t \\ Y(t)=\widetilde{D}_tX(t) \end{matrix} \tag{20}X(t)=Ψt​ξ(t∣t)+Φt​ΔU(t∣t)+Υt​Y(t)=Dt​X(t)​(20)
其中,
(21)X(t)=[ξ(t+1∣t)ξ(t+2∣t)ξ(t+3∣t)⋮ξ(t+Np∣t)],Y(t)=[η(t+1∣t)η(t+2∣t)η(t+3∣t)⋮η(t+Np∣t)],ΔU=[Δu(t∣t)Δu(t+1∣t)Δu(t+2∣t)⋮Δu(t+Np−1∣t)],Υt=[C~A~C~+C~A~2C~+A~C~+C~⋮∑i=0Np−1A~iC~],Ψt=[A~tA~t2A~t3⋮A~tNp],Φt=[B~t00⋯0A~tB~tB~t0⋯0⋮⋮⋯⋯⋯A~tNp−1B~tA~tNp−2B~t⋯⋯B~t]X(t)=\begin{bmatrix} \xi(t+1|t)\\ \xi(t+2|t)\\ \xi(t+3|t)\\ \vdots\\ \xi(t+N_p|t)\\ \end{bmatrix}, Y(t)=\begin{bmatrix} \eta(t+1|t)\\ \eta(t+2|t)\\ \eta(t+3|t)\\ \vdots\\ \eta(t+N_p|t)\\ \end{bmatrix}, \Delta U=\begin{bmatrix} \Delta u(t|t)\\ \Delta u(t+1|t)\\ \Delta u(t+2|t)\\ \vdots\\ \Delta u(t+N_p-1|t)\\ \end{bmatrix}, \Upsilon_t=\begin{bmatrix} \widetilde{C}\\ \widetilde{A}\widetilde{C} + \widetilde{C}\\ \widetilde{A}^2\widetilde{C} + \widetilde{A}\widetilde{C} + \widetilde{C}\\ \vdots\\ \sum_{i=0}^{N_p-1}\widetilde{A}^i\widetilde{C} \end{bmatrix},\\ \Psi_t=\begin{bmatrix} \widetilde{A}_t\\ \widetilde{A}_t^2\\ \widetilde{A}_t^3\\ \vdots\\ \widetilde{A}_t^{N_p}\\ \end{bmatrix}, \Phi_t=\begin{bmatrix} \widetilde{B}_t &amp; 0 &amp; 0 &amp; \cdots &amp; 0\\ \widetilde{A}_t\widetilde{B}_t &amp; \widetilde{B}_t &amp; 0 &amp; \cdots &amp; 0\\ \vdots &amp; \vdots &amp; \cdots &amp; \cdots &amp; \cdots \\ \widetilde{A}_t^{N_p-1}\widetilde{B}_t &amp; \widetilde{A}_t^{N_p-2}\widetilde{B}_t &amp; \cdots &amp; \cdots &amp; \widetilde{B}_t\\ \end{bmatrix} \tag{21}X(t)=⎣⎢⎢⎢⎢⎢⎡​ξ(t+1∣t)ξ(t+2∣t)ξ(t+3∣t)⋮ξ(t+Np​∣t)​⎦⎥⎥⎥⎥⎥⎤​,Y(t)=⎣⎢⎢⎢⎢⎢⎡​η(t+1∣t)η(t+2∣t)η(t+3∣t)⋮η(t+Np​∣t)​⎦⎥⎥⎥⎥⎥⎤​,ΔU=⎣⎢⎢⎢⎢⎢⎡​Δu(t∣t)Δu(t+1∣t)Δu(t+2∣t)⋮Δu(t+Np​−1∣t)​⎦⎥⎥⎥⎥⎥⎤​,Υt​=⎣⎢⎢⎢⎢⎢⎢⎡​CAC+CA2C+AC+C⋮∑i=0Np​−1​AiC​⎦⎥⎥⎥⎥⎥⎥⎤​,Ψt​=⎣⎢⎢⎢⎢⎢⎢⎡​At​At2​At3​⋮AtNp​​​⎦⎥⎥⎥⎥⎥⎥⎤​,Φt​=⎣⎢⎢⎢⎡​Bt​At​Bt​⋮AtNp​−1​Bt​​0Bt​⋮AtNp​−2​Bt​​00⋯⋯​⋯⋯⋯⋯​00⋯Bt​​⎦⎥⎥⎥⎤​(21)
通过公式20我们可以看出,预测时域内的状态和输出量都可以通过从系统当前的状态量ξ(t∣t)\xi(t|t)ξ(t∣t)和控制增量ΔU(t∣t)\Delta U(t|t)ΔU(t∣t)求得,这也即是模型预测控制算法中“预测”功能的实现。
结合mpc_slover.cc,对MPC的模型进行分析:

  unsigned int horizon = reference.size();  // horizon =10// Update augment reference matrix_t// matrix_t为60*1的矩阵,存储的参考轨迹信息Matrix matrix_t = Matrix::Zero(matrix_b.rows() * horizon, 1);...// Update augment control matrix_v// matrix_v为20*1的矩阵,存储控制信息Matrix matrix_v = Matrix::Zero((*control)[0].rows() * horizon, 1);...// matrix_a_power为含有10个矩阵的容器,每个矩阵为6*6,matrix_a为6*6矩阵std::vector<Matrix> matrix_a_power(horizon);...// matrix_k为60*20的矩阵,matrix_b为6*2矩阵Matrix matrix_k =Matrix::Zero(matrix_b.rows() * horizon, matrix_b.cols() * horizon);...

令Ref=matrix_t,Ctr=matrix_v,A=matrix_a,AP=matrix_a_power,B=matrix_b,K=matrix_kRef=matrix\_t, Ctr=matrix\_v, A=matrix\_a, AP=matrix\_a\_power, B=matrix\_b, K=matrix\_kRef=matrix_t,Ctr=matrix_v,A=matrix_a,AP=matrix_a_power,B=matrix_b,K=matrix_k,根据代码有:
(22)Ref=[ref1ref2⋮ref10],Ctr=[ctr1ctr2⋮ctr10],PA=[AA2⋮A10],K=[AB0⋯0A2BAB⋯0⋮⋮⋯⋮A10BA9B⋯AB]Ref=\begin{bmatrix} ref_1\\ ref_2\\ \vdots\\ ref_{10} \end{bmatrix}, Ctr=\begin{bmatrix} ctr_1\\ ctr_2\\ \vdots\\ ctr_{10} \end{bmatrix}, PA=\begin{bmatrix} A\\ A^2\\ \vdots\\ A^{10} \end{bmatrix},\\ K=\begin{bmatrix} AB &amp; 0 &amp; \cdots &amp; 0 \\ A^2B &amp; AB &amp; \cdots &amp; 0 \\ \vdots &amp; \vdots &amp; \cdots &amp; \vdots \\ A^{10}B &amp; A^9B &amp; \cdots &amp; AB \end{bmatrix}\tag{22}Ref=⎣⎢⎢⎢⎡​ref1​ref2​⋮ref10​​⎦⎥⎥⎥⎤​,Ctr=⎣⎢⎢⎢⎡​ctr1​ctr2​⋮ctr10​​⎦⎥⎥⎥⎤​,PA=⎣⎢⎢⎢⎡​AA2⋮A10​⎦⎥⎥⎥⎤​,K=⎣⎢⎢⎢⎡​ABA2B⋮A10B​0AB⋮A9B​⋯⋯⋯⋯​00⋮AB​⎦⎥⎥⎥⎤​(22)
其中,refiref_irefi​为参考轨迹序列,ctrictr_ictri​为预测控制序列,预测时域为10个采样周期。

滚动优化

MPC的线性优化问题可以结合无人驾驶车辆模型预测控制第3.3.1节及以下文章:Model predictive control of a mobile robot using linearization进行学习。

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

因此,需要设计合适的优化目标,以获得尽可能最优的控制序列,目标函数的一般形式可表示为状态和控制输入的二次函数:
(23)J(k)=∑j=1N(x~(k+j∣k)TQx~(k+j∣k)+u~(k+j−1∣k)TRu~(k+j−1∣k))J(k)=\sum_{j=1}^N(\widetilde{x}(k+j|k)^TQ\widetilde{x}(k+j|k)+\widetilde{u}(k+j-1|k)^TR\widetilde{u}(k+j-1|k)) \tag{23}J(k)=j=1∑N​(x(k+j∣k)TQx(k+j∣k)+u(k+j−1∣k)TRu(k+j−1∣k))(23)

其中,NNN为预测时域,Q,RQ, RQ,R为权重矩阵,且满足Q≥0,R&gt;0Q\ge0, R&gt;0Q≥0,R>0的正定矩阵。形如a(m∣n)a(m|n)a(m∣n)表示,在nnn时刻下预测的mmm时刻的aaa值。第一项反映了系统对参考轨迹的跟踪能力,第二项反映了对控制量变化的约束。此外,上式(公式23)在书写过程中,累加和函数∑\sum∑后几乎都不加"()",但我看起来实在难受,所以自行将x,ux,ux,u一起括起来。
优化求解的问题可以理解为在每一个采样点kkk,寻找一组最优控制序列u~t∗\widetilde{u}_t^*ut∗​和最优开销J∗(k)J^*(k)J∗(k),其中:
u~t∗=arg⁡min⁡u~J(k)\widetilde{u}_t^*=\arg\min_{\widetilde{u}}{J(k)}ut∗​=argumin​J(k)
在MPC控制规律中,将控制序列中的第一个参数作为控制量,输入给被控系统。

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

  1. 看过Apollo官方控制模块视频的人,可能知道在设计代价函数时候,一般设计为二次型的样式,为的是避免在预测时域内,误差忽正忽负,导致误差相互抵消;此外,对于实在不理解为什么代价函数要采用平方形式的同学,也可以参考损失函数为什么用平方形式(二)。
  2. 可考虑的代价有:
    a. 距离误差(Cross Track Error, CTE),指实际轨迹点与参考轨迹点间的距离,误差项可表示为:(zi−zref,i)2(z_i-z_{ref,i})^2(zi​−zref,i​)2;
    b. 速度误差,指实际速度与期望速度的差,误差项可表示为:(vi−vref,i)2(v_i-v_{ref,i})^2(vi​−vref,i​)2;
    c. 刹车/油门调节量,目的是为了保证刹车/油门变化的平稳性,误差项可表示为:(ai+1−ai)2(a_{i+1}-a_i)^2(ai+1​−ai​)2;
    d. 航向误差等…
  3. 约束条件
    a. 最大前轮转角
    b. 最大刹车/油门调节量
    c. 最大方向盘转角
    d. 最大车速等

因此公式23中的第一项可表示为:
(24)∑j=1Nx~(k+j∣k)TQx~(k+j∣k)=∑j=1N(w1(zi−zref,i)2+w2(vi−vref,i)2+w3(ai+1−ai)2+...)\sum_{j=1}^N\widetilde{x}(k+j|k)^TQ\widetilde{x}(k+j|k)=\sum_{j=1}^N(w_1(z_i-z_{ref,i})^2+w_2(v_i-v_{ref,i})^2+w_3(a_{i+1}-a_i)^2+...) \tag{24}j=1∑N​x(k+j∣k)TQx(k+j∣k)=j=1∑N​(w1​(zi​−zref,i​)2+w2​(vi​−vref,i​)2+w3​(ai+1​−ai​)2+...)(24)
其中,wiw_iwi​为该项误差的权重,对应权重矩阵Q中的某一项。

对于上述的目标函数(公式23),是有多个变量,且要服从于这些变量的线性约束的二次函数,因此可以通过适当处理将其转换为二次规划问题。

基于公式20,将控制量变为控制增量,以满足系统对控制增量的要求,则目标函数可以改写为:
(25)J(ξ(t),u(t−1),ΔU(t))=∑i=1N∣∣η(t+i∣t)−ηref(t+i∣t)∣∣Q2+∑i=1N−1∣∣ΔU(t+i∣t)∣∣R2J(\xi(t), u(t-1), \Delta U(t))=\sum_{i=1}^N||\eta(t+i|t)-\eta_{ref}(t+i|t)||_Q^2+\sum_{i=1}^{N-1}||\Delta U(t+i|t)||_R^2\tag{25}J(ξ(t),u(t−1),ΔU(t))=i=1∑N​∣∣η(t+i∣t)−ηref​(t+i∣t)∣∣Q2​+i=1∑N−1​∣∣ΔU(t+i∣t)∣∣R2​(25)

在此基础上满足一些约束条件,一般如下:

(26){控制量约束:umin(t+k)≤u(t+k)≤umax(t+k)控制增量约束:Δumin(t+k)≤Δu(t+k)≤Δumax(t+k)输出约束:ymin(t+k)≤y(t+k)≤ymax(t+k)\begin{cases} 控制量约束:u_{min}(t+k) \le u(t+k) \le u_{max}(t+k) \\ 控制增量约束:\Delta u_{min}(t+k) \le \Delta u(t+k) \le \Delta u_{max}(t+k)\\ 输出约束:y_{min}(t+k) \le y(t+k) \le y_{max}(t+k) \end{cases}\tag{26}⎩⎪⎨⎪⎧​控制量约束:umin​(t+k)≤u(t+k)≤umax​(t+k)控制增量约束:Δumin​(t+k)≤Δu(t+k)≤Δumax​(t+k)输出约束:ymin​(t+k)≤y(t+k)≤ymax​(t+k)​(26)
其中,k=0,1,2,3,...,N−1k=0,1,2,3,...,N-1k=0,1,2,3,...,N−1。

将公式20代入公式23中,并将预测时域内输出量偏差表示为:
(27)E(t)=Ψtξ(t∣t)−Yref(t)E(t)=\Psi_t\xi(t|t)-Y_{ref}(t) \tag{27}E(t)=Ψt​ξ(t∣t)−Yref​(t)(27)
其中,Yref=[ηref(t+1∣t),...,ηref(t+N∣t)]TY_{ref}=[\eta_{ref}(t+1|t),...,\eta_{ref}(t+N|t)]^TYref​=[ηref​(t+1∣t),...,ηref​(t+N∣t)]T。
经过一定的矩阵计算,可将目标函数调整为与控制增量相关的函数:
(28)J(ξ(t),u(t−1),ΔU(t))=ΔU(t)HtΔU(t)T+GtΔU(t)T+PtJ(\xi(t), u(t-1), \Delta U(t))=\Delta U(t)H_t\Delta U(t)^T+G_t\Delta U(t)^T+P_t \tag{28}J(ξ(t),u(t−1),ΔU(t))=ΔU(t)Ht​ΔU(t)T+Gt​ΔU(t)T+Pt​(28)
其中,Ht=ΦTQeΦ+Re,Gt=2E(t)TQeΦ,Pt=E(t)TQeE(t),PtH_t=\Phi^TQ_e\Phi +R_e,G_t=2E(t)^TQ_e\Phi,P_t=E(t)^TQ_eE(t),P_tHt​=ΦTQe​Φ+Re​,Gt​=2E(t)TQe​Φ,Pt​=E(t)TQe​E(t),Pt​为常量,Qe,ReQ_e,R_eQe​,Re​为权重矩阵Q,RQ,RQ,R的扩充矩阵。
结合mpc_slover.cc中的代码,

// Initialize matrix_k, matrix_m, matrix_t and matrix_v, matrix_qq, matrix_rr,// vector of matrix A powerMatrix matrix_m = Matrix::Zero(matrix_b.rows() * horizon, 1);      // 60*1Matrix matrix_qq = Matrix::Zero(matrix_k.rows(), matrix_k.rows()); // 60*60Matrix matrix_rr = Matrix::Zero(matrix_k.cols(), matrix_k.cols()); // 20*20Matrix matrix_ll = Matrix::Zero(horizon * matrix_lower.rows(), 1); //20*1Matrix matrix_uu = Matrix::Zero(horizon * matrix_upper.rows(), 1); //20*1...// Update matrix_m1, matrix_m2, convert MPC problem to QP problem doneMatrix matrix_m1 = matrix_k.transpose() * matrix_qq * matrix_k + matrix_rr;Matrix matrix_m2 = matrix_k.transpose() * matrix_qq * (matrix_m - matrix_t);...// TODO(QiL) : change qp solver to box constraint or substitute QPOASES// Method 1: QPOASESMatrix matrix_inequality_constrain_ll =Matrix::Identity(matrix_ll.rows(), matrix_ll.rows());...// 求解std::unique_ptr<QpSolver> qp_solver(new ActiveSetQpSolver(matrix_m1, matrix_m2, matrix_inequality_constrain,matrix_inequality_boundary, matrix_equality_constrain,matrix_equality_boundary));auto result = qp_solver->Solve();

令S=matrix_initial_state,M=matrix_m,M1=matrix_m1,M2=matrix_m2,Q=matrix_q,R=matrix_r,QQ=matrix_qq,RR=matrix_rr,LL=matrix_ll,UU=matrix_uuS=matrix\_initial\_state, M=matrix\_m, M1=matrix\_m1, M2=matrix\_m2, Q=matrix\_q, R=matrix\_r, QQ=matrix\_qq, RR=matrix\_rr, LL=matrix\_ll, UU=matrix\_uuS=matrix_initial_state,M=matrix_m,M1=matrix_m1,M2=matrix_m2,Q=matrix_q,R=matrix_r,QQ=matrix_qq,RR=matrix_rr,LL=matrix_ll,UU=matrix_uu,根据代码有:
(29)M=[AS(t∣t)+CAM[0]+C⋮AM[8]+C]=[AS(t∣t)+CA2S(t∣t)+AC+C⋮A10S(t∣t)+∑i=09AiC],QQ=[Q0⋯00Q⋯0⋮⋮⋱⋮00⋯Q],RR=[R0⋯00R⋯0⋮⋮⋱⋮00⋯R],M1=KT∗QQ∗K+RR=Ht,M2=KT∗QQ(M−Ref)=KT∗QQ∗E(t)M=\begin{bmatrix} AS(t|t)+C\\ AM[0]+C \\ \vdots\\ AM[8]+C \end{bmatrix}=\begin{bmatrix} AS(t|t)+C \\ A^2S(t|t)+AC+C \\ \vdots\\ A^{10}S(t|t)+\sum_{i=0}^9 A^iC \end{bmatrix},\\ QQ= \begin{bmatrix} Q &amp; 0 &amp; \cdots &amp; 0\\ 0 &amp; Q &amp; \cdots &amp; 0\\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots\\ 0 &amp; 0 &amp; \cdots &amp; Q \end{bmatrix}, RR= \begin{bmatrix} R &amp; 0 &amp; \cdots &amp; 0\\ 0 &amp; R &amp; \cdots &amp; 0\\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots\\ 0 &amp; 0 &amp; \cdots &amp; R \end{bmatrix},\\ \ \\ M1=K^T*QQ*K+RR=H_t,M2=K^T*QQ(M-Ref)=K^T*QQ*E(t) \tag{29}M=⎣⎢⎢⎢⎡​AS(t∣t)+CAM[0]+C⋮AM[8]+C​⎦⎥⎥⎥⎤​=⎣⎢⎢⎢⎡​AS(t∣t)+CA2S(t∣t)+AC+C⋮A10S(t∣t)+∑i=09​AiC​⎦⎥⎥⎥⎤​,QQ=⎣⎢⎢⎢⎡​Q0⋮0​0Q⋮0​⋯⋯⋱⋯​00⋮Q​⎦⎥⎥⎥⎤​,RR=⎣⎢⎢⎢⎡​R0⋮0​0R⋮0​⋯⋯⋱⋯​00⋮R​⎦⎥⎥⎥⎤​, M1=KT∗QQ∗K+RR=Ht​,M2=KT∗QQ(M−Ref)=KT∗QQ∗E(t)(29)

因此,对模型预测控制的每一步进行带约束条件的优化问题,可转换为如下的二次规划问题:
(30)min⁡ΔUtΔU(t)HtΔU(t)T+GtΔU(t)TΔUmin≤ΔUt(k)≤ΔUmaxUmin≤u(t−1)+∑i=1NΔU(i)≤UmaxYmin≤Ψtξ(t∣t)+ΦtΔU(t∣t)+Υt≤Ymax\min_{\Delta U_t}\Delta U(t)H_t\Delta U(t)^T+G_t\Delta U(t)^T \\ \Delta U_{min} \le \Delta U_t(k) \le \Delta U_{max}\\ U_{min} \le u(t-1)+\sum_{i=1}^N\Delta U(i) \le U_{max} \\ Y_{min} \le \Psi_t\xi(t|t)+\Phi_t\Delta U(t|t)+\Upsilon_t \le Y_{max} \tag{30}ΔUt​min​ΔU(t)Ht​ΔU(t)T+Gt​ΔU(t)TΔUmin​≤ΔUt​(k)≤ΔUmax​Umin​≤u(t−1)+i=1∑N​ΔU(i)≤Umax​Ymin​≤Ψt​ξ(t∣t)+Φt​ΔU(t∣t)+Υt​≤Ymax​(30)

此外,在mpc_slover.cc中有注释如下:

 // Update matrix_m1, matrix_m2, convert MPC problem to QP problem done// Format in qp_solver/*** *           min_x  : q(x) = 0.5 * x^T * Q * x  + x^T c* *           with respect to:  A * x = b (equality constraint)* *                             C * x >= d (inequality constraint)* **/// TODO(QiL) : change qp solver to box constraint or substitute QPOASES// Method 1: QPOASES

可知,Apollo将MPC的优化求解转化为二次规划(Quadratic Programming, QP)问题,且QP问题的求解采用QPOASES的方法,QPOASES方法详解请见:qpOASES: a parametric active-set algorithm for quadratic programming,可以结合active_set_qp_solver.cc以及矩阵计算库Eigen对QPOASES方法进行理解分析。

反馈矫正

2018.12.28更新
有博友提醒该步骤在Apollo代码中并未实现,我在学习的过程中,确实在Apollo代码中没有特别清晰的对应上这一步,可能是我理解的不够深吧。
但该步骤是我在参考书中看到的MPC求解的一般步骤,所以在此处我也写了。辩证地看待吧,我尽量保证我写的内容没有什么原则性的错误,感谢各位博友的提点和支持。

在每个控制周期内,按照公式30完成优化求解后,得到控制时域内的一系列控制增量:
(31)ΔUt∗=[Δut∗,Δut+1∗,...,Δut+N−1∗]\Delta U_t^*=[\Delta u_t^*,\Delta u_{t+1}^*,...,\Delta u_{t+N-1}^*] \tag{31}ΔUt∗​=[Δut∗​,Δut+1∗​,...,Δut+N−1∗​](31)
将序列中的第一个控制增量作为实际的控制输入增量作用于系统,则有:
(32)u(t)=u(t−1)+Δut∗u(t)=u(t-1)+\Delta u_t^* \tag{32}u(t)=u(t−1)+Δut∗​(32)
将u(t)u(t)u(t)作为此时的控制量输入给系统,直到下一个控制时刻,系统根据新的状态信息预测下一时段内的输出,然后通过优化得到一组新的控制序列。如此反复,直至完成整个控制过程。

总结

综上所述,MPC控制器的工作原理大致如下所示:

图4 MPC控制原理框图

其中,x(t)x(t)x(t)为ttt时刻车辆的观测状态,x(t)^\hat{x(t)}x(t)^​为ttt时刻车辆的估计状态,u∗(t)u^*(t)u∗(t)为t时刻的最优控制解,y(t)y(t)y(t)为ttt时刻的系统输出。

模型预测控制的实现,依赖MPC控制器、被控车辆、状态估计器、轨迹规划等信息。结合图1和图4,模型预测控制器的一般工作步骤可以概括如下:
1、在ttt时刻,结合历史信息和当前状态以及预测模型,预测NNN步的系统输出;
2、结合约束条件等,设计目标函数,计算最优控制解u∗(t)u^*(t)u∗(t),输入到被控车辆,使其在当前控制量下运动;
3、获取车辆状态x(t)x(t)x(t),输入到状态估计器中,对那些无法直接用传感器获取或观测成本较高的的状态量进行估计,然后将x^(t)\hat{x}(t)x^(t)输入到MPC控制器,再次进行优化求解,以得到未来一段时间的预测控制序列;
4、然后在t+1t+1t+1时刻重复上述步骤,如此,滚动地实现带约束的优化问题,从而实现对被控对象的连续控制。
此外,x(t)x(t)x(t)也可在需要的时候,被用来更新规划轨迹,以便得到更好的控制效果。


  1. 无人驾驶汽车系统入门(十)——基于运动学模型的模型预测控制 ↩︎

  2. 龚建伟, 姜岩, 徐威. 无人驾驶车辆模型预测控制[M]. 北京理工大学出版社, 2014. ↩︎ ↩︎ ↩︎

Apollo代码学习(六)—模型预测控制(MPC)相关推荐

  1. Apollo代码学习(六)—模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码

    Apollo代码学习(六)-模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码

  2. Apollo代码学习(七)—MPC与LQR比较

    Apollo代码学习-MPC与LQR比较 前言 研究对象 状态方程 工作时域 目标函数 求解方法 前言 Apollo中用到了PID.MPC和LQR三种控制器,其中,MPC和LQR控制器在状态方程的形式 ...

  3. Apollo代码学习(二)—车辆运动学模型

    Apollo代码学习-车辆运动学模型 前言 车辆模型 单车模型(Bicycle Model) 车辆运动学模型 阿克曼转向几何(Ackerman turning geometry) 小结 Apollo( ...

  4. 无人车系统(十一):轨迹跟踪模型预测控制(MPC)原理与python实现【40行代码】

    前面介绍的PID,pure pursuit方法,Stanley方法都只是利用当前的系统误差来设计控制器.人们对这些控制器的设计过程中都利用了构建模型对无人车未来状态的估计(或者说利用模型估计未来的运动 ...

  5. Apollo代码学习(五)—横纵向控制

    Apollo代码学习-横纵向控制 前言 纵向控制 横向控制 前馈控制 注意 反馈控制 总结 补充 2018.11.28 前言 在我的第一篇博文:Apollo代码学习(一)-控制模块概述中,对横纵向控制 ...

  6. 【控制control】机器人运动控制器----基于模型预测控制MPC方法

    系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录 前言 一.模型预测控制(MPC)的介绍及构成 1.介绍 2.构成 二.模型 ...

  7. 【附C++源代码】模型预测控制(MPC)公式推导以及算法实现,Model Predictive control介绍

    2022年的第一篇博客,首先祝大家新年快乐! 提示:本篇博客主要集中在对MPC的理解以及应用.这篇博客可以作为你对MPC控制器深入研究的一个开始,起到抛砖引玉,带你快速了解其原理的作用. 这篇博客将介 ...

  8. 模型预测控制_模型预测控制(MPC)算法之一MAC算法

    引言 随着自动驾驶技术以及机器人控制技术的不断发展及逐渐火热,模型预测控制(MPC)算法作为一种先进的控制算法,其应用范围与领域得到了进一步拓展与延伸.目前提出的模型预测控制算法主要有基于非参数模型的 ...

  9. MATLAB代码:基于模型预测控制的楼宇负荷需求响应研究

    MATLAB代码:基于模型预测控制的楼宇负荷需求响应研究 关键词:楼宇负荷 空调 模型预测控制 需求响应 参考文档:<Model Predictive Control of Thermal St ...

最新文章

  1. Windows服务器上Mysql为设置允许远程连接提示:not allowed to connect to this MySQL server
  2. python使用循环结构计算10_十二、 python中的循环结构
  3. 怎样添加、移除、移动、复制、创建和查找节点?
  4. ORACLE1.21 PLSQL 01
  5. php 递归创建目录、递归删除非空目录、迭代创建目录
  6. java远程debug
  7. 分布式日志收集系统Apache Flume的设计详细介绍
  8. URAL 1081 Binary Lexicographic Sequence
  9. eoe·Android 开发门户 - android开发者的必备网站
  10. 识别速度3.6ms/帧!人像抠图、工业质检、遥感识别,用这一个分割模型就够了...
  11. 拼接播放地址_西安户外did拼接屏批发业务广泛_金伟达电子
  12. delphi让exe开机自启动
  13. 1.Prometheus 监控技术与实践 --- 云计算时代的监控系统
  14. Git和Github详细入门教程
  15. 数据结构-顺序表基本操作的实现(含全部代码)
  16. 【报告分享】 红宝书-超级案例大赏-阿里妈妈(附下载)
  17. 无线传感器网络(双语)复习
  18. mxplayer battle游戏接入
  19. mbedtls学习3.mbedtls_API分析
  20. 优化算法—人工蜂群算法(ABC)

热门文章

  1. 《肥鸟笔记--基础数据结构》一、栈
  2. Content-Type四种常见取值application/x-www-form-urlencoded,multipart/form-data,application/json,text/xml
  3. UE4后期处理材质:扁平化风格描边
  4. 搜狗输入法语音转文字体验报告
  5. rocketmq中broker的端口
  6. 2021上半年全国计算机二级报名江苏,江苏2021年3月全国计算机等级考试报名公告...
  7. iPhone4升级iOS7输入卡顿的完美解决办法
  8. android固定位置拍照,Android调用系统相机拍照并保存到指定位置
  9. 编辑数码照片最快最有趣的方式——NCH PhotoPad for Mac
  10. Java == equals() hashCoed()的区别