Genesis - MacOS環境での実行メモ（サンプルの学習と実行まで）

# Genesis - MacOS環境での実行メモ（サンプルの学習と実行まで）
大まかな流れは以下の記事を参照して実行しました。
https://qiita.com/hEnka/items/cc5fd872eb0bf7cd3abc

MacOS用に環境構築とコードの変更をいくつか加えて実行しています。

### 環境構築
まず最初に、pythonのバージョンに制限があるためpyenvで環境指定して環境構築します。
https://github.com/Genesis-Embodied-AI/Genesis/issues/313#issuecomment-2562407431
```bash
cd <workspace>
# pyenv settings
pyenv install miniconda3-3.10-24.9.2-0
pyenv local miniconda3-3.10-24.9.2-0
# install dependencies
pip3 install torch torchvision torchaudio
pip install genesis-world 
```
### Exampleの実行
```bash
cd <workspace>
# get Genesis examples
git clone https://github.com/Genesis-Embodied-AI/Genesis.git
cd <workspace>/Genesis
# run macos example (need --vis option)
python3 examples/render_on_macos.py --vis
> [Genesis] [15:52:13] [WARNING] Non-linux system detected. In order to use the interactive viewer, you need to manually run simulation in a separate thread and then start viewer. See `examples/render_on_macos.py`.
```

### 学習の実行
```bash
cd <workspace>
git clone https://github.com/leggedrobotics/rsl_rl
cd <workspace>/rsl_rl
git checkout v1.0.2 && pip install -e .
pip install tensorboard
cd <workspace>/Genesis
python examples/locomotion/go2_train.py
>  File "~/.pyenv/versions/miniconda3-3.10-24.9.2-0/lib/python3.10/site-packages/torch/cuda/__init__.py", line 310, in _lazy_init
    raise AssertionError("Torch not compiled with CUDA enabled")
AssertionError: Torch not compiled with CUDA enabled
```
MacBookにはNvidiaデバイスがないので代わりにmpsを利用する。データがcpuとgpuのメモリに分散しているとエラーが発生したのでその修正も加えた以下の変更を行う。
```diff
diff --git a/examples/locomotion/go2_env.py b/examples/locomotion/go2_env.py
index 0ff5825..497e91f 100644
--- a/examples/locomotion/go2_env.py
+++ b/examples/locomotion/go2_env.py
@@ -9,7 +9,7 @@ def gs_rand_float(lower, upper, shape, device):
 
 
 class Go2Env:
-    def __init__(self, num_envs, env_cfg, obs_cfg, reward_cfg, command_cfg, show_viewer=False, device="cuda"):
+    def __init__(self, num_envs, env_cfg, obs_cfg, reward_cfg, command_cfg, show_viewer=False, device="mps"):
         self.device = torch.device(device)
 
         self.num_envs = num_envs
diff --git a/examples/locomotion/go2_train.py b/examples/locomotion/go2_train.py
index 7c77990..db9003b 100644
--- a/examples/locomotion/go2_train.py
+++ b/examples/locomotion/go2_train.py
@@ -142,7 +142,7 @@ def main():
     parser.add_argument("--max_iterations", type=int, default=100)
     args = parser.parse_args()
 
-    gs.init(logging_level="warning")
+    gs.init(backend=gs.gpu, logging_level="warning")
 
     log_dir = f"logs/{args.exp_name}"
     env_cfg, obs_cfg, reward_cfg, command_cfg = get_cfgs()
@@ -156,7 +156,7 @@ def main():
         num_envs=args.num_envs, env_cfg=env_cfg, obs_cfg=obs_cfg, reward_cfg=reward_cfg, command_cfg=command_cfg
     )
 
-    runner = OnPolicyRunner(env, train_cfg, log_dir, device="cuda:0")
+    runner = OnPolicyRunner(env, train_cfg, log_dir, device="mps:0")
 
     pickle.dump(
         [env_cfg, obs_cfg, reward_cfg, command_cfg, train_cfg],
```

実行すると数分で終了する。実際の実行時間は以下に記載。
```
python3 examples/locomotion/go2_train.py  173.21s user 31.67s system 55% cpu 6:11.18 total
```
### 学習結果の評価
シミュレーションの実行には以下の変更を加える。
```diff
--- a/examples/locomotion/go2_eval.py
+++ b/examples/locomotion/go2_eval.py
@@ -15,7 +15,7 @@ def main():
     parser.add_argument("--ckpt", type=int, default=100)
     args = parser.parse_args()
 
-    gs.init()
+    gs.init(backend=gs.gpu)
 
     log_dir = f"logs/{args.exp_name}"
     env_cfg, obs_cfg, reward_cfg, command_cfg, train_cfg = pickle.load(open(f"logs/{args.exp_name}/cfgs.pkl", "rb"))
@@ -30,17 +30,20 @@ def main():
         show_viewer=True,
     )
 
-    runner = OnPolicyRunner(env, train_cfg, log_dir, device="cuda:0")
+    runner = OnPolicyRunner(env, train_cfg, log_dir, device="mps:0")
     resume_path = os.path.join(log_dir, f"model_{args.ckpt}.pt")
     runner.load(resume_path)
-    policy = runner.get_inference_policy(device="cuda:0")
+    policy = runner.get_inference_policy(device="mps:0")
+    gs.tools.run_in_another_thread(fn=run_sim, args=(env, policy))
+    env.scene.viewer.start()
 
+def run_sim(env, policy):
     obs, _ = env.reset()
     with torch.no_grad():
         while True:
             actions = policy(obs)
             obs, _, rews, dones, infos = env.step(actions)
-
+    env.scene.viewer.stop()
 
 if __name__ == "__main__":
     main()
```

下記のコマンドで実行可能
```bash
python examples/locomotion/go2_eval.py -e go2-walking
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660438/3b5f7fc4-91b2-f72d-cfe4-c11318ac43bf.png)

無事、歩いてくれました。

# 参考資料
- https://qiita.com/hEnka/items/cc5fd872eb0bf7cd3abc
- https://note.com/npaka/n/n07b448c74613
- https://qiita.com/sakusaku3939/items/1a133729c7f38e8403ce