🤖

SO-ARMとACTで実践する模倣学習

に公開

はじめに

本記事では、オープンソースのロボットアーム SO-ARM と模倣学習アルゴリズム ACT を用いて、模倣学習を実施する一連のプロセスを紹介します。

環境構築、データ収集、モデル学習、そして実機評価まで、筆者が実際に試したコマンド、直面した課題について詳しく解説します。可能な限り、つまずきやすいポイントや気になった部分を細かく記載しているので、これから始める方の参考になれば幸いです。

SO-ARMとは

SO-ARM(Standard Open Arm) は、RobotStudio と HuggingFace が共同で開発したオープンソースのロボットアームです。3Dモデル、ソフトウェア、部品リストなど、ロボットを作るために必要な情報がすべて無償で公開されており、誰でも市販のパーツを揃え、3Dプリンターでパーツを出力することで、本格的なロボットアームを自作できます。

以下のGitHubリポジトリで、「SO-100」や「SO-101」といったモデルの設計データが公開されています。「SO-100」は旧バージョン、「SO-101」が新バージョンのモデルとなります。

https://github.com/TheRobotStudio/SO-ARM100

SO-ARMは2つのアームで構成されています。

  • リーダーアーム: 人が操作するためのコントローラーの役割を持つアーム
  • フォロワーアーム: 実際に物をつかんだり動かしたりするアーム


左図: フォロワーアーム 右図: リーダーアーム

SO-ARMには、リーダーアームの動きをフォロワーアームがそっくりそのまま真似できる仕組みが標準で備わっています。これにより、遠隔から直感的に操作できるだけでなく、動きを記録してAIに覚えさせ、自律的に動かすといった高度な使い方も可能になります。

模倣学習とは

模倣学習(Imitation Learning) とは、専門家や熟練者の行動を観察し、それを模倣することで行動パターンを学習する機械学習の一手法です。特に、ロボット制御や自動運転、ゲームAIなど、エージェントが特定のタスクを遂行する場面で活用されています。

強化学習のように試行錯誤を繰り返しながら報酬を最大化するのではなく、人間などの熟練者が実際にどのように行動したかというデモンストレーションデータから直接学習する点が特徴です。

強化学習では、エージェントが環境内で行動を探索し、膨大な試行回数を通じて最適な方策を学習します。しかし、現実世界のロボットや自動運転では、こうした試行には時間やコスト、安全性の課題が伴います。さらに、探索が非効率でタスク達成までに多くの無駄な行動が必要になったり、適切な報酬関数を設計することが難しかったりする問題もあります。
こうした課題を解決する手段として、熟練者の行動データを活用し、効率的に望ましい行動を学習できる模倣学習が注目されています。


模倣学習と強化学習の違い 出典: https://qiita.com/michi_i/items/e80489a3c385b777599f

模倣学習の基本的な仕組み

模倣学習では、主に以下のような流れで学習が行われます。

  1. 専門家デモンストレーションの収集
    熟練者がタスクを実行する様子を記録します。これには、状態(環境情報)と行動(操作や判断)のペアを大量に収集する必要があります。

  2. 方策(Policy)の学習
    収集した状態 – 行動のペアを使って、エージェントがある状態において専門家と同じ行動を取るように方策(行動ルール)を学習します。

  3. 模倣行動の実行と評価
    学習した方策を用いて実際にタスクを遂行し、専門家に近い振る舞いができるか評価します。必要に応じて再学習やデータの追加収集を行い、性能を改善します。

ただし、模倣学習には以下のような課題があります。

  • 分布のシフト(Distributional Shift)
    学習時に観測しなかった状態に遭遇した場合、エージェントが誤った行動を取りやすい問題です。専門家デモだけではタスクに登場するすべての状態を網羅できず、未知の状況で失敗しやすくなります。

  • 誤差の蓄積
    小さな行動の誤差が繰り返し積み重なり、徐々に専門家の軌跡から乖離していく現象です。このため、単純な教師あり学習では不十分なことも多いです。

  • データの収集コスト
    質の高い専門家データを収集するには多大な手間とコストがかかります。特にロボットや自動運転では実世界での収集が大きな負担となります。

こうした課題を克服するため、近年は長期的な行動パターンを一貫して学習できる新たなアプローチが注目されています。その一つが Action Chunking Transformer Policy(ACT) です。

ACTとは

ACTでは、状態に対して単発の行動を出力するのではなく、まとまった行動のチャンクを一括して生成することで、誤差の蓄積や分布のシフトに強い方策を構築します。また、Transformerアーキテクチャを活用することで、行動シーケンス全体における長期依存関係を効果的に捉えることが可能です。

https://arxiv.org/abs/2304.13705

ACTの最大の特徴は、1ステップ先だけを予測するのではなく、複数ステップ先のアクション列を「チャンク」としてまとめて予測する点です。たとえば、10秒間(500ステップ)のタスクで、100ステップ分のチャンクを一度に出力すれば、制御の決定は5回だけで済みます。これにより、タスク全体を俯瞰しながら動作を計画でき、誤差が蓄積しにくくなります。

ACTはこうしたチャンク予測を支えるために、条件付き変分オートエンコーダ(Conditional Variational Autoencoder: CVAE)Transformer を組み合わせたアーキテクチャを採用しています。モデルは大きく「エンコーダ」と「デコーダ」に分かれています。エンコーダは人間のデモンストレーションから得られた複数タイムステップ分の観測情報とアクション系列を入力として受け取り、それらを潜在変数 z に圧縮します(下図の左側)。この潜在変数は動作のスタイルや多様なバリエーションを表現する役割を担っています。一方、デコーダは現在の観測とこの潜在変数を条件として、将来のアクションチャンクを一度に生成します(下図の右側)。

入力としては、ロボットの周囲を捉える複数台のRGBカメラ画像(例:4台の480×640ピクセル)と関節角度が用いられます。画像はまずCNN(ResNet18など)によって高次の特徴ベクトルに変換され、位置エンベディングを付与されます。また、関節状態も埋め込みベクトルに変換され、Transformerエンコーダに入力されます。CVAEのエンコーダは、これらと実際のアクション列を組み合わせて潜在空間を学習し、潜在変数の分布を推定します。推論時はこの潜在変数を0に固定することで、決定論的かつ安定した行動生成が可能になります。

一方、アクションチャンクを長くすると、生成後に環境が変化した際、行動修正が遅れるリスクがあります。また、チャンクの切り替えがうまくいかないと、動きが途切れたり不自然になったりする恐れもあります。

これを補うため、ACTでは 「時間的アンサンブル(Temporal Ensembling)」 が導入されています。これは、毎タイムステップで最新の観測から新たなチャンクを再予測し、直近の複数チャンクを重み付けして平均化する仕組みです。最新の予測を最も重視しつつ、直前の計画も滑らかに反映することで、環境の変化に柔軟に対応しながら一貫性ある制御を実現します。

さらに詳しく知りたい方は、以下の記事も参考になります。
https://note.com/masato_ka/n/n397774650499

今回使用する lerobot ライブラリには、このACTが実装されており、比較的容易に高性能な模倣学習を試すことができます。

模倣学習の実践

ここからは、実際に SO-ARM を用いた模倣学習に取り組んでいきます。

検証環境

以下は、私が検証に使用した環境情報です。PCのスペックとしてはギリギリでしたので、動作させる際の目安として参考にしてください。なお、SO-ARM は Ubuntu または Mac でのみ動作します。Windows ユーザーの方はご注意ください。

PC環境

  • モデル: MacBook Air
  • チップ: Apple M1
  • メモリ: 16GB
  • OS: macOS Sequoia 15.3.2
  • Python: 3.11.0

ロボットアーム

以下は、私がロボットアームを組み立てる際に購入した部品一覧です。目的や予算に応じて必要な部品や仕様を検討してください。おおよそ5万円ちょっとで組み立て可能です。

SO-ARM101

私は Seeed Studio でキットを購入しました。中国の倉庫からの発送で、送料や輸入関連費込みで50,401円、到着まで約5日ほどかかりました。現在は秋月電子通商でも取り扱いがあるようなので、そちらを利用すると、より安く早く入手できるかもしれません。(結構売れていて在庫が少ないという噂も。。。)

モーターなどを含むアームサーボモーターキットと、3Dプリントパーツをそれぞれ用意する必要があります。より強い力が必要な場合は Pro版を、特にこだわりがなければ通常版で問題ないと思います。

https://www.seeedstudio.com/SO-ARM101-Low-Cost-AI-Arm-Kit-Pro-p-6427.html
https://www.seeedstudio.com/SO-ARM101-3D-printed-Enclosure-p-6428.html

カメラ

アームの手首に取り付ける手首カメラと、全体を俯瞰撮影するサイドカメラの2台構成にしました。サイドカメラはもともとWeb会議用に使用していたもので、特に機種にこだわりはありません。

https://www.amazon.co.jp/dp/B0CLRJZG8D
https://www.amazon.co.jp/dp/B07MBQ1PT3

クランプ

リーダーアームとフォロワーアームを机に固定するためのクランプです。片側のみの固定では外れやすいため、各アームに1セットずつ(計2点)購入しました。

https://www.amazon.co.jp/dp/B00G8PR80G

アームの組み立て

アームの組み立て手順については、公式ドキュメントや解説記事が多数公開されているため、本記事では詳細な説明は割愛します。以下に参考になる記事や動画をいくつか紹介します。

https://huggingface.co/docs/lerobot/so101
https://tech-blog.abeja.asia/entry/so101-assembly-report-v2-202506
https://www.youtube.com/watch?v=70GuJf2jbYk&t=548s

組み立ての際は、ファームウェアのバージョンやモーターの配線、組み立ての順序など、いくつか注意すべきポイントがあります。参考記事をよく確認しながら、慎重に作業を進めることをおすすめします。

私は以下のイベントに参加し、ロボスタディオン様にサポートいただきながら組み立てを行いました。一人での作業に不安がある方は、こうしたイベントに参加したり、ロボスタディオン様に訪問してに相談するのもおすすめです。

https://robostadion.connpass.com/event/360113/

環境構築

模倣学習を進めるための環境構築手順を紹介します。

公式手順は以下に記載されています。
https://huggingface.co/docs/lerobot/installation

仮想環境の作成

公式では Anaconda による環境構築が推奨されていますが、私は Anaconda を使いたくなかったため、venv を利用しました。現在のところ特に問題は発生していませんが、不安な方は公式手順に従ってください。

venv で仮想環境を作成・アクティベートします。

python -m venv venv
source venv/bin/activate

ffmpegのインストール

カメラを利用する場合、ffmpeg が必要です。Homebrew でインストールします。

brew install ffmpeg

LeRobotのインストール

LeRobot のリポジトリをクローンし、必要なライブラリをインストールします。

git clone https://github.com/huggingface/lerobot.git
cd lerobot && pip install -e ".[feetech]"

キャリブレーションとテレオペレーション

次に、各アームの初期設定(キャリブレーション)と遠隔操作(テレオペレーション)が正しく機能するか確認します。

公式手順は以下に記載されています。
https://huggingface.co/docs/lerobot/so101

キャリブレーション

キャリブレーションは、リーダーアームとフォロワーアームが同じ物理位置にあるとき、同じ座標データを持つよう調整するプロセスです。具体的な手順は公式の参考動画も併せてご確認ください。

  1. 各アームをPCに接続し、以下のコマンドを実行します。

    フォロワーアームの場合

    python -m src.lerobot.calibrate \
      --robot.type=so101_follower \
      --robot.port=/dev/tty.usbmodemXXXXXXXXXXX \
      --robot.id=my_follower_arm
    

    リーダーアームの場合

    python -m src.lerobot.calibrate \
      --teleop.type=so101_leader \
      --teleop.port=/dev/tty.usbmodemYYYYYYYYYYY \
      --teleop.id=my_leader_arm
    
  2. 各関節を中間位置(ミドルポジション)にセットします。
    下の画像を参考にアームをまっすぐ伸ばし、この状態で Enter キーを押します。

  3. 各関節を可動範囲の両端まで動かし、可動域を記録します。
    ロボットの全関節(6つのモーター)を可動範囲いっぱいに動かし、可動域を記録してください。完了後に Enter キーを押します。

テレオペレーション

キャリブレーション完了後、実際にリーダーアームでフォロワーアームを操作してみます。

カメラなしでのテレオペレーション

python -m src.lerobot.teleoperate \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodemXXXXXXXXXXX \
  --robot.id=my_follower_arm \
  --teleop.type=so101_leader \
  --teleop.port=/dev/tty.usbmodemYYYYYYYYYYY \
  --teleop.id=my_leader_arm

カメラありでのテレオペレーション

python -m src.lerobot.teleoperate \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodemXXXXXXXXXXX \
  --robot.id=my_follower_arm \
  --robot.cameras='{
    "wrist": {"type": "opencv", "index_or_path": 0, "width": 1280, "height": 720, "fps": 30},
    "side": {"type": "opencv", "index_or_path": 1, "width": 1280, "height": 720, "fps": 30}
  }' \
  --teleop.type=so101_leader \
  --teleop.port=/dev/tty.usbmodemYYYYYYYYYYY \
  --teleop.id=my_leader_arm \
  --display_data=true
カメラの設定方法がわからない方へ

以下の記事に、接続されているカメラの検出や設定値を確認する方法が紹介されています。
https://huggingface.co/docs/lerobot/cameras

データ収集方法

いよいよ、模倣学習のお手本となるデータを収集します。
例として「おもちゃのブロックを掴んでお皿に入れる」というタスクを、10エピソード分記録します。

python -m src.lerobot.record \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodemXXXXXXXXXXX \
  --robot.id=my_follower_arm \
  --robot.cameras='{
    "wrist": {"type": "opencv", "index_or_path": 0, "width": 1280, "height": 720, "fps": 30},
    "side": {"type": "opencv", "index_or_path": 1, "width": 1280, "height": 720, "fps": 30}
  }' \
  --teleop.type=so101_leader \
  --teleop.port=/dev/tty.usbmodemYYYYYYYYYYY \
  --teleop.id=my_leader_arm \
  --dataset.repo_id=ricky0526/so101_pick_toy \
  --dataset.single_task="Pick up the toy and place it on the plate." \
  --dataset.num_episodes=10 \
  --dataset.episode_time_s=20 \
  --dataset.reset_time_s=10 \
  --display_data=False \
  --resume=False

良いデータセットの収集方法については、以下の記事が参考になります。
https://huggingface.co/blog/lerobot-datasets#what-makes-a-good-dataset

また、HuggingFace にデータセットを公開している場合、以下のサイトでリポジトリ名を入力すると収集したデータを可視化して確認することができます。
https://huggingface.co/spaces/lerobot/visualize_dataset

モデル学習

収集したデータを模倣学習にて学習します。私は手元に十分なGPU環境がなかったため、Google Colab Pro(A100 GPU)を使用して学習を行いました。カメラ1台の場合で約3時間、2台の場合で約6時間ほど学習に時間がかかりました。カメラの台数や解像度、バッチサイズによって、学習時間は変動すると思います。

Google Colab における学習コードが知りたい方へ

参考までに、以下に私が学習に使用したコードを共有します。

まず、学習済みモデルのチェックポイントを Google Drive 上にバックアップしたい場合、Drive をマウントします。不要な場合はコメントアウトしてください。

from google.colab import drive
drive.mount("/content/drive")

# ディレクトリを移動
%cd /content/drive/MyDrive/Python/PhysicalAI/LeRobot

 
condacolab を利用して、Colab 内で Conda 環境を構築します。

!pip install -q condacolab
import condacolab
condacolab.install()

 
HuggingFace から lerobot リポジトリをクローンし、FFmpeg をインストールして依存パッケージをセットアップします。(pip install で一度カーネルがクラッシュしますが、セッションを再起動すれば問題なく進めます。)

!git clone https://github.com/huggingface/lerobot.git
!conda install ffmpeg=7.1.1 -c conda-forge
!cd lerobot && pip install -q -e .

 
Weights & Biases にログインして実験ログの記録を有効化し、HuggingFace にもログインしてチェックポイントをアップロードできるようにします。各サービスのAPIキーはあらかじめ取得しておいてください。

!wandb login
!huggingface-cli login

 
使用する学習データやモデルの出力先を変数として定義しておきます。

# 学習データとモデル出力先の指定
exp_name = "so101_pick_toy"
DATASET_REPO_ID = f"ricky0526/{exp_name}"
POLICY_REPO_ID = f"ricky0526/act_{exp_name}"
OUTPUT_DIR = f"outputs/train/act_{exp_name}"
JOB_NAME = f"act_{exp_name}"

 
lerobot ライブラリの train.py を実行し、ロボット制御ポリシーをトレーニングします。

!cd lerobot && python src/lerobot/scripts/train.py \
  --dataset.repo_id=$DATASET_REPO_ID \
  --policy.repo_id=$POLICY_REPO_ID \
  --policy.type=act \
  --output_dir=$OUTPUT_DIR \
  --job_name=$JOB_NAME \
  --policy.device=cuda \
  --wandb.enable=true

 
念のため、中間のチェックポイントも HuggingFace にアップロードしておきます。

!huggingface-cli upload ricky0526/act_so101_pick_toy_020000 \
lerobot/outputs/train/act_so101_pick_toy/checkpoints/020000/pretrained_model

!huggingface-cli upload ricky0526/act_so101_pick_toy_040000 \
lerobot/outputs/train/act_so101_pick_toy/checkpoints/040000/pretrained_model

!huggingface-cli upload ricky0526/act_so101_pick_toy_060000 \
lerobot/outputs/train/act_so101_pick_toy/checkpoints/060000/pretrained_model

!huggingface-cli upload ricky0526/act_so101_pick_toy_080000 \
lerobot/outputs/train/act_so101_pick_toy/checkpoints/080000/pretrained_model

学習結果

今回は、おもちゃのブロックを掴んでお皿に入れるタスクに取り組みました。うまくいくまでに試行錯誤を繰り返したので、その過程もあわせて紹介します。

モデルの推論時にはデータ収集時に使用した record.py にモデルのパスを指定することで推論することが可能です。

python -m src.lerobot.record  \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodemXXXXXXXXXXX \
  --robot.id=my_follower_arm \
  --robot.cameras='{
    "wrist": {"type": "opencv", "index_or_path": 0, "width": 1280, "height": 720, "fps": 30},
    "side": {"type": "opencv", "index_or_path": 1, "width": 1280, "height": 720, "fps": 30}
}' \
  --display_data=false \
  --dataset.repo_id=ricky0526/eval_so101_pick_toy \
  --dataset.single_task="Pick up the toy and place it on the plate" \
  --dataset.num_episodes=1 \
  --dataset.episode_time_s=30 \
  --dataset.push_to_hub=false \
  --policy.path=ricky0526/act_so101_pick_toy \
  --policy.device=mps \
  --display_data=False \
  --resume=False

Take 1

まずは手探りでベースラインを作るため、あまり設定を詰めすぎずに学習を試しました。
カメラは手首とロボット真上に1台ずつ設置し、アームがさまざまな位置に置かれたブロックを掴もうとする動作を記録しました。

学習条件

撮影環境

結果

https://youtu.be/BmvNciF4U9s

アームがブロックには近づくことはできるものの、全く掴むことができませんでした。見た目にも惜しい感じはなく、まだまだ試行が必要そうです。

考察

  • 真上のカメラでは、アームがブロックに近づく際にブロックが隠れてしまうため、カメラの位置が良くないのではないか。
  • 初期位置が毎回ランダムで、ロボットアームのスピードが速く動きも雑であったため、モデルが安定した動きを覚えられなかったのではないか。

Take 2

Take 1の反省から、ブロックがカメラに隠れにくい配置に変更し、一貫した動きを覚えさせることを目指しました。
真上カメラをやめ、斜めからのサイドカメラを導入してロボットの動作全体が映るようにしました。また、同じ初期配置を10エピソードずつ繰り返し、安定した軌道をしっかり学習させる方針に変更しました。

学習条件

撮影環境

結果

https://youtu.be/j6eEtyiHlkY

前回より明らかに進歩し、アームがブロックにしっかり近づいて掴もうとする動作が見られました。ただ、最後の位置合わせがうまくいかず、まだ成功には至りませんでした。また、手首カメラの映像を隠して実行したところ(動画の episode2)、むしろブロックへの接近がうまくいく現象も確認できました。これは後々気づいたのですが、PCのスペック不足でデータ収集時にアームが大きく揺れ、手元カメラの映像がぶれてしまい、学習がうまくいっていないことが原因でした。

考察

  • 手首カメラを使わないほうが動作が安定するのではないか。
  • 同じ条件を繰り返したことで特定のパターンは覚えられたが、条件が少し変わるとうまく動かず汎化性能が低くなるのではないか。
  • 50エピソードではまだデータが少なく、ロバストな動作には不十分ではないか。

Take 3

Take 2の気づきを踏まえ、カメラ構成をシンプルにし、データの量と多様性を両立する方針に切り替えました。
手首カメラを廃止し、サイドカメラのみを使用。カメラ位置も調整し、真横から全体が映るようにしました。データ収集では、基本的な動きを5エピソードずつ集めた上で、残りはランダム配置にして汎化性能を高める工夫をしました。収集エピソード数も80エピソードに増やしています。

学習条件

撮影環境

結果

https://youtu.be/H1b2BlbL15A

ついにブロックを掴んで持ち上げることに成功しました!ただし、いくつかのケースでは奥行きの位置合わせが不安定で、うまく掴めない場面も残りました。

考察

  • カメラが横からのみだと、奥行きの認識が難しいため失敗しやすいのではないか。
  • サイドカメラ1台構成でも一定の学習が可能だが、精度を上げるにはやはり視点の多様性が必要そう。

Take 4

最後に奥行き方向の認識精度を上げるため、フロントカメラを追加し検証しました。それ以外の条件は特に変えていません。

学習条件

撮影環境

結果

https://youtu.be/malf5xhytcw

ほとんどのケースでブロックをしっかり掴み、運べるようになりました。位置が遠かったりブロックが傾いた場合は成功率がやや下がりますが、数回トライすることでほとんど達成できるレベルになりました!

まとめ

このようなブロックを掴むタスクにおいては、ブロックの位置合わせが非常に重要となるため、カメラの設置位置が大きな影響を及ぼすと感じました。私は環境の都合上、手首カメラをうまく使えませんでしたが、もし手首カメラを使わない場合には、異なる二方向から俯瞰できるようにカメラを配置し、ブロックの位置を正確に把握できるようにするのが有効だと思います。

データの収集方法については、一定の規則性を持たせつつも、ブロックの位置や向きをランダムに変化させることで、汎化性能が高まる印象がありました。目安としては、少なくとも50エピソード以上のデータを用意すると良さそうです。また、アームの操作についても、あまり気を使いすぎず、あらかじめ基本的な動作のパターン(例えば「アームを開く → 位置合わせをする → 掴む」)を決めておく程度で問題ないと感じました。

※ 私はプロではないので、あくまで一例として参考にしていただければと思います。また、タスクの内容によって最適な条件は大きく変わります。

詳細分析

ある程度うまくいったTake 4のモデルで、追加でいくつか検証を行いました。

汎化性

まずは、学習データにない条件で動作確認を行いました。
ブロックを2つ置いた場合(episode1)では、間を掴もうとする挙動を確認できました。複数のターゲットがあるとattentionが分散し、一方に狙いを定めるのが難しいのかもしれません。学習と異なる種類のブロックを置いた場合(episode2)には、関係なく掴もうとする動作が見られました。

https://youtu.be/p2u1r0cNDg8

ステップ数比較

次に、学習ステップ数が動作の安定性にどの程度影響するかを確認しました。
20,000ステップの時点でも、ある程度目的に沿った動きをする様子が見られましたが、まだ失敗が多く、動作が不安定となっていました。ステップ数を増やすごとに挙動のブレが減り、成功率も高まる傾向が確認できました。今回のような簡単なタスクであれば、40,000~60,000ステップでも十分に機能しそうです。

https://youtu.be/K8YMw_pE6DA

学習時のロスもステップ数を重ねるにつれて、下がり続けていました。

Attention Mapの確認

Attention Mapの確認にも挑戦しました。これは、ロボットがどの部分の視覚情報に注目して判断しているかを分析するというものです。

以下のリポジトリにあるコードを利用しようとしたのですが、Lerobot側のコードが大幅に更新されており、そのままでは動作しませんでした。色々と弄っては見たものの、かなりの改修が必要と判断し今回は途中で断念しました。もし興味のある方は試してみると面白いと思います。(もしやり方がわかったら教えてほしいです!)

https://github.com/villekuosmanen/physical-AI-interpretability

つまずきポイント

最後に作業中に直面した問題と、その解決策を共有します。同じ課題に遭遇した方やこれから始める方の参考になれば幸いです。

手首カメラの取り付け部品がない

Seeed Studio の3Dプリントパーツセットには、手首カメラを固定する部品が含まれていません。そのため、公式リポジトリのCADデータから該当パーツを3Dプリントする必要があります。また、取り付け用のネジ(M3 12mmくらい)も付属していないので、別途用意する必要がありました。もし、Seeed Studio で購入予定で手首カメラを使おうと考えている方は、取り付けパーツとネジを準備しておいた方が良さそうです。

データ収集時の ConnectionError

USBカメラを2台接続し、rerun のUI(--display_data=true)を有効にしてデータ収集を行うと、以下のエラーが発生しました。

ConnectionError: Failed to sync read 'Present_Position' on ids=[1, 2, 3, 4, 5, 6] after 1 tries. [TxRxResult] There is no status packet!

テレオペレーション時には問題なかったため、データ記録とリアルタイム描画の負荷が原因だと思います。--display_data=False に変更して描画をなくすことでエラーは解消しました。M1 Mac の処理能力では、2台のカメラ映像を描画しながらのデータ記録は厳しいのかもしれません。

カメラ接続時の TimeoutError

当初、Androidスマホのカメラを仮想Webカメラ化する「Camo」というソフトを利用しようとしたところ、データ収集時に以下のエラーが発生しました。

TimeoutError: Timed out waiting for frame from camera OpenCVCamera(1) after 200 ms. Read thread alive: True.

rerun で映像を確認したところ1秒以上の遅延があり、明らかに帯域不足でした。Camo をやめてUSB接続のWebカメラに切り替えることで解決しました。

テレオペ時にアームがガタつく

USBカメラを2台接続した状態でテレオペレーションを行ったところ、フォロワーアームがガクガクと震えながら動くという現象が発生しました。カメラを1台に減らすとこの現象は解消されたことから、USB通信の帯域やPCの処理能力が原因であると考えられます。そこでUSBハブを変更して試みましたが改善は見られなかったため、PCの処理能力不足の可能性が高そうです。今回はやむを得ずこの状態のまま作業を継続しましたが、アームの振動はモデル学習に悪影響を及ぼす恐れがあるため、十分に注意しながら進める必要があります。

アームの部品が折れた

ブロックを掴んだ際に、フォロワーアームの先端部品が破損しました。この部分はキャリブレーション時に先端を手で動かすため、力が集中しやすい部分です。また、Pro版ではサーボモーターの出力が大きく、部品を掴む際にも余計に負荷がかかったのかもしれません。部品の扱いは丁寧に行う必要があるという教訓を得ました。

おわりに

本記事では、オープンソースのロボットアーム SO-ARM を使い、模倣学習を行うプロセスを紹介しました。自分が苦労して収集したデータを学習させて、モデルが想定通りに動いてくれたときはとても嬉しいものでした。

今後は、より複雑なタスクやVLAのファインチューニングにも挑戦してみたいと思います。最後までお読みいただき、ありがとうございました。

Discussion