如何在Python GEKKO中定义依赖前时间步的斜坡约束?
在GEKKO MPC中实现斜坡约束的方法
对于MPC(IMODE=6)中的状态变量(SV)和操纵变量(MV)斜坡约束,直接通过m.Equation()定义硬约束即可,以下是具体实现方式和示例:
1. 状态变量的绝对值变化约束
状态变量满足|x(tk) - x(tk-1)| ≤ Cx,可拆分为两个线性不等式:
x(tk) - x(tk-1) ≤ Cxx(tk-1) - x(tk) ≤ Cx
在GEKKO中,遍历预测时域内的每个时间步(从第1步到最后一步),对每个状态变量添加上述约束。
2. 操纵变量的比例变化约束
操纵变量满足0.9 ≤ u(tk)/u(tk-1) ≤ 1.1,需确保u(tk-1)不为0(可通过设置MV的下限u.lower = 1e-3避免),拆分为:
u(tk) ≥ 0.9 * u(tk-1)u(tk) ≤ 1.1 * u(tk-1)
同样遍历预测时域内的时间步,添加约束。
完整示例代码
from gekko import GEKKO import numpy as np import matplotlib.pyplot as plt # 初始化模型 m = GEKKO(remote=False) m.time = np.linspace(0,10,11) # 预测时域:10秒,11个时间点 # 定义参数和常数 Cx = 0.5 # 状态变量的最大允许变化量 K = 1.0 # 系统增益 tau = 2.0 # 时间常数 # 状态变量(SV) x = m.SV(value=0, name='x') # 操纵变量(MV) u = m.MV(value=1, name='u') u.lower = 0.1 # 避免u为0,防止除法问题 u.STATUS = 1 # 允许优化调整u u.DCOST = 0.01 # 可选:添加小的变化惩罚,让控制更平滑 # 系统动态模型(一阶系统) m.Equation(tau*x.dt() == -x + K*u) # 目标:跟踪设定值(这里设为5) sp = m.Param(value=5, name='setpoint') m.Obj((x - sp)**2) # 添加状态变量的斜坡约束 for i in range(1, len(m.time)): m.Equation(x[i] - x[i-1] <= Cx) m.Equation(x[i-1] - x[i] <= Cx) # 添加操纵变量的比例约束 for i in range(1, len(m.time)): m.Equation(u[i] >= 0.9 * u[i-1]) m.Equation(u[i] <= 1.1 * u[i-1]) # 设置MPC模式 m.options.IMODE = 6 m.options.CV_TYPE = 2 m.options.NODES = 2 # 求解 m.solve(disp=True) # 绘图展示结果 plt.figure(figsize=(10,6)) plt.subplot(2,1,1) plt.plot(m.time, x.value, 'b-', label='状态变量x') plt.plot(m.time, sp.value, 'r--', label='设定值') plt.ylabel('x值') plt.legend() plt.grid(True) plt.subplot(2,1,2) plt.plot(m.time, u.value, 'g-', label='操纵变量u') plt.xlabel('时间 (s)') plt.ylabel('u值') plt.legend() plt.grid(True) plt.show()
关键说明
- 避免使用
DCOST:DCOST是对MV的变化量添加软惩罚,而非硬约束,无法严格限制变化范围。 - 时间步遍历:通过
range(1, len(m.time))遍历每个后续时间步,与前一时间步的变量值做约束。 - MV下限设置:必须确保MV不为0,否则比例约束会出现除以0的错误,可设置一个极小的下限如
0.1。
内容的提问来源于stack exchange,提问作者Nikola Gerov
相关产品推荐
相关产品推荐

