Isaac Gym入門(活用編)

執筆者:野口 裕貴
監修者:稲葉 貴昭・高橋 浩和


1. はじめに

前回の環境構築編では、深層強化学習とIsaac Gymの解説を行い、Isaac Gymの環境構築を行いました。 本稿では、Isaac Gym入門の活用編ということでIsaac Gymでの学習の実行方法について必要な知識等を解説していきます。

2. 実行環境

前回の環境構築編と同じ環境で実施していきます。

  • Ubuntu 20.04
  • Conda 23.7.4
  • Python3.7(conda)
  • GeForce RTX 3060 Laptop (VRAM 6GB)
  • NVIDIA driver version 535.113.01
  • Isaac Gym Preview 4
  • Isaac Gym Env Release 1.5.1

実行するタスクによってはシミュレーションの描写がカクつく、またはGPUのメモリ不足による影響で実行できなくなることがあります。 実行する際にパラメータを設定することで一部対処することはできますが、VRAMが8GB以上のNVIDIA GPUを使用することを強く推奨します。

3. Isaac Gymで深層強化学習

3.1 実行方法について

Isaac Gymで深層強化学習を行う際には、IsaacGymEnvs/isaacgymenvs内にあるtrain.pyを使用します。

train.pyは実行時にコマンドライン引数を渡すことで、学習するタスクを選択することができます。 前回は動作確認として、Cartpole(倒立振子)での学習を実施しましたが、今回はBall Balanceを実行してみます。

Ball Balanceはテーブルの上でボールが落ちないように、テーブルがバランスを取るための動きを学習するタスクとなります。

以下のコマンドから実行できます。

# python3 train.py task=BallBalance

実行すると以下のような画面が表示されます。

Ball Balance

コマンドの引数であるtask=にはそれぞれIsaac Gym Envに用意されているタスク名を指定することで、対応したタスクの学習を行うことができます。

用意されているタスクとして以下のものがあります。

  • Ant
    四足歩行ロボットが移動する
  • Humanoid
    人型ロボットが移動する
  • Shadow Hand
    ロボットハンド(Shadow Hand)が所持するキューブの向きを目標と一致するよう持ち替える
  • Allegro Hand
    Shadow Handと同じタスク。ただし使用するロボットモデルが異なる
  • ANYmal
    四足歩行ロボット(ANYmal)が平坦な地形を移動する
  • ANYmal Rough Terrain
    ANYmalのタスクと基本的に同じだが、起伏の多い地形を移動する
  • TriFinger
    3本指のロボットハンド(TriFinger)で物体の向きを目標の向きと一致するよう移動させる
  • NASA Ingenuity Helicopter
    小型の自律型ヘリコプター(Ingenuity Helicopter)の単純化されたモデルを使用し、移動する物体を追従する
  • Cartpole
    倒立振子のモデルが棒を倒さないようにする
  • Ball Balance
    上から降ってくるボールを落とさないようにテーブルを制御する
  • Franka Cabinet
    ロボットアームが棚の引き出しを開ける

この他にも、モーションキャプチャーから得られたデータを元に人間の動作を学習させる手法(AMP: Adversarial Motion Priors)を用いたタスクなど複数のタスクが利用できます。

より詳細な情報を確認したい場合は、以下のリンク先を参照してください。

IsaacGymEnvs/docs/rl_examples.md at aeed298638a1f7b5421b38f5f3cc2d1079b6d9c3 · NVIDIA-Omniverse/IsaacGymEnvs · GitHub

3.2 実行時の引数について

train.pyは実行時に引数を渡すことで様々なオプションを実行することができます。
以下、引数について解説します。

  • task=
    学習するタスクを指定する

  • train=
    学習に使用するニューラルネットワークのモデルやパラメータなどの設定が記載されたファイルを指定する。指定できるファイルはIsaacGymEnvs/isaacgymenvs/cfg/trainにある。AllegroHandを例に取ると、AllegroHandPPO.yamlAllegroHandLSTMPPO.yamlの2つのファイルが存在する。この2つは明確な違いとしては学習に使用されるニューラルネットワークのモデルが異なる

  • num_envs=
    並行してシミュレーションを行う環境の数。ここでの環境というのは強化学習における環境(Environment)のことを指す。前回の記事で記載した強化学習の概要図での赤丸部分が該当する。

    環境の数を増やすことで、学習を効率化し、学習にかかる時間を短縮することができる。しかし増やしすぎるとGPUのメモリ不足のエラーが発生しやすくなる。
    デフォルトの値はIsaacGymEnvs/isaacgymenvs/cfg/taskにある各タスクのyamlファイルに記載されている

  • seed=
    学習におけるランダム性を制御するための値seedを設定する
    (ランダム化される対象:エージェントの初期位置や姿勢など)

    値を設定することで学習の再現性が確保される。そのため、同じ値で学習や推論を行えば、基本的には常に同じ結果を生成される*1。 デフォルトではこの値はseed=42になるように設定されている。再現性に関する詳細な情報はIsaacGymEnvs/docsにあるreproducibility.mdに記載されている

  • sim_device=
    シミュレーションの物理演算に使用されるデバイスを指定する。GPUを使用する場合はcuda:0。CPUならcpuとする。デフォルトはsim_device=cuda:0(GPU)

  • rl_device=
    学習に使用されるデバイスを指定する。デフォルトはrl_device=cuda:0(GPU)

  • graphics_device_id=
    シミュレーションの描画に使用するVulkan*2 のグラフィックス デバイス IDを指定する。デフォルトはgraphics_device_id=0。基本的にはデフォルトの設定で問題ないが、複数のGPUを利用している場合やIDの確認を行いたい場合はvulkaninfoを実行することで、それぞれのIDで利用できるGPUを確認できる。

    例として、筆者の実行環境でのvulkaninfoの実行時の出力を以下に示す。

      VK_LAYER_LUNARG_standard_validation (LunarG Standard Validation Layer) Vulkan version 1.0.131, layer version 1:
      Layer Extensions: count = 0
      Devices: count = 3
          GPU id  : 0 (Intel(R) UHD Graphics (CML GT2))
          Layer-Device Extensions: count = 0
    
          GPU id  : 1 (NVIDIA GeForce RTX 3060 Laptop GPU)
          Layer-Device Extensions: count = 0
    
          GPU id  : 2 (llvmpipe (LLVM 12.0.0, 256 bits))
          Layer-Device Extensions: count = 0
    

    ID 0はIntelの統合グラフィクス、ID 1はNVIDIAのGPU、ID 2はグラフィックハードウェアが存在しない場合に出力される。 この場合、筆者はgraphics_device_id=として、0か1のいずれかを選択することができる。

  • pipeline=PIPELINE
    どのAPIパイプラインを使用するか選択できる。GPUパイプラインを使用するとすべてのデータはGPU上に残るため高速に処理が行える。CPUを使用する場合は常に各ステップでCPU↔GPU間でデータのコピーが行われるため、処理が遅くなる。デフォルトはpipeline=gpu(GPU)

  • test=
    デフォルトはtest=Falseであり、学習のみが実施される。test=Trueに設定することで推論のみが実施され、学習済みの方策の評価を行うことができる

  • checkpoint=
    途中で終了した学習や学習済みの方策を推論するのに使用される。/runsに保存されているディレクトリを指定することで使用できる

  • headless=
    headless=Trueに設定することで、シミュレーションの描写を無効化する。無効化することで描写に割くリソースが削減されるため、学習にかかる時間が短縮される

  • experiment=
    実験の名前を設定する。推論や再学習の際に使用するチェックポイントの名称を自由に設定可能

  • max_iterations=
    タスクを実行する反復回数を指定する。デフォルトの値はIsaacGymEnvs/isaacgymenvs/cfg/taskにある各タスクのyamlファイルに記載されている

これらの引数の説明だけではイメージがしづらいと思いますので、以下に具体的な使用例を紹介します。

1. Antタスク・シミュレーションの描写無効

python3 train.py task=Ant headless=True

描写の無効化を行うと以下のようにTerminal (CUI)から学習の様子を確認できます。

fps step: 41360 fps step and policy inference: 30946 fps total: 30207 epoch: 1/500 frames: 0
fps step: 429814 fps step and policy inference: 380742 fps total: 319300 epoch: 2/500 frames: 65536
fps step: 252399 fps step and policy inference: 232556 fps total: 207916 epoch: 3/500 frames: 131072
fps step: 435901 fps step and policy inference: 372269 fps total: 312375 epoch: 4/500 frames: 196608
fps step: 425134 fps step and policy inference: 363559 fps total: 307593 epoch: 5/500 frames: 262144
fps step: 419380 fps step and policy inference: 359696 fps total: 302603 epoch: 6/500 frames: 327680
fps step: 431078 fps step and policy inference: 369211 fps total: 309127 epoch: 7/500 frames: 393216
fps step: 428803 fps step and policy inference: 367575 fps total: 311003 epoch: 8/500 frames: 458752
fps step: 413447 fps step and policy inference: 354608 fps total: 299470 epoch: 9/500 frames: 524288
fps step: 412243 fps step and policy inference: 353059 fps total: 297661 epoch: 10/500 frames: 589824

2. Antタスク・環境数を制限する

python3 train.py task=Ant num_envs=2048

num_envsの値を設定すると、学習に使用する環境の数を調整することができます。これにより学習時に割り当てるメモリが削減されるため、今回使用しているGPU(GeForce RTX 3060 Laptop)でも学習を行うことができるようになります。

学習実行時に以下のようにメモリ不足のエラーが出た際にはこのパラメータを調整する必要があります。

[Error] [carb.gym.plugin] Gym cuda error: out of memory: ../../../source/plugins/carb/gym/impl/Gym/GymPhysX.cpp: 1721

しかし注意点もあります。それはコマンドライン引数として渡すnum_envsは値によっては、デフォルトのnum_envsよりも値を小さくしたにもかかわらず、メモリ不足のエラーが発生します。

このような場合にはnum_envsの他にも、学習時の1回毎のパラメータ更新に用いられるデータ数であるminibatch_sizeの値を変更するなど、対処する必要があります。*3

3. ShadowHandタスク・LSTM*4での学習

python3 train.py task=ShadowHand train=ShadowHandPPOLSTM

一部のタスクでは使用するニューラルネットワークモデルを変更して学習を行うことができます。

3.3 Isaac Gymの推論とチェックポイント

Isaac Gymは学習の記録をIsaacGymEnvs/isaacgymenvs/runsにセーブします。

このセーブを行う周期はIsaacGymEnvs/isaacgymenvs/cfg/trainにある各タスクのyamlファイルに記載されているパラメータsave_frequencyの値によって変化します。

例えば、CartPoleの場合はIsaacGymEnvs/isaacgymenvs/cfg/train/CartpolePPO.yamlに記載されており、パラメータはsave_frequency: 25となっています。

この値は学習中のepoch数が25の倍数になるたびにチェックポイントのファイルが生成されることを指します。

以下、Cartpoleの学習を完了した際のチェックポイントファイルの一覧です。

gymuser@hiroki:/gymworkspace/IsaacGymEnvs/isaacgymenvs/runs/Cartpole_12-12-40-36/nn$ ls

Cartpole.pth                            last_Cartpole_ep_100_rew__492.75_.pth  last_Cartpole_ep_50_rew_484.99435.pth
last_Cartpole_ep_100_rew_492.75037.pth  last_Cartpole_ep_25_rew_137.96257.pth  last_Cartpole_ep_75_rew_491.30405.pth

これを見ると、epoch数が25, 50, 75, 100になるタイミングでチェックポイントが生成されていることがわかります。

また/runsに生成されるチェックポイントのディレクトリ名は基本的には以下のような規則で命名されます。

# task名 + '_{date:%d-%H-%M-%S}'

例:CartPoleで12月10日の9時25分15秒に実行した場合

# CartPole_10-9-25-15

ただし、コマンドライン引数でexperiment=で何らかの名称を設定している場合は、前述したtask名の部分が変更されます。

例:CartPoleで12月4日の8時23分35秒に実行 experiment=learning_test_No1に設定

# learning_test_No1_4-8-23-35

生成されたチェックポイントとして使用することで、途中で終了させた学習の再開や、学習済みの方策の推論を行うことができます。

以下に具体的な使用例を示します。

1. Cartpoleタスク・途中で終了させた学習を再開させる場合

 python3 train.py task=Cartpole checkpoint=runs/Cartpole_12-12-40-36/nn/Cartpole.pth 

コマンド実行時以下のような出力が表示されれば、checkpointの読み込みに成功している

=> loading checkpoint '/gymworkspace/IsaacGymEnvs/isaacgymenvs/runs/Cartpole_12-12-40-36/nn/Cartpole.pth'

2. Cartpoleタスク使用・学習済みの方策を推論し、評価する場合

 python3 train.py task=Cartpole checkpoint=runs/Cartpole_12-12-40-36/nn/Cartpole.pth test=True

テスト時には以下のようにsteps数と報酬が表示される。 test終了時には報酬とstep数の平均が表示される。

reward: 499.57 steps: 500.0
reward: 499.55 steps: 500.0
reward: 499.56 steps: 500.0
reward: 499.56 steps: 500.0
1023098.359375
av reward: 499.5597457885742 av steps: 500.0

3.4 学習パラメータの設定方法

学習に使用されるパラメータ等が記載された設定ファイルはyamlファイルで記載されています。 Isaac GymはこのyamlファイルをHydraで管理するようにしています。 これにより、学習に使用される各種変数は対象となるyamlファイルを編集するか、またはコマンドライン引数として設定することもできます。

これらのyamlファイルはisaacgymenvs/cfg/のディレクトリ内にあります。

学習のタスクに対する設定はisaacgymenvs/cfg/task/のディレクトリにあり、学習に使用されるパラメータ等の設定はisaacgymenvs/config/train/内にあります。

taskにあるyamlファイルには

  • env
    学習環境に関するパラメータ。numEnvs(環境数)などが該当
  • sim
    シミュレーションに関するパラメータ。dtgravity(重力加速度)などの物理パラメータなどが該当
  • task
    環境のランダム化に関するパラメータ。randomize(ランダム化を有効にするかどうかのフラグ)などが該当

などがあり

trainにあるyamlファイルには

  • network
    学習に使用するニューラルネットワークモデルの設定
  • config
    学習時に使用するパラメータ。学習率やバッチサイズなどが該当

などがあります。

これらの設定ファイルはIsaac Gymを用いた学習環境を作成する上で必ず必要となるファイルになります。

4. 最後に

今回はIsaac Gymで学習を実行する上で必要な知識について解説しました。次回はこれらの知識を活用し、オリジナルの学習環境を作成します。

ex. Dockerでの環境構築

前回の環境構築編ではcondaを利用した環境構築のみを紹介しましたが、本稿のおまけとして、Dockerを用いた環境構築についても紹介します。

Isaac GymをDockerで環境構築するためには以下をインストールする必要があります。

これらに関しては、リンク先を参照して環境構築を行ってください。

上記がインストールし終わった後、前回と同じように、公式のWebsiteからIsaac Gym Preview 4 releaseをダウンロードします。

Isaac Gym - Preview Release | NVIDIA Developer

ダウンロード後、以下のコマンドで展開します。

# tar -xf IsaacGym_Preview_4_Package.tar.gz

展開後、以下のコマンドで環境構築を行ってください。

# cd isaacgym/docker
# ./build.sh
# ./run.sh $DISPLAY

コンテナを起動できたら、以下のコマンドを実行し、動作確認を行ってください。

# cd python/examples
# python3 joint_monkey.py

以下のような画面が出れば、成功です。

これでisaacgymの機能を使用できるようになります。

しかし、このままでは、本稿で解説したtrain.pyなどを含むIsaacGymEnvsを使用することができません。

そこで構成とファイルを一部編集し、isaacgymIsaacGymEnvsの両方を使用できるようにします。

ファイル構成を以下のように変更してください。

~/gymworkspace  
├── isaacgym
├── IsaacGymEnvs  
└── docker

ホームディレクトリにgymworkspaceという名前のディレクトリを作成し、その中にisaacgymIsaacGymEnvsを入れてください。dockerについては後述しますが、isaacgymにあるdockerをコピーしたものになります。

以下に作成方法について記載しておきます。

# cd ~
# mkdir gymworkspace
# cd gymworkspace
# mv ~/Downloads/IsaacGym_Preview_4_Package.tar.gz .
# tar -xf IsaacGym_Preview_4_Package.tar.gz
# git clone https://github.com/NVIDIA-Omniverse/IsaacGymEnvs.git
# cp -r isaacgym/docker ./docker

isaacgymからコピーしてきたdockerはそのままでは使用できないので、以下の2つのファイルを編集します。

  • Dockerfile
  • run.sh

以下の内容に書き換えてください。

Dockerfile

FROM nvcr.io/nvidia/pytorch:21.09-py3
ENV DEBIAN_FRONTEND=noninteractive 

# dependencies for gym
#
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
 libxcursor-dev \
 libxrandr-dev \
 libxinerama-dev \
 libxi-dev \
 mesa-common-dev \
 zip \
 unzip \
 make \
 gcc-8 \
 g++-8 \
 vulkan-utils \
 mesa-vulkan-drivers \
 pigz \
 git \
 libegl1 \
 git-lfs

# Force gcc 8 to avoid CUDA 10 build issues on newer base OS
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 8
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 8

# WAR for eglReleaseThread shutdown crash in libEGL_mesa.so.0 (ensure it's never detected/loaded)
# Can't remove package libegl-mesa0 directly (because of libegl1 which we need)
RUN rm /usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0 /usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0.0.0 /usr/share/glvnd/egl_vendor.d/50_mesa.json

COPY docker/nvidia_icd.json /usr/share/vulkan/icd.d/nvidia_icd.json
COPY docker/10_nvidia.json /usr/share/glvnd/egl_vendor.d/10_nvidia.json

WORKDIR /gymworkspace

RUN useradd --create-home gymuser
USER gymuser

# copy gym repo to docker
COPY --chown=gymuser . .

# install gym modules
ENV PATH="/home/gymuser/.local/bin:$PATH"
RUN cd isaacgym/python && pip install -q -e .

ENV NVIDIA_VISIBLE_DEVICES=all NVIDIA_DRIVER_CAPABILITIES=all

RUN cd IsaacGymEnvs && pip install -q -e .

run.sh

#!/bin/bash
set -e
set -u

if [ $# -eq 0 ]
then
    echo "running docker without display"
    docker run -it --network=host --gpus=all --name=isaacgym_container isaacgym /bin/bash
else
    export DISPLAY=$DISPLAY
    echo "setting display to $DISPLAY"
    xhost +
    docker run -it --rm -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY --network=host --gpus=all --name=isaacgym_container -v $HOME/gymworkspace:/gymworkspace:rw isaacgym /bin/bash
    xhost -
fi

ファイル編集後、以下のコマンドを実行し、コンテナを作成・実行してください。

# cd ~/gymworkspace/docker
# ./build.sh
# ./run.sh $DISPLAY

コンテナ起動後、以下のコマンドを実行し、isaacgymIsaacGymEnvsの両方の機能が使用できるかどうか確認してください。

isaacgymの動作確認

# cd isaacgym/python/examples/
# python3 joint_monkey.py 

IsaacGymEnvsの動作確認

# cd IsaacGymEnvs/isaacgymenvs
# python3 train.py task=Cartpole

両方で動作確認ができれば、dockerでの環境構築は終了となります。


VA Linux は、千葉工業大学 未来ロボティクス学科のロボカップチーム「CIT Brains」をスポンサーとして応援しており、インターン生も数名受け入れています。
本記事は、その一環としてインターン生の野口さんが記事を執筆し、弊社が監修を行いました。

*1:学習に使用されるPyTorchの再現性に関するドキュメントにも記載されているが、同一のシード値を利用しても、使用するCPU、GPUが異なることで計算結果が異なることがあります。

*2:主にゲームなどに使用されるグラフィクスAPIです。OpenGLの後継であり、NVIDIAのGPUの多くはこれをhttps://blog.hatena.ne.jp/valinux/valinux.hatenablog.com/edit?entry=6801883189056805136#previewサポートしています。https://developer.nvidia.com/vulkan#vulkan

*3:https://forums.developer.nvidia.com/t/gym-cuda-error-running-out-of-memory

*4:「Long Short Term Memory」と呼ばれるRNN(再帰型 ニューラル ネットワーク)の一種です。