基于Gekko的一维飞机飞行最优控制问题求解失败求助
解决Gekko最优控制问题中“Solution Not Found”的问题
我帮你排查了代码里的几个关键问题,这些应该是导致优化器找不到解的核心原因,下面一步步拆解修正:
1. 修复低级语法错误
你代码里Cd = value=0.1这行是明显的语法错误,直接改成常量或者Gekko参数即可:
Cd = 0.1 # 如果后续需要调整这个值,也可以用 m.Param(value=0.1)
2. 修正FuelFlow的变量类型
FuelFlow应该是**参数(Param)**而不是变量(Var)——燃油流量是固定的消耗系数,不是优化过程中需要求解的变量,改成参数后优化器的求解逻辑会更清晰:
FuelFlow = m.Param(value=0.7)
3. 补充缺失的初始条件
变量V(速度)没有设置初始值,优化器需要明确的初始状态才能启动迭代,给它一个合理的初始值,比如:
V = m.Var(value=0) # 初始速度设为0,也可以根据实际场景调整
4. 改进终端约束的写法
用final*x==1000约束终端位置虽然可行,但Gekko提供了更直观且易被优化器识别的终端约束方式,直接固定x在最终时刻的值:
# 替换原来的 final*x==1000 这行 m.fix(x, pos=nt-1, val=1000)
另外你原来设置的时间区间是0到100秒,可以先尝试缩短时间(比如改成0到50秒),确保飞机能在规定时间内完成1000米飞行,避免因时间冗余或不足导致无解。
5. 可选:调整优化器参数
如果还是无解,可以给IPOPT优化器增加最大迭代次数、放松收敛阈值,帮助它找到可行解:
m.options.MAX_ITER = 1000 m.options.RTOL = 1e-6 m.options.ATOL = 1e-6
修正后的完整代码
import numpy as np import matplotlib.pyplot as plt from gekko import GEKKO import math # Gekko model m = GEKKO(remote=False) # Time points - 先尝试缩短时间,确保可行性 nt = 101 m.time = np.linspace(0, 50, nt) # Parameters Tcontr = m.MV(value=0.5, lb=0.3, ub=1) # throttle pedal position Tcontr.STATUS = 1 Tcontr.DCOST = 0.1 # 增加一点DCOST,避免油门频繁突变(可选优化) # Constants/Parameters Ro = 1.1 # air density S = 122.6 Cd = 0.1 # 修复语法错误 FuelFlow = m.Param(value=0.7) # 改为Param类型 Thrmax = 200000 # maximum theoretical throttle # Variables - 补充V的初始值 Thr = m.Var() # real throttle V = m.Var(value=0) # Velocity,初始速度设为0 x = m.Var(value=0) mass = m.Var(value=60000) D = m.Var() # drag p = np.zeros(nt) p[-1] = 1.0 final = m.Param(value=p) # Equations m.Equation(x.dt() == V) m.Equation(Thr == Tcontr * Thrmax) # Throttle m.Equation(V.dt() == (Thr - D) / mass) m.Equation(mass.dt() == -Thr * FuelFlow) m.Equation(D == 0.5 * Ro * (V**2) * Cd * S) # Drag # 改进终端约束写法 m.fix(x, pos=nt-1, val=1000) # Objective Function: 最大化最终质量(等价于最小化燃油消耗) m.Obj(-mass * final) # 优化器设置 m.options.IMODE = 6 m.options.NODES = 2 m.options.MV_TYPE = 1 m.options.SOLVER = 3 # 可选:增加迭代次数,提升求解成功率 m.options.MAX_ITER = 1000 m.open_folder() m.solve(disp=True) # 打开disp=True,查看求解过程输出,方便进一步排查 # 绘图查看结果 plt.figure(figsize=(12,8)) plt.subplot(311) plt.plot(m.time, x.value, 'b-', label='Position (x)') plt.ylabel('x (m)') plt.legend() plt.subplot(312) plt.plot(m.time, V.value, 'r-', label='Velocity (V)') plt.ylabel('V (m/s)') plt.legend() plt.subplot(313) plt.plot(m.time, mass.value, 'g-', label='Mass') plt.plot(m.time, Tcontr.value, 'k--', label='Throttle') plt.xlabel('Time (s)') plt.ylabel('Mass (kg) / Throttle') plt.legend() plt.show()
额外排查建议
如果还是无解,打开disp=True查看求解过程的输出,IPOPT会给出具体的错误提示:
- 检查油门上下限是否合理:
lb=0.3是否限制了飞机的加速能力?如果初始阶段需要更大油门才能在规定时间内飞到1000米,可以尝试降低下限。 - 验证参数量级匹配性:比如Thrmax是200000N,mass是60000kg,初始加速度为
(0.3*200000)/60000=1 m/s²,这个加速度足够在50秒内完成1000米飞行(匀加速下x=0.5150²=1250米),所以参数量级是合理的。
内容的提问来源于stack exchange,提问作者Tom Blums
相关产品推荐
相关产品推荐

