1. MPC模型预测控制的核心思想
第一次接触MPC时,我被它"滚动优化"的工作方式深深吸引。与传统PID控制不同,MPC不是被动响应误差,而是主动预测未来多步的系统行为。就像下棋时高手会预判后面几步的走法,MPC通过求解优化问题来规划最优控制序列。
1.1 预测模型的选择
MPC的核心是预测模型,常见的有:
- 状态空间模型:x(k+1)=Ax(k)+Bu(k)
- 传递函数模型:通过离散化得到差分方程
- 非线性模型:适用于复杂系统但计算量大
我在车辆控制项目中实测发现,对大多数工业过程,线性时不变(LTI)模型既能保证精度又便于实时计算。比如汽车巡航控制中,用一阶惯性加纯延迟模型就能很好描述车速响应特性。
1.2 滚动时域优化
MPC的魔力在于这三个关键步骤的循环:
- 在当前时刻t,基于模型预测未来N步的系统输出
- 求解最优控制序列u(t),u(t+1)...u(t+N-1)
- 只实施第一步控制u(t),到下一时刻重新预测优化
这种"计划-执行-调整"的机制,使得MPC对模型误差和干扰具有天然鲁棒性。我在温控实验中对比发现,当存在20%模型失配时,PID出现持续振荡而MPC仍能稳定控制。
2. MPC的数学推导过程
2.1 问题建模
考虑离散状态空间模型:
x(k+1) = Ax(k) + Bu(k)
y(k) = Cx(k)
优化目标通常为二次型:
J = Σ[y(k)-r(k)]² + λΣu(k)²
其中r(k)为参考轨迹,λ是控制量权重
2.2 推导预测方程
将未来p步的状态表示为:
X = [x(k+1|k); x(k+2|k); ... ; x(k+p|k)]
= Sx x(k) + Su U
其中U=[u(k);...;u(k+m-1)], m为控制时域
Sx和Su是扩展的可达性矩阵:
Sx = [A; A²; ... ; A^p]
Su = [B 0 ... 0; AB B ... 0; ... ; A^{p-1}B ... B]
2.3 转化为QP问题
将目标函数表示为:
J = (Y-R)ᵀQ(Y-R) + UᵀRU
其中Y = [y(k+1);...;y(k+p)] = CₑX
Cₑ = diag(C,...,C)
代入预测方程后得到标准QP形式:
J = 1/2 UᵀH U + fᵀU + const
H = 2(SᵤᵀCₑᵀQCₑSᵤ + R)
f = -2SᵤᵀCₑᵀQ(R-Sₓx(k))
3. Octave实现详解
3.1 环境配置
推荐使用Octave 6.4+版本,需安装优化工具箱:
octave复制pkg install -forge optim
pkg load optim
3.2 核心代码实现
octave复制function [u, x_pred] = mpc_controller(x0, A, B, C, Q, R, p, m, umax)
% 构建预测矩阵
Sx = zeros(size(A,1)*p, size(A,2));
Su = zeros(size(A,1)*p, size(B,2)*m);
for i = 1:p
Sx((i-1)*size(A,1)+1:i*size(A,1), :) = A^i;
for j = 1:min(i,m)
Su((i-1)*size(A,1)+1:i*size(A,1), (j-1)*size(B,2)+1:j*size(B,2)) = A^(i-j)*B;
end
end
% 构建QP参数
Ce = kron(eye(p), C);
H = 2*(Su'*Ce'*Q*Ce*Su + kron(eye(m), R));
f = -2*Su'*Ce'*Q*(repmat(-C*x0,p,1) - Sx*x0);
% 求解QP
options = optimset('Display', 'off');
U = quadprog(H, f, [], [], [], [], -umax*ones(m,1), umax*ones(m,1), [], options);
u = U(1:size(B,2));
x_pred = Sx*x0 + Su*U;
end
3.3 仿真测试案例
以二阶系统为例:
octave复制A = [0.9 0.2; -0.1 0.8];
B = [0.1; 0.2];
C = [1 0];
Q = eye(10);
R = 0.1*eye(2);
p = 10; m = 2;
umax = 1;
x = [0;0];
for k = 1:100
r = 1*(k>20); % 阶跃信号
[u, x_pred] = mpc_controller(x, A, B, C, Q, R, p, m, umax);
x = A*x + B*u;
y(k) = C*x;
end
plot(y);
4. 工程实践中的关键技巧
4.1 参数整定经验
- 预测时域p选择:
- 一般取系统阶跃响应上升时间的1.5~2倍
- 可通过仿真观察"预测尾巴"是否收敛
- 控制时域m选择:
- 通常取p的1/3~1/2
- 增大m会提高计算量但改善控制效果
- 权重调整:
- 先设Q=1, R=0.01作为基准
- 若响应过慢,按比例减小R
- 若超调大,增大Q中对输出误差的惩罚
4.2 实时性优化
- 热启动技巧:
octave复制U_prev = [U(2:end); U(end)]; % 上一时刻解作为初值
U = quadprog(..., U_prev, ...);
- 降阶处理:
对慢动态系统,可用奇异值分解(SVD)降维:
octave复制[U,S,V] = svd(H);
r = find(diag(S)/S(1,1)<1e-3, 1);
H_red = V(:,1:r)'*H*V(:,1:r);
4.3 异常处理机制
- QP无解时的应对:
octave复制try
U = quadprog(...);
catch
U = pinv(Su)*(repmat(r,p,1)-Sx*x0); % 最小二乘解
end
- 状态估计补偿:
当存在测量噪声时,建议采用Kalman滤波器:
octave复制x_est = kalman_update(y_meas, u_prev, A, B, C, Q_kal, R_kal);
5. 典型应用场景实现
5.1 车辆轨迹跟踪
模型特点:
- 采用自行车模型
- 输出为横向偏差和航向角偏差
- 控制量为前轮转角和加速度
octave复制% 车辆参数
lf = 1.2; lr = 1.6; % 前后轴距
Caf = 80000; Car = 80000; % 轮胎侧偏刚度
% 状态矩阵
A = [0 1 0 0;
0 -(Caf+Car)/m/u 0 -u-(Caf*lf-Car*lr)/m/u;
0 0 0 1;
0 -(Caf*lf-Car*lr)/Iz/u 0 -(Caf*lf^2+Car*lr^2)/Iz/u];
B = [0; Caf/m; 0; Caf*lf/Iz];
5.2 温度控制系统
特殊处理:
- 需考虑执行器(加热器)的饱和特性
- 加入积分环节消除静差
octave复制% 增广系统
A_aug = [A zeros(2,1); -C 1];
B_aug = [B; 0];
% 带积分项的代价函数
Q_aug = blkdiag(Q, 1000); % 积分项权重
5.3 无人机悬停控制
挑战:
- 强耦合多输入多输出系统
- 需处理执行器延迟
解决方案:
- 采用分散式MPC结构
- 在预测模型中加入延迟环节:
octave复制A_delay = [A B; zeros(size(B,2), size(A,2)) eye(size(B,2))];
B_delay = [zeros(size(A,1), size(B,2)); eye(size(B,2))];
6. 常见问题排查指南
6.1 发散振荡问题
现象:控制量剧烈波动,系统失稳
可能原因:
-
预测时域p过短
- 检查p是否覆盖主要动态
- 仿真观察预测轨迹是否合理
-
权重设置不当
- 临时增大控制量权重R
- 检查Q矩阵是否正定
6.2 计算超时问题
优化方案:
-
减少时域参数:
octave复制while toc<0.1*Ts % Ts为采样周期 p = p-1; m = m-1; rebuild_QP_matrices; end -
使用显式MPC:
离线计算参数分区:octave复制[solution,diagnostics] = mpcsolver(A,B,Q,R,constraints);
6.3 稳态误差问题
解决方法:
-
引入积分动作:
octave复制x_aug = [x; cumsum(y-r)]; -
修改目标函数:
octave复制Q(end-p:end,:) = 10*Q(end-p:end,:); % 终端加重
7. 进阶扩展方向
7.1 非线性MPC实现
- 连续线性化方法:
octave复制for i = 1:p
[A_i,B_i] = linearize(x_pred(:,i),u_prev);
% 更新Sx和Su矩阵...
end
- 粒子群优化替代QP:
octave复制cost_func = @(U) (Y-R)'*Q*(Y-R) + U'*R*U;
U = particleswarm(cost_func, m*nu, lb, ub);
7.2 鲁棒MPC设计
考虑模型不确定性:
octave复制% 多场景优化
H_total = [];
f_total = [];
for scen = 1:N_scenarios
[A_s,B_s] = generate_scenario();
% 构建各场景的H,f...
H_total = blkdiag(H_total, H);
f_total = [f_total; f];
end
U = quadprog(H_total, f_total, ...);
7.3 嵌入式部署技巧
- 代码生成:
octave复制pkg load generate
generate_quadprog_c_code(H, f, lb, ub);
- 定点数优化:
octave复制H_fixed = fi(H, 1, 16, 8); % 16位总长,8位小数
在无人机飞控项目中,我将MPC采样周期压缩到10ms内,关键是把QP求解分解为预处理(离线)和在线求解两部分。预处理计算所有可能的激活约束组合,运行时只需查表求解简化后的方程组。这种方案在STM32H7上仅需1.2ms即可完成10维状态的MPC计算。
