はじめに
SO-101のロボットアームを購入し、フィジカルAIに入門してみました。組み立てから機械学習までやってみた感想をご紹介しますので良かったらご一読くださいませ。
環境について
- Python 3.12
- LeRobot 0.5.1
huggingface/lerobotを参考に環境構築します。
組み立て
SO-101は3Dプリンターで印刷された各パーツとサーボをレゴブロックのようにくっつけて完成させる必要があります。そこで必要になった工具が下記のリストになります。
- 精密ドライバー
- マスキングテープ
- 油性ペン
- ゴムヘッドのハンマー
- 先曲がりのピンセット
- 鉄製のやすり
SO-101はリーダーアームとフォロワーアームの2つを組み立てる必要があり、それぞれで必要なサーボが異なります。また、サーボを組み立てる前にIDの割り当てなどシステム的なことをやったりする必要もあるため、マスキングテープをサーボに貼り付け、メモ出来るようにすると組み立て時に役に立ちます。加えて3Dプリンター製のパーツになるため、接続先の穴が小さかったりなどスムーズに組み立てられなかったりします。そこでゴムヘッドのハンマーや鉄製のやすりがあると便利です。サーボにケーブルを差し込む穴が深いため、先曲がりのピンセットは欲しいところです。
以上の工具を準備して実際に組み立てた感想として、先にサーボのIDの割り当てをし、最後にデイジーチェーンをすると手戻りに苦戦することなくスムーズに組み立てることが出来ます。キャリブレーションは公式が動画を上げているため、そちらを参考にすることをお勧めします。
学習から検証
キャリブレーションまで済ませたら、次にテレオペレーションをします。今回はカメラを2台使用するため、次のコマンドでカメラのIDを確認します。
lerobot-find-cameras opencv
実行するとoutputsフォルダーにIDごとの撮影した画像とログにカメラのスペックが出力されます。そちらの情報をもとにオプションを定義し、次のテレオペレーションのコマンドを実行します。
lerobot-teleoperate \ --robot.type=so101_follower \ --robot.port=/dev/{yr_follower_arm_port_path}\ --robot.id={yr_follower_arm_id} \ --robot.cameras="{front: {yr_front_camera_option}, wrist: ...}" \ --teleop.type=so101_leader \ --teleop.port=/dev/{yr_leader_arm_port_path} \ --teleop.id={yr_leader_arm_id} \ --display_data=true
問題なく組み立てまで完了していると2つのアームが立ち上がり、リーダーアームの動きにフォロワーアームが追従します。この仕組みを用いて学習用データを作ります。
Hugging Faceのトークンを作成し、hfコマンドを使って事前にログインします。ログイン完了後、Hugging Faceのページから+New Datasetと+New Modelでデータセットとポリシーを保存するためのものを作ります。準備完了後、下記のコマンドを叩きデータセットを手動で作りに行きます。
lerobot-record \ ... # テレオペレーションと同じ設定 --display_data=true \ --dataset.repo_id={Datasetのid} \ --dataset.root=./record-test \ # 適当なフォルダ名を定義 --dataset.single_task="タスク説明 例えば: Pick up the blockなど" \ --dataset.num_episodes=20 \ # 今回レコーディングするデータ数 --dataset.episode_time_s=30 \ # 1エピソードの時間 --dataset.reset_time_s=10 # 状態を戻すための猶予時間
この例だと1エピソードを作るのに30秒+10秒+プログラムのリセット時間で約50秒ほどになります。それを20エピソード作るため、全体では約50秒 x 20回、およそ約17分にわたってロボットアームを操作することになります。これまで何回か調査をしたところ少なくとも約50エピソードはあると良いため、1回の実行で10エピソードずつレコーディングし、休憩を挟みながら5回繰り返すことをお勧めします。追加で学習データを作るには、上記のコマンドに繋げて下記オプションを入れます。
lerobot-record \ ... --dataset.reset_time_s=10 \ --resume=true
データを作成したら、次に学習させる必要があります。ポリシーについて、今回はACTを選択します。また、macOSの環境で学習を行うため、deviceはmpsを選択しています。NVIDIA系のGPUなどをお使いの環境ではcudaを選択してください。
lerobot-train \ --dataset.repo_id={} \ # レコーディングで使用したデータセットのid --batch_size=2 \ # 環境に合わせて調整してください --num_workers=0 \ # 環境に合わせて調整してください --policy.type=act \ --policy.device={} \ # macOSならmps --steps=100000 \ # 環境に合わせて調整してください --output_dir=outputs/train/policy-test \ # 適当な出力先を定義 --policy.repo_id={} \ # +New Modelで作ったポリシーのID --policy.push_to_hub=true \ --wandb.enable=false
学習はバッチサイズ8の10万ステップが良いとされていますが、今回用意した環境では学習に40日かかるためバッチサイズを2でやっています。それでも時間がかかる環境であれば、クラウドで学習環境を用意するかステップ数を減らすことをお勧めします。学習が完了したら検証コマンドを叩き、実際にロボットに自律動作してもらいます。
lerobot-record \ --robot.type=so101_follower \ --robot.port={} \ # 基本的にテレオペレーションで使用したのと同じものを入れます --robot.id={} \ --robot.cameras="{...}" \ --dataset.repo_id={evalをつける必要があります} \ # レコーディングの時のrepo_idがAAA/my_datasetならAAA/eval_my_datasetとします --dataset.single_task="レコーディングと同じ内容で入れると良いでしょう" \ --dataset.num_episodes=3 \ --dataset.episode_time_s=120 \ --dataset.reset_time_s=5 \ --dataset.push_to_hub=false \ --policy.path=./pretrained_model \ # 後述 --display_data=false # GUIが必要であればtrueにする
pretrained_modelは学習コマンドで定義した出力先にあるlastフォルダーの中にあります。そのフォルダーへのpathを定義する必要があります。今回はルートにコピペしているため、”./pretrained_model” としています。出来上がったポリシーを実際に動かした結果が次の動画になります。
まとめ
組み立てに手こずり、データ収集に時間がかかり、学習にも根気が必要でしたが、最終的にロボットアームが自分の意図した動きをしてくれたときは素直に感動しました。フィジカルAIは触ってみるまでハードルが高そうに感じていましたが、実際に手を動かしてみると得られる学びが多く、非常に良い経験になりました。これからハードウェアとAIの学習に挑戦してみたいという方の参考になれば幸いです。
