MyoSuite Tutorial No.5

# はじめに
本記事は以下の人を対象としています．

- 筋骨格シミュレータに興味がある人
- MuJoCoに興味がある人

:::note warn
本記事では[5_Move_Hand_Fingers.ipynb](https://github.com/MyoHub/myosuite/blob/main/docs/source/tutorials/5_Move_Hand_Fingers.ipynb)をGoogle Colabで実行した際の手順と結果に関してまとめる．
:::

# MyoSuiteとは

https://sites.google.com/view/myosuite

MuJoCoを学習モジュールとして組み込んだ筋骨格シミュレータ

:::note info
2024年にICRAにてworkshopを展開
https://sites.google.com/view/myosuite/myosymposium/icra24
:::

# Tutorial Notebook

https://github.com/MyoHub/myosuite/tree/main/docs/source/tutorials

# 実施事項
Tutorialに記載のコードを1つずつ試して, Errorになったところは都度修正版を記載する.

## ライブラリのinstallと環境変数設定

```bash
!pip install -U myosuite
!pip install tabulate matplotlib torch gym==0.13 git+https://github.com/aravindr93/mjrl.git@pvr_beta_1vk
!pip install scikit-learn

%env MUJOCO_GL=egl
```

## ライブラリのimportと結果表示の関数

```python
from myosuite.utils import gym
import skvideo.io
import numpy as np
import os

from IPython.display import HTML
from base64 import b64encode

def show_video(video_path, video_width = 400):

  video_file = open(video_path, "r+b").read()

  video_url = f"data:video/mp4;base64,{b64encode(video_file).decode()}"
  return HTML(f"""<video autoplay width={video_width} controls><source src="{video_url}"></video>""")
```

## handとfingerの動作デモ

```python
import mujoco
env = gym.make('myoHandPoseRandom-v0', normalize_act = False)

env.env.init_qpos[:] = np.zeros(len(env.env.init_qpos),)
mjcModel = env.env.sim.model

# actuatorの名称については後述
musc_fe = [mjcModel.actuator('FDP2').id,mjcModel.actuator('EDC2').id]
L_range = round(1/mjcModel.opt.timestep)
skip_frame = 50
env.reset()

frames_sim = []
for iter_n in range(3):
    print("iteration: "+str(iter_n))
    res_sim = []
    for rp in range(2): #alternate between flexor and extensor
        for s in range(L_range):
            if not(s%skip_frame):
                frame = env.sim.renderer.render_offscreen(
                                width=400,
                                height=400,
                                camera_id=0)
                frames_sim.append(frame)

            ctrl = np.zeros(mjcModel.na,)

            act_val = 1 # maximum muscle activation
            if rp==0:
                ctrl[musc_fe[0]] = act_val
                ctrl[musc_fe[1]] = 0
            else:
                ctrl[musc_fe[1]] = act_val
                ctrl[musc_fe[0]] = 0
            env.step(ctrl)

os.makedirs('videos', exist_ok=True)
# make a local copy
skvideo.io.vwrite('videos/MyoSuite.mp4', np.asarray(frames_sim),outputdict={"-pix_fmt": "yuv420p"})

# show in the notebook
show_video('videos/MyoSuite.mp4')
```

出力結果(実際は2秒ほど)

![5_Move_Hand_Fingers-default-camera0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2043769/d67681c7-e897-77e7-8a2e-5192371c3d46.gif)

:::note alert
動作のはじめに腕が半回転するような挙動が見てとれるが、原因は不明
:::


### actuatorに関して
以下のコマンドを実行するとMuscleとJointの情報を得ることができる

```python
print("Muscles:")
for i in range(mjcModel.na):
    print([i,mjcModel.actuator(i).name])

print("\nJoints:")
for i in range(mjcModel.njnt):
    print([i,mjcModel.joint(i).name])
```

<details><summary>出力結果</summary>

```bash
Muscles:
[0, 'ECRL']
[1, 'ECRB']
[2, 'ECU']
[3, 'FCR']
[4, 'FCU']
[5, 'PL']
[6, 'PT']
[7, 'PQ']
[8, 'FDS5']
[9, 'FDS4']
[10, 'FDS3']
[11, 'FDS2']
[12, 'FDP5']
[13, 'FDP4']
[14, 'FDP3']
[15, 'FDP2']
[16, 'EDC5']
[17, 'EDC4']
[18, 'EDC3']
[19, 'EDC2']
[20, 'EDM']
[21, 'EIP']
[22, 'EPL']
[23, 'EPB']
[24, 'FPL']
[25, 'APL']
[26, 'OP']
[27, 'RI2']
[28, 'LU_RB2']
[29, 'UI_UB2']
[30, 'RI3']
[31, 'LU_RB3']
[32, 'UI_UB3']
[33, 'RI4']
[34, 'LU_RB4']
[35, 'UI_UB4']
[36, 'RI5']
[37, 'LU_RB5']
[38, 'UI_UB5']

Joints:
[0, 'pro_sup']
[1, 'deviation']
[2, 'flexion']
[3, 'cmc_abduction']
[4, 'cmc_flexion']
[5, 'mp_flexion']
[6, 'ip_flexion']
[7, 'mcp2_flexion']
[8, 'mcp2_abduction']
[9, 'pm2_flexion']
[10, 'md2_flexion']
[11, 'mcp3_flexion']
[12, 'mcp3_abduction']
[13, 'pm3_flexion']
[14, 'md3_flexion']
[15, 'mcp4_flexion']
[16, 'mcp4_abduction']
[17, 'pm4_flexion']
[18, 'md4_flexion']
[19, 'mcp5_flexion']
[20, 'mcp5_abduction']
[21, 'pm5_flexion']
[22, 'md5_flexion']
```
</details>

今回はこの内Muscleの```FDP2```と```EDC2```を用いて動作をさせるものである

```rp```が0か否かで屈筋と伸筋のactuationを選択している(muscle activationは0~1の範囲で指定)

:::note info
https://myosuite.readthedocs.io/en/latest/suite.html#myohand によると
- ```FDP2```: Flexor Digitorum Profundus [深指屈筋](https://ja.wikipedia.org/wiki/%E6%B7%B1%E6%8C%87%E5%B1%88%E7%AD%8B#:~:text=%E6%B7%B1%E6%8C%87%E5%B1%88%E7%AD%8B%EF%BC%88%E3%81%97%E3%82%93%E3%81%97%E3%81%8F%E3%81%A3,%E3%81%AE%E6%8E%8C%E5%B1%88%E3%82%92%E8%A1%8C%E3%81%86%E3%80%82)(***2- index***, 3- middle, 4- ring, 5- little)
- ```EDC2```: Extensor Digitorum Communis [総指伸筋](https://ja.wikipedia.org/wiki/%E7%B7%8F%E6%8C%87%E4%BC%B8%E7%AD%8B)(***2- index***, 3- middle, 4- ring, 5- little)
:::