用于 FOPDT 模型(死区时间)仿真的 Gekko cspline 函数

Gekko cspline function for FOPDT model (Dead-time) simulation

为了使用 GEKKO 包模拟 FOPDT 模型中的死区时间,我使用了 Gekko 'cspline' 函数来使时移操作更加平滑。
当输入在死区时间长度后发生变化时,它会很好地工作。 (例如,当死区时间 = 10 时,输入在 t = 15 时发生变化)

但是,当输入在死区时间长度之前发生变化时(例如,当死区时间=10 时,输入在 t=5 处发生变化),看起来 cspline 函数过度外推了输入值。请给出一些建议来避免这个问题。

from gekko import GEKKO
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

tf = 50 
npt = 51 
t = np.linspace(0,tf,npt)
u1 = np.zeros(npt)
u1[5:] = 5

m = GEKKO(remote=True)
m.time = t 
time = m.Var(0)
m.Equation(time.dt()==1)

K1 = m.FV(1,lb=0,ub=1);      K1.STATUS=1
tau1 = m.FV(5, lb=1,ub=300);  tau1.STATUS=1
theta1 = m.FV(10, lb=2,ub=30); theta1.STATUS=1

uc1 = m.Var(u1) 
tc1 = m.Var(t) 
m.Equation(tc1==time-theta1)
m.cspline(tc1,uc1,t,u1,bound_x=False)

yp1 = m.Var()
m.Equation(yp1.dt() == -yp1/tau1 + K1*uc1/tau1) 

m.options.IMODE=4
m.solve()

print('K1: ', K1.value[0])
print('tau1: ',  tau1.value[0])
print('theta1: ', theta1.value[0])
print('')

plt.figure()
plt.subplot(2,1,1)
plt.plot(t,u1)
plt.legend([r'u1'])
plt.ylabel('Input')
plt.subplot(2,1,2)
plt.plot(t,yp1)
plt.legend([r'y1'])
plt.ylabel('Output')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()

cspline 对象被赋予 t=0t=50 范围内的数据,但它访问 t=-10t=40 范围内的值。错误是由于三次样条的外推。您可以生成 t=-theta_ubt=50 范围内的样条数据以避免外推问题。

from gekko import GEKKO
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

theta_ub = 30
tf = 50

m = GEKKO(remote=True)
m.time = np.linspace(0,tf,tf+1)
time = m.Param(m.time)

K1 = m.FV(1,lb=0,ub=1)
tau1 = m.FV(5,lb=1,ub=300)
theta1 = m.FV(10,lb=2,ub=theta_ub)

u_step = [0 if ti<=5 else 5 for ti in m.time]
uc1 = m.Var() 
tc1 = m.Var()
m.Equation(tc1==time-theta1)

# for cspline
t1 = np.linspace(-theta_ub,tf,500)
u1 = [0 if ti<=5 else 5 for ti in t1]
m.cspline(tc1,uc1,t1,u1,bound_x=False)

yp1 = m.Var()
m.Equation(tau1*yp1.dt()+yp1==K1*uc1) 

m.options.IMODE=4
m.solve()

print('K1: ', K1.value[0])
print('tau1: ',  tau1.value[0])
print('theta1: ', theta1.value[0])
print('')

plt.figure()
plt.subplot(2,1,1)
plt.plot(t1,u1,label='Unshifted Input')
plt.plot(m.time,uc1,label='Shifted Spline')
plt.xlim([0,tf])
plt.legend()
plt.ylabel('Input')
plt.subplot(2,1,2)
plt.plot(m.time,yp1)
plt.legend([r'y1'])
plt.ylabel('Output')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()