用于 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=0
到 t=50
范围内的数据,但它访问 t=-10
到 t=40
范围内的值。错误是由于三次样条的外推。您可以生成 t=-theta_ub
到 t=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()
为了使用 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=0
到 t=50
范围内的数据,但它访问 t=-10
到 t=40
范围内的值。错误是由于三次样条的外推。您可以生成 t=-theta_ub
到 t=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()