想象一个周一的早高峰:你坐进驾驶座,打开手机导航。和只能告诉你“当前车速 70”的仪表盘不同,导航会“向前看”——它知道你前方 800 米有减速带、2 公里后有个急弯、再往前一段在修路。它先预测一整条未来路线,让你提前松油门、提前并线。更聪明的是,它不会一次播报完全程就撒手不管:每开过几个路口,它会根据你此刻的真实位置,把路线重新算一遍——刚才被加塞耽误了,它马上换一条更快的路。而你听完后,只按最近这一段路开,等下一次重新播报。这种“走一步、看一程、重新算一路”的开车智慧,就是 MPC(Model Predictive Control,模型预测控制)的生活原型。在机器人世界里,轮式机器人、机械臂和自动驾驶汽车,都是用这套“导航式”思路来控制自己身体的。

岗位关联

掌握 MPC 是进入机器人控制和自动驾驶控制岗位的关键技能。理解“预测-优化-重规划”这个闭环思维,你就能读懂现代控制系统的核心架构,也为学习最优控制与强化学习打下基础。

目录
  1. 可视化演示
  2. 核心思想:导航式的控制智慧
  3. 数学建模:把开车直觉翻译成数学
  4. 约束处理:车不能飞出马路
  5. 求解器选择:导航背后的算路引擎
  6. 自动驾驶应用:马路上的人车合一
  7. 机械臂控制:让机器手稳准柔
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

核心思想:导航式的控制智慧

新手司机上高速,眼睛只盯着车头前几米的白线:歪了就往左打一点,又歪了往右打一点,车在车道里来回“画龙”,坐车的人晕头转向。老司机恰恰相反,眼睛看得很远——提前几百米就知道前方有弯道、哪里有实线,方向盘早早就柔和地切进去。如果把“看远处”这件事交给机器,就得到了 MPC 的第一个直觉:不要只盯着当前那一刻的误差,要把未来的路况算清楚,再决定现在怎么打方向盘。

那么机器凭什么“看见未来”?答案是系统模型。所谓模型,就是大脑里的“交通地图”:它回答一个问题——如果我现在这样打方向盘、这样踩油门,未来 N 个时刻车会开到哪儿?有了“演算未来”的能力,控制器就能在迈出下一步之前,把所有可能的未来路线都推演一遍,从中挑出最好的那条。这就是“预测模型 + 优化”的组合拳。

但世界是变化的:轮胎打滑、风阻变化、路面起伏,模型永远不可能全知全能。所以 MPC 绝不一次性规划完全程,而是“走到哪、算到哪”:每个控制周期都用最新的传感器读数重新初始化预测,解出未来 N 步的控制序列,然后只执行第一步;下一步开始前,又用新的测量值从头重算。这个循环就是滚动优化(也叫滚动时域控制、退避时域控制)。因为不断用真实反馈校正,即使模型有偏差,控制也不会一路跑偏。这里的“只看未来 N 步”就是有限时域——不贪心,看太远反而算不动、也不准。

回到开车这件事:导航每 5 秒用真实位置重新算一次路,你只执行最近一段的指令——这就是“走一步、看一程、重新算一路”。MPC 的每一个控制周期,都在重复这个老司机与导航之间心照不宣的默契。

xt+1=A xt+B utx_{t+1} = A\, x_t + B\, u_t
这就是最经典的“预测模型”:用当前的状况和当前的动作,推算下一刻的状况。A 描述系统自身的惯性,B 描述控制输入的影响力。
  1. 下一时刻状态 $x_{t+1}$系统在未来一个采样时刻的完整描述,比如小车的位置和航向角。它是“预测”的输出对象。
    xt+1∈Rnx_{t+1} \in \mathbb{R}^{n}
  2. 当前状态 $x_t$此刻由传感器测得的真实状态,是每一次重规划的起点,相当于导航读到的“你的实时定位”。
    xt∈Rnx_t \in \mathbb{R}^{n}
  3. 状态转移矩阵 $A$描述系统“自己会怎么演变”——不踩油门时,车也会因为惯性继续滑行。它刻画了系统的固有动态。
    A∈Rn×nA \in \mathbb{R}^{n \times n}
  4. 输入项 $B\, u_t$描述控制动作(方向盘、油门)如何改变下一时刻的状态。没有它,控制器就失去了“干预未来”的手。
    B∈Rn×m,ut∈RmB \in \mathbb{R}^{n \times m},\quad u_t \in \mathbb{R}^{m}

数学建模:把开车直觉翻译成数学

导航软件为什么推荐这条路而不是那条?因为后台有一套“打分规则”:时间不能太长、路程不能太绕、高速尽量多走。MPC 也一样,它需要一个明确的代价函数(也叫目标函数)来评判哪条未来轨迹更好——分数越低,这条路越令人满意。

建模第一步是写状态方程,也就是上一节那个“地图”的具体形式:状态向量记录位置、航向角等信息,输入是车速、转向等控制量。状态方程把“输入→未来状态”的因果关系写清楚,这就是预测的物理基础。第二步是写代价函数:它通常由两项组成——第一项衡量“未来状态离参考轨迹有多远”,叫跟踪误差项;第二项衡量“控制动作有多粗暴”,叫输入惩罚项。两个权重矩阵 Q 和 R 分别表达“我更想要准”还是“我更想要稳”。

在数学上,还要明确两个重要设定:预测步长 N(也可以叫预测时域)决定“眼光看多远”;优化变量则是从当前时刻到未来 N-1 步的所有控制输入组成的一串序列——注意,要优化的不是单个输入,而是一整段“未来的操作计划”。把打分函数、步长和变量都定义清楚,MPC 就成了一个纯粹的数学问题:找一段控制序列,让打分函数最小。

导航软件把人的偏好写成评分规则,MPC 把控制目标写成代价函数——分数由优化器负责压到最低。规则越是贴合真实需求,机器开起车来就越像一位沉稳的老司机。

Jt=∑k=0N−1(xt+k−xref,t+k)⊤Q(xt+k−xref,t+k)+ut+k⊤R ut+kJ_t = \sum_{k=0}^{N-1} \left( x_{t+k} - x_{\text{ref},t+k} \right)^{\top} Q \left( x_{t+k} - x_{\text{ref},t+k} \right) + u_{t+k}^{\top} R\, u_{t+k}
这段公式就是 MPC 的“导航评分表”:第一项统计未来所有时刻偏离参考路线的总账,第二项统计所有控制动作“猛不猛”的总账,权重 Q 和 R 决定两者谁更重要。
  1. 代价函数 $J_t$给整条未来计划“打分”的结果,数值越小代表这条路线越接近老司机的理想驾驶。
    Jt≥0J_t \ge 0
  2. 求和符号 $\sum_{k=0}^{N-1}$从当前步到第 N-1 步,把未来 N 个时刻的损失全部累加,体现“全时段考虑”。
    ∑k=0N−1\sum_{k=0}^{N-1}
  3. 跟踪误差项每一时刻的实际状态偏离参考轨迹的“距离平方”,乘以权重 Q 后累加。偏离越远,这项分数越难看。
    (xt+k−xref,t+k)⊤Q(xt+k−xref,t+k)\left( x_{t+k} - x_{\text{ref},t+k} \right)^{\top} Q \left( x_{t+k} - x_{\text{ref},t+k} \right)
  4. 输入惩罚项每一时刻控制输入的“力度平方”乘以权重 R。这一项专门抑制急打方向盘、猛踩油门这类粗暴动作。
    ut+k⊤R ut+ku_{t+k}^{\top} R\, u_{t+k}

约束处理:车不能飞出马路

导航给出的每一条路线都必须“合法”:不能闯红灯、不能逆行、不能从大楼中间穿过去。真实世界的控制系统同样到处是“不允许”:车有最高车速,轮胎有抓地力上限,机械臂关节有机械限位,自动驾驶车绝不能压上人行道。新手司机最容易忽略边界,老司机则把“合法”当作一切计划的前提。MPC 的一大优势,就是天然可以把这些“不允许”写成数学上的约束条件,让优化器从第一步起就绕着边界走。

约束主要分两类。第一类是硬约束:必须严格满足的物理极限与安全边界。状态和输入各自被限制在上限与下限之间,优化器一旦越界,方案直接判为“非法”。比如转向角不能超过 ±35 度、车速不能超过 120km/h,这就是输入饱和与安全边界在数学上的化身。第二类是软约束:允许“商量”。当意外情况导致硬约束真的无法满足时(比如障碍物近到避无可避),引入一个松弛变量,让约束以一定代价被轻微打破,从而保证优化问题永远有一个“还能用”的可行解,而不是直接崩溃。

把代价函数与约束合在一起,就得到一个标准的“约束优化问题”——和中学数学里“求最小值 + 附加条件”是同一个思路,只是变量更多、条件更密、还要在几个毫秒内算完。这正是 PID 类反馈控制做不到的:PID 只会出了事再纠偏,而 MPC 从源头上就把“违章路线”排除在候选方案之外。

导航不会给你一条“穿过大楼”的路线,不是因为算法笨,而是因为“不能穿楼”从一开始就被写进了约束。MPC 带给工程师的安全感,正是来自这些提前画好的边界线。

min⁡ut, …, ut+N−1 Jts.t.xk+1=A xk+B uk,  xmin⁡≤xk≤xmax⁡,  umin⁡≤uk≤umax⁡\min_{u_t,\ \dots,\ u_{t+N-1}}\ J_t \quad \text{s.t.} \quad x_{k+1} = A\, x_k + B\, u_k,\ \ x_{\min} \le x_k \le x_{\max},\ \ u_{\min} \le u_k \le u_{\max}
这个式子是 MPC 的“完整任务书”:让打分最低,同时所有候选路线必须满足运动规律(等式约束)、不越状态边界、不超输入极限(不等式约束)。
  1. 最小化符号 $\min$在全部“合法”的候选方案里,选出打分函数最低的那一个,这是优化器的核心任务。
    min⁡ut, …, ut+N−1 Jt\min_{u_t,\ \dots,\ u_{t+N-1}}\ J_t
  2. 系统方程约束任何候选路线都必须符合物理规律——车不能瞬移,每一步状态变化都受运动学方程支配。
    xk+1=A xk+B ukx_{k+1} = A\, x_k + B\, u_k
  3. 状态边界约束位置、速度等状态量被限制在上下限之间,这就是“安全走廊”的数学写法。
    xmin⁡≤xk≤xmax⁡x_{\min} \le x_k \le x_{\max}
  4. 输入边界约束油门、刹车、转向角都有物理极限,控制器不能要求电机做做不到的事。
    umin⁡≤uk≤umax⁡u_{\min} \le u_k \le u_{\max}

求解器选择:导航背后的算路引擎

导航软件的地图数据再全,如果后台路径搜索算法太慢,等你开到下一个路口才算出结果,一切都晚了。MPC 同理:求解器就是它背后的“算路引擎”,负责在极短时间内把优化问题解出来。机器人控制周期通常只有十几毫秒到几毫秒,求解器必须“不堵车”——这直接决定了 MPC 能不能落地。

当系统模型是线性的、代价函数是二次的、约束也是线性的,优化问题就变成一个标准的二次规划(Quadratic Programming,简称 QP)问题。QP 有非常成熟的求解器:工程常用的 OSQP、qpOASES 等,毫秒级即可给出结果,是控制界的“轻量级快引擎”。但如果系统是非线性的——比如轮胎打滑、机械臂大幅摆动——代价函数和约束都变得“扭曲”,就得上非线性规划(NLP)求解器(如 IPOPT、SNOPT),精度高但耗时、对初值敏感,更像需要仔细调教的“重引擎”。

于是出现一个永恒的工程权衡:模型越精细,预测越准,求解越慢。聪明的折中是“在当前工作点线性化”——把非线性系统在每一时刻重新近似成线性系统,然后继续用 QP 求解,这就是线性时变 MPC(LTV-MPC),在自动驾驶中非常流行。记住一个铁律:实时性永远是第一位。算得再准,超过控制周期就是废纸一张;反过来,在在线求解的约束下选择一个恰到好处的模型,才是工程智慧。

就像导航在手机算力有限时会主动避开“计算量爆炸”的路线,MPC 工程师也在模型复杂度与求解速度之间小心翼翼地走钢丝。目标始终只有一个:在每个控制周期内,交出一条立即可执行的最优路线。

min⁡z 12 z⊤G z+g⊤zs.t.C z≤d\min_{z}\ \frac{1}{2}\, z^{\top} G\, z + g^{\top} z \quad \text{s.t.} \quad C\, z \le d
这是 QP 问题的标准写法:把未来 N 步的所有决策变量打包成一个大向量 z,目标函数写成“二次项 + 一次项”,所有约束统一写成一个矩阵不等式。任何线性 MPC 最终都能翻译成这个形式。
  1. 决策变量 $z$把未来 N 步的全部控制输入(以及需要的状态)首尾相接,排成一列长向量,让优化器统一处理。
    z=[ut⊤, ut+1⊤, …, ut+N−1⊤]⊤z = \left[ u_t^{\top},\ u_{t+1}^{\top},\ \dots,\ u_{t+N-1}^{\top} \right]^{\top}
  2. 二次项 $\frac{1}{2} z^{\top} G z$由代价函数中的权重 Q、R 组合而成,描述目标函数这个“地形”的陡峭程度。
    12 z⊤G z\frac{1}{2}\, z^{\top} G\, z
  3. 一次项 $g^{\top} z$参考轨迹带来的“推力”——它让最优解整体偏向参考路线所在的方向。
    g⊤zg^{\top} z
  4. 线性不等式 $C z \le d$把输入饱和、安全边界等全部约束统一写成一个矩阵不等式,交给求解器一次性处理。
    C z≤dC\, z \le d

自动驾驶应用:马路上的人车合一

自动驾驶系统通常分三层:感知(眼睛)、规划(大脑)、控制(手脚)。规划模块给出参考轨迹——一条由时间和期望位置构成的“理想路线”;MPC 的任务就是手脚协调,让车贴着这条路线稳稳地走。如果说规划是“导航在指路”,那 MPC 就是那位真正握着方向盘的老司机。

先说横向控制,也就是转向。车是一个非完整约束系统,不能横着走,前轮转角 $\delta$ 与航向角变化率之间存在一个经典的运动学关系(见下式)。MPC 用这个模型做预测,把“横向偏差小、方向盘不猛打”写进代价函数,每个控制周期输出一个平滑的前轮转角。再看纵向控制,也就是油门刹车:把“车速接近设定值、不突然加速急刹”写成另一组代价。横向与纵向在工程上常常解耦,分别用两个 MPC 或一个分层 MPC 来处理。

安全是自动驾驶的生命线,而 MPC 的绝活正是处理安全:把“与行人的最小距离”“车道边界”直接写成不等式约束。前方突然出现障碍物时,MPC 会在下一拍立刻重算,给出一条“不压线又能避开”的新轨迹——这就是避障约束的实战价值。它不像传统方法那样先躲开再说,而是从一开始就在合法边界内找最优解。

这正是导航式智慧的最高级形态:不按死背书的感觉开车,而是每时每刻用“未来视界”和“规则边界”重新做决定。因此近十年主流自动驾驶方案,几乎都把 MPC 作为运动控制层的基准算法。

θ˙=vL tan⁡δ\dot{\theta} = \frac{v}{L}\, \tan \delta
这是自行车模型的核心关系式:车的航向角变化率 $\dot{\theta}$,等于车速 v 乘以前轮转角 $\delta$ 的正切,再除以轴距 L。
  1. 航向角变化率 $\dot{\theta}$车头朝向转动的快慢,也就是“这辆车现在有多急地在转弯”。
    θ˙\dot{\theta}
  2. 车速 $v$车速越快,同样的前轮转角产生的转弯越剧烈——高速时方向盘必须更谨慎。
    vv
  3. 轴距 $L$前轮与后轮的距离。车身越长,转向越“钝”;这也是大货车掉头比小车费劲的原因。
    LL
  4. 前轮转角 $\delta$控制输入中的转向量,在 MPC 中被约束在物理允许的上下限内,并受代价函数抑制。
    tan⁡δ\tan \delta

机械臂控制:让机器手稳准柔

一位大厨炖汤,既要让味道精准地达到目标,又要防止汤在沸腾时溢出锅沿——“目标味道”和“不能溢锅”必须同时满足。工业机械臂的控制正是这个难题的放大版:末端要沿着毫米级精度的轨迹焊接、喷涂,同时每个关节都绝对不能撞上机械限位,电机也不能过载。机械臂是多关节强耦合的非线性系统,一个关节发力会牵连其他关节,直接套 PID 常常顾此失彼。

机械臂的“身体说明书”是一个二阶动力学方程(见下式):$M(q)$ 是惯性矩阵,描述每个关节有多“重”;$C(q,\dot{q})$ 是科氏力与离心力项,描述关节之间怎样互相“拽”;$g(q)$ 是重力项,描述每个姿态下要费多大力气抵抗重力;$\tau$ 是电机输出的关节力矩。MPC 把这个方程当作预测器:给定一串未来的力矩序列,就能推演出未来关节角会不会超限、末端会不会脱离期望轨迹。

这就是 MPC 在机械臂上的三大用武之地。第一,末端轨迹跟踪:让焊枪、夹爪沿着规划好的空间曲线平滑移动。第二,关节限位:把关节角度、速度、力矩的上限全部写成硬约束,从根源上杜绝“撞限位”事故。第三,力矩优化:把力矩的平顺程度写进代价函数,既保护电机又让动作更柔和。如果再配上相机做视觉伺服,每个控制周期用视觉测量更新状态,MPC 就能实时追踪运动中的目标——手术机器人、协作机械臂里大量使用这类方案。

老司机开车靠的是“预测 + 边界 + 重规划”,机械臂控制本质上也是一样——只不过“道路”变成了多维的关节空间,“车道线”变成了关节限位。工具换了,智慧是相通的。

M(q) q¨+C(q, q˙) q˙+g(q)=τM(q)\, \ddot{q} + C(q,\ \dot{q})\, \dot{q} + g(q) = \tau
机械臂的动力学方程:左边是“惯性 + 关节牵连 + 重力”三股力量的总和,右边是电机提供的驱动力矩。MPC 依靠它来预测“如果我给这个力矩,关节未来会怎么动”。
  1. 惯性项 $M(q)\, \ddot{q}$每个关节的“质量效应”——关节越重、加速越猛,需要的力矩越大。
    M(q) q¨M(q)\, \ddot{q}
  2. 科氏与离心项 $C(q,\dot{q})\, \dot{q}$一个关节转动时对另一个关节产生的“牵连力”,是机械臂强耦合的根源。
    C(q, q˙) q˙C(q,\ \dot{q})\, \dot{q}
  3. 重力项 $g(q)$不同姿态下抵抗重力所需的分量,比如手臂水平伸直时最费力。
    g(q)g(q)
  4. 驱动力矩 $\tau$电机提供的力,是 MPC 的输出变量,同时也是需要限制在安全范围内的“输入”。
    τ\tau

AI 应用场景

场景1:自动驾驶车辆的轨迹跟踪控制

阶段:感知-规划-控制闭环中的“运动控制”环节。

解决的问题:传统 PID 横向控制只能盯着当前的横向偏差打方向盘,遇到弯道曲率突变容易“切弯”或来回抖动,而且无法把“不能压车道线”“加速度不能过大”这类安全约束直接纳入决策。MPC 通过预测未来 1~3 秒的车辆状态,在代价函数中同时惩罚跟踪误差和转向剧烈程度,并把车道边界写成硬约束,一次求解同时满足安全与舒适。

具体案例:某自动驾驶公司在城市道路测试中,以 10Hz 运行线性时变 MPC(LTV-MPC)跟踪规划模块输出的参考轨迹。每个控制周期,把非线性车辆模型在参考点附近线性化,交给 QP 求解器(OSQP)求前轮转角指令,预测时域设 2 秒共 20 步。实测数据表明,在 60km/h 过弯时横向误差稳定在 ±15cm 内,全程未发生压线。

场景2:机械臂的关节限位与平滑运动控制

阶段:机器人“运动规划与控制”执行层。

解决的问题:机械臂在焊接、喷涂任务中需要高速高精度跟踪末端轨迹,但直接反解得到的关节速度可能超过电机驱动上限,关节也可能撞上机械限位。MPC 把关节角度限制、速度限制、力矩限制全部写成约束,在预测时域内滚动优化关节力矩,把“安全”和“平滑”变成优化问题的一部分,而不是事后补救。

具体案例:某汽车焊装产线的六轴机器人原先用“梯形速度规划 + PID 跟踪”,高速运动时末端抖动明显。改用非线性 MPC 后,代价函数包含末端跟踪误差与力矩平顺项,约束包含各关节位置、速度、力矩上限,控制周期 2ms 内用嵌入式 OCP 求解器完成求解。实测末端轨迹误差从 ±2mm 降到 ±0.3mm,关节噪声明显下降,焊点质量也更稳定。

Python 演示

python78 行
import numpy as npfrom scipy.optimize import minimize  class TrackingMPC:    """基于运动学模型的 MPC 轨迹跟踪器"""     def __init__(self, dt=0.1, horizon=10, v_max=1.0, w_max=2.0):        self.dt = dt        self.horizon = horizon        self.v_max = v_max        self.w_max = w_max     def predict(self, state, u_seq):        # 积分运动学模型, 得到未来 horizon+1 个状态        x = state.copy()        traj = [x.copy()]        for u in u_seq:            v, w = u            x = x + np.array([                v * np.cos(x[2]) * self.dt,                v * np.sin(x[2]) * self.dt,                w * self.dt            ])            traj.append(x.copy())        return np.array(traj)     def cost(self, flat_u, state, ref_seq):        # 轨迹跟踪误差 + 输入惩罚        u_seq = flat_u.reshape(-1, 2)        traj = self.predict(state, u_seq)        err = traj[1:] - ref_seq        return np.sum(err[:, :2] ** 2) + 0.02 * np.sum(flat_u ** 2)     def solve(self, state, ref_seq):        # 约束优化: 输入幅值上限写入 bounds        u0 = np.zeros((self.horizon, 2)).flatten()        bounds = [(-self.v_max, self.v_max), (-self.w_max, self.w_max)] * self.horizon        res = minimize(self.cost, u0, args=(state, ref_seq),                       method='SLSQP', bounds=bounds)        return res.x.reshape(-1, 2)     def run(self, state, ref_traj, steps=200):        traj = [state.copy()]        for i in range(steps):            end = min(i + self.horizon, len(ref_traj))            ref_seq = ref_traj[i:end]            if len(ref_seq) < self.horizon:                pad = ref_seq[-1][None, :].repeat(                    self.horizon - len(ref_seq), axis=0)                ref_seq = np.vstack([ref_seq, pad])            u_seq = self.solve(state, ref_seq)            v, w = u_seq[0]            state = state + np.array([                v * np.cos(state[2]) * self.dt,                v * np.sin(state[2]) * self.dt,                w * self.dt            ])            traj.append(state.copy())        return np.array(traj)  def main():    mpc = TrackingMPC()    t = np.arange(0, 20, mpc.dt)    ref = np.stack([2 * np.cos(t), 2 * np.sin(t)], axis=1)    ref_full = np.hstack([ref, np.zeros((len(ref), 1))])  # theta 列占位    state = np.array([2.0, 0.0, 0.5])   # 初始位置与航向角    traj = mpc.run(state, ref_full)    err = np.sqrt((traj[1:, 0] - ref[:, 0]) ** 2                  + (traj[1:, 1] - ref[:, 1]) ** 2)    print("滚动优化次数:", len(traj) - 1)    print("平均跟踪误差:", round(float(err.mean()), 4))    print("最终跟踪误差:", round(float(err[-1]), 4))  if __name__ == "__main__":    main()
目的:用最简化的“自行车模型 + scipy 优化器”实现一个完整的 MPC 轨迹跟踪器,控制一个小车沿圆形参考轨迹行驶,并打印滚动优化次数与跟踪误差。
  1. class TrackingMPC:定义了 MPC 控制器的主体,封装“预测、打分、求解、滚动执行”四个能力。
  2. def predict(self, state, u_seq):对应正文里的“预测模型”:给定未来一串控制输入,逐步积分运动学方程,算出一整条预测轨迹。
  3. def cost(self, flat_u, state, ref_seq):对应“代价函数”:第一项是跟踪误差平方和(偏离参考线多严重),第二项是输入惩罚(控制动作多猛)。
  4. bounds = [(-self.v_max, self.v_max), ...]对应“输入饱和约束”:把油门与转向的上下限直接交给优化器,禁止越界方案出现。
  5. res.x.reshape(-1, 2)求解器返回的是未来 N 步的最优控制序列,这里把它还原成“每步两个输入”的二维数组。
  6. u_seq = self.solve(state, ref_seq)` / `v, w = u_seq[0]对应“滚动优化”:只取最优序列的第一步作为当前控制量,剩下的事等下一拍重算。
  7. err = np.sqrt(...)最后用欧氏距离统计跟踪误差,验证这 200 次“走一步、算一路”的累积效果。

常见误区

误区我看到 MPC 公式里有个模型,模型不准那预测全是错的,控制肯定崩,所以这算法只能活在论文里吧?

正解模型确实重要,但 MPC 的“滚动”机制自带纠错能力:每个控制周期都用最新的传感器反馈重新初始化状态,预测误差只影响当前这一拍的决策,不会一路滚雪球。就像导航地图有一点偏差,只要每到一个路口用真实位置重新定位,仍然能把你送到目的地。工业实践中还会在预测模型之外叠加“预测误差补偿项”,进一步吸收模型失配。

为何常见:初学者看公式时只盯着开环预测那一段,忽略了“每步重规划”这个隐藏的反馈回路,误把“基于模型预测”理解成“一次性开环预测”。

误区LQR 也是优化,MPC 也是优化,最后都是算出一个控制律,两者区别不大吧。

正解两者有本质区别。LQR 求解的是无限时域问题,离线算一次,得到固定的状态反馈增益 K,在线只是做一个矩阵乘法;MPC 求解的是有限时域问题,在线反复求解,得到的是“未来 N 步的控制序列”,只执行第一步后整窗前移重算。更关键的是,LQR 加入输入、状态约束非常困难,而 MPC 把约束当作问题的天然组成部分。类比一下:LQR 像一次雇人定好的“常年最优路线”,MPC 像导航每时每刻重算。

为何常见:两者代价函数长得极像,都出现 Q、R 权重矩阵,很容易让人以为只是同一种算法的两个名字。

误区看得远肯定更聪明,我把预测时域设成 100 步,系统一定跟踪得更稳更准。

正解N 增大带来双重代价。第一,决策变量成倍增加,在线求解时间急剧上升,很可能超过控制周期——算不完的 MPC 还不如不算。第二,模型误差随预测步长累积,远期预测的可信度迅速下降,过大的 N 等于在优化一个“根本不会发生的未来”。工程上 N 通常取 10~30 步(对应 1~3 秒),并用终端代价或终端约束来弥补“只看有限步”造成的短视。

为何常见:“看得远=更聪明”是日常直觉,但忽略了预测的不确定性随距离指数级增大,也忽略了算力是每毫秒都在燃烧的稀缺资源。

误区MPC 公式里全是 A、B 这种线性矩阵,这是线性系统的专利,非线性机器人根本没戏。

正解非线性 MPC(NMPC)是 MPC 家族的重要分支:可以直接对非线性模型做在线数值优化(交给 NLP 求解器),也可以把非线性模型在当前工作点线性化后继续用 QP 求解——这就是 LTV-MPC。汽车轮胎非线性、机械臂动力学恰恰是 NMPC 最典型的舞台。代价只是求解更慢、对初值更敏感,所以工程上常用“离线线性化 + 在线 QP”或“多级求解”来折中。

为何常见:教材入门推导几乎都用线性系统,A、B 矩阵太扎眼,导致误以为 MPC 被线性模型限制死,其实线性只是“最简单的可用模型”。

面试题

Q1. 模型预测控制(MPC)最核心的思想是什么?

单选题 · easy

  • A.只依据当前误差比例放大控制
  • B.预测未来并滚动优化当前输入← 正确答案
  • C.查表得到固定的控制增益值
  • D.完全依赖模型而忽略反馈量

答案:B。MPC 用系统模型预测未来若干步的状态,通过优化求当前输入,并且每步重新求解。A 是 PID 的特点,C 是 LQR/增益调度的做法,D 是开环控制,都缺失了“预测+滚动”这个核心。

Q2. “滚动优化”在 MPC 中的含义是?

单选题 · easy

  • A.离线一次性算好全部控制序列
  • B.移动预测窗口每步重新求解← 正确答案
  • C.用随机搜索替代数值优化
  • D.固定预测窗口但永不更新

答案:B。滚动优化指每个控制周期都把预测窗口向前移动一步,用最新测量值重新求解优化问题,只执行第一步。A 是开环规划,C、D 都与“滚动”的语义相悖。

Q3. MPC 相比 PID 的关键优势是?

单选题 · mid

  • A.PID 能显式处理安全约束
  • B.MPC 靠预测来显式处理约束← 正确答案
  • C.两者原理完全相同可以互换
  • D.MPC 完全不需要反馈环节

答案:B。MPC 把输入饱和、安全边界写成约束条件,直接在优化中处理,而 PID 只能事后纠偏、无法提前考虑限制。C 明显错误,D 忽略了 MPC 的反馈校正机制。

Q4. 预测时域步长 N 取值过大,主要带来什么影响?

单选题 · mid

  • A.计算量减小但精度略有下降
  • B.计算量增大且远期预测误差累积← 正确答案
  • C.系统稳定性必然显著增强
  • D.约束条件将自动被优化器忽略

答案:B。N 越大,决策变量越多,求解越慢;同时模型误差随预测步长累积,远期预测不可信。所以 N 并非越大越好,工程上常取 10~30 步并配合终端代价。

Q5. 线性 MPC 通常被转化为哪类优化问题求解?

单选题 · mid

  • A.线性规划 LP 问题来求解
  • B.二次规划 QP 问题来求解← 正确答案
  • C.遗传算法寻优的随机搜索
  • D.模拟退火启发式全局搜索

答案:B。线性模型 + 二次代价函数 + 线性约束,组合起来恰是标准的二次规划(QP)。QP 有成熟的快速求解器,是线性 MPC 的主流求解方式;LP 要求目标也是线性的,C、D 是元启发式方法。

Q6. 模型存在失配误差时,MPC 仍能稳定跟踪的原因是?

单选题 · hard

  • A.因为假设模型始终完全精确
  • B.滚动时域不断用新测量校正← 正确答案
  • C.因为只关心最后一步的结果
  • D.因为约束会自动消失失效

答案:B。MPC 每步都用最新传感器反馈重新初始化状态,预测误差只影响当前拍决策,不会长期累积——这就是“滚动”自带鲁棒性的根源。A、D 与现实不符,C 恰好说反了(关心的是第一步)。

Q7. 下列哪一项不属于 MPC 代价函数的组成?

单选题 · mid

  • A.状态跟踪误差代价项
  • B.控制输入惩罚的代价项
  • C.预测时域长度的取值← 正确答案
  • D.终端状态的额外代价项

答案:C。代价函数由跟踪误差项、输入惩罚项、可选的终端代价项组成;预测时域长度 N 是控制器设计参数,决定“看多远”,本身不是代价函数的一项。

Q8. 关于 MPC 求解器的选择,下列说法正确的有?

多选题 · hard

  • A.线性系统通常采用 QP 求解← 正确答案
  • B.非线性系统常采用 NLP 求解← 正确答案
  • C.实时性是关键的工程指标← 正确答案
  • D.求解器与系统模型完全无关

答案:ABC。线性 MPC 化为 QP 用专用求解器(OSQP、qpOASES 等),非线性 MPC 用 NLP 求解器(IPOPT、SNOPT 等),两者都必须在控制周期内算完,实时性至关重要。求解器选择与模型类型强相关,D 错误。

Q9. MPC 中可以把哪些要求写成约束条件?

多选题 · mid

  • A.输入幅值的上下限边界← 正确答案
  • B.状态量的安全边界范围← 正确答案
  • C.输入变化率的平滑限制← 正确答案
  • D.目标函数必须恒等于零

答案:ABC。输入饱和、安全边界、输入变化率限制都可以写成不等式约束,这也是 MPC 处理安全问题的核心能力。目标函数是待最小化的对象,不是约束,D 无意义。

Q10. MPC 在机器人领域的典型应用场景包含?

多选题 · easy

  • A.自动驾驶汽车的轨迹跟踪← 正确答案
  • B.机械臂关节限位与平滑控制← 正确答案
  • C.图像压缩与视频编解码处理
  • D.语音识别与自然语言翻译

答案:AB。自动驾驶轨迹跟踪和机械臂控制正是 MPC 的两大主战场——都具有明确动力学模型、需要处理约束、要求实时优化。C、D 属于信号处理与自然语言领域,与机器人运动控制无关。