第二章:MPC数学基础——状态空间模型、离散化方法、二次规划(QP)问题、约束处理
各位同学,欢迎来到第二章。
说实话,MPC(模型预测控制)听起来挺唬人的。但拆开来看,核心就四个东西:状态空间模型、离散化、二次规划、约束处理。搞懂了这四个,你就拿到了MPC的钥匙。
我个人习惯,讲数学之前先讲直觉。咱们先不推公式,先想想:你要控制一个系统,总得知道它长什么样吧?这就是状态空间模型。计算机只能处理离散数据,所以得把连续模型离散化。然后,你要在每一步算出一个最优的控制量,这就是二次规划。最后,你总不能把电机转速拉到一万转吧?这就是约束。
好,咱们一个一个来。
2.1 状态空间模型:系统的“身份证”
状态空间模型,说白了就是描述系统内部状态的数学工具。我刚开始做电机控制时,总觉得用传递函数就够了。直到有一次,我需要同时控制位置和速度,传递函数那套东西根本搞不定。嗯,从那以后,我就老老实实用状态空间了。
标准形式长这样:
连续时间状态空间方程:
ẋ(t) = A x(t) + B u(t)
y(t) = C x(t) + D u(t)
其中:
x(t) —— 状态向量(比如位置、速度)
u(t) —— 输入向量(比如电压、扭矩)
y(t) —— 输出向量(比如传感器读数)
A —— 系统矩阵(描述内部动态)
B —— 输入矩阵(描述输入如何影响状态)
C —— 输出矩阵(描述状态如何映射到输出)
D —— 前馈矩阵(通常为0)
关键点:状态变量必须能完全描述系统的未来行为。选错了状态变量,你的MPC就废了。
举个例子,一个简单的直流电机模型:
状态变量:x = [θ (角度), ω (角速度)]
输入:u = V (电枢电压)
输出:y = θ (角度)
A = [0, 1; 0, -b/J]
B = [0; Kt/J]
C = [1, 0]
D = [0]
其中 b 是阻尼系数,J 是转动惯量,Kt 是扭矩常数
我在项目中遇到过一个问题:有人把电机电流也当作状态变量,结果模型阶数太高,控制器跑不动。你想想看,MPC是要在线求解的,模型越复杂,计算量越大。所以,状态变量的选择要精炼。
2.2 离散化方法:让计算机听懂你的模型
计算机是离散的,而物理世界是连续的。所以,你得把连续模型变成离散模型。常用的方法有三种:
| 方法 | 精度 | 计算量 | 适用场景 |
|---|---|---|---|
| 前向欧拉法 | 低 | 小 | 采样频率高、精度要求低 |
| 后向欧拉法 | 中 | 中 | 数值稳定性要求高 |
| 零阶保持法(ZOH) | 高 | 大 | 工业标准,推荐使用 |
我个人习惯用零阶保持法。为什么?因为它假设输入在两个采样点之间保持不变,这跟实际DAC输出一模一样。我曾经试过用前向欧拉法,结果采样频率不够高时,模型直接发散。嗯,那场面,挺尴尬的。
离散化后的模型长这样:
离散时间状态空间方程:
x(k+1) = A_d x(k) + B_d u(k)
y(k) = C_d x(k) + D_d u(k)
其中:
A_d = e^(A*Ts)
B_d = ∫(0→Ts) e^(A*τ) dτ * B
C_d = C
D_d = D
Ts —— 采样时间
避坑指南:我曾经在STM32上实现MPC,采样时间设成了1ms,结果A_d矩阵计算用了0.5ms。你想想看,控制器还没算完,下一个采样点就到了。所以,采样时间的选择要综合考虑模型复杂度和处理器性能。
2.3 二次规划(QP)问题:MPC的“大脑”
MPC的核心,就是在每个采样时刻,求解一个优化问题。这个优化问题,通常是一个二次规划(QP)问题。
标准形式:
minimize: 0.5 * z^T * H * z + f^T * z
subject to: A_ineq * z ≤ b_ineq
A_eq * z = b_eq
lb ≤ z ≤ ub
其中:
z —— 决策变量(通常是未来N步的控制量和状态量)
H —— Hessian矩阵(必须是半正定)
f —— 梯度向量
A_ineq, b_ineq —— 不等式约束
A_eq, b_eq —— 等式约束
lb, ub —— 上下界约束
为什么是二次规划?因为MPC的目标函数通常是二次型:
J = Σ (x_ref - x)^T * Q * (x_ref - x) + Σ u^T * R * u
Q —— 状态权重矩阵(越大,跟踪越紧)
R —— 输入权重矩阵(越大,控制越平缓)
说白了,就是让状态尽量靠近目标,同时控制量不要太大。我刚开始做时,Q和R都是瞎调的。后来发现,Q和R的比值决定了系统的响应速度和控制能耗。你想想看,Q设得太大,系统响应快但容易震荡;R设得太大,系统反应慢得像老牛拉车。
注意:Hessian矩阵H必须是半正定的,否则QP问题可能无解。我在项目中遇到过,因为Q矩阵设成了负定,结果求解器直接报错。嗯,那一次排查了整整两天。
2.4 约束处理:MPC的“安全锁”
MPC最大的优势之一,就是能显式处理约束。没有约束的MPC,跟LQR没什么区别。
常见的约束类型:
- 输入约束:u_min ≤ u ≤ u_max(比如电机最大电压)
- 状态约束:x_min ≤ x ≤ x_max(比如位置极限)
- 输出约束:y_min ≤ y ≤ y_max(比如传感器量程)
- 变化率约束:Δu_min ≤ Δu ≤ Δu_max(比如加速度限制)
约束处理的核心,就是把它们全部写成线性不等式的形式,塞进QP问题里。
举个例子,输入约束:
u_min ≤ u(k) ≤ u_max
写成矩阵形式:
[ I ] * u ≤ u_max
[ -I ] * u ≤ -u_min
我曾经在无人机项目中,只加了输入约束,没加状态约束。结果无人机在急转弯时,姿态角超出了安全范围,差点炸机。嗯,从那以后,我再也不敢漏掉状态约束了。
经验之谈:约束越紧,可行域越小,QP求解越容易失败。所以,约束要尽量宽松,但必须保证安全。我一般会留10%-20%的余量。
2.5 知识体系总览
下面这张图,是我自己画的MPC数学基础框架。你把它存下来,以后写代码时对照着看。
好了,这一章的内容就到这里。数学基础打牢了,后面写代码才不慌。下一章,咱们直接上代码,用Python实现一个完整的MPC控制器。
公众号:蓝海资料掘金营,微信deep3321