4. MPC模型失配鲁棒性
任务目标
本案例研究模型参数失配时MPC的控制性能退化问题。给定标称模型与实际被控对象之间存在参数偏差,要求通过调节权重矩阵和预测/控制时域,使闭环系统在模型失配下仍保持稳定并满足输出约束。
问题设定
标称二阶系统(用于MPC内部预测模型):
G_nom(s) = 1 / (s² + 1.2s + 1)
实际被控对象(模拟失配):
G_act(s) = 1.3 / (s² + 0.8s + 0.9)
失配体现在:增益+30%,阻尼比降低,自然频率降低。采样时间Ts=0.1s,输出约束 |y|≤1.5,控制量约束 |u|≤2.0。
实现代码(Python + NumPy)
import numpy as np
from scipy.signal import c2d, lsim
# 标称模型(预测模型)
A_nom = np.array([[0, 1], [-1, -1.2]])
B_nom = np.array([[0], [1]])
C_nom = np.array([[1, 0]])
D_nom = np.array([[0]])
# 实际对象(失配模型)
A_act = np.array([[0, 1], [-0.9, -0.8]])
B_act = np.array([[0], [1.3]])
C_act = np.array([[1, 0]])
D_act = np.array([[0]])
# 离散化
Ts = 0.1
Ad_nom, Bd_nom, Cd_nom, Dd_nom, _ = c2d(
(A_nom, B_nom, C_nom, D_nom), Ts, method='zoh')
Ad_act, Bd_act, Cd_act, Dd_act, _ = c2d(
(A_act, B_act, C_act, D_act), Ts, method='zoh')
# 增广状态(积分器消除稳态误差)
def augment(Ad, Bd, Cd):
n = Ad.shape[0]
A_aug = np.block([[Ad, np.zeros((n, 1))],
[Cd @ Ad, np.eye(1)]])
B_aug = np.block([[Bd], [Cd @ Bd]])
return A_aug, B_aug
A_n, B_n = augment(Ad_nom, Bd_nom, Cd_nom)
A_a, B_a = augment(Ad_act, Bd_act, Cd_act)
# MPC参数
Np = 15 # 预测时域
Nc = 3 # 控制时域
Q = np.diag([1.0, 1.0, 10.0]) # 状态权重(含积分状态)
R = 0.1 # 控制权重
# 构建预测矩阵
n_aug = A_n.shape[0]
Phi = np.zeros((Np * n_aug, n_aug))
Gamma = np.zeros((Np * n_aug, Nc))
for i in range(Np):
Phi[i*n_aug:(i+1)*n_aug, :] = np.linalg.matrix_power(A_n, i+1)
for j in range(min(i+1, Nc)):
Gamma[i*n_aug:(i+1)*n_aug, j:j+1] = (
np.linalg.matrix_power(A_n, i-j) @ B_n)
# 输出矩阵(取第一个状态)
H = np.zeros((Np, Np * n_aug))
for i in range(Np):
H[i, i*n_aug] = 1.0
# 二次规划矩阵
H_qp = 2 * (Gamma.T @ np.kron(np.eye(Np), Q) @ Gamma + R * np.eye(Nc))
f_qp = lambda x: 2 * Gamma.T @ np.kron(np.eye(Np), Q) @ (Phi @ x)
# 约束:|u|≤2, |y|≤1.5
A_ineq = np.vstack([np.eye(Nc), -np.eye(Nc)])
b_ineq = np.ones(2*Nc) * 2.0
A_y = np.zeros((2*Np, Nc))
b_y = np.ones(2*Np) * 1.5
for i in range(Np):
A_y[i, :] = H[i, :] @ Gamma
A_y[Np+i, :] = -H[i, :] @ Gamma
A_ineq = np.vstack([A_ineq, A_y])
b_ineq = np.concatenate([b_ineq, b_y])
# 仿真
def run_mpc(A_plant, B_plant, Nsim=100, x0=np.array([0, 0, 0])):
x = x0.copy()
u_hist, y_hist = [], []
for _ in range(Nsim):
# 求解QP(使用拉格朗日法简化,实际可用quadprog)
xk = x.copy()
f = f_qp(xk)
# 简化:忽略约束求解(演示用)
du = -np.linalg.solve(H_qp, f)
u = du[0]
# 实际对象更新
x_plant = x[:2]
x_plant = A_plant @ x_plant + B_plant.flatten() * u
y = C_act @ x_plant
# 增广状态更新
x = np.concatenate([x_plant, [x[2] + (1.0 - y[0])]])
u_hist.append(u)
y_hist.append(y[0])
return np.array(u_hist), np.array(y_hist)
# 执行仿真(标称 vs 失配)
u_nom, y_nom = run_mpc(Ad_nom, Bd_nom)
u_act, y_act = run_mpc(Ad_act, Bd_act)
# 输出关键指标
print(f"标称模型最大输出: {np.max(np.abs(y_nom)):.3f}")
print(f"失配模型最大输出: {np.max(np.abs(y_act)):.3f}")
print(f"失配模型最大控制: {np.max(np.abs(u_act)):.3f}")
运行方式
pip install numpy scipy
python mpc_robustness.py
验证方法与判定标准
运行脚本后观察:
- 标称模型输出应收敛至1.0(单位阶跃跟踪),无超调超过1.5约束;
- 失配模型若出现输出超调超过1.5或振荡发散,说明当前权重/时域参数鲁棒性不足;
- 调整Np(增大至20~30)、Nc(减小至2)或增大Q中积分项权重(至20~50),重新运行,直到失配模型输出满足|y|≤1.5且稳态误差小于5%。
通过条件:失配模型在调整参数后输出约束满足、稳态误差≤5%,且控制量未持续饱和。
关键说明
本案例代码为教学演示,QP求解采用无约束解析解(忽略约束),实际工程需接入quadprog或cvxpy求解约束QP。约束处理仅展示构建方法,完整约束MPC需替换求解器。参数调整方向:增大Np提升鲁棒性但增加计算量;增大积分权重加快消除稳态误差但可能降低稳定性裕度。