
SO-ARM101 を組み立てて LeRobot でテレオペレーションしてみた
はじめに
こんにちは、クラスメソッド製造ビジネステクノロジー部の森茂です。
以前の記事では、Isaac Sim のシミュレーション環境で SO-ARM101 の強化学習に取り組み、報酬関数のカスタマイズで学習結果がどう変わるかを観察しました。今回は第二弾、あの黄色いロボットアームを実際に組み立てて、LeRobot のテレオペレーションで動かしてみます。組み立て手順の詳細は公式リソースに譲り、「やってみて分かったこと」「ハマったこと」を中心にお伝えします。
今回のゴール
3 段階で進めます。
- SO-ARM101 Pro キットの組み立て(フォロワーアーム + リーダーアーム)
- キャリブレーションの実施
- LeRobot でテレオペレーション動作確認

前提環境
| 項目 | バージョン |
|---|---|
| マシン | MacBook Pro(M4) |
| OS | macOS Tahoe 26.3 |
| Python | 3.12 |
| LeRobot | v0.4.4 |
| uv | 0.9.21 |
SO-ARM101 Pro キットの内容
今回使ったのは Seeed Studio の SO-ARM101 Pro Kit(Print Parts Kit) です。フォロワーアームとリーダーアームの 2 本分のパーツが一式入っています。3D プリント済みパーツ、サーボモーター 12 個、USB シリアルアダプタ 2 本、アダプタボード 2 枚という構成ですね。
ここで気になるのがサーボモーターの違いです。12 個入っていますが、4 種類の型番が混在しています。
| 型番 | 数量 | 用途 | 電圧 | ギア比 |
|---|---|---|---|---|
| C047 | 6 | フォロワー全関節 | 12V | 1/345 |
| C044 | 2 | リーダー Joint 1, 3 | 7.4V | 1/191 |
| C046 | 3 | リーダー Joint 4, 5, 6 | 7.4V | 1/147 |
| C001 | 1 | リーダー Joint 2 | 7.4V | 1/345 |
フォロワーアームは C047 で統一されているのでシンプルですが、リーダーアームは関節ごとにギア比が異なるサーボを使い分けています。リーダーは人が手で操作するアームなので、関節によって操作感を軽くするためにギア比を下げているわけですね。サーボの外見がほぼ同じなので、型番シールをよく確認してから組み立てに入るのがおすすめです。
キットに含まれないものとして、AC アダプタが 2 つ必要です。フォロワー用に 12V 5A、リーダー用に 5V 4A、いずれも DC 5.5mm/2.1mm のセンタープラスです。自分は PSE マーク付きのスイッチング式 AC アダプタを別途調達しました。
環境構築
LeRobot のインストールには uv を使いました。Python 3.12 を明示的に指定するのがポイントです。
uv init --python 3.12 lerobot-workspace
cd lerobot-workspace
uv add lerobot
モーター ID の設定
組み立ての前に、サーボモーターの ID を設定します。工場出荷時はすべてのモーターが同じ ID を持っているため、1 つずつ接続して順番に ID を書き込んでいく作業です。
まずはポートを確認します。
uv run lerobot-find-port
USB シリアルアダプタを差し込む前後で実行すると、どのポートに割り当てられたかがわかります。macOS だと /dev/tty.usbmodemXXXX のような名前になりますね。
フォロワーから設定していきます。
uv run lerobot-setup-motors \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodemXXXX
対話式のプロンプトに従って、1 モーターずつ接続 → ID 設定 → 次のモーターを接続、というサイクルを繰り返します。フォロワー 6 個が終わったら、リーダーも同じ要領で進めます。
uv run lerobot-setup-motors \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodemYYYY

地味な作業ですが、作業自体は画面の指示に従うだけなので迷うことはありませんでした。
組み立て
参考リソース
組み立て手順の詳細は、以下の公式リソースを参照してください。
- WowRobo Assembly Guide(動画) — 組み立て工程を通しで見られます
- HuggingFace SO-101 公式ドキュメント — モデルの組み合わせ動画とテキストベースの手順書
- Seeed Studio Wiki — Pro Kit 固有の情報が充実
この記事では手順の再現ではなく、実際に組み立てて気づいたことを中心に書いていきます。
フォロワーアームの組み立て
フォロワーアームの組み立ては約 2 時間でした。WowRobo の動画を見ながら進めれば、特に難しいところはありません。3D プリントパーツとサーボモーターをネジで固定していく作業の繰り返しです。
一点、ケーブル配線について。WowRobo の動画では組み立てが終わってからケーブルを通していますが、個人的には組み立てと同時にケーブルを引き回した方が楽でした。パーツを組み付ける前ならケーブルの取り回しに余裕がありますが、組み上がった後だとパーツの隙間を通すのがけっこう大変です。
後からケーブルを通す場合は、細身のラジオペンチやコネクタリムーバーがあると作業がはかどります。自分は最初の数箇所を後配線にしてしまい、パーツの隙間にケーブルを押し込むのに苦戦しました。
リーダーアームの組み立て
リーダーアームは 1 時間半程度で完了しました。フォロワーと基本構造は同じですが、サーボの型番が関節ごとに異なるので、どの関節にどのサーボを取り付けるかを間違えないよう注意が必要です。
リーダーアームの組み立てで少し困ったのが、参考写真の少なさです。WowRobo の動画はフォロワーアームの組み立てがメインで、リーダーアーム固有のパーツ配置にはあまり触れていません。HuggingFace のドキュメントもフォロワー寄りの説明です。結局、Seeed Studio の Wiki が一番参考になりました。

キャリブレーション
組み立てが終わったら、各関節のキャリブレーションを行います。キャリブレーションについては HuggingFace のドキュメントにある動画が参考になります。
フォロワーのキャリブレーション
フォロワーのキャリブレーションは問題なく完了しました。
uv run lerobot-calibrate \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodemXXXX \
--robot.id=my_follower
画面の指示に従ってアームを指定のポーズに動かし、Enter を押すだけです。
リーダーのキャリブレーション(マルチターン問題)
リーダーのキャリブレーションでは elbow_flex 関節でエラーに遭遇しました。ここは今回一番ハマったところなので、詳しく書いておきます。
uv run lerobot-calibrate \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodemYYYY \
--teleop.id=my_leader
キャリブレーション中に以下のエラーが表示されました。
Magnitude 2943 exceeds 2047
原因
STS3215 サーボの位置レジスタ(Present_Position)がマルチターン値を蓄積してしまっていました。通常は 0〜4095 の範囲に収まるべき値が、組み立て中に軸を何度も回してしまったようで 33644 のような大きな値になってしまっていました。。。
診断手順
scservo_sdk を使って、サーボの位置レジスタを直接読み取って確認しました。
from scservo_sdk import PortHandler, PacketHandler
port = PortHandler('/dev/tty.usbmodemXXXX')
port.openPort()
port.setBaudRate(1000000)
ph = PacketHandler(0)
# Present_Position(レジスタ 56)を読み取り
motor_id = 4 # elbow_flex
pos, result, error = ph.read2ByteTxRx(port, motor_id, 56)
print(f"Raw position: {pos}")
# => 33644(異常値、正常なら 2048 前後)
位置の値が 33644 と、明らかに正常範囲(2048 前後)を超えていました。
解決手順
Homing_Offset レジスタをリセットして、電源サイクルを実施することで解消できました。
# Homing_Offset(レジスタ 33)を 0 にリセット
ph.write2ByteTxRx(port, motor_id, 33, 0)
- 上記のコードで Homing_Offset(レジスタ 33)を 0 に書き込む
- USB ケーブルと DC 電源の両方を抜いて、5 秒ほど待機する
- 再接続して、raw 位置が正常範囲(2048 前後)に戻っていることを確認する
電源の完全遮断が重要です。USB ケーブルだけ抜いてもサーボに微弱な電流が流れ続ける場合があるので、DC 電源も忘れずに抜いてください。
復帰を確認したら、改めてキャリブレーションを実行します。今度は問題なく完了しました。
テレオペレーション
いよいよ本題のテレオペレーションです。リーダーアームを手で動かすと、フォロワーアームがその動きを追従します。
個人的にはファミリーコンピューターロボットが動いた時くらいの感動です:)
ポートの確認
USB アダプタを 2 本同時に接続すると、ポート番号が単体接続時とは異なる割り当てになることがあります。テレオペの前に lerobot-find-port でフォロワーとリーダーそれぞれのポートを確認しておきましょう。
uv run lerobot-find-port
テレオペの実行
uv run lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodemXXXX \
--robot.id=my_follower \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodemYYYY \
--teleop.id=my_leader
60Hz で安定して動作しました。リーダーアームを動かすとフォロワーアームがほぼリアルタイムで追従します。グリッパーの開閉も含めて、手で操作した通りにフォロワーが動く様子は感動の瞬間でした。
前回の記事では Isaac Sim の中で黄色いロボットアームをスライダーで操作していましたが、実際に手で動かせるとやはり感覚が違います。関節のバックラッシュ(遊び)やサーボのトルク特性など、シミュレーションでは見えない部分が体感できます。
ハマりポイントまとめ
今回の作業で遭遇した問題を整理しておきます。
| 問題 | 原因 | 対処 |
|---|---|---|
| Python 3.14 で TypeError | draccus が Python 3.14 非対応 | Python 3.12 を指定して環境作成 |
| キャリブレーションで Magnitude 超過 | STS3215 の位置レジスタがマルチターン値を蓄積 | Homing_Offset リセット + 電源サイクル |
| 2 ポート接続でポート番号が変わる | USB アダプタ同時接続時のポート割り当て変化 | lerobot-find-port で都度確認 |
| リーダーアームの組み立て情報が少ない | 公式動画・ドキュメントがフォロワー寄り | Seeed Studio Wiki を参照 |
まとめ
SO-ARM101 Pro キットの組み立てからテレオペレーションまでを一通り進めました。組み立てはフォロワー約 2 時間、リーダー約 1.5 時間の合計 3.5 時間ほどです。キャリブレーションとテレオペの確認を含めても、半日あれば動くところまで持っていけるかなと思います。
個人的に印象的だったのは、やはりシミュレーションと実機の感覚の違いでしょうか。Isaac Sim では Physics Inspector のスライダーで関節を動かしていましたが、実機のリーダーアームを手で握って操作すると、関節ごとの重さの違いやグリッパーの開閉感など、物理的なフィードバックがあります。この「手で触れる」体験は、Sim2Real のギャップを理解する上でも意味があるかなと感じました。
キャリブレーション時のマルチターン問題は、同じキットを購入した方が遭遇する可能性がある問題だと思います。scservo_sdk でレジスタを直接読む診断手順を記録しておいたので、同じ症状が出た場合の参考になれば幸いです。
次は USB カメラを接続してデータ収集環境を整え、LeRobot の ACT ポリシーで模倣学習を試そうと思います。










