使用REVIVE SDK控制着陆器进行悬停

example-of-lander_hover

着陆器悬停任务描述

着陆器悬停环境是对Gym中月球着陆器环境的改造,任务的目标从着陆改为在月球表面悬停。 此环境是 Box2D环境 的一部分。

Action Space

Discrete(4)

Observation

Shape (4,)

Observation

High [1.5 1.5 5. 5. ]

Observation

Low [-1.5 -1.5 -5. -5. ]

这是一个经典的火箭轨道优化问题。根据Pontryagin的最大值原理,以完全打开或关闭发动机为最佳的动作选择。 根据该原理,动作是离散的:发动机打开或关闭。悬停目标点始终位于坐标 (0,1)。另外,状态向量的前两个维度是坐标值, 并且设定着陆器携带无穷多的燃料。

动作空间

动作空间中有四个独立的动作可用:不做任何动作、启动左引擎、启动主引擎和启动右引擎。

观察空间

状态是一个4维矢量,包括:着陆器的 \(X\) 轴坐标,着陆器的 \(Y\) 轴坐标,着陆器的 \(X\) 轴线速度,着陆器的 \(Y\) 轴线速度。

悬停目标

悬停目标点位于(0,1)。如果着陆器的 \(x\)\(y\) 坐标的偏差小于0.2。 则着陆器悬停被认可是成功的,并获得10分的奖励,否则将受到0.3分的惩罚。

if abs(state[0]) <= 0.2 and abs(state[1]-1) <= 0.2:
   reward = 10
else:
   reward = -0.3

初始状态

着陆器从顶部中心开始,向其质心施加随机初始力。随机初始力将使着陆器具有随机初始速度。

任务强制结束

如果发送下面的情况则当前任务会被强行停止:
  1. 着陆器坠毁(着陆器的身体与月球表面接触);

  2. 着陆器离开窗口(坐标: \(x\) 轴大于1或小于-1);

  3. 达到400步的时间步长;

  4. 着陆器没有唤醒。根据 Box2D 的定义, 这样的着陆器没有任何位移变化并且也没有和其他物体产生碰撞: 当Box2D确定一个物体(或一组物体)已经静止休眠时,此时CPU开销非常小。如果一个物体清醒并与休眠中的其他无力产生碰撞,则会唤醒休眠中的物体。

使用REVIVE SDK训练控制策略

REVIVE SDK是一个历史数据驱动的工具,根据文档教程部分的描述,在悬停任务上使用REVIVE SDK可以分为以下几步:

  1. 收集悬停任务的历史决策数据;

  2. 结合业务场景和收集的历史数据构建 决策流图和数组数据,其中决策流图主要描述了业务数据的交互逻辑, 使用 .yaml 文件进存储,数组数据存储了决策流图中定义的节点数据,使用 .npz.h5 文件进行存储。

  3. 有了上述的决策流图和数组数据,REVIVE SDK已经可以进行虚拟环境模型的训练。但为了获得更优的控制策略,需要根据任务目标定义 奖励函数 ,奖励函数定义了 策略的优化目标,可以指导控制策略将着陆器更好的悬停在目标位置。

  4. 定义完 决策流图训练数据奖励函数 之后,我们就可以 使用REVIVE SDK开始虚拟环境模型训练和策略模型训练。

  5. 最后将REVIVE SDK训练的策略模型进行上线测试。

收集历史数据

我们使用基于坐标信息的控制策略来模拟历史决策过程收集数据。具体而言,基于坐标信息的控制策略会根据当前的着陆器的位置偏离目标位置 的程度给出相应的动作,以控制着陆器尽可能的靠近目标位置。控制效果如下图所示:

example-of-rule_result

定义决策流图和准备数据

完成历史数据收集后,我们就需要根据业务场景来构建决策流图和数组数据。决策流程图准确地定义了数据之间的决策因果关系。 在着陆悬停任务中,我们可以观察到着落器的相关状态信息。状态是一个4维矢量,包括:着陆器的 \(X\) 轴坐标, 着陆器的 \(Y\) 轴坐标,着陆器的 \(X\) 轴线速度,着陆器的 \(Y\) 轴线速度。 动作空间中由四个独立的动作构成:不做任何动作、启动左引擎、启动主引擎和启动右引擎。

基于对业务的理解,我们构建了如下决策流图,决策流图包含3个节点,其中 obs 节点代表了着陆器的状态, action 节点代表着陆器动作, next_obs 节点代表着陆器下一时刻的状态。 从 obs 节点到 action 节点边表示着陆器的动作应仅由着陆器状态决定,而从 obs 节点和 action 节点到 next_obs 节点的表明着陆器下一时刻的状态受其当前时刻状态和控制动作的共同影响。

decision_graph of hover lander

上述决策流图对应的 .yaml 文件如下:

metadata:
   columns:
     - obs_0:
         dim: obs
         type: continuous
     - obs_1:
         dim: obs
         type: continuous
     - obs_2:
         dim: obs
         type: continuous
     - obs_3:
         dim: obs
         type: continuous
     - action:
         dim: action
         type: category
         values: [0,1,2,3]

   graph:
     action:
     - obs
     next_obs:
     - obs
     - action

在准备决策流图的过程中我们也将原始的数据转换为 .npz 文件进行存储 。

定义决策流图和准备数据的更多细节描述可以参考 准备数据 章节的文档介绍。

定义奖励函数

奖励函数的设计对于学习策略至关重要。一个好的奖励函数应该能够指导策略向着预期的方向进行学习。REVIVE SDK支持支持以python源文件的方式定义奖励函数。

悬停目标点位于(0,1)。如果着陆器的 \(x\)\(y\) 坐标的偏差小于0.2。则着陆器悬停被认可是成功的,并获得10分的奖励,否则将受到0.3分的惩罚。 下面展示了将着陆器悬停环境提供的任务目标转换为REVIVE SDK所需的奖励函数。

import torch
from typing import Dict

def get_reward(data : Dict[str, torch.Tensor]):

   return torch.where((torch.abs(data["next_obs"][...,0:1]) < 0.2) \&
                      (torch.abs(data["next_obs"][...,1:2] - 1) < 0.2), 10,-0.3)

定义奖励函数的更多细节描述可以参考 奖励函数 章节的文档介绍。

使用REVIVE SDK训练控制策略

REVIVE SDK已经提供了训练所需的数据和代码,详情请参考 REVIVE SDK源码库。 完成REVIVE SDK的安装后,可以切换到 examples/task/LanderHover 目录下,运行下面的Bash命令开启虚拟环境模型训练和策略模型训练。在训练过程中,我们可以随时使用tensorboard打开日志目录以监控训练过程。当REVIVE SDK完成虚拟环境模型训练和策略模型训练后。 我们可以在日志文件夹( logs/<run_id>)下找到保存的模型( .pkl.onnx)。

python train.py -df data/LanderHover.npz -cf data/LanderHover.yaml -rf data/LanderHover.py -rcf data/config.json -vm once -pm once --run_id revive --revive_epoch 1000 --ppo_epoch 500

训练模型的更多细节描述可以参考 训练模型 章节的文档介绍。

在任务场景中测试训练后的策略模型

训练完成后,可以使用REVIVE SDK提供的 jupyter notebook 脚本在着陆器悬停任务中进行策略的控制效果测试。详情可以参考 jupyter notebook

example-of-jupyter_plt

由上述测试结果可知,用于采样数据的基于规则策略的轨迹奖励均值是358, 使用REVIVE SDK训练得到的控制策略的轨迹奖励均值可以达到2808,策略控制效果提升是非常明显的。

不同策略的控制效果展示

下面动画显示了使用不同策略进行控制的效果。

策略1:随机选择动作进行控制

example-of-random_result

策略2:根据坐标信息通过特定规则进行控制(采样数据所用的策略)

example-of-rule_result

策略3:使用DQN算法在线训练的策略进行控制

example-of-result_dqn

策略4:通过使用REVIVE SDK离线训练策略进行控制

example-of-revive_result