学习笔记搜索

03.4|从预测方程推到有约束 QP:MPC 究竟每一步在解什么

PID 在当前误差上生成需求,再由下游裁剪;MPC 则在计算需求时就预测未来状态并显式考虑能力约束。本课输入是当前状态、参考、离散模型和约束,输出仍只是当前一个控制量。先推一般线性多步形式,再用两步标量问题手算最优解,最后说明为什么有限时域最优不自动等于闭环稳定。

符号含义与维度单位/坐标约定
xk,uk,Ad,Bdx_k,u_k,A_d,B_d状态n×1、输入m×1、离散矩阵n×n与n×m例子为NED一轴位置/速度与加速度;矩阵元素按单位映射
N,X,U,XrN,X,U,X_r预测步数、堆叠状态nN×1、输入mN×1、参考nN×1N无量纲;各分量继承物理单位
Φ,Γ\Phi,\Gamma自由响应与输入响应矩阵nN×n、nN×mN
Qˉ,Rˉ,H,f\bar Q,\bar R,H,f状态权重、输入权重、Hessian、线性项nN×nN、mN×mN、mN×mN、mN×1;以归一化变量计无量纲
P,K,XfP,K,\mathcal X_f终端权重、局部反馈、终端集合n×n、m×n、状态空间子集;同一归一化误差坐标

需要补的数学只读这些: 平方目标与最小二乘和状态空间预测。先能口头解释本页小例,再进入完整推导;不必预先背下矩阵公式。

先不用优化器:在几条未来动作之间做选择

MPC每拍做三件事:用模型预测一段未来;在允许的动作中比较好坏;只执行所选序列的第一个动作。下一拍重新测量、重新规划,因此它仍是反馈控制,而不是一次算好后闭眼执行整段计划。

代价、约束与梯度各回答不同的问题。 代价回答“可行方案里更喜欢哪个”;约束回答“哪些方案根本不允许”;梯度回答“当前方案稍微改一点,代价朝哪里变”。例如速度误差超过偏好范围可以得到更高代价,但推进器绝不能超过硬上限。把上限只写成一个很大的罚分,并不等于严格禁止越界。

以归一化的一个动作 uu 为例,x=1x=1、模型 x+=x+ux^+=x+u,希望下一步接近零又不愿动作太大。所有量在此小例均无量纲,选择

J(u)=(1+u)2+0.1u2.J(u)=(1+u)^2+0.1u^2.
  1. 第一项衡量动作后还剩多少误差;第二项惩罚动作幅度,系数 0.10.1 表示本例的取舍,不是概率。
  2. 梯度在一维就是斜率:dJ/du=2(1+u)+0.2udJ/du=2(1+u)+0.2u。在 u=0u=0 处为正,因此稍微减小 uu 会降低代价;求导不是一个新的动力学方程。
  3. 令斜率为零得到无约束最优 u=−1/1.1u=-1/1.1。若要求 −0.6≤u≤0.6-0.6\le u\le0.6,只能选边界 u=−0.6u=-0.6。此处斜率仍为正,但唯一允许的微小方向是增大 uu,会增加代价,因此边界可以最优而梯度不为零。

后面两步例会揭示新的困难:第一个动作还影响第二个未来状态,两个动作不再独立。因此“一维最优值裁剪到区间”的直觉不能直接逐项用于多步MPC。Hessian是各方向的斜率怎样变化,即代价曲率;它不是传感器观测矩阵,也不是艇体惯性矩阵。

为什么用Lyapunov“能量”解释稳定性

稳定性需要知道误差是否持续趋近零,而不只看某一拍代价小。Lyapunov函数是一个非负的误差尺度:除目标外为正,沿闭环运动下降。它可以像能量,但不必是真实焦耳数;对归一化状态常选 V=xTPxV=x^TPx,因为正定 PP 使任何非零误差都付出正值,而且二次型容易与线性模型配合。

先看 x˙=−λx\dot x=-\lambda x,xx 无量纲、λ>0\lambda>0 单位 s−1\mathrm{s^{-1}}。选 V=x2/2V=x^2/2,就有 V˙=xx˙=−λx2<0\dot V=x\dot x=-\lambda x^2<0(非零状态时),单位为每秒。选择这个平方不是因为“所有系统都守恒”,而是因为它对正负误差一视同仁,并能证明衰减。复杂系统随便选 P=IP=I 未必能让导数为负,所以后面的终端矩阵不等式要验证,不能只把某个函数叫作能量。

微练习: 约束最优点的梯度非零是否说明求解器错了?把控制代价权重加大是否保证更快到目标?

概念答案:先看允许方向,再谈偏好

不一定错,应检查所有可行微小方向是否还能降低代价。加大控制权重通常更不愿用力,未必更快,可能跟踪更慢。先做二维分配与限幅认识可达域,再比较本课两步约束优化;分配练习不是MPC求解器,不应据它宣称已完成预测控制。

先把可预测模型写对

x=[pv],p˙=v,v˙=u,xk+1=Adxk+Bduk,Ad=[1T01],Bd=[T2/2T].(3.19)\begin{aligned}x&=\begin{bmatrix}p\\v\end{bmatrix},\quad\dot p=v,\quad\dot v=u,\\x_{k+1}&=A_dx_k+B_du_k,\quad A_d=\begin{bmatrix}1&T\\0&1\end{bmatrix},\quad B_d=\begin{bmatrix}T^2/2\\T\end{bmatrix}.\end{aligned}\tag{3.19}

为什么位置那一项不是 T2T^2。 周期内速度从 vkv_k 线性变到 vk+Tukv_k+Tu_k,平均速度为 vk+Tuk/2v_k+Tu_k/2,乘 TT 即得到位移增量。因此 BdB_d 第一项是 T2/2T^2/2,不是简单把新速度乘整个周期。以 T=0.2 sT=0.2\,\mathrm s、pk=1 mp_k=1\,\mathrm m、vk=0.3 m/sv_k=0.3\,\mathrm{m/s}、uk=0.5 m/s2u_k=0.5\,\mathrm{m/s^2} 为例,下拍速度为 0.4 m/s0.4\,\mathrm{m/s},位置为 1.07 m1.07\,\mathrm m。矩阵 AdA_d 中右上角带秒,BdB_d 的两项分别带秒平方、秒,这就是不同物理状态能够放进同一向量的单位解释。

这是周期内加速度恒定的精确积分:先把速度积分得到增加量 uT,再把线性变化的速度积分得到位移 vT+uT²/2。若已有阻尼模型,应对它离散,而不是把所有对象都当双积分器。物理位置 m 与速度 m/s 不能不加说明地直接平方相加;可先分别除以允许误差尺度,再选择无量纲权重。输入也除以代表性加速度尺度。以下二次规划(QP) 推导默认已经完成这种归一化。

xk+1∣k=Adxk+Bduk∣k,xk+2∣k=Ad2xk+AdBduk∣k+Bduk+1∣k,xk+j∣k=Adjxk+∑i=0j−1Adj−1−iBduk+i∣k.(3.20)\begin{aligned}x_{k+1|k}&=A_dx_k+B_du_{k|k},\\x_{k+2|k}&=A_d^2x_k+A_dB_du_{k|k}+B_du_{k+1|k},\\x_{k+j|k}&=A_d^jx_k+\sum_{i=0}^{j-1}A_d^{j-1-i}B_du_{k+i|k}.\end{aligned}\tag{3.20}

推广式的指数来自输入作用了多久。 第 ii 个未来输入先通过 BdB_d 进入下一状态,再经过 j−1−ij-1-i 次状态转移到第 jj 个预测状态,所以权重是 Adj−1−iBdA_d^{j-1-i}B_d。当 i=j−1i=j-1 时指数为零,最新输入只经过一次 BdB_d;当 i=0i=0 时传播最久。写循环时外层遍历预测步 jj,内层只遍历 0≤i<j0\le i<j,不要让尚未发生的输入影响更早的状态。用标量 Ad=0.9,Bd=0.1A_d=0.9,B_d=0.1 核对两步:第二步系数应为 0.81xk+0.09uk+0.1uk+10.81x_k+0.09u_k+0.1u_{k+1}。

第二行把第一行代入一次状态转移;继续代入就得到第三行。上标 j 表示矩阵幂,不是单位。竖线后的 k 表示这些量都是在当前时刻 k 的预测,它们不是未来已经测到的真值。把未来一至 N 步的状态竖着堆叠,过去输入对更晚状态持续起作用,因此输入矩阵是下三角块结构。

X=[xk+1∣k⋮xk+N∣k]=Φxk+ΓU,U=[uk∣k⋮uk+N−1∣k],Φ=[AdAd2⋮AdN],Γ=[Bd0⋯0AdBdBd⋯0⋮⋮⋱⋮AdN−1BdAdN−2Bd⋯Bd].(3.21)\begin{aligned}X&=\begin{bmatrix}x_{k+1|k}\\\vdots\\x_{k+N|k}\end{bmatrix}=\Phi x_k+\Gamma U,\quad U=\begin{bmatrix}u_{k|k}\\\vdots\\u_{k+N-1|k}\end{bmatrix},\\\Phi&=\begin{bmatrix}A_d\\A_d^2\\\vdots\\A_d^N\end{bmatrix},\quad\Gamma=\begin{bmatrix}B_d&0&\cdots&0\\A_dB_d&B_d&\cdots&0\\\vdots&\vdots&\ddots&\vdots\\A_d^{N-1}B_d&A_d^{N-2}B_d&\cdots&B_d\end{bmatrix}.\end{aligned}\tag{3.21}

堆叠是在消去状态决策变量。 第 jj 个块行对应一个未来状态,Φ\Phi 只传播当前状态;Γ\Gamma 的第 jj 行第 ii 列块记录该输入对该状态的贡献。XX 为 nNnN 维,UU 为 mNmN 维,因此乘法要求 Γ∈RnN×mN\Gamma\in\mathbb R^{nN\times mN}。对于双积分器、N=2N=2,Γ\Gamma 为 4×24\times2 矩阵,其第一列上半块为 (T2/2,T)T(T^2/2,T)^T,下半块为 (3T2/2,T)T(3T^2/2,T)^T;第二列上半块为零。这份稀疏结构是调试预测矩阵最直观的测试。

二次目标为什么产生这个 Hessian

J=(X−Xr)⊤Qˉ(X−Xr)+U⊤RˉU,e0=Φxk−Xr,J=(e0+ΓU)⊤Qˉ(e0+ΓU)+U⊤RˉU=12U⊤HU+f⊤U+e0⊤Qˉe0,H=2(Γ⊤QˉΓ+Rˉ),f=2Γ⊤Qˉe0.(3.22)\begin{aligned}J&=(X-X_r)^\top\bar Q(X-X_r)+U^\top\bar R U,\\e_0&=\Phi x_k-X_r,\\J&=(e_0+\Gamma U)^\top\bar Q(e_0+\Gamma U)+U^\top\bar R U\\&=\tfrac12U^\top H U+f^\top U+e_0^\top\bar Qe_0,\\H&=2(\Gamma^\top\bar Q\Gamma+\bar R),\qquad f=2\Gamma^\top\bar Qe_0.\end{aligned}\tag{3.22}

Hessian 是代价曲率,不是系统动力学。 对 12UTHU\tfrac12U^THU 求梯度得到 HUHU,需要 HH 对称;再求导才得到 Hessian HH 本身。对任意非零方向 zz,zTHz=2(Γz)TQˉ(Γz)+2zTRˉz>0z^THz=2(\Gamma z)^T\bar Q(\Gamma z)+2z^T\bar Rz>0,最后一个严格大于零来自输入权重正定。这证明了唯一极小值,而不是仅凭“看起来是平方和”断言求解可靠。若所有输入权重设为零且预测存在不影响状态的输入方向,Hessian 可能奇异;代码必须处理这种情况,而不能总假定求逆存在。

堆叠权重取 Qˉ=blkdiag⁡(Q1,…,QN)\bar Q=\operatorname{blkdiag}(Q_1,\ldots,Q_N)、Rˉ=blkdiag⁡(R0,…,RN−1)\bar R=\operatorname{blkdiag}(R_0,\ldots,R_{N-1}),每个状态权重为 n×n 对称半正定矩阵,每个输入权重为 m×m 对称正定矩阵。未来状态加权形式若使用终端权重,则令最后一块 QN=PQ_N=P;其余块按相应阶段设置。展开平方的两个交叉项互为转置、又都是标量,所以合并成两倍。采用一半 UTHUU^THU 的求解器约定,H 和 f 都必须带这个二;若只漏掉其中一个,最优解就变了。最后一项不含决策变量,可以从求解器目标中删去,但比较真实代价时需加回。Qˉ\bar Q 半正定、Rˉ\bar R 正定使 HH 正定,因此无约束唯一极小值满足 HU+f=0HU+f=0;有约束时仍是凸二次规划。

umin⁡≤U≤umax⁡⟺[I−I]U≤[umax⁡−umin⁡],xmin⁡≤Φxk+ΓU≤xmax⁡⟺[Γ−Γ]U≤[xmax⁡−Φxk−xmin⁡+Φxk].(3.23)\begin{aligned}u_{\min}\le U\le u_{\max}&\Longleftrightarrow\begin{bmatrix}I\\-I\end{bmatrix}U\le\begin{bmatrix}u_{\max}\\-u_{\min}\end{bmatrix},\\x_{\min}\le\Phi x_k+\Gamma U\le x_{\max}&\Longleftrightarrow\begin{bmatrix}\Gamma\\-\Gamma\end{bmatrix}U\le\begin{bmatrix}x_{\max}-\Phi x_k\\-x_{\min}+\Phi x_k\end{bmatrix}.\end{aligned}\tag{3.23}

双边约束为什么要变成两组。 一个上界 ΓU≤xmax⁡−Φxk\Gamma U\le x_{\max}-\Phi x_k 可直接保留;下界 ΓU≥xmin⁡−Φxk\Gamma U\ge x_{\min}-\Phi x_k 两侧乘负一会翻转不等号,于是得到 −ΓU≤−xmin⁡+Φxk-\Gamma U\le -x_{\min}+\Phi x_k。最常见实现错误就是右端当前状态项忘记变号。对标量 x+=x+ux^+=x+u、x=0.8x=0.8、要求 −1≤x+≤1-1\le x^+\le1,得到 u≤0.2u\le0.2 与 −u≤1.8-u\le1.8,也即 −1.8≤u≤0.2-1.8\le u\le0.2;这个小例应在加入长时域前先过测试。

这些上下界都是按时域堆叠的向量。第一组只限制命令,第二组把位置或速度限制转换成决策变量的不等式。若控制变化率有限,再用差分矩阵形成相邻输入之差,第一行必须减去已经施加的上一拍输入。水下艇还可以把 G 的可达集合变成线性约束;若忽略混控的多轴争用,即使 QP 自己可行,实际推进器仍可能不可行。

两步手算:不能把无约束解逐项裁剪就当作 MPC

取归一化标量速度模型 xk+1=xk+ukx_{k+1}=x_k+u_k、两步时域、当前 x=1x=1、零参考、状态权重均为 11、输入权重均为 0.10.1。它等价于用 1 s 为时间尺度、速度和加速度各自归一化的一阶积分模型;不要把它误认成上面的二维位置模型。限制每个输入绝对值不超过 0.6。

Φ=[11],Γ=[1011],J=(1+u0)2+(1+u0+u1)2+0.1(u02+u12),H=[4.2222.2],f=[42],det⁡H=5.24>0,Ufree=−H−1f=[−0.91603053−0.07633588].(3.24)\begin{aligned}\Phi&=\begin{bmatrix}1\\1\end{bmatrix},\quad\Gamma=\begin{bmatrix}1&0\\1&1\end{bmatrix},\\J&=(1+u_0)^2+(1+u_0+u_1)^2+0.1(u_0^2+u_1^2),\\H&=\begin{bmatrix}4.2&2\\2&2.2\end{bmatrix},\quad f=\begin{bmatrix}4\\2\end{bmatrix},\quad\det H=5.24>0,\\U_{\rm free}&=-H^{-1}f=\begin{bmatrix}-0.91603053\\-0.07633588\end{bmatrix}.\end{aligned}\tag{3.24}

手工复算每个矩阵元素。 ΓTΓ\Gamma^T\Gamma 的第一对角为 12+12=21^2+1^2=2,第二对角为 02+12=10^2+1^2=1,非对角为 11。加 0.1I0.1I 后乘二,才得到对角 4.2,2.24.2,2.2 与非对角 22。自由响应为 (1,1)T(1,1)^T,所以 2ΓTe0=(4,2)T2\Gamma^Te_0=(4,2)^T。这条计算说明第一拍输入为什么权重更大:它影响两个未来状态,而第二拍只影响最后一个。求解 HU=−fHU=-f 时先检验行列式为 5.245.24,然后才应用二维消元或逆矩阵。

第一个输入违反下界,因此先假设它在下界;固定它之后重新优化第二个输入,而不是保留原来的第二项。将 u0=−0.6u_0=-0.6 代回第二个偏导方程,得到 2(0.4+u1)+0.2u1=02(0.4+u_1)+0.2u_1=0。解落在允许区间内,再检查第一项边界方向的梯度是否满足最优条件。

u0∗=−0.6,u1∗=−0.41.1=−0.36363636,X∗=[0.40.03636364],HU∗+f=[0.752727270],J∗=0.21054545.(3.25)\begin{aligned}u_0^*&=-0.6,\quad u_1^*=-\frac{0.4}{1.1}=-0.36363636,\\X^*&=\begin{bmatrix}0.4\\0.03636364\end{bmatrix},\\HU^*+f&=\begin{bmatrix}0.75272727\\0\end{bmatrix},\qquad J^*=0.21054545.\end{aligned}\tag{3.25}

活动集是一组需要验证的假设。 假定第一项在下界只减少了一个未知数,并没有自动证明答案正确。还必须检验第二项在区间内,以及固定变量的负梯度指向可行域外(梯度沿可行方向使代价增加)。对于下界 ui≥liu_i\ge l_i,可行微扰 Δui≥0\Delta u_i\ge0,局部一阶增量为 giΔuig_i\Delta u_i;要不降低代价就需 gi≥0g_i\ge0。上界则需 gi≤0g_i\le0,内部需 gi=0g_i=0。完整枚举对两个变量只有九种“下界、自由、上界”组合,因此标准库即可实现可核验的求解器,而无需隐藏在优化包后面。

下界处唯一可行的微小方向是增大 u0u_0,梯度为正意味着沿该方向代价增加;第二项在内部、梯度为零,故 KKT 条件满足,凸性保证全局最优。直接裁剪无约束解会得到 (−0.6,−0.0763),第二步制动太弱,不是约束最优解。这也说明约束影响会通过预测动力学在时间上耦合。

参考解答(展开查看)
// 教学实现:枚举两变量盒约束QP的九种活动集。
#include <array>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
struct Result { double cost; std::array<double,2> u,gradient; };
Result solve(double bound) {
    const double H[2][2]={{4.2,2},{2,2.2}}, f[2]={4,2};
    Result best{std::numeric_limits<double>::infinity(),{}, {}};
    for(int s0=-1;s0<=1;++s0) for(int s1=-1;s1<=1;++s1) {
        const int status[2]={s0,s1};
        std::array<double,2> u={s0*bound,s1*bound}, g{};
        if(s0==0 && s1==0){
            const double det=H[0][0]*H[1][1]-H[0][1]*H[1][0];
            u={(-f[0]*H[1][1]+H[0][1]*f[1])/det,
               (-H[0][0]*f[1]+f[0]*H[1][0])/det};
        } else if(s0==0 || s1==0) {
            const int i=s0==0 ? 0 : 1,j=1-i;
            u[i]=-(f[i]+H[i][j]*u[j])/H[i][i];
        }
        bool valid=true;
        for(int i=0;i<2;++i){
            g[i]=H[i][0]*u[0]+H[i][1]*u[1]+f[i];
            if(std::abs(u[i])>bound+1e-10) valid=false;
            if(status[i]==-1 && g[i]<-1e-9) valid=false;
            if(status[i]==1 && g[i]>1e-9) valid=false;
            if(status[i]==0 && std::abs(g[i])>1e-9) valid=false;
        }
        if(!valid) continue;
        const double x1=1+u[0],x2=x1+u[1];
        const double cost=x1*x1+x2*x2+.1*(u[0]*u[0]+u[1]*u[1]);
        if(cost<best.cost) best={cost,u,g};
    }
    return best;
}
int main(){
    const auto r=solve(.6);
    std::cout<<std::setprecision(12)<<r.cost<<' '<<r.u[0]<<' '<<r.u[1]<<'\n';
    assert(std::abs(r.cost-.21054545454545454)<1e-10);
    assert(std::abs(r.u[1]+4.0/11)<1e-10);
    assert(std::abs(solve(.4).cost-.432)<1e-10);
    assert(std::abs(solve(1).u[0]+.916030534351145)<1e-10);
}

滚动时域、终端代价与稳定性的真正连接

一次求解得到整段 UU,只施加第一项;下一拍用新状态重新预测和求解,称为滚动时域。反馈来自不断重估状态与重算,不是执行整段开环计划。求解失败时要有保持可行的备选控制,不能把超时输出或任意零输入当作稳定性保证。为了理解标准稳定性论证,以下统一改用调节误差状态,并采用从当前状态计阶段成本的约定;它和前面“未来状态加权”的索引只差权重安排。

VN(x)=min⁡U∑i=0N−1ℓ(xi,ui)+Vf(xN),x0=x,xi+1=Adxi+Bdui,i=0,…,N−1,xi∈X,ui∈U,xN∈Xf⊆X,ℓ(x,u)=x⊤Qx+u⊤Ru,Vf(x)=x⊤Px,u=Kx,AK=Ad+BdK,AK⊤PAK−P⪯−(Q+K⊤RK),x∈Xf⇒Kx∈U,AKx∈Xf.(3.26)\begin{aligned}V_N(x)&=\min_U\sum_{i=0}^{N-1}\ell(x_i,u_i)+V_f(x_N),\\x_0&=x,\quad x_{i+1}=A_dx_i+B_du_i,\quad i=0,\ldots,N-1,\\x_i&\in\mathcal X,\quad u_i\in\mathcal U,\quad x_N\in\mathcal X_f\subseteq\mathcal X,\\\ell(x,u)&=x^\top Qx+u^\top Ru,\qquad V_f(x)=x^\top Px,\\u&=Kx,\quad A_K=A_d+B_dK,\\A_K^\top PA_K-P&\preceq-(Q+K^\top RK),\\x\in\mathcal X_f&\Rightarrow Kx\in\mathcal U,\quad A_Kx\in\mathcal X_f.\end{aligned}\tag{3.26}

这些条件分别承担什么证明责任。 初始约束 x0=xx_0=x 把问题连接到当前测量;动力学约束保证计划可以按模型执行;xi∈X,ui∈Ux_i\in\mathcal X,u_i\in\mathcal U 表示全过程合法;xN∈Xf⊆Xx_N\in\mathcal X_f\subseteq\mathcal X 则保证计划末尾进入可由局部反馈接管的安全区域。Q,R,PQ,R,P 都是对称权重,本段取 Q≻0,R≻0,P≻0Q\succ0,R\succ0,P\succ0;KK 的符号已经包含在反馈 u=Kxu=Kx 中,所以不能再额外写一个负号。矩阵不等式要求任意向量左、右乘后都满足标量不等式,它不是逐元素比较。将 xx 左右乘上该式就得到 Vf(AKx)−Vf(x)≤−ℓ(x,Kx)V_f(A_Kx)-V_f(x)\le-\ell(x,Kx),这才是终端“减少多少”的含义。

第一组条件保证终端局部控制每走一步减少的终端代价,至少抵偿这一步的阶段成本;第二组保证终端集合内的局部控制满足约束并留在集合中。若当前最优序列可行,下一拍把余下的输入左移,再接上终端反馈,便构造了一条新的可行候选。比较新旧候选成本,中间项相消,终端不等式消去尾部,留下当前阶段成本的严格下降。TB03-S4

VN(xk+1)−VN(xk)≤−ℓ(xk,uk).(3.27)V_N(x_{k+1})-V_N(x_k)\le-\ell(x_k,u_k).\tag{3.27}

把移位证明完整写下来。 旧最优序列为 (u0∗,…,uN−1∗)(u_0^*,\ldots,u_{N-1}^*),对应 (x0∗,…,xN∗)(x_0^*,\ldots,x_N^*)。准确模型下执行第一拍后新状态等于 x1∗x_1^*。新候选取 (u1∗,…,uN−1∗,KxN∗)(u_1^*,\ldots,u_{N-1}^*,Kx_N^*):前 N−1N-1 项继承旧约束,末项由终端条件满足输入约束,新末状态 AKxN∗A_Kx_N^* 仍在终端集合。故新问题至少存在一条可行解。其成本减去旧最优成本,所有重叠阶段相消,仅剩 −ℓ(x0∗,u0∗)+ℓ(xN∗,KxN∗)+Vf(AKxN∗)−Vf(xN∗)-\ell(x_0^*,u_0^*)+\ell(x_N^*,Kx_N^*)+V_f(A_Kx_N^*)-V_f(x_N^*);末三项由终端不等式不大于零。新最优成本不大于这个候选成本,才最终得到式(3.27)。两个比较缺一不可:候选可行负责递归可行性,最优值不大于候选值负责下降。

这条证明需要模型准确、初始可行、终端集合有效、求解满足相应条件以及状态成本正定等假设;“时域很长”不是替代证明的句子。以标量积分器、Q=1Q=1、R=0.1R=0.1 为例,离散 Riccati 正解满足 P2−P−0.1=0P^2-P-0.1=0,即 P≈1.091608P\approx1.091608,K=−P/(0.1+P)≈−0.916080K=-P/(0.1+P)\approx-0.916080。取终端集合 ∣x∣≤0.6/∣K∣≈0.655|x|\le0.6/|K|\approx0.655,局部输入不越过 0.6,且闭环倍率 1+K≈0.083921+K\approx0.08392,使下一步仍在集合中。这个计算展示如何从局部 LQR 设计得到可用的终端条件,而不是仅给 PP 任意大数。

模型有误差时,上述移位序列未必仍满足状态约束。鲁棒 MPC 可以用误差界收紧约束并配局部反馈;扰动增广 MPC 可以把上一课的扰动估计带入预测,减少稳态偏差。二者解决的不是同一个问题:估计值是预测的中心,误差界才决定鲁棒裕度。

接回 ArduSub:先选择控制层级,再选优化变量

若 MPC 输出导航系速度,它应接在制导与 Guided 速度目标之间,保留现有速度控制和深度通道;预测模型就必须包含内环动态,而非假设速度命令瞬间实现。若输出导航系加速度,则需要明确替代位置/速度串级的哪一层,并继续处理姿态旋转、G 的局部效能与 AP_Motors6DOF 最终可达域。预测输入与项目输入类型一致,比“把 PID 换成 MPC”这句口号更重要。

手写练习:把盒约束缩成 ±0.4,重新枚举。

参考解答(展开查看)

答案两项都在下界,预测状态为 (0.6,0.2),梯度为 (1.52,0.32),代价为 0.432;两项梯度均非负满足下界最优条件。再把上限放宽到 1,恢复无约束解。精读 TB03-S4 时先看线性二次最优控制与有限时域约束,再读终端条件、递归可行性和稳定性证明;每个抽象条件都用本课标量例代入一次。

TB03-S4 · J. B. Rawlings, D. Q. Mayne, M. Diehl — Model Predictive Control: Theory, Computation, and Design, 2nd ed.

免费教材;本课以自行构造的两步QP和标量终端例连接预测、约束与稳定性。

写出二维两步预测矩阵,再谈通用软件

对本课双积分器且 N=2N=2,有 Ad2=[12T01]A_d^2=\begin{bmatrix}1&2T\\0&1\end{bmatrix},因为两次匀速传播各增加一次 TvTv。再计算 AdBd=(3T2/2,T)TA_dB_d=(3T^2/2,T)^T,于是

Φ=[1T0112T01],Γ=[T2/20T03T2/2T2/2TT].\Phi=\begin{bmatrix}1&T\\0&1\\1&2T\\0&1\end{bmatrix},\qquad \Gamma=\begin{bmatrix}T^2/2&0\\T&0\\3T^2/2&T^2/2\\T&T\end{bmatrix}.

逐行解释:第一拍位置受第一个输入的半周期平方影响;第一拍速度受一个周期输入影响;第二拍位置既受第一拍输入持续改变的速度影响,也受第二拍输入本身影响;第二拍速度累积两个输入。取 T=0.2T=0.2、当前 (p,v)=(1,0.3)(p,v)=(1,0.3)、计划 (u0,u1)=(0.5,−0.5)(u_0,u_1)=(0.5,-0.5),第一拍为 (1.07,0.4)(1.07,0.4),第二拍为 (1.14,0.3)(1.14,0.3)。直接矩阵乘法与逐拍状态推进必须给出同一个结果,这是凝聚预测矩阵的关键回归测试。

矩阵堆叠只是一种求解形式,不是 MPC 的定义。也可以把每步状态作为优化变量,保留稀疏动力学等式;凝聚形式把状态消掉,变量少但矩阵可能更稠密。小例选择凝聚形式是为了看清 Hessian 来源,不代表大系统一定应显式构造或求逆整个 Hessian。数值实现通常解线性方程而非计算逆矩阵;本章二维逆解只是手算检查。

目标权重的单位:为什么“都设成一”可能没有意义

假设允许的位置误差尺度为 sp=0.2 ms_p=0.2\,\mathrm m,速度误差尺度为 sv=0.1 m/ss_v=0.1\,\mathrm{m/s},输入尺度为 su=0.5 m/s2s_u=0.5\,\mathrm{m/s^2}。先考虑固定平衡参考 xrx_r 且平衡输入为零,即 Adxr=xrA_dx_r=x_r;对双积分器,这意味着目标位置固定、目标速度为零。定义 x~=Sx−1(x−xr)\tilde x=S_x^{-1}(x-x_r)、Sx=diag⁡(sp,sv)S_x=\operatorname{diag}(s_p,s_v),以及 u~=u/su\tilde u=u/s_u。在这个平衡假设下,归一化模型矩阵为 A~=Sx−1AdSx\tilde A=S_x^{-1}A_dS_x、B~=Sx−1Bdsu\tilde B=S_x^{-1}B_ds_u。归一化后用单位状态权重,实际含义是“达到允许误差尺度的两类误差同等重要”,而不是一米误差与一米每秒误差无理由等价。

对移动参考,应改为 u~k=(uk−ur,k)/su\tilde u_k=(u_k-u_{r,k})/s_u,并要求参考满足 xr,k+1=Adxr,k+Bdur,kx_{r,k+1}=A_dx_{r,k}+B_du_{r,k},误差动态才仍只有上述两项。若给定参考不满足这条动力学,还要加入已知偏置 Sx−1(Adxr,k+Bdur,k−xr,k+1)S_x^{-1}(A_dx_{r,k}+B_du_{r,k}-x_{r,k+1});这项不能靠改变权重自动消失。

如果不显式归一化,也可以把量纲吸收到物理权重中:位置平方权重带 m−2\mathrm{m^{-2}},速度平方权重带 s2/m2\mathrm{s^2/m^2},这样代价无量纲。跨坐标或单位修改模型时,权重也要一起换;将状态从米改厘米却保留全部数值权重,会改变优化问题而不是仅改变显示单位。

约束与失败处理:在线一拍真正需要做的事

一拍 MPC 的最小流程是:读取当前状态与上一拍执行输入 → 将参考变成与模型一致的误差坐标 → 组装自由响应及线性项 → 更新约束右端 → 求 QP → 检查可行性残差与解是否有限 → 只输出第一项 → 保存移位候选作为下一拍初值。对静态模型,Γ,H\Gamma,H 可以提前计算;ff 和状态约束右端仍随当前状态改变。求解器返回一个数字不等于任务成功,输入边界、状态预测和求解状态必须一起检查。

本页二维活动集代码用完整 KKT 符号测试,而不是只枚举九个点;自由变量还会通过方程重新求解。对于真实多维 MPC,活动集合数指数增长,不能把这段枚举器直接推广为在线大规模解法;它的教学价值是每个候选为何接受或拒绝都能手算。若希望加入输入变化率约束,第一拍差分为 u0−uprevu_0-u_{\rm prev},其余为 ui−ui−1u_i-u_{i-1};上一拍实际输入和上一拍请求不同的时候,应根据物理约束定义选择正确基准。

再核对一次终端例的代数

标量模型为 x+=x+ux^+=x+u,阶段权重为 Q=1,R=0.1Q=1,R=0.1。无限时域二次值函数候选 V(x)=Px2V(x)=Px^2,贝尔曼一步最小化为 Px2=min⁡u[x2+0.1u2+P(x+u)2]Px^2=\min_u[x^2+0.1u^2+P(x+u)^2]。对 uu 求导得 0.2u+2P(x+u)=00.2u+2P(x+u)=0,所以 u=−Px/(0.1+P)u=-P x/(0.1+P)。把它代回并比较 x2x^2 系数,得到 P=1+P−P2/(0.1+P)P=1+P-P^2/(0.1+P),移项整理成 P2−P−0.1=0P^2-P-0.1=0。负根不满足正定值函数,故取正根。这一推导明确了 PP 与 KK 不是凭经验同时指定的两个独立参数。

取约束 ∣u∣≤0.6|u|\le0.6,选 Xf={x:∣x∣≤0.6/∣K∣}\mathcal X_f=\{x:|x|\le0.6/|K|\},是先用局部反馈把输入约束反解回状态空间;还必须检查 Xf⊆X\mathcal X_f\subseteq\mathcal X。如果另有更紧的状态边界,就取更小的区间。由于 ∣1+K∣<1|1+K|<1,下一状态绝对值缩小,因此该区间正不变。这两个检查分别负责输入合法和状态不逃离,不能只做其中一个。

本章编程练习

查看全部练习

仅保存在当前浏览器,可在学习记录页导出。