openai-gym 的 LunarLander 模拟自杀烧伤

Simulation of suicide burn in openai-gym's LunarLander

我想模拟suicide burn来学习和理解火箭着陆。 OpenAI gym 已经有一个 LunarLander 环境,用于训练强化学习代理。我正在使用这个环境来模拟 python 中的自杀式烧伤。我从该环境的状态向量的前两个值中提取了坐标 (x,y)。根据这些值,将 y 坐标视为高度;我已经使用这些方程计算了下落着陆器的速度和加速度

velocity(v) = delta_y/ delta_t
acceleartion(a) = delta_v/delta_t

由于模拟是逐步递增的,时间差delta_t被取为1。无法找到LunarLander的重力参数,我给它一个默认值g=1。然后使用 reddit comment

中的以下等式

altitude to start suicide burn = [ (current altitude)(acceleration of gravity) + (1/2)(current velocity)2 ] / (acceleration of engines)

我试图计算高度以开始自杀式燃烧。这是我的完整 python 代码。我只打算使用四个可能的动作中的两个动作 0(什么都不做)和 2(启动主机)。

import gym
env = gym.make('LunarLander-v2')
env.seed(0)

g = 1
delta_t = 1
action = 0

state = env.reset()

# x0 = state[0]
y0 = state[1]
v0 = 0

for t in range(3000):
    state, reward, done, _  = env.step(action)
    y = state[1]
    if done or y <0:
        break
    v = (y-y0)/delta_t  # velocity
    a = (v - v0)/delta_t # acceleration

    # (altitude to start suicide burn) = [ (current altitude)(acceleration of gravity) + (1/2)(current velocity)2 ] / (acceleration of engines)
    alt_burn = [y*g+0.5*v*v]/a

    v0 = v
    y0 = y

    print(" y",round(y,5)," v",round(v,5)," a",round(a,5)," Alt_burn",round(alt_burn[0],5))

输出结果看起来像这样

 y 1.41542  v 0.00196  a 0.00196  Alt_burn 722.35767
 y 1.41678  v 0.00136  a -0.0006  Alt_burn -2362.78166
 y 1.41754  v 0.00076  a -0.0006  Alt_burn -2362.63867
 y 1.4177  v 0.00016  a -0.0006  Alt_burn -2362.43506
 y 1.41726  v -0.00044  a -0.0006  Alt_burn -2362.64046
 y 1.41622  v -0.00104  a -0.0006  Alt_burn -2359.03148
 y 1.41458  v -0.00164  a -0.0006  Alt_burn -2358.17355
 y 1.41233  v -0.00224  a -0.0006  Alt_burn -2353.50518
 y 1.40949  v -0.00284  a -0.0006  Alt_burn -2349.24118
 y 1.40605  v -0.00344  a -0.0006  Alt_burn -2343.51016
 y 1.40201  v -0.00404  a -0.0006  Alt_burn -2336.31535
 y 1.39737  v -0.00464  a -0.0006  Alt_burn -2329.04954

如果我们查看海拔高度 (y),它是一个小于 1.5 的非常小的值,而计算出的开始自杀式燃烧的海拔高度非常高。我该如何解决这个问题?

在reddit评论中他们只提到了启动引擎而没有提到关闭它。有人知道动态关闭引擎的数学原理吗?

您的代码有两个问题:

  1. delta_t 根据 lunar_lander source
  2. 应该是 1.0/50.0
 FPS = 50
 #...
 self.world.Step(1.0/FPS, 6*30, 2*30)

其中 Box2D documentation 表示

的典型时间步长
 # [...]Typically we use a time step of 1/60 of a
 # second (60Hz) and 6 velocity/2 position iterations. This provides a 
 # high quality simulation in most game scenarios.
 timeStep = 1.0 / 60
  1. 引擎的加速度不应像
  2. 中那样定义为当前加速度
alt_burn = [y*g+0.5*v*v]/a

但是由于引擎的推动,定义here

MAIN_ENGINE_POWER  = 13.0

着陆器的质量没有在creation of the lander body中指定,而是使用

env.lander.mass

我们可以发现质量是 4.82。鉴于此,发动机的正确加速度为1

alt_burn = (y * g + 0.5 * v*v) / (13.0 / env.lander.mass * 0.5)

如果我们运行将代码进行上述修改,

import gym
env = gym.make('LunarLander-v2')
env.seed(0)

g = 1.0
delta_t = 1.0/50.0
action = 0

state = env.reset()

y0 = state[1]

for t in range(3000):
    state, reward, done, _  = env.step(action)
    y = state[1]
    v = (y - y0) / delta_t
    y0 = y
    if done or y < 0:
        break

    alt_burn = (y*g+0.5*v*v)/(13.0 / env.lander.mass * 0.5)

    print(" y",round(y,5)," v",round(v,5)," Alt_burn",round(alt_burn,5))

我们得到了更合理的燃烧高度答案:

 y 1.41542  v 0.09797  Alt_burn 1.05242
 y 1.41678  v 0.06799  Alt_burn 1.05158
 y 1.41754  v 0.03799  Alt_burn 1.05097
 y 1.4177  v 0.00799  Alt_burn 1.05057
 y 1.41726  v -0.02201  Alt_burn 1.0504
 y 1.41622  v -0.05202  Alt_burn 1.05045
 y 1.41458  v -0.08202  Alt_burn 1.05073
 y 1.41233  v -0.11202  Alt_burn 1.05123
 y 1.40949  v -0.14202  Alt_burn 1.05194
 y 1.40605  v -0.17202  Alt_burn 1.05289
 y 1.40201  v -0.20202  Alt_burn 1.05405
 y 1.39737  v -0.23202  Alt_burn 1.05544
 y 1.39213  v -0.26203  Alt_burn 1.05705
 y 1.38629  v -0.29202  Alt_burn 1.05887
 ...
 y 0.56683  v -1.58312  Alt_burn 1.34863
 y 0.53456  v -1.61311  Alt_burn 1.36025
 y 0.5017  v -1.64311  Alt_burn 1.37209
 y 0.46824  v -1.67311  Alt_burn 1.38416
 y 0.43418  v -1.70311  Alt_burn 1.39644
 y 0.39951  v -1.73311  Alt_burn 1.40895
 y 0.36425  v -1.76311  Alt_burn 1.42168
 y 0.32839  v -1.79311  Alt_burn 1.43463
 y 0.29193  v -1.82311  Alt_burn 1.44781
 y 0.25487  v -1.85311  Alt_burn 1.46121
 y 0.2172  v -1.88311  Alt_burn 1.47483
 y 0.17894  v -1.91311  Alt_burn 1.48867
 y 0.14008  v -1.94311  Alt_burn 1.50274
 y 0.10062  v -1.97311  Alt_burn 1.51702
 y 0.06055  v -2.00311  Alt_burn 1.53154
 y 0.01989  v -2.03311  Alt_burn 1.54626

自杀燃烧的执行2现在很简单,我们只需要在着陆器低于燃烧高度时启动引擎,并在着陆器低于截止高度时停用它们高度。

import gym
env = gym.make('LunarLander-v2')
env.seed(0)

g = 1.0
delta_t = 1.0/50.0
action = 0

state = env.reset()

y0 = state[1]
v0 = 0
cut_off = 0.01

for t in range(3000):
    env.render()
    state, reward, done, _  = env.step(action)
    y = state[1]
    v = (y - y0)/delta_t
    if done or y < 0 or v == 0.001:
        break

    alt_burn = (y*g+0.5*v*v)/(13.0 / env.lander.mass * 0.5)

    v0 = v
    y0 = y
    if y < alt_burn and y > cut_off:
        action = 2
    else:
        action = 0

    print(" y",round(y,5)," v",round(v,5)," Alt_burn",round(alt_burn,5))

着陆器将悬停:


1可耻的是我找不到这个等式的来源。我拥有应用物理学学位,重点是天体物理学,并且有 1000 多个小时的 KSP - 所以我绝对确定这个方程是正确的,但我永远记不起我是从哪里得到它的。

2这种自杀式烧伤也被称为 hoverslam。 SpaceX 创造了这个术语,因为当猎鹰 9 号助推器着陆时,一台发动机在最小推力下产生的 TWR 大于 1.00,这意味着没有像阿波罗任务那样的 Powered Descent 容量。因此,只有瞬时悬停 - 因此 hoverslam.