简体   繁体   English

如何使用 Gekko 求解可重复使用的再入飞行器的最优控制

[英]How to use Gekko to solve for optimal control for a reusable reentry vehicle

I am seeking to find optimal control (aoa and bank angle) to maximize cross range for a shuttle type reentry vehicle using Gekko.我正在寻找最佳控制(aoa 和坡度角),以最大化使用 Gekko 的穿梭型再入飞行器的横向范围。 Below is my code currently and I am getting a "Solution not found" with "EXIT: Maximum Number of Iterations Exceeded".下面是我目前的代码,我得到一个带有“退出:超过最大迭代次数”的“未找到解决方案”。 The simulation assumes a point mass with a non-rotating earth frame.模拟假设点质量具有非旋转地球框架。 The EOMS are 6 coupled, non-linear ODEs. EOMS 是 6 个耦合的非线性 ODE。 I have tried using different solvers, implementing/removing state and control constraints, increasing maximum number of iterations, etc. I am not confident with my setup and implementation of the problem in Gekko and am hoping for some feedback on what I can try next.我尝试使用不同的求解器,实现/删除 state 和控制约束,增加最大迭代次数等。我对我在 Gekko 中问题的设置和实现没有信心,并希望对我接下来可以尝试的问题提供一些反馈。 I have tried to follow the setup and layouts in APMonitor's Example 11. Optimal Control with Integral Objective , Inverted Pendulum Optimal Control , and Example 13. Optimal Control: Minimize Final Time .我尝试遵循APMonitor 的示例 11. Optimal Control with Integral ObjectiveInverted Pendulum Optimal Control示例 13. Optimal Control: Minimize Final Time中的设置和布局。 Solutions I'm seeking are below.我正在寻找的解决方案如下。

Any help is very much appreciated!很感谢任何形式的帮助!

from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
import math

pi = math.pi

########################
######FRONT MATTER######
########################
m = GEKKO() # initialize GEKKO
nt = 2501 #simulation time is 2500 seconds
tfin = 2500
m.time = np.linspace(0,tfin,nt) #time array

#==================#
#PARAMS
#==================#
Re  = m.Param(value = 6371203.92)           # radius of the earth, m
S   = m.Param(value = 249.9091776)          # vehicle surface area, m^2
cl0 = m.Param(value = -0.2070)              # coeff lift param 1
cl1 = m.Param(value = 1.6756)               # coeff lift param 2
cd0 = m.Param(value = 0.0785)               # coeff drag param 1
cd1 = m.Param(value = -0.3529)              # coeff drag param 2
cd2 = m.Param(value = 2.0400)               # coeff drag param 3
H   = m.Param(value = 7254.24)              # density scale height, m
rho0= m.Param(value = 1.225570827014494)    # sea level atmospheric density, kg/m^3
mu  = m.Param(value = 3.986031954093051e14) #earth gravitational param, m^3/s^2
mass= m.Param(value = 92079.2525560557)     #vehicle mass, kg

#===============================#
#BOUNDARY CONDITIONS
#===============================#
t0     = 0
alt0   = 79248
rad0   = alt0+Re
altf   = 24384
radf   = altf+Re
lon0   = 0
lat0   = 0
speed0 = +7802.88
speedf = +762
fpa0   = -1*pi/180
fpaf   = -5*pi/180
azi0   = +90*pi/180
azif   = -90*pi/180

#===============================#
#LIMITS ON VARIABLES
#===============================#
tfMin = 0;              tfMax = 3000;
radMin = Re;            radMax = rad0;
lonMin = -pi;           lonMax = -lonMin;
latMin = -70*pi/180;    latMax = -latMin;
speedMin = 10;          speedMax = 45000;
fpaMin = -80*pi/180;    fpaMax =  80*pi/180;
aziMin = -180*pi/180;   aziMax =  180*pi/180;
aoaMin = -90*pi/180;    aoaMax = -aoaMin;
bankMin = -90*pi/180;   bankMax =   1*pi/180;

#===============================#
#VARIABLES
#===============================#

#state variables and bounds
rad = m.Var(value=rad0, lb=radMin, ub=radMax)       # radius, m
lon = m.Var(value=lon0, lb=lonMin, ub=lonMax)       # longitude, rad
lat = m.Var(value=lat0, lb=latMin, ub=latMax)       # latitude, rad
vel = m.Var(value=speed0, lb=speedMin, ub=speedMax) # velocity, m/sec
fpa = m.Var(value=fpa0, lb=fpaMin, ub=fpaMax)       # flight path angle, rad
azi = m.Var(value=azi0, lb=aziMin, ub=aziMax)       # azimuth angle, rad

#control variables
aoa     = m.MV(value=-20, lb=aoaMin, ub=aoaMax)    # angle of attack, rad
aoa.STATUS = 1
aoa.DCOST = 1e-2
bank    = m.MV(value=0, lb=bankMin, ub=bankMax)    # bank angle, rad
bank.STATUS = 1
bank.DCOST = 1e-2

#===============================#
#INTERMEDIATE VARIABLES
#===============================#
altitude = m.Intermediate(rad - Re)
CD       = m.Intermediate(cd0+cd1*aoa+cd2*aoa**2)
rho      = m.Intermediate(rho0*m.exp(-altitude/H))
CL       = m.Intermediate(cl0+cl1*aoa)
q        = m.Intermediate(0.5*rho*vel**2)
D        = m.Intermediate(q*S*CD/mass)
L        = m.Intermediate(q*S*CL/mass)
gravity  = m.Intermediate(mu/rad**2)

#===============================#
#EOMS
#===============================#

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

m.Equation(rad.dt() == vel*m.sin(fpa))
m.Equation((rad*m.cos(lat))*lon.dt() == vel*m.cos(fpa)*m.sin(azi))
m.Equation(rad*lat.dt() == vel*m.cos(fpa)*m.cos(azi))
m.Equation(vel.dt() == -D-gravity*m.sin(fpa))
m.Equation(vel*fpa.dt() == (L*m.cos(bank)-m.cos(fpa)*(gravity-vel**2/rad)))
m.Equation(vel*azi.dt() == (L*m.sin(bank)/m.cos(fpa)+vel**2*m.cos(fpa)*m.sin(azi)*m.tan(lat)/rad))

#===============================#
#OPTIMIZATION SOLVER
#===============================#
m.Obj(-lat*final)


# m.options.SOLVER = 3
# m.options.IMODE = 6
# m.solve(disp=True)

m.options.MAX_ITER = 500
m.options.IMODE = 6
# m.options.NODES = 3
# m.options.MV_TYPE = 1
m.options.SOLVER = 3
# m.open_folder()
m.solve()

The solution should look something like this for altitude, velocity, AOA and bank angle: Altitude Velocity AngleofAttack Bank高度、速度、迎角和坡度角的解决方案应该是这样的: Altitude Velocity AngleofAttack Bank

I got a successful solution by decreasing the final time (max=0.04 for successful solution) and rearranging the equations to avoid a possible divide-by-zero:我通过减少最终时间(成功解决方案最大 = 0.04)并重新排列方程以避免可能的被零除来获得成功的解决方案:

m.Equation(rad.dt() == vel*m.sin(fpa))
m.Equation((rad*m.cos(lat))*lon.dt() == vel*m.cos(fpa)*m.sin(azi))
m.Equation(rad*lat.dt() == vel*m.cos(fpa)*m.cos(azi))
m.Equation(vel.dt() == -D-gravity*m.sin(fpa))
m.Equation(vel*fpa.dt() == (L*m.cos(bank)-m.cos(fpa)*(gravity-vel**2/rad)))
m.Equation(m.cos(fpa)*rad*vel*azi.dt() == \
           (L*m.sin(bank)*rad+vel**2*(m.cos(fpa))**2*m.sin(azi)*m.tan(lat)))

Starting with a small time period and observing the states can help to troubleshoot the model.从一小段时间开始并观察状态有助于对 model 进行故障排除。

图表

from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
import math

pi = math.pi

########################
######FRONT MATTER######
########################
m = GEKKO() # initialize GEKKO
nt = 101 # 2501 #simulation time is 2500 seconds
tfin = 0.04
m.time = np.linspace(0,tfin,nt) #time array

#==================#
#PARAMS
#==================#
Re  = m.Param(value = 6371203.92)           # radius of the earth, m
S   = m.Param(value = 249.9091776)          # vehicle surface area, m^2
cl0 = m.Param(value = -0.2070)              # coeff lift param 1
cl1 = m.Param(value = 1.6756)               # coeff lift param 2
cd0 = m.Param(value = 0.0785)               # coeff drag param 1
cd1 = m.Param(value = -0.3529)              # coeff drag param 2
cd2 = m.Param(value = 2.0400)               # coeff drag param 3
H   = m.Param(value = 7254.24)              # density scale height, m
rho0= m.Param(value = 1.225570827014494)    # sea level atmospheric density, kg/m^3
mu  = m.Param(value = 3.986031954093051e14) #earth gravitational param, m^3/s^2
mass= m.Param(value = 92079.2525560557)     #vehicle mass, kg

#===============================#
#BOUNDARY CONDITIONS
#===============================#
t0     = 0
alt0   = 79248
rad0   = alt0+Re
altf   = 24384
radf   = altf+Re
lon0   = 0
lat0   = 0
speed0 = +7802.88
speedf = +762
fpa0   = -1*pi/180
fpaf   = -5*pi/180
azi0   = +90*pi/180
azif   = -90*pi/180

#===============================#
#LIMITS ON VARIABLES
#===============================#
tfMin = 0;              tfMax = 3000;
radMin = Re;            radMax = rad0;
lonMin = -pi;           lonMax = -lonMin;
latMin = -70*pi/180;    latMax = -latMin;
speedMin = 10;          speedMax = 45000;
fpaMin = -80*pi/180;    fpaMax =  80*pi/180;
aziMin = -180*pi/180;   aziMax =  180*pi/180;
aoaMin = -90*pi/180;    aoaMax = -aoaMin;
bankMin = -90*pi/180;   bankMax =   1*pi/180;

#===============================#
#VARIABLES
#===============================#

#state variables and bounds
rad = m.Var(value=rad0, lb=radMin, ub=radMax)       # radius, m
lon = m.Var(value=lon0, lb=lonMin, ub=lonMax)       # longitude, rad
lat = m.Var(value=lat0, lb=latMin, ub=latMax)       # latitude, rad
vel = m.Var(value=speed0, lb=speedMin, ub=speedMax) # velocity, m/sec
fpa = m.Var(value=fpa0, lb=fpaMin, ub=fpaMax)       # flight path angle, rad
azi = m.Var(value=azi0, lb=aziMin, ub=aziMax)       # azimuth angle, rad

#control variables
aoa     = m.MV(value=-20, lb=aoaMin, ub=aoaMax)    # angle of attack, rad
aoa.STATUS = 1
bank    = m.MV(value=0, lb=bankMin, ub=bankMax)    # bank angle, rad
bank.STATUS = 1

#===============================#
#INTERMEDIATE VARIABLES
#===============================#
altitude = rad - Re
CD       = cd0+cd1*aoa+cd2*aoa**2
rho      = rho0*m.exp(-altitude/H)
CL       = cl0+cl1*aoa
q        = 0.5*rho*vel**2
D        = q*S*CD/mass
L        = q*S*CL/mass
gravity  = mu/rad**2

#===============================#
#EOMS
#===============================#

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

m.Equation(rad.dt() == vel*m.sin(fpa))
m.Equation((rad*m.cos(lat))*lon.dt() == vel*m.cos(fpa)*m.sin(azi))
m.Equation(rad*lat.dt() == vel*m.cos(fpa)*m.cos(azi))
m.Equation(vel.dt() == -D-gravity*m.sin(fpa))
m.Equation(vel*fpa.dt() == (L*m.cos(bank)-m.cos(fpa)*(gravity-vel**2/rad)))
m.Equation(m.cos(fpa)*rad*vel*azi.dt() == \
           (L*m.sin(bank)*rad+vel**2*(m.cos(fpa))**2*m.sin(azi)*m.tan(lat)))

#===============================#
#OPTIMIZATION SOLVER
#===============================#
m.Maximize(lat*final)
m.options.SOLVER = 3
m.options.IMODE = 6
m.solve(disp=True)

plt.subplot(4,2,1)
plt.plot(m.time,rad.value,label='rad')
plt.legend()
plt.subplot(4,2,2)
plt.plot(m.time,lon.value,label='lon')
plt.legend()
plt.subplot(4,2,3)
plt.plot(m.time,lat.value,label='lat')
plt.legend()
plt.subplot(4,2,4)
plt.plot(m.time,vel.value,label='vel')
plt.legend()
plt.subplot(4,2,5)
plt.plot(m.time,fpa.value,label='fpa')
plt.legend()
plt.subplot(4,2,6)
plt.plot(m.time,azi.value,label='azi')
plt.legend()
plt.subplot(4,2,7)
plt.plot(m.time,aoa.value,label='aoa')
plt.xlabel('Time')
plt.legend()
plt.subplot(4,2,8)
plt.plot(m.time,bank.value,label='bank')
plt.xlabel('Time')
plt.legend()
plt.show()

A suggestion is to turn off the degrees of freedom to verify the solution ( STATUS=0 ) with smaller time horizons.一个建议是关闭自由度以验证具有较小时间范围的解决方案 ( STATUS=0 )。 Additional constraints may also be needed to keep the trigonometric functions in the -2 pi to 2 pi region.可能还需要额外的约束来将三角函数保持在 -2 pi 到 2 pi 区域。 There is additional information on initializing challenging problems:还有关于初始化具有挑战性的问题的其他信息:

Success.. Thank you for your feedback and pointers @John Hedengren.成功.. 感谢您的反馈和指点@John Hedengren。 After incorporating what I learned here and reinstating the bounds on the states I was able successfully use Gekko to produce an answer consistent with previous solutions.在结合了我在这里学到的知识并恢复了状态的界限之后,我能够成功地使用 Gekko 产生与以前的解决方案一致的答案。 Very excited about Gekko and the potential here!对 Gekko 和这里的潜力感到非常兴奋!

穿梭型车辆再入状态与控制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM