ABCI で singularity + mujoco210 (+ robomimic！)

# 追記
- どうやら**最新の**mujocoは `MUJOCO_GL=egl` を指定することで、apt系の操作なしでpipのみでインストールできるみたいです！
  - 流石deepmind
  - ただsingularity君とは仲良くなっといたほうが得な気がします笑
  - `MUJOCO_GL` を指定することで機能的な制約があるのかないのかはよくわかんないです
- この記事は古いmujocoを動かすときに参考にしてみてください
  - 実は古いmujocoも、condaを使ってごにょるとaptなしでインストールできるらしいですが、ちょっと工数が多そう＆condaを信用するかどうかという問題が発生します笑

# みんな大好きABCI！

- 産総研さまさま！！
- 余談ですが、個人的にABCIとローカル間のデータの転送にはsshfsを推してます
  - Finderとかエクスプローラーとかで、ローカルのファイルと同じようにデータを扱えます (WSLでも)

```shell
# `ssh abci`でログインできる人用のコマンド
$ sshfs abci:/home/<username>/ ~/path/to/local/dir -o allow_other
# 例) $ sshfs abci:/home/nya12345an/ ~/mnt/abci -o allow_other
```

# 本題
## Definition File

- (最近cudaのdockerfileがアップデートされてbuildでエラーが出るようになったので、修正版をこの記事のコメントに追記しました)

```bash:mujoco210.def
# [1] https://gitlab.com/nvidia/container-images/cuda
# [2] https://github.com/openai/mujoco-py/blob/master/Dockerfile
Bootstrap: docker
From: nvidia/cudagl:11.1.1-devel-ubuntu20.04
%post
    export DEBIAN_FRONTEND=noninteractive
    apt update
    # python
    apt install -y python3-dev python3 python3-pip python3-venv
    # mujoco
    apt install -y libgl1-mesa-dev libgl1-mesa-glx libglew-dev libosmesa6-dev patchelf
    # xvfb
    apt install -y xvfb libglfw3-dev libosmesa-dev python-opengl
    # utils
    apt install -y wget curl unzip git zsh vim ffmpeg
```

- `cudagl` を使うとlibEGL周りのエラーが解決するらしい?

## singularityに入る

```bash
$ singularity build --fakeroot mujoco210.sif mujoco210.def
$ singularity shell -s /bin/bash --nv mujoco210.sif
```

## singularity内で (初回のみ)

```bash
$ mkdir -p ~/.mujoco
# ※1
$ wget https://mujoco.org/download/mujoco210-linux-x86_64.tar.gz -O mujoco.tar.gz
$ tar -xf mujoco.tar.gz -C ~/.mujoco
$ rm mujoco.tar.gz

$ python3 -m venv ~/venv/mujoco
$ source ~/venv/mujoco/bin/activate
$ pip3 install --upgrade pip

$ git clone https://github.com/openai/mujoco-py.git -b v2.1.2.14 --depth 1
$ cd mujoco-py
$ pip3 install -r requirements.txt
# ※2
$ sed -i -e 's/= LinuxCPU/= LinuxGPU/g' mujoco_py/builder.py
$ pip3 install -e .
$ cd
$ pip3 install gym wheel moviepy

$ echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/.mujoco/mujoco210/bin' >> ~/.bashrc
```

- ※1: なぜかabciの中から mujoco.tar.gz の `wget` ができなかったので、手元のPCで `wget` して `sshfs` (or `scp` 等) で転送しました
- ※2: GPUレンダリングを強制的に有効にしています（意図せずCPUレンダリングになることがあるそう?）
- `install gym[all]` はまだ対応してないです…


## 実行！

```python:mujoco_sample.py
import gym
env = gym.make("Humanoid-v3")
o = env.reset()

frames = []
for _ in range(100):
    obs = env.render(mode="rgb_array")
    frames.append(obs)
    a = env.action_space.sample()
    o, r, done, info = env.step(a)
    if done:
        o = env.reset()
env.close()

import moviepy.editor as mpy
clip = mpy.ImageSequenceClip(frames, fps=30)
clip.write_gif("~/humanoid.gif")
```

```bash
# 実はXvfb要らないかも
$ export DISPLAY=:0; Xvfb :0 -screen 0 1400x900x24 &
$ python3 mujoco_sample.py
```

- `server already running` が出たら、ABCIノードを落として入り直すと直ったりする

![vid.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188173/b9729b18-04dd-4e4c-24d0-5f42cce05a60.gif)


- レンダリング結果はsshfsとかでabciから拾ってきましょう

## 次回ログイン以降

```bash
$ singularity shell -s /bin/bash --nv singularity/mujoco210.sif

$ source ~/venv/mujoco/bin/activate
$ python mujoco_sample.py
```

# 以上！

- スペシャルサンクス to 松尾研の先輩方