目的
so101 を題材にして、Isaac Lab 上で強化学習した policy を ROS 2 経由で実機へ流し、学習時に近い動きを再現できるところまで実践しました。
初めてCodexを使用してプログラムはすべてAIにまかせて環境を作成しましたが、AIの凄さを目の当たりにしました。。。
もうコーディングAIなしではいられない体になりましたね。本当に。
参考にさせていただいた記事
今回のゴール
今回のゴールは、固定目標位置への到達タスクを対象に、以下を確認することです。
-
so101用の到達タスクをIsaac Lab上で学習する - 学習したpolicyを
Isaac Sim上のso101を用いて、sim上で動作確認する - 実機の
so101に学習したpolicyを繋ぎ、動作確認を行う。
学習して、simで確認して、実機でも確認。
まずはこの流れを体験したいと考えています。
環境について
ハード構成
- ロボットアーム:
so101 - GPU:
5070ti
ソフト構成
- OS:
Ubuntu: 24.04 - シミュレータ:
Isaac Sim: 5.1.0 - 学習基盤:
Isaac Lab: - ミドルウェア:
ROS 2: Jazzy - 推論形式:
policy.onnxまたはpolicy.pt - 実装言語:
Python
今回の構成で揃えた前提
- 制御対象の関節は 6 軸
RotationPitchElbowWrist_PitchWrist_RollJaw
- topic は以下のように整理
- joint state:
/isaac_joint_states - policy command:
/isaac_joint_command - adapter 用 array command:
/isaac_joint_command_array
- joint state:
- EE 位置は
base_link -> gripper_frame_linkの TF から取得する構成を基本にした - policy / physics の更新周期は
60 Hzを基準にそろえた
手順
ここからは、so101 を動かすまでに実際に進めた内容を順番にまとめます。
1. Isaac Lab テンプレートをベースにプロジェクトを作成
まずは Isaac Lab のテンプレートをベースに、so101 用のプロジェクトを作成しました。
リポジトリを IsaacLab 本体とは別に用意し、使用しているpython環境にインストールする形にしておくと、学習環境の変更や ROS 2 連携の試作を独立して進めやすくなります。
インストールは次のような形です。
python -m pip install -e <hoge-hoge>
2. so101 用の到達タスクを実装
次に、固定目標位置へ end-effector を到達させるタスクを作成しました。
実機で扱える構成を意識しながら、まずは Sim 上で学習が回る状態を作り、policy 観測と action の流れを定義しました。
当初の観測は 26 次元で、主に以下を使っていました。
- 正規化した joint position
- joint velocity
- EE の絶対位置
- target との差分
- wrist / jaw の状態
- previous action
ただし、あとで実機評価を進める中で、この観測設計がそのままでは良くないことが分かります。
3. ROS 2 推論ノードと Isaac Sim 連携を作成
実機で policy を動かすために、まずは policy 実行部を ROS 2 ノードとして切り出し、あわせて Isaac Sim 側との topic 通信部分も整理しました。
主に追加したのは以下です。
scripts/ros2/policy_runner.pyscripts/ros2/real_policy_runner.pyscripts/ros2/joint_trajectory_to_array.py
この構成では、policy runner がやることを明確に分けています。
-
joint_statesを受け取る - TF から EE 位置を取る
- 学習時と同じ形式の観測を組み立てる
-
policy.onnx/policy.ptで推論する(今回はonnxを使用していました。) - 出力 action を関節目標へ変換して publish する
このとき、Isaac Sim 側と ROS 2 側が最低限どの topic をやり取りすればよいかもあわせて整理しました。
最低限必要だったのは次の 3 点です。
- 6 関節の
JointStateを publish できること -
base_link -> gripper_frame_linkの TF が取れること - policy が出した関節目標値を subscribe して反映できること
JointTrajectory をそのまま Sim 側で扱いにくい場面があったため、必要に応じて Float64MultiArray へ変換する adapter も用意しました。
python3 scripts/ros2/joint_trajectory_to_array.py \
--input-topic /isaac_joint_command \
--output-topic /isaac_joint_command_array
下記は学習した結果を確認した際の動画です。
4. Sim で先に通信確認
いきなり実機で試すのではなく、まずは Isaac Sim 上で配線が正しいかを確かめました。
確認したポイントは次の通りです。
-
joint_statesの joint 名と順序が想定通りか - TF で EE の姿勢が取れるか
- policy runner が観測を組み立てられているか
- command topic にデータが出ているか
- 実際に Sim の関節が動くか
5. 実機に流して動作確認
Sim 側の動作確認ができたあと、同じ系統の policy runner を実機側にもつなぎ、学習時に近い動きがどこまで再現できるかを確認しました。
結果としては、全然想定していた動きではありませんでした。
結論からいいますと、学習の際に使用していた観測データと、実機から取得できる観測データが全く異なっていたため、policyから出力されるactionデータがおかしな値になっていました。
6. 観測設計を 26 次元から 17 次元へ整理
そこで観測設計を見直し、以下を policy 入力から外しました。
- 6 次元の joint velocity
- 3 次元の EE 絶対位置
ee_pos_w
固定目標タスクで重要なのは「今どこにいるか」より「target まであとどれだけか」だったため、EE の絶対位置そのものではなく target_delta を残す形に整理しました。
最終的な観測は 17 次元です。
obs = [
joint_pos_normalized(6),
target_delta(3),
wrist_roll(1),
jaw(1),
prev_action(6),
]
この修正により、実機へ policy を流すこと自体はかなり安定しました。
7. reward と応答モデルも見直した
その後は、Jaw が開きやすい問題や、Sim の追従性が Real より良すぎる問題にも手を入れました。
具体的には次のようなことを行っています。
-
Jawを対称誤差ではなく、開く側だけを罰する片側ペナルティへ変更 - action noise 環境を拡張し、rate limit / tracking delay / transport lag を試す
- policy 周期と physics 周期を
60 Hzにそろえる
このあたりは「とりあえず動かす」フェーズよりも、「なぜ Sim と Real がズレるのかを詰める」フェーズの作業です。
結果
今回の時点で得られた結果は以下の通りです。
できたこと
-
Isaac Lab上で so101 の到達タスクを学習できた -
ROS 2の policy runner とIsaac Sim側の連携を整え、学習済み policy から関節目標を返せた - 実機 so101 を動かすところまでは確認できた
- 観測設計を 17 次元へ整理したことで、実機での挙動がかなり安定した
下記に動画を置いておきます。
いろいろな姿勢からでも戻れそうです。
分かったこと
- 実機を動かすには、Sim で動くこととは別に観測や追従性の整合を取る必要があった
- policy 観測に使う信号は、Sim と Real で意味が一致しているかをかなり慎重に見る必要があった
感想
AIってすげー
この一言に限ります。
今回の大目的としてはIsaacLabの学習結果を実機で確認することでしたが、それよりもコーディングAIが本当になんでも作ってくれるので、もうプログラミングしてないです。
その驚きに面食らってます。
この記事のたたき台もAIに作成していただいていますし、どんどん楽になりますね。
ただ、この記事に関してはもっと丁寧に手順を作成できればよかったのですが、ボリュームも大きくなって、まとめるのにも時間が掛かるし、かと言って時間を掛けすぎても、、、
という葛藤からもう面倒になって今回の状態でアップロードしています。
初めて強化学習を進めようと考えている人からすると、あまりいい記事ではないですね。。。
次回はもっと丁寧に作れるようにします!!!
今回の検証の話しをすると、 ROS 2 を共通インターフェースにしたことで、Sim で確認した実行系を実機へ流用することを確認しましたが、どのロボットも基本的にROS2に対応していると思うので、この手順は他でも流用できるだろうと考えています。
一方で、Sim2Real の難しさはまだまだ理解できていません。
今回行ったことは、決められた地点に移動するだけのタスクでしたが、フィジカルAIという意味ではロボットに自立して動いて貰いたい。そうするとカメラを付けたり、触覚センサを増やしたり、トルクセンサを用いたり、色々な情報を扱う必要があり、センサが増えていくことでどのような壁があるのか?またその解決方法を実際に手を動かしながら理解したいなと、考えています。
おわりに
今回は、so101 を実機で動かすことを主目的に、Isaac Lab で学習環境を作り、ROS 2 を介して Isaac Sim と実機をつなぎ、動作確認を進めた過程をまとめました。
まだ「学習通りの動きを実機で完全に再現できた」とは言えませんが、少なくとも
- IsaacLabによる学習環境の作成方法
- sim2realの動作方法
- 観測、報酬の考え方
は今回の動作検証をする前と今とでは解像度がかなり上がったかなと思います。
次はカメラも使用してisaac関連のアプリケーションを触ろうと思います。
お時間があればまた記事を見ていただけると幸いです!