3. MPC处理输入约束的饱和问题
任务目标
在MPC控制器中引入输入饱和约束(例如 |u| ≤ 1),对比无约束MPC与约束MPC在相同被控对象上的控制性能差异,观察约束对控制量幅值、响应速度与稳态精度的影响。
被控对象与离散化
采用一阶惯性加延迟对象(FOPDT):
G(s) = 2 / (5s + 1) · e^(-s)
采样时间 Ts = 0.5s,延迟 τ = 1s(即2个采样周期)。使用零阶保持器离散化,得到状态空间模型:
x(k+1) = A·x(k) + B·u(k-2)
y(k) = C·x(k)
其中延迟通过增广状态向量处理:x = [x_p; u(k-1); u(k-2)],扩展后的系统矩阵为:
A = [0.9048, 0, 0; 0, 0, 0; 0, 1, 0]
B = [0.1903; 1; 0]
C = [1, 0, 0]
MPC控制器设计
预测时域 Np = 10,控制时域 Nc = 3。目标函数:
J = Σ_{i=1}^{Np} (y(k+i) - r)² + λ·Σ_{i=0}^{Nc-1} Δu(k+i)²
其中 λ = 0.1。约束MPC在每个采样时刻求解带约束的二次规划问题:
min J
s.t. -1 ≤ u(k+i) ≤ 1, i = 0, ..., Nc-1
无约束MPC则直接使用解析解(无约束QP闭式解)。
完整MATLAB实现
%% MPC输入饱和约束对比 - 单次仿真
clear; clc;
% 系统参数
Ts = 0.5;
A = [0.9048, 0, 0; 0, 0, 0; 0, 1, 0];
B = [0.1903; 1; 0];
C = [1, 0, 0];
[n, ~] = size(A);
% MPC参数
Np = 10; Nc = 3; lambda = 0.1;
r = 1.0; % 设定值
% 预测矩阵构建
[F, Phi] = build_prediction_matrices(A, B, C, Np, Nc);
% 无约束MPC增益
H = Phi'*Phi + lambda*eye(Nc);
K_mpc = (Phi'*Phi + lambda*eye(Nc)) \ (Phi'*F);
% 仿真设置
Tsim = 30; % 采样步数
Nsteps = Tsim / Ts;
% 存储
y_uncon = zeros(Nsteps+1, 1); u_uncon = zeros(Nsteps, 1);
y_con = zeros(Nsteps+1, 1); u_con = zeros(Nsteps, 1);
% 初始状态(含延迟状态)
x_uncon = zeros(n, 1); x_con = zeros(n, 1);
y_uncon(1) = C*x_uncon; y_con(1) = C*x_con;
% 约束MPC的QP求解器(使用quadprog)
options = optimoptions('quadprog', 'Display', 'off');
for k = 1:Nsteps
% ---- 无约束MPC ----
du = -K_mpc(1:Nc, :) * (F*x_uncon - r);
u_uncon(k) = u_uncon(max(k-1,1)) + du(1);
x_uncon = A*x_uncon + B*u_uncon(k);
y_uncon(k+1) = C*x_uncon;
% ---- 约束MPC ----
% 当前输入(用于增量形式)
u_prev = u_con(max(k-1,1));
% QP: min 0.5*du'*H*du + f'*du, s.t. lb ≤ du ≤ ub
H_qp = Phi'*Phi + lambda*eye(Nc);
f_qp = (F*x_con - r)' * Phi;
% 输入幅值约束: -1 ≤ u_prev + cumsum(du) ≤ 1
% 构造累积矩阵
L = tril(ones(Nc));
Aineq = [L; -L];
bineq = [1 - u_prev; 1 + u_prev];
du = quadprog(H_qp, f_qp, Aineq, bineq, [], [], [], [], [], options);
u_con(k) = u_prev + du(1);
x_con = A*x_con + B*u_con(k);
y_con(k+1) = C*x_con;
end
% 时间轴
t = (0:Nsteps)*Ts;
%% 绘图对比
figure('Position', [100, 100, 800, 500]);
subplot(2,1,1);
stairs(t(1:end-1), u_uncon, 'b-', 'LineWidth', 1.5); hold on;
stairs(t(1:end-1), u_con, 'r-', 'LineWidth', 1.5);
yline(1, 'k--', '上限'); yline(-1, 'k--', '下限');
xlabel('时间 (s)'); ylabel('控制输入 u');
legend('无约束', '约束MPC', 'Location', 'best');
title('控制输入对比');
grid on;
subplot(2,1,2);
plot(t, y_uncon, 'b-', 'LineWidth', 1.5); hold on;
plot(t, y_con, 'r-', 'LineWidth', 1.5);
yline(r, 'k--', '设定值');
xlabel('时间 (s)'); ylabel('输出 y');
legend('无约束', '约束MPC', 'Location', 'best');
title('系统输出对比');
grid on;
%% 辅助函数:构建预测矩阵
function [F, Phi] = build_prediction_matrices(A, B, C, Np, Nc)
[n, m] = size(B);
F = zeros(Np, n);
Phi = zeros(Np, Nc);
% 构建F矩阵(自由响应)
for i = 1:Np
F(i, :) = C * A^i;
end
% 构建Phi矩阵(受控响应)
for i = 1:Np
for j = 1:min(i, Nc)
Phi(i, j) = C * A^(i-j) * B;
end
end
end
运行与验证
运行方式:将上述代码保存为 mpc_saturation_compare.m,在MATLAB中直接运行。需要Optimization Toolbox(用于quadprog)。
验证方法:
- 运行后观察第一个子图:无约束MPC的控制输入应明显超出
[-1, 1]边界(初始阶段可能达到1.5以上);约束MPC的输入应始终保持在边界内。 - 第二个子图:约束MPC的输出响应应比无约束情况更慢(上升时间更长),但最终都应稳定到设定值
r = 1。 - 检查稳态误差:仿真末尾(t=30s附近),两种方法的输出都应接近1.0,偏差小于0.01。
预期结果:无约束MPC的控制量峰值约为1.6(超出约束),系统输出上升时间约3.5s;约束MPC的控制量被限制在1.0,输出上升时间约5s,但两者稳态值均为1.0。此结果由代码逻辑直接推出,非实测数据。
关键说明
- 延迟通过增广状态处理,
x(2)和x(3)分别存储u(k-1)和u(k-2),确保预测模型正确反映延迟影响。 - 约束MPC使用增量形式
Δu作为决策变量,幅值约束通过累积矩阵L转换为线性不等式约束。 - 无约束MPC直接使用解析解
du = -K_mpc·(F·x - r),避免了QP求解开销。