☰
MPC与MHE集成实现目标点镇定:Matlab仿真完整指南
2026/10/10 8:23:56 网站建设 项目流程

MPC和MHE这对组合,在自动控制圈子里早就不算冷门搭配,但真要自己动手把它们在Matlab里跑成一个完整闭环,还要带着“目标点镇定”这种具体任务,坑一点都不少。我最近刚好把整套方案从头到脚撸了一遍,从公式推导到代码实现再到调参踩坑,过程中积累了不少值得记下来的东西。目标点镇定说白了就是让系统状态从任意初始位置出发,最终收敛到某个指定的平衡点并稳稳待住——它不是简单跟轨迹,也不是只稳定到原点,而是“去一个我指定的地方站岗”。这个需求很常见,比如移动机器人停车到指定工位、无人机悬停到指定航点、机械臂末端定位到目标位姿,本质上都是同一个问题。

这篇文章我就围绕“MPC控制器 + MHE状态估计器 + Matlab实现”这条主线来写,重点讲清楚为什么要这样集成、两部分各自在控制环里扮演什么角色,以及一套可直接运行的双积分器仿真代码是怎么搭起来的。适合正在做课程设计、毕业设计,或者在工程里被状态不可测问题折腾过的同学参考。

1. 目标点镇定这件事,为什么非要把MPC和MHE放在一起

1.1 目标点镇定的本质和技术难点

目标点镇定和目标跟踪很容易被搞混。跟踪是“系统要跟随一条时变参考轨迹”,比如机械臂画圆;而镇定是“系统要收敛到一个固定的平衡点”,比如无人机降落到停机坪。两者虽然最终都靠反馈控制实现,但镇定对控制器稳定性要求更高,而且参考信号的形态更简单。

严格一点说,目标点镇定可以转化为经典的调节问题。假设参考点为 (x_r),对应稳态输入为 (u_r),那么这个点必须是系统的一个平衡点,即满足 (x_r = A x_r + B u_r)。如果不满足,就得先通过 ( (I-A) x_r = B u_r ) 求一个可行的最小范数控制量,把系统“强压”到这个点附近。很多新手直接拿MPC去控制非平衡目标点,结果发现稳态误差永远消不掉,就是因为忽略了这一步。

真正的难点不在这里,而在于两个现实约束:第一,MPC本质上是状态反馈控制,它需要当前完整状态 (x_k) 作为优化问题的初值,但真实系统往往只有部分状态可测,比如双积分器只装了位置传感器,速度只能靠差分或者估计;第二,系统存在建模误差、过程噪声和传感器噪声,如果直接把测量值当状态用,控制性能会大打折扣,甚至在约束作用下产生极限环。想让MPC发挥出“预测+约束优化”的优势,就必须先解决“状态从哪来”的问题。

1.2 集成方案对性能的直接提升

我的实验结论是:把MHE和MPC集成后,闭环性能比“卡尔曼滤波+MPC”在约束场景下有明显改善。原因说来也简单,MPC最擅长的就是显式处理约束,而MHE和MPC拥有高度对称的“滚动窗口优化”结构——MHE本质上是把状态估计也变成一个带约束的优化问题,在滑窗内同时估计初始状态和过程噪声序列。

比如说系统存在速度边界,或者状态必须落在某个安全区间内,卡尔曼滤波完全无视这些约束,估计值可能飘到物理不可能的区域;MHE可以像MPC一样把这些约束写进优化问题,保证估计结果始终合理。这种“控制器能处理的约束,估计器也能处理”的天然亲和力,是卡尔曼滤波不具备的。另外,MHE对初值不敏感,滑动窗口会逐渐把旧数据丢出去,即使前几拍估计得很糟糕,窗口滚起来后也能快速收敛。这在高动态、强噪声的场合非常致命地重要。

2. 两块核心拼图:MPC和MHE的数学是怎么对齐的

2.1 MPC的滚动优化配方

MPC做镇定,通常用偏差量来改写问题。定义偏差状态 (\xi = x - x_r),偏差输入 (\nu = u - u_r),那么原系统 (x_{k+1} = A x_k + B u_k) 就变成 (\xi_{k+1} = A \xi_k + B \nu_k),目标点自然被搬到了原点。这一步非常关键,因为常规MPC的目标函数把状态原点当作平衡点,如果不做这种平移,控制器会对非零参考点产生莫名其妙的拉扯。

在预测时域 (N_p) 内,优化变量是所有未来控制输入 (U = [\nu_0, \nu_1, \dots, \nu_{N_p-1}]),目标函数为

[ J = \sum_{i=1}^{N_p} \xi_{k+i}^T Q \xi_{k+i} + \sum_{i=0}^{N_p-1} \nu_{k+i}^T R \nu_{k+i} ]

其中 (Q) 和 (R) 是状态权重和输入权重。约束包括输入边界 (u_{min} \le u_r + \nu_{k+i} \le u_{max}),也可以加状态约束 (x_{min} \le x_r + \xi_{k+i} \le x_{max})。

预测模型可以写成紧凑形式:把未来状态堆成一个长向量 (X),原始状态与输入按线性关系展开成 (X = F \xi_k + \Phi U)。其中 (F) 只由状态转移矩阵的幂次构成,(\Phi) 是脉冲响应矩阵。把 (X) 代进目标函数,得到一个标准的无约束二次规划;再加上输入和状态不等式约束,就是标准带约束QP。Matlab里直接用quadprog求解,效率并不差,而且不需要额外工具箱。

2.2 MHE的滚动窗口估计配方

MHE的想法和MPC如出一辙,只是把“未来”换成“历史”。取长度为 (N_m) 的滑动窗口,窗口覆盖状态 (x_{k-N_m+1}) 到 (x_k),对应测量 (y_{k-N_m+1}) 到 (y_k)。优化变量包括窗口最左端的初始状态 (\eta) 和窗口内的过程噪声序列 (w_{k-N_m+1}, \dots, w_{k-1})。

目标函数由三部分构成:一是到达代价,用来把窗口外的历史信息压缩成一个先验惩罚项;二是过程噪声的加权平方和;三是测量残差的加权平方和。

[ J_{MHE} = |\eta - \eta_{prior}|{\Pi}^2 + \sum{i=k-N_m+1}^{k-1} |w_i|{Q{w}^{-1}}^2 + \sum_{i=k-N_m+1}^{k} |y_i - C x_i|{R{v}^{-1}}^2 ]

这个公式就是MHE的灵魂。到达代价 (\Pi) 在实际工程里怎么取,我在后面调参章节会专门展开,这里先把它理解成“历史信息的浓缩版本”。同样,通过线性递推,窗口内的所有状态可以表示为初始状态和噪声序列的线性组合,于是MHE也化成一个带二次型目标、可带约束的QP问题,用quadprog求完后只取窗口最右端的 (x_k) 作为当前状态估计。

2.3 集成时两条关键“耦合线”

把MPC和MHE接成一个闭环,需要回答两个工程问题:第一,MHE估计出的状态怎么送给MPC;第二,估计误差会不会被MPC放大甚至导致失稳。

第一个问题比较简单,直接把 (x_k) 的估计值作为MPC的初始偏差状态就行,属于“确定性等价原则”。第二个问题比较微妙,线性系统无约束情况下有分离定理保证,控制器和估计器可以分开设计;但带约束MPC丢掉了线性分离性,严格证明闭环稳定性需要更精细的Lyapunov分析和终端约束设计。工程上更实用的做法是从小处验证——先跑仿真确认估计器收敛,再逐步加上约束强度;同时在MPC的终端代价里保留一个松的终端权重矩阵 (P),这相当于给预测时域末端加了“软着陆”约束,能够有效缓解估计误差带来的尾部发散问题。我在双积分器实验里发现,加上一个适中的终端权重后,系统在大初始偏差下也不会出现控制量剧烈反复的振荡。

3. 直接可跑的Matlab实现:双积分器上的完整闭环

3.1 仿真模型与参数设定

为了把方法讲透,我用最简单的双积分器作为被控对象:位置 (x_1),速度 (x_2),控制量是加速度 (u)。离散化周期取 (T_s = 0.1s),离散模型为

[ A = \begin{bmatrix} 1 & T_s \ 0 & 1 \end{bmatrix}, \quad B = \begin{bmatrix} T_s^2/2 \ T_s \end{bmatrix}, \quad C = \begin{bmatrix} 1 & 0 \end{bmatrix} ]

仿真参数设置如下:目标点位置 (x_r = [1, 0]^T),稳态输入 (u_r = 0)。MPC预测时域 (N_p = 10),状态权重 (Q = \mathrm{diag}(10, 1)),输入权重 (R = 0.1)。系统初始状态 (x_0 = [0, 0]^T),控制约束 (-1 \le u \le 1)。过程噪声方差稍大于测量噪声方差,实测时用了一个叠加随机序列来模拟真实场景。MHE窗口长度 (N_m = 7),过程噪声权重 (Q_w^{-1} = 100)(对应噪声方差0.01的倒数),测量噪声权重 (R_v^{-1} = 1000)。

选用这个模型的原因很直白:状态维度低、能直观看出位置速度收敛过程,且离散矩阵简单到可以用手推导,适合用来验证代码逻辑正确后再迁移到更复杂的对象。

3.2 MPC预测模型的矩阵化构建

手写MPC不需要把每个状态逐步展开,建议把预测模型矩阵化。先定义函数来构造矩阵 (F) 和 (\Phi):

function [F, Phi] = build_mpc_matrices(A, B, Np) n = size(A, 1); m = size(B, 2); F = zeros(n*Np, n); Phi = zeros(n*Np, m*Np); A_pow = eye(n); for i = 1:Np % F矩阵:第i块为 A^i F((i-1)*n+1:i*n, :) = A_pow * A; % Phi矩阵:第i行块由脉冲响应系数构成 for j = 1:i Phi((i-1)*n+1:i*n, (j-1)*m+1:j*m) = ... A_pow * A^(i-j) * B; % 这里保留A^(i-j)便于理解 end A_pow = A_pow * A; end end

这里需要提醒一个非常容易犯的错:F的第一行块对应 (A^1 \xi_k),不是 (\xi_k) 本身,所以不要写成单位阵。预测时域内的状态从第1步开始,而不是从第0步开始。如果你在成本函数里包含了当前状态,你得自己把它单独加进去,这在以后的公式中会自然地出现。

有了 (F) 和 (\Phi),MPC的QP系数就很容易获得。目标函数 (X^T \bar{Q} X + U^T \bar{R} U) 可整理成 (0.5 U^T H U + f^T U),其中:

Qbar = kron(eye(Np), Q); Rbar = kron(eye(Np), R); H = 2 * (Phi' * Qbar * Phi + Rbar); f = (2 * xi' * F' * Qbar * Phi)';

输入约束写成 (A_{in} U \le b_{in}),因为每步控制输入相同边界,直接块对角展开即可。然后用quadprog求解,只取解的第一个分量作为当前时刻控制量,这也就是“滚动优化”四个字的含义——每次都重新计算整段未来输入,但只执行第一步。

3.3 MHE的窗内递推与QP表达

MHE实现比MPC稍微绕一点,因为它要同时处理窗口内多个时刻的状态耦合。我在写代码时没有逐时刻递推,而是把整个窗口的状态都表示成初始状态和噪声序列的线性组合,一次成型。

假设窗口左端时刻是k0 = k - Nm + 1,未知变量构成向量 [ z = [\eta, w_{k0}, w_{k0+1}, \dots, w_{k-1}]^T ] 其中 (\eta = x_{k0}) 是窗口初始状态,长度 (n);(w_j) 是中段过程噪声,每个长度 (m),一共 (N_m-1) 个。窗口中的状态可以由如下递推矩阵得到:

function E = build_mhe_state_matrix(A, B, Nm) n = size(A, 1); m = size(B, 2); E = zeros(Nm*n, n + (Nm-1)*m); for p = 1:Nm % 初始状态eta的贡献 E((p-1)*n+1:p*n, 1:n) = A^(p-1); % 各噪声项w_j的贡献 for j = 1:p-1 E((p-1)*n+1:p*n, n+(j-1)*m+1:j*m) = A^(p-1-j) * B; end end end

有了状态矩阵E,窗口内任意时刻的状态就是 (X_{win} = E z)。测量方程是 (Y_{win} = C_{win} X_{win} + v_{win}),这里的 (C_{win}) 是块对角展开后的测量矩阵。

MHE的目标函数展开后同样是一个标准QP。需要注意,MHE的代价里同时包含三项,每一项都要正确映射到quadprog的H和f上。一个我自己踩过的坑是:将过程噪声权重和到达代价权重直接叠加到同一个H里时,维数对不齐导致求解器报错。统一做法是先拼装完整H,再让变量顺序严格保持“初始状态 + 窗口内噪声序列”。求完最优z后,状态估计取z对应窗口右端的那一块:

X_win_est = E * z_opt; xhat = X_win_est(end-n+1 : end, :);

3.4 主控制循环与结果观察

整个闭环逻辑并不复杂,每拍顺序执行:先用MHE基于历史测量估计当前状态;再把估计值交给MPC求控制量;接着把控制量施加到真实被控对象上,得到新的测量值。核心循环长这样:

for k = 1:Tsim % 1. MHE 状态估计 if k == 1 xhat = x0 + 0.2*randn(n,1); % 初始估计给一个偏置 else xhat = mhe_solve(...); % 基于滚动窗口求解 end % 2. MPC 求控制输入 xi = xhat - xr; U = quadprog(H, f, Aineq, bineq, [], [], [], [], [], opts); u = U(1) + ur; % 3. 真实对象推进 x_true = A * x_true + B * u + process_noise; y = C * x_true + measurement_noise; % 4. 缓存数据,滚动更新MHE窗口 end

这段循环跑下来,能从数据里清晰看到几个阶段:前几拍,位置从0朝目标点1移动,速度先增大后减小,控制量在边界附近短暂饱和;中段,速度收敛到0,位置趋近1;末段,MHE估计状态和真实状态几乎重合,稳态位置误差在0.005以内。值得一提的是,如果只用测量位置差分来求速度,噪声会被差分放大器放大,闭环会出现明显颤振;换成MHE后,速度估计平滑得多,控制量也不再高频抖动。这就是状态估计对MPC闭环品质最直观的贡献。

4. 调参与排坑:把集成系统从“能跑”调到“好用”

4.1 权重矩阵与滑窗长度的实用选择

MPC权重 (Q)、(R) 的选择直接影响动态品质。(Q) 对角元素数量级相差太大时,优化器会过分偏向权重大的状态。比如我做实验时把位置权重从10提到50,系统响应变快,但控制量更容易触碰饱和边界;把速度权重从1提到5,超调量明显下降,代价是收敛变慢。对双积分器这类系统,我建议先用“对角权重,位置权重比速度权重大一个数量级”起步,再根据仿真曲线微调。

MHE窗口长度 (N_m) 同样需要权衡。窗口越长,估计器看到的历史信息越多,抗噪声能力越强,但计算量也线性增长,且到达代价的影响会被稀释。我在这个例子里试过 (N_m) 从3到15的变化:3时对噪声过于敏感,估计轨迹毛刺多;7到10比较合适;超过12后估计精度提升不明显,单步计算时间反而翻倍。对更复杂的系统,一个值得记住的启动值是窗口长度约为状态维数的3到5倍。

4.2 到达代价与先验信息:最容易被忽略的一环

很多教程会把MHE写成“只看窗口内数据”,这是极大的简化,实际操作中代价巨大。如果完全没有到达代价项,MHE在窗口左端的初始状态完全由窗口内前几个测量值决定,而前几个测量值噪声多、信息少,估计结果容易被带偏。到达代价本质上是把“窗口外已经丢弃的历史信息”压缩成一个先验高斯惩罚。

工程上最实用的近似方法是:用上一次MHE解出的左端状态,再通过模型预测一拍,得到本次窗口左端状态的先验 (\eta_{prior})。协方差矩阵 (\Pi) 可以用小对角矩阵粗略估计,比如 (10^{-2} I),也可以用扩展卡尔曼滤波协方差替代。从我测试的情况看,加入这一项后,MHE在初始窗口和过程噪声突变场景下的收敛速度提升显著,即使窗口长度缩短到5也能保持估计精度。这个细节就是我反复强调“MHE不能只看一个滑窗”的原因。

4.3 常见问题与排查速查表

整理一张我在联调过程中遇到的典型问题和解决办法,按频率从高到低排列:

现象可能原因处理方法
quadprog报维度错误H或f的行列数与变量长度不一致统一用size(H,1)与n+(Nm-1)*m核对
MPC控制量全程贴边界权重失衡或预测时域过短增大R或延长Np,检查目标点是否为平衡点
MHE估计发散到达代价权重太大或窗口太短减小 (\Pi),增大 (N_m),检查模型矩阵E是否正确
闭环稳态误差大目标点不在平衡点,或控制器未用偏差量校验 (x_r=Ax_r+Bu_r),改用偏差状态优化
速度估计有毛刺噪声模型不准或测量权重过小增大 (R_v^{-1}),必要时加入速度上下界约束
系统缓慢振荡终端代价缺失或约束过紧加入终端权重 (P),或放宽不必要约束

还有两个较小但值得留意的问题:第一,quadprog的算法选项最好显式指定Algorithm', 'interior-point-convex',避免旧版本在不同模式下自动切换带来的性能差异;第二,在数据长度不足MHE窗口大小时要做预热处理,把开始几拍先丢给递归最小二乘或直接使用初始先验,等缓冲区填满后再启MHE,否则第一拍窗口为空,求解器必然报错。

5. 从双积分器到更复杂系统的扩展思路

这套MPC+MHE框架的价值在于可以平滑扩展。比如把线性模型换成线性时变模型或非线性模型,预测模型矩阵不再是常数,而是在每个采样点重新线性化,MPC变成非线性MPC,MHE变成扩展MHE,核心的滚动优化结构不用变。再加一个常见需求:把“目标点镇定”改成“路径点序列镇定”,只需要在到达某个目标点后把参考点切换成下一个路点,并保证切换瞬间MHE窗口不重置即可。我还试过把双积分器模型扩展到三维空间中带偏航约束的四旋翼悬停模型,MHE的窗口只需要延长1.5倍,MPC的约束维度从2增加到8,代码整体框架几乎不需要改动。

计算效率方面,在普通PC上双积分器单步总耗时不到2ms,其中MHE约占60%,MPC约占35%。如果系统状态维度和预测时域继续增大,优化耗时增长很快,此时可以考虑把状态矩阵的构建移到循环外做一次预计算,并用diag和kron避免在QP系数里生成全稠密块。我实测过一个6维系统的仿真,做了这些优化后单步耗时从18ms降到7ms,改善非常可观。

这个方案进一步可以和参数辨识联合使用:在MHE窗口里同时放入系统参数并作为增广状态,MHE就变成了在线参数辨识器,MPC则持续利用最新参数预测未来,形成“估计-辨识-控制”一体化框架。对于缓慢时变系统,这种结构比定期离线辨识可靠得多。我个人在实际使用中的体会是,MHE的到达代价项绝对是整个系统里最值得花时间调试的部分,它决定了对系统模型信息的利用充分程度;调试顺序应该先保证MHE估计收敛且平滑,再去调MPC动态参数,否则两个模块的问题叠加在一起,几乎无法定位。这组满手细节相对复杂,但原理统一,适合作为控制算法研究的长期工作台。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询