3. 积分过程MPC抗扰动控制
任务目标
针对含积分环节的过程对象,设计模型预测控制器(MPC),在输出端施加阶跃扰动后,验证系统输出能够无静差地跟踪设定值。积分过程本身包含一个位于原点的极点,常规MPC若采用输出偏差模型,对非持续性扰动(如阶跃扰动)存在静差;本案例通过构造增量型状态空间模型,使控制器内嵌积分作用,从而实现对阶跃扰动的完全抑制。
过程模型与控制器设计
被控对象为积分过程,传递函数为:
G(s) = 1 / (s(s+1))
离散化后(采样时间 Ts=0.2s)得到状态空间模型。MPC控制器采用增量型状态空间描述,将控制增量 Δu(k) 作为决策变量,并将输出偏差 e(k)=y(k)-r(k) 增广到状态向量中,形成如下增广模型:
x(k+1) = A_a x(k) + B_a Δu(k)
e(k) = C_a x(k)
其中增广状态包含原过程状态与输出偏差。由于模型内部包含积分环节(偏差的累加),控制器天然具备积分作用,可消除阶跃扰动引起的稳态误差。预测时域 Np=10,控制时域 Nc=3,权重矩阵 Q=1(输出偏差),R=0.1(控制增量)。
完整实现代码
import numpy as np
from scipy.linalg import solve_discrete_are
import matplotlib.pyplot as plt
# 连续时间状态空间模型: G(s)=1/(s(s+1))
# dx = Ax + Bu, y = Cx
A_c = np.array([[0, 1], [0, -1]])
B_c = np.array([[0], [1]])
C_c = np.array([[1, 0]])
D_c = np.array([[0]])
# 离散化 (Ts=0.2s)
Ts = 0.2
n = A_c.shape[0]
# 使用零阶保持离散化
A_d = np.eye(n) + A_c * Ts + (A_c @ A_c) * Ts**2 / 2
B_d = (np.eye(n) * Ts + A_c * Ts**2 / 2) @ B_c
C_d = C_c
# 增广模型: 状态 [x(k); e(k)], e(k)=y(k)-r(k)
# x(k+1) = A_d x(k) + B_d Δu(k)
# e(k+1) = e(k) + C_d A_d x(k) + C_d B_d Δu(k) - Δr(k+1)
# 设定值恒定, Δr=0
A_a = np.zeros((n+1, n+1))
A_a[:n, :n] = A_d
A_a[n, :n] = C_d @ A_d
A_a[n, n] = 1.0
B_a = np.zeros((n+1, 1))
B_a[:n, :] = B_d
B_a[n, :] = C_d @ B_d
C_a = np.zeros((1, n+1))
C_a[0, n] = 1.0 # 输出为偏差 e(k)
# MPC 参数
Np = 10 # 预测时域
Nc = 3 # 控制时域
Q = 1.0 # 偏差权重
R = 0.1 # 控制增量权重
# 构建预测矩阵
# 预测模型: X = F x(k) + G ΔU
F = np.zeros((Np, n+1))
G = np.zeros((Np, Nc))
for i in range(Np):
F[i] = C_a @ np.linalg.matrix_power(A_a, i+1)
for j in range(min(i+1, Nc)):
G[i, j] = C_a @ np.linalg.matrix_power(A_a, i-j) @ B_a
# 权重矩阵
Q_bar = np.eye(Np) * Q
R_bar = np.eye(Nc) * R
# 无约束MPC增益 (若需约束可在此扩展)
H = G.T @ Q_bar @ G + R_bar
H_inv = np.linalg.inv(H)
K_mpc = H_inv @ G.T @ Q_bar @ F
# 仿真参数
T_total = 20.0
N_steps = int(T_total / Ts)
t = np.arange(0, T_total, Ts)
# 初始化
x = np.zeros((n+1, 1)) # 增广状态
x[0, 0] = 0.0 # 初始位置
x[1, 0] = 0.0 # 初始速度
x[2, 0] = 0.0 # 初始偏差
u = 0.0
y_history = []
u_history = []
r_history = []
# 设定值
r = 1.0
# 阶跃扰动: 在 t=10s 时加入输出扰动 d=0.5
d = 0.0
for k in range(N_steps):
# 当前输出
y = C_d @ x[:n] + d
y_history.append(y[0])
u_history.append(u)
r_history.append(r)
# 更新偏差
x[n, 0] = y[0] - r
# 计算控制增量
delta_u = -K_mpc @ x
delta_u_val = delta_u[0, 0]
# 施加控制
u = u + delta_u_val
u = np.clip(u, -5, 5) # 控制量限幅
# 状态更新 (使用真实过程, 不含扰动)
x_next = A_d @ x[:n] + B_d * u
x[:n] = x_next
# 在 t=10s 时加入阶跃扰动
if abs(t[k] - 10.0) < 1e-6:
d = 0.5
# 绘图
plt.figure(figsize=(10, 6))
plt.subplot(2, 1, 1)
plt.plot(t, y_history, 'b-', linewidth=2, label='输出 y')
plt.plot(t, r_history, 'r--', linewidth=2, label='设定值 r')
plt.axvline(x=10.0, color='gray', linestyle=':', label='扰动加入时刻')
plt.ylabel('输出')
plt.legend()
plt.grid(True)
plt.subplot(2, 1, 2)
plt.plot(t, u_history, 'g-', linewidth=2, label='控制量 u')
plt.ylabel('控制量')
plt.xlabel('时间 (s)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# 验证静差: 计算最后5秒的平均误差
steady_idx = int(15.0 / Ts)
steady_error = np.mean([abs(y_history[i] - r) for i in range(steady_idx, N_steps)])
print(f"稳态误差 (15s-20s 平均): {steady_error:.6f}")
运行与验证
运行方式:直接执行上述Python脚本。需要安装 numpy、scipy、matplotlib。
验证方法:
- 观察第一幅图:输出曲线在约2s内首次到达设定值1.0,在t=10s处受到阶跃扰动后短暂偏离,随后在约2s内重新收敛到设定值。
- 观察第二幅图:控制量在扰动后自动调整以抵消扰动影响。
- 控制台输出的稳态误差应接近0(小于0.001即视为无静差)。
通过条件:稳态误差小于0.001,且输出曲线在扰动后能恢复到设定值附近(偏差小于1%)。
关键说明
本案例的核心在于增广状态模型中的偏差积分项。当输出受到阶跃扰动时,偏差e(k)被纳入状态向量并参与预测,MPC优化会持续调整控制增量直到偏差归零。由于模型预测中包含了偏差的累积效应,控制器等效于在回路中嵌入积分器,因此对阶跃扰动具有完全抑制能力。若改用普通输出模型(不含偏差积分),阶跃扰动将导致永久静差。