LeRobot SO-101
お手伝いしていた「Hamamatsu Micro Maker Faire 2025」の目玉展示LeRobot SO-101。Seeedさんからお借りすることができました。
ひとまずテレオペ(遠隔操作)で動かすところから、学習データを取得するところまでやってみました。LeRobot SO-101に関しては、ネットにそれなりに情報あるの見かけてたので簡単だろうと思っていましたが、やってみたらそれなりに色々大変でした。ハードウェアはやっぱりハードですね。
ハードウェアとしては組み立て済みのLeRobot SO-101と制御するPCとして、これまたSeeedさんからの貸与品であるところのSeeed reComputer J4012(Jetson Orin NX 16GB)を使用しています。
reComputer(Jetson)のセットアップに関しては、以下記事を参照してください。
今回はJetsonを使いましたが、普通のLinux PCやMacでもほぼ同じ流れでセットアップできると思います。
リポジトリ動作確認
まずは以下リポジトリで基本的なセットアップをします。公式リポジトリとnpakaさんの記事を参考にしました。
リポジトリをクローンします。
$ git clone https://github.com/huggingface/lerobot.git
$ cd lerobot
必要なパッケージをインストールしておきます。以下はLinuxのケースですので、他のOSの場合は公式リポジトリを参考によしなにしてください。
$ sudo apt-get install cmake build-essential python3-dev pkg-config libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libswresample-dev libavfilter-dev
Pythonのパッケージ管理、公式はminicondaを推奨していますが、uvを使いたかったのでuvでセットアップしました(なお、lerobot公式はuvでのセットアップをわざわざrevertしたりしているのでuvに対応する気はないようです)。uvのセットアップに関しては以下記事参照してください。
uvをセットアップしたらlerobot
ディレクトリ以下で以下実行します。
続いて、以下でデータセットの可視化を試します。
$ uv run python -m lerobot.scripts.visualize_dataset \
--repo-id lerobot/pusht \
--episode-index 0
以下のようなメッセージが出て、失敗することもあります。
huggingface_hub.errors.LocalEntryNotFoundError: An error happened while trying to locate the file on the Hub and we cannot find the requested files in the local cache. Please check your connection and try again or make sure your Internet connection is on.
error: Failed to fetch: `https://pypi.org/simple/debugpy/`
Caused by: request or response body error
Caused by: error reading a body from connection
Caused by: connection reset
めげずに何回か実行すると、成功しました。以下のように表示されます。
ロボットキャリブレーション
続いてロボットのキャリブレーションをします。なお、この後使うので最初に説明しておきますが、2つのロボットのうち、レバーがついて人が操作するロボット(写真だと黒いロボット)がLeader。 人の操作に追従して動くロボット(写真の白いロボット)がFollowerとなります。
ロボットのキャリブレーションは、以下の公式サイトとnpakaさんのサイトを参考に実施しました。
まずはロボットとPCをUSB-Cで接続して、以下コマンドを実行します。
$ uv run python -m lerobot.find_port
以下のメッセージが出てきます。
Finding all available ports for the MotorsBus.
Ports before disconnecting: ['/dev/ttyACM0', '/dev/ttyGS0', '/dev/ttyTHS2', '/dev/ttyTHS1', '/dev/ttyTCU0', '/dev/ttyS3', '/dev/ttyS2', '/dev/ttyS1', (略) '/dev/ttyAMA0']
Remove the USB cable from your MotorsBus and press Enter when done.
最後に、USBケーブルを抜けと指示があるので、指示のとおり、PCからコネクタを抜いて、Enterキーを押します。すると、以下のようにデバイス名(以下の場合は/dev/ttyACM0
)が取得できます。USB接続前後で、デバイス名の差分を取得して、接続したデバイスを特定するスクリプトのようですね。
The port of this MotorsBus is '/dev/ttyACM0'
Reconnect the USB cable.
今回は、ttyACM0
に特定できました、Linuxの場合は以下のようにパーミッション設定すると、モータをソフトから制御できるようになります(Macの場合は多分不要)。
ただ、このように毎回デバイス名確認して、パーミッション設定するのはめんどうですし、間違いのもとですね。Linuxの場合は、udevルールを使うと便利です。udevルールの使い方は以下記事を参照してください。
簡単に手順を書いておきます(詳細は上記記事を確認してください)。USB接続前後で以下コマンドを実行して差分を確認します。
USB接続すると、以下が増えていたので以下がモータのUSBシリアルと確定できます。
Bus 001 Device 006: ID 1a86:55d3 QinHeng Electronics USB Single Serial
今回2つのUSBデバイスが同一のため、区別するためにシリアルを確認する必要があります。シリアルを確認するために、以下のコマンドを実行します。
$ lsusb -v -s 001:006 | grep -i serial
シリアルが取得できます。2台のロボット(Leader, Follower)両方でコマンド実行して、シリアル情報を取得しましょう。
Bus 001 Device 008: ID 1a86:55d3 QinHeng Electronics USB Single Serial
iProduct 2 USB Single Serial
iSerial 3 5AA9018069
続いて、以下のudevルールの設定ファイルを編集します。
/etc/udev/rules.d/99-lerobot-serial.rules
今回は、以下のように2つのロボットをそれぞれ設定します。
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", ATTRS{serial}=="5AA9018069", SYMLINK+="usbserial_lerobot_follower", MODE="0666"
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", ATTRS{serial}=="5AA9017941", SYMLINK+="usbserial_lerobot_leader", MODE="0666"
設定を以下コマンドで反映します。
$ sudo udevadm control --reload
USBケーブルを接続しなおします。すると、以下のようにデバイス名が自動で固定されます。パーミッションも自動で設定されます。
$ ls /dev/usbserial*
/dev/usbserial_lerobot_follower /dev/usbserial_lerobot_leader
このあとはモータにIDを割り振ります。私はIDが設定された組み立て済みのロボットを使用したので、この手順はスキップしました。ここの手順はABEJAさんの記事がとても詳しいので、参考にするのが良いと思います。
モータの設定が終わったらキャリブレーションを実施します。
lerobot
ディレクトリで以下コマンドでuvの設定をします。
$ uv sync
$ uv pip install "lerobot[feetech]"
以下コマンドを実行して、フォロワーロボットのキャリブレーションを実施します。
$ uv run python -m lerobot.calibrate \
--robot.type=so101_follower \
--robot.port=/dev/usbserial_lerobot_follower \
--robot.id=lerobot_follower
キャリブレーションは、以下の公式の動画やnpakaさんのサイトを参考に実施しました。
流れとしては、Middleという全てのモーターの中間位置のポーズを初期姿勢として、1つずつモーターの角度をMin, Maxまで動かすこととなります。一回やると理屈が分かるかと思います。
続いて、同様に以下コマンド実行して、Leaderロボットのキャリブレーションを実施します。
$ uv run python -m lerobot.calibrate \
--teleop.type=so101_leader \
--teleop.port=/dev/usbserial_lerobot_leader \
--teleop.id=lerobot_leader
これでキャリブレーションは完了です。
テレオペレーション(遠隔操作)
キャリブレーションの後は、テレオペをします。
lerobot
ディレクトリで以下コマンドでuvの設定をします。モータ関係のライブラリを追加でセットアップしています。
$ uv sync
$ uv pip install "lerobot[feetech]"
あとは以下コマンドでテレオペができます。robot.port
, teleop.port
は、先ほどudevルールで固定したデバイス名を使用しましょう。
$ uv run python -m lerobot.teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/usbserial_lerobot_follower \
--robot.id=lerobot_follower \
--teleop.type=so101_leader \
--teleop.port=/dev/usbserial_lerobot_leader \
--teleop.id=lerobot_leader
カメラの確認
以下の公式サイトとnpakaさんの記事を参考にしました。
カメラはUSBカメラならなんでもよいのですが、今回はロジクール ウェブカメラ C270nを使いました。
lerobot
ディレクトリで以下コマンドでuvの設定をします。
$ uv sync
$ uv pip install "lerobot[feetech]"
カメラを接続して、以下コマンドを実行します。
$ uv run python -m lerobot.find_cameras opencv
カメラの情報が表示されます。
--- Detected Cameras ---
Camera #0:
Name: OpenCV Camera @ /dev/video0
Type: OpenCV
Id: /dev/video0
Backend api: V4L2
Default stream profile:
Format: 0.0
Width: 640
Height: 480
Fps: 30.0
--------------------
公式サイトのスクリプトを動かします。width
, height
だけカメラに合わせて値を修正しています。
from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig
from lerobot.cameras.opencv.camera_opencv import OpenCVCamera
from lerobot.cameras.configs import ColorMode, Cv2Rotation
config = OpenCVCameraConfig(
index_or_path=0,
fps=15,
width=640,
height=480,
color_mode=ColorMode.RGB,
rotation=Cv2Rotation.NO_ROTATION
)
camera = OpenCVCamera(config)
camera.connect()
try:
for i in range(10):
frame = camera.async_read(timeout_ms=200)
print(f"Async frame {i} shape:", frame.shape)
finally:
camera.disconnect()
以下のように表示されます。
Async frame 0 shape: (480, 640, 3)
Async frame 1 shape: (480, 640, 3)
Async frame 2 shape: (480, 640, 3)
(略)
Async frame 9 shape: (480, 640, 3)
なお、解像度を修正しないと、以下のようなエラーが出ました。
RuntimeError: OpenCVCamera(0) failed to set capture_width=1920 (actual_width=1280, width_success=True).
カメラはRealSenseにも対応しているようですが、本記事では省略します。
カメラ付きテレオペ(遠隔操作)
カメラ付きのテレオペです。以下公式サイトの記事を参照しました。
コマンドでも動かせるのですが、今回は、APIを使ってプログラムで動かしてみます。
from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig
from lerobot.teleoperators.so101_leader import SO101LeaderConfig, SO101Leader
from lerobot.robots.so101_follower import SO101FollowerConfig, SO101Follower
camera_config = {
"front": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=30)
}
robot_config = SO101FollowerConfig(
port="/dev/usbserial_lerobot_follower",
id="lerobot_follower",
cameras=camera_config
)
teleop_config = SO101LeaderConfig(
port="/dev/usbserial_lerobot_leader",
id="lerobot_leader",
)
robot = SO101Follower(robot_config)
teleop_device = SO101Leader(teleop_config)
robot.connect()
teleop_device.connect()
while True:
observation = robot.get_observation()
action = teleop_device.get_action()
robot.send_action(action)
遠隔操作ができます。カメラをつけたことによある違いはよくわかりませんでした。
学習用データ記録
続いてロボットの学習用データの記録です。以下公式記事とnpakaさんの記事を参考にしました。
lerobot
ディレクトリで以下を実行します。
$ uv sync
$ uv pip install "lerobot[feetech]"
$ uv pip install -U "huggingface_hub[cli]"
HuggingFaceにログインします。あらかじめ、HuggingFaceに登録して、トークンを取得しておいてください。
以下の${HUGGINGFACE_TOKEN}
にはトークンを入れます。
$ git config --global credential.helper store
$ uv run huggingface-cli login --token ${HUGGINGFACE_TOKEN} --add-to-git-credential
以下でユーザー名を取得します。
$ HF_USER=$(uv run huggingface-cli whoami | head -n 1)
$ echo $HF_USER
準備ができたら、以下コマンドで学習を記録します。
$ uv run python -m lerobot.record \
--robot.type=so101_follower \
--robot.port=/dev/usbserial_lerobot_follower \
--robot.id=lerobot_follower \
--teleop.type=so101_leader \
--teleop.port=/dev/usbserial_lerobot_leader \
--teleop.id=lerobot_leader \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--display_data=true \
--dataset.repo_id=${HF_USER}/record-test \
--dataset.episode_time_s=60 \
--dataset.reset_time_s=10 \
--dataset.num_episodes=2 \
--dataset.single_task="Play drum"
こんな感じで記録ができます。
記録が終わると、ローカルの~/.cache/huggingface/lerobot/
以下にデータが保存されると同時に、自動的にHugging Faceにもデータがアップされます。
記録はカメラの固定とか準備とか色々下準備が大変です。
自分は記録中ロボットが暴走してしまいました…
まとめ
LeRobotのソフトウェアの基本的なセットアップからテレオペ、学習データの取得までを一通り実施しました。
最初、ハードウェアの動作確認のところは少し手間取りましたが、動き出すとスムーズでした。テレオペの操作感もよく、結構丈夫なのでハードウェアとしてよくできているなと感じました。これだけ手軽にテレオペしてロボットのデータを取得してHuggingFaceと連携しているのは素晴らしいなと思いました。
今回はデータの取得までだったので、学習したデータから模倣学習させて動かしてみたり、LeRobotは、ROSに対応しているようなので、ROSで動かすとかもやってみても良いかなと思ったりしました。
参考リンク
関連記事
Views: 0