LeRobot SO-101 Setup to Teleoperation
Introduction
I fully referenced the following article by Professor Karaage @karaage0703. I express my gratitude.
LeRobot SO-101 From Teleoperation to Learning Data Acquisition
https://zenn.dev/karaage0703/articles/8042463b476fbf
Hardware Setup
- Name each motor (like F3 for the 3rd motor of Follower) and attach paper with the name using tape so it doesn't fall off. Numbers start from 1 at the base and increase toward the gripper.
- Obtain the configuration tool (FD1.9.8.5).
https://gitee.com/ftservo/fddebug Click on FD1.9.8.5(250729).7z here, and on the next screen click "Download (167.88 KB)" to save it to the download folder. "Extract All" from this. This is a Windows-only tool. - Execute the tool with both Leader and Follower arms connected to the Windows PC.
- Com: Select the leader arm's COM port and enter BaudR: 1000000.
- Click "Open" and then click "Search".
- ID and motor names will appear in the lower left column. When all 6 leader arm motors are displayed, click "Stop".
- Click the "Upgrade" tab on the screen.
- Select ID: 1 and click "Online" at the bottom of the screen.
- Repeat the same procedure up to ID: 6.
- Com: Select the follower arm's COM port and perform the same process for 6 motors.
The relationship between leader arm motor IDs and model numbers is as follows:
| ID | Reduction Ratio | Model Number |
|---|---|---|
| 1 | 1/191 | STS3215-C044 |
| 2 | 1/345 | STS3215-C001 |
| 3 | 1/191 | STS3215-C044 |
| 4 | 1/147 | STS3215-C046 |
| 5 | 1/147 | STS3215-C046 |
| 6 | 1/147 | STS3215-C046 |
The follower arm, not being a Pro kit, all motors are 1/345 S0TS3215-C001.
Arm Assembly
Following the instructions from the official site below or npaka's note, mount the motors to the 3D printer arms.
https://huggingface.co/docs/lerobot/so101
https://note.com/npaka/n/n8424d322ebd4#c705eb65-f01b-4ea4-b4cd-9f1325627cbc
Software Setup
LeRobot SO-101 Setup
The OS is Ubuntu 22.04 alone without dual boot.
I mostly followed Karaage-san's Zenn article "LeRobot SO-101"
https://zenn.dev/karaage0703/articles/8042463b476fbf
for installation.
First, clone the official repository.
git clone https://github.com/huggingface/lerobot.git
cd lerobot
Execute the next script.
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
Set the path
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Install curl (failed example, so you don't need to execute this.)
sudo snap install curl
I was able to install it, but couldn't execute it, so I removed it.
snap remove curl
This time I installed curl with apt without using snap.
sudo apt install -y curl
All commands from here on are executed in the home/lerobot folder
Following Karaage-san, setup with uv instead of miniconda.
curl -LsSf https://astral.sh/uv/install.sh | sh
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Once installed, execute the following command. It took quite a while. At this time I didn't execute opencv-python on line 3, so I got an error later. Install opencv-python here. Note that from here on, everything is executed in the ~/lerobot folder.
cd ~/lerobot
uv sync
uv pip install "lerobot[feetech]"
uv pip install opencv-python
In Karaage-san's article, I tried visualizing the dataset,
but after it was displayed I didn't know what to do next, so I moved on.
I followed Karaage-san's method for device name configuration processing.
After connecting the driver board's USB port to the PC's USB port with a cable, execute lsusb.
lsusb
``` : Example notation
The following will be displayed. Among these, QinHeng Electronics USB Single Serial is the motor.
You can distinguish between leader and follower by unplugging one USB and running lsusb.
``` : Example notation
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 5986:0297 Acer, Inc USB HD Webcam
Bus 001 Device 003: ID 044e:301d Alps Electric Co., Ltd UGNZH
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 028: ID 1a86:55d3 QinHeng Electronics USB Single Serial
Bus 003 Device 011: ID 413c:301a Dell Computer Corp. Dell MS116 Optical Mouse
Bus 003 Device 027: ID 1a86:55d3 QinHeng Electronics USB Single Serial
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Here, combine Bus 003 and Device 28 and execute the following.
lsusb -v -s 003:028 | grep -i serial
Then the following is displayed, and we can see that the motor's Serial number is 5AA9017949.
Couldn't open device, some information will be missing
Bus 003 Device 028: ID 1a86:55d3 QinHeng Electronics USB Single Serial
iProduct 2 USB Single Serial
iSerial 3 5AA9017949
line coding and serial state
Also, combine the other Bus 003 and Device 27 and execute the following.
lsusb -v -s 003:027 | grep -i serial
Then similarly, we can see that the motor's Serial number is 5AA9017159.
Note these numbers and write them in the text file below.
Name the text file 99-lerobot-serial.rules as in Karaage-san's article,
and change the 5AA... part between the " " in ATTRS{serial}=="5AA9017949", ATTRS{serial}=="5AA9017159".
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", ATTRS{serial}=="5AA9017949", SYMLINK+="usbserial_lerobot_follower", MODE="0666"
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", ATTRS{serial}=="5AA9017159", SYMLINK+="usbserial_lerobot_leader", MODE="0666"
Note that I couldn't create a new text file in /etc/udev/rules.d/,
so I first created the file in the Documents folder. Then I copied it with the following method.
sudo cp ドキュメント/99-lerobot-serial.rules /etc/udev/rules.d/
Now that we're ready, execute the following.
sudo udevadm control --reload
Connect the USB and execute the following
ls /dev/usbserial*
This will be displayed. Device setup is now complete.
/dev/usbserial_lerobot_follower /dev/usbserial_lerobot_leader
Calibration Program
When I executed calibrate.py in /lerobot/src/lerobot, I got the following error.
ModuleNotFoundError: No module named 'cv2'
At this time, I didn't understand why cv2 couldn't be found, so
I commented out the following parts in calibrate.py.
# from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig # noqa: F401
# from lerobot.cameras.realsense.configuration_realsense import RealSenseCameraConfig # noqa: F401
# from lerobot.robots import lekiwi
If I had executed the following first, I might not have needed to modify the program.
At that time, I executed the first two lines but not the third line.
uv sync
uv pip install "lerobot[feetech]"
uv pip install opencv-python
Calibration
Connect leader and follower arms to PC and execute the following in ~/lerobot folder.
uv run python -m lerobot.calibrate --robot.type=so101_follower --robot.port=/dev/usbserial_lerobot_follower --robot.id=lerobot_follower
The following is displayed and calibration begins.
INFO 2025-08-07 13:22:01 calibrate.py:72 {'robot': {'calibration_dir': None,
'cameras': {},
'disable_torque_on_disconnect': True,
'id': 'lerobot_follower',
'max_relative_target': None,
'port': '/dev/usbserial_lerobot_follower',
'use_degrees': False},
'teleop': None}
INFO 2025-08-07 13:22:01 follower.py:101 lerobot_follower SO101Follower connected.
INFO 2025-08-07 13:22:01 follower.py:108
Running calibration of lerobot_follower SO101Follower
Move lerobot_follower SO101Follower to the middle of its range of motion and press ENTER....
This is displayed, so move the leader to middle position and press ENTER.
Then the following display appears, so move each servo from minimum angle to maximum angle.
The numbers in the table below change in real time as you move the arm servos.
Move all joints sequentially through their entire ranges of motion.
Recording positions. Press ENTER to stop...
-------------------------------------------
NAME | MIN | POS | MAX
shoulder_pan | 744 | 2016 | 3276
shoulder_lift | 847 | 850 | 3212
elbow_flex | 858 | 3040 | 3049
wrist_flex | 990 | 2809 | 2852
wrist_flex | 990 | 2809 | 2852
wrist_roll | 148 | 1989 | 3971
gripper | 2046 | 2176 | 3216
After moving, press ENTER to end calibration and the following display appears.
Calibration saved to /home/abc/.cache/huggingface/lerobot/calibration/robots/so101_follower/lerobot_follower.json
INFO 2025-08-07 13:23:48 follower.py:210 lerobot_follower SO101Follower disconnected.
When I first calibrated, the program crashed midway,
and I tried many times repeatedly. For some reason, calibration went smoothly the next day.
(I assume the commercial 100V happened to be at a low voltage)
For calibration (leader side), execute the following.
~/lerobot$ uv run python -m lerobot.calibrate --teleop.type=so101_leader --teleop.port=/dev/usbserial_lerobot_leader --teleop.id=lerobot_leader
Then the following is displayed and calibration begins.
INFO 2025-08-07 13:30:08 calibrate.py:72 {'robot': None,
'teleop': {'calibration_dir': None,
'id': 'lerobot_leader',
'port': '/dev/usbserial_lerobot_leader',
'use_degrees': False}}
INFO 2025-08-07 13:30:08 01_leader.py:79 lerobot_leader SO101Leader connected.
INFO 2025-08-07 13:30:08 01_leader.py:86
Running calibration of lerobot_leader SO101Leader
Move lerobot_leader SO101Leader to the middle of its range of motion and press ENTER....
This is displayed, so move the leader to middle position and press ENTER.
Then the following display appears, so move each servo from minimum angle to maximum angle.
The numbers in the table below change in real time as you move the arm servos.
Move all joints sequentially through their entire ranges of motion.
Recording positions. Press ENTER to stop...
-------------------------------------------
NAME | MIN | POS | MAX
shoulder_pan | 744 | 2016 | 3276
shoulder_lift | 847 | 850 | 3212
elbow_flex | 858 | 3040 | 3049
wrist_flex | 990 | 2809 | 2852
wrist_flex | 990 | 2809 | 2852
wrist_roll | 148 | 1989 | 3971
gripper | 2046 | 2176 | 3216
After moving, press ENTER to end calibration and the following display appears.
Calibration saved to /home/abc/.cache/huggingface/lerobot/calibration/teleoperators/so101_leader/lerobot_leader.json
INFO 2025-08-07 13:31:46 1_leader.py:143 lerobot_leader SO101Leader disconnected.
Execute Teleoperation
uv sync
uv pip install "lerobot[feetech]"
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
The following is displayed and teleoperation is possible. When you move the leader by hand, the follower moves.
INFO 2025-08-07 13:32:02 eoperate.py:112 {'display_data': False,
'fps': 60,
'robot': {'calibration_dir': None,
'cameras': {},
'disable_torque_on_disconnect': True,
'id': 'lerobot_follower',
'max_relative_target': None,
'port': '/dev/usbserial_lerobot_follower',
'use_degrees': False},
'teleop': {'calibration_dir': None,
'id': 'lerobot_leader',
'port': '/dev/usbserial_lerobot_leader',
'use_degrees': False},
'teleop_time_s': None}
INFO 2025-08-07 13:32:02 01_leader.py:79 lerobot_leader SO101Leader connected.
INFO 2025-08-07 13:32:02 follower.py:101 lerobot_follower SO101Follower connected.
Above, teleoperation is complete.