微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Gekko 最优控制如何创建多个终止目标/条件?

如何解决Gekko 最优控制如何创建多个终止目标/条件?

所以我正在模拟飞机飞行。飞机飞行一定距离(pathxpathy 变量),然后当达到某些 pathxpathy 值时,模拟停止。求解器试图通过最大化质量值来最小化燃料消耗 (m.Maximize(mass*tf*final)。求解器控制加速踏板位置 (Tcontr)。

现在终止条件定义如下:

对于 X 轴:

m.Equation(x*final<=pathx)

m.Minimize(final*(x-pathx)**2)

对于 Y 轴:

m.Equation(y*final<=pathy)

m.Minimize(final*(y-pathy)**2)

现在,当达到所需的 X 值而未达到所需的 Y 值时,模拟结束。

如何在达到所需的(X 和 Y)值时强制结束模拟?

我的代码

import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
import math
#Gekko model
m = GEKKO(remote=False)

#Time points
nt = 11
tm =  np.linspace(0,100,nt)
m.time = tm

# Variables
Ro = m.Var(value=1.1)#air density
g = m.Const(value=9.80665)
pressure = m.Var(value=101325)#
T = m.Var(value=281,lb=100)#temperature
T0 = m.Const(value=288)#temperature at see level
S = m.Const(value=122.6)
Cd = m.Const(value=0.1)#drag coef
Cl = m.Var(value=1)#lift couef
FuelFlow = m.Var()
D = m.Var(value=25000,lb=0)#drag
Thrmax = m.Const(value=200000)#maximum throttle
Thr = m.Var()#throttle
V = m.Var(value=100,lb=50,ub=240)#veLocity
gamma = m.Var(value=0)# Flight-path angle
gammaa = gamma.value
Xi = m.Var(value=0)# heading angle
Xii = Xi.value
x = m.Var(value=0,lb=0)#x position
y = m.Var(value=0,lb=0)#y position
h = m.Var(value=1000,lb=0)# height
mass = m.Var(value=60000,lb=10000)
pathx = m.Const(value=50000) #intended distance length
pathy = m.Const(value=50000)
L = m.Var(value=0.1)#lift

p = np.zeros(nt)
p[-1] = 1.0
final = m.Param(value=p)

m.options.MAX_ITER=10000 # iteration number

#Fixed Variable
tf = m.FV(value=1,lb=0.0001,ub=1000.0)#
tf.STATUS = 1

# Controlled parameters
Tcontr = m.MV(value=0.2,lb=0.1,ub=1)# solver controls throttle pedal position
Tcontr.STATUS = 1
Tcontr.dcosT = 0

#Mu = m.Var(value=0)
Mu = m.MV(value=0,lb=-1.5,ub=1.5)# solver controls bank angle 
Mu.STATUS = 1
Mu.dcosT = 0

Muu = Mu.value

# Equations
m.Equation(Thr==Tcontr*Thrmax)
m.Equation(FuelFlow==0.75882*(1+(V/2938.5)))
m.Equation(D==0.5*Ro*(V**2)*Cd*S)
m.Equation(mass.dt()==tf*(-Thr*(FuelFlow/60000)))#
m.Equation(V.dt()==tf*((Thr-D)/mass))#
m.Equation(x.dt()==tf*(V*(math.cos(gammaa.value))*(math.cos(Xii.value))))#
m.Equation(x*final<=pathx)
#pressure and density part
m.Equation(T==T0-(0.0065*h))
m.Equation(pressure==101325*(1-(0.0065*h)/T0)**((g*0.0289652)/(8.31446*0.0065)))#
m.Equation(Ro*(8.31446*T)==(pressure*0.0289652))
#2D addition part
m.Equation(L==0.5*Ro*(V**2)*Cl*S)
m.Equation(Xi.dt()==tf*((L*math.sin(Muu.value))/(mass*V)))
m.Equation(y.dt()==tf*(V*(math.cos(gammaa.value))*(math.sin(Xii.value))))#
m.Equation(y*final<=pathy)

# Objective Function
m.Minimize(final*(x-pathx)**2) #1D part
m.Minimize(final*(y-pathy)**2) #2D part
m.Maximize(mass*tf*final) #objective function
m.options.IMODE = 6
m.options.NODES = 2 # it was 3 before
m.options.MV_TYPE = 1
m.options.soLVER = 3
#m.open_folder() # to search for infeasibilities
m.solve()

tm = tm * tf.value[0]
    
fig,axs = plt.subplots(8)
fig.suptitle('Results')
axs[0].plot(tm,Tcontr,'r-',linewidth=2,label=r'$Tcontr$')
axs[0].legend(loc='best')
axs[1].plot(tm,V.value,'b-',label=r'$V$')
axs[1].legend(loc='best')
axs[2].plot(tm,x.value,'r--',label=r'$x$')
axs[2].legend(loc='best')
axs[3].plot(tm,D.value,'g-',label=r'$D$')
axs[3].legend(loc='best')
axs[4].plot(tm,mass.value,'g:',label=r'$mass$')
axs[4].legend(loc='best')
axs[5].plot(tm,T.value,'p-',label=r'$T$')
axs[5].legend(loc='best')
axs[6].plot(tm,Mu.value,label=r'$Mu$')
axs[6].legend(loc='best')
axs[7].plot(tm,y.value,label=r'$y$')
axs[7].legend(loc='best')
plt.xlabel('Time')
#plt.ylabel('Value')
plt.show()

重要更新

看起来终止条件(以上所有内容)都按预期工作。无法达到 Y 轴值,因为看起来涉及它的数学运算不正常。

Y 值由以下等式计算:

enter image description here

我变成了这个:m.Equation(y.dt()==tf*(V*(math.cos(gammaa.value))*(math.sin(Xii.value))))

其中:V 是真实空速(正常工作);

tf 是控制模拟时间的变量(正常工作);

gammaa 衍生自 gamma,即飞行路径角,在本次模拟中为 0(正常工作);

Xii 派生自 Xi,即航向角(罪魁祸首)。

Xi 值由以下等式定义:

enter image description here

我把它变成了这样:m.Equation(Xi.dt()==tf*((L*math.sin(Muu.value))/(mass*V)))

其中:L 是升力(正常工作);

mass 是质量(正常工作);

V 是真实的空气速度(正常工作);

Muu 源自 Mu,即坡度角,求解器控制变量(可能是这里的坏苹果)。

Y 值计算应该是这样工作的:求解器更改 Mu,这会影响航向角 Xi,然后应该会影响 Y 值。

经过一些实验,看起来模拟过程中Mu值的变化范围很小,几乎不影响Y值。但它应该更宽,因为 Mu 边界非常宽 (lb=-1.5,ub=1.5)。我试图去除这些边界,但它并没有影响模拟的结果。

是什么把这里的一切搞砸了?

解决方法

尝试为两者添加硬终端约束:

m.Equation((x-pathx)*final==0)
m.Equation((y-pathy)*final==0)

或者,增加终端条件的权重。

w = 1e3
m.Minimize(w*final*(x-pathx)**2) #1D part
m.Minimize(w*final*(y-pathy)**2) #2D part

您可能需要使用一种或两种策略。解决终端条件可能具有挑战性。

对重要更新的回应

将 Gekko 函数与 m.sin()m.cos() 一起使用,而不是 math 函数。另外,不要在方程中使用 .value。 Gekko 需要完整的符号图,以便它可以将方程编译为字节码并生成函数评估和自动微分的导数。

m.Equation(y.dt()==tf*(V*(m.cos(gammaa))*(m.sin(Xii))))

通过将任何分母相乘到另一侧也有助于避免被零除。

m.Equation(mass*V*Xi.dt()==tf*((L*m.sin(Muu))))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。