SO-101 is the arm that made teleoperated data collection something you can buy on a hobbyist budget instead of requisitioning through a robotics lab. Designed by TheRobotStudio in collaboration with Hugging Face, it is a 3D-printable, 6-DoF leader-follower pair built on commodity serial bus servos — you move the leader by hand, the follower mirrors it, and the LeRobot library records both sides as a synchronized dataset. It is the reference hardware for a large share of the open imitation-learning community's published datasets, which is exactly why it is worth understanding as a data collection instrument and not just a kit.
The arm exists because teleoperation research kept needing a cheap, reproducible rig to validate ideas on before anyone commits to Franka- or UR-class hardware. SO-101 is that rig: a few hundred dollars in parts and servos, an afternoon of 3D printing and assembly, and you have a leader-follower pair that speaks the same dataset format as arms costing twenty times as much.
Both the hardware bill of materials and the LeRobot software stack are released under Apache-2.0, which is part of why SO-101 shows up so widely: nothing about reproducing a published SO-101 dataset or a published SO-101 policy requires a commercial license, a vendor relationship, or access to hardware you cannot simply order and print yourself.
Control interfaces that matter for data collection
Both the follower and leader arms use six Feetech STS3215 serial bus servos, daisy-chained on a single bus per arm. The follower's six servos all use 1/345 gearing for consistent, adequate torque. The leader arm deliberately mixes gear ratios by joint so it can be backdriven with light finger pressure while still supporting its own weight:
| Leader joint | Gear ratio |
|---|---|
| Base / shoulder pan | 1/191 |
| Shoulder lift | 1/345 |
| Elbow flex | 1/191 |
| Wrist flex | 1/147 |
| Wrist roll | 1/147 |
| Gripper | 1/147 |
Everything is driven through the LeRobot Python library over USB serial. There is no separate vendor SDK to learn — lerobot-find-port identifies the USB device for each arm, lerobot-setup-motors assigns servo IDs and baud rates one motor at a time during first assembly, and lerobot-calibrate walks each arm through its full range of motion so leader and follower positions line up in the same coordinate frame. That calibration step matters more than it looks: a policy trained on one physical SO-101 unit is only portable to another unit if both were calibrated the same way.
Teleoperation options
SO-101's whole design point is that the leader arm is the teleoperation interface — there is no VR headset, space mouse, or haptic device in the loop by default. You physically puppet the leader, and joint positions stream to the follower over the bus at whatever rate the LeRobot control loop is configured for (commonly in the tens of hertz, matched to camera frame rate for recording).
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.cameras='{"front": {"type": "opencv", "index_or_path": 0, "width": 1920, "height": 1080, "fps": 30}}' \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--display_data=trueThe trade-off is the same one every leader-follower system makes: joint-space correspondence is direct and low-latency, so operators develop fine control quickly, but you are tied to whatever workspace and gripper the leader arm physically has. There is no path to retargeting a VR controller's pose onto SO-101 that LeRobot ships out of the box — if you want that interface, you are building it yourself on top of the same follower-arm API. For most SO-101 users this is a feature, not a limitation: the arm's whole appeal is a rig simple enough that a single person can own the entire stack from servo to dataset.
What a clean dataset looks like on this platform
lerobot-record is the same binary as lerobot-teleoperate with a dataset attached — it captures the leader's commanded joint positions as the action, the follower's actual joint positions as the observation.state, and each configured camera as a synchronized video stream, all on one clock:
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.cameras='{"front": {"type": "opencv", "index_or_path": 0, "width": 1920, "height": 1080, "fps": 30}}' \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--dataset.repo_id=your-name/pick-place-v1 \
--dataset.num_episodes=50 \
--dataset.single_task="Pick up the cube and place it in the tray"- Arm DoF
- 6, both leader and follower
- Actuators
- Feetech STS3215 serial bus servos
- Interface
- USB serial, LeRobot Python library
- Dataset format
- LeRobot dataset — Parquet state/action + MP4 per camera
Every episode is written with matching camera and state timestamps by construction — LeRobot's recording loop, not a post-hoc alignment step, is what keeps them synchronized. Right-arrow saves an episode and starts the next, left-arrow discards and retries, escape stops the session and encodes video. That keyboard loop is doing the job that episode boundary labeling and success annotation would otherwise require as a separate pass — which is a big part of why SO-101 sessions produce usable data as fast as they do.
Common pitfalls
Treating the leader arm as disposable. Because it is cheap and printable, teams sometimes under-invest in the leader's ergonomics — a poorly tuned gripper handle or a leader that fights the operator's hand produces visibly worse demonstrations, the same way a bad input device degrades any teleoperation session.
Single-camera datasets. SO-101's default examples often show one wrist or front camera because that is what fits a desktop rig. Production-quality imitation learning generally wants at least two viewpoints; if your dataset only has one, say so in the metadata rather than let it look like a full multi-camera capture.
Skipping lerobot-calibrate after hardware changes. Covered above, but worth repeating: any servo replacement, cable reroute, or arm swap should be followed by a fresh calibration pass before recording resumes.
Confusing SO-100 and SO-101 datasets. They share a dataset schema and mostly share code paths, but the leader gearing differs, which changes the felt teleoperation experience and, potentially, the demonstrator's motion statistics. If you are pooling data across the two hardware revisions, note which arm each episode came from.
Underestimating how much the gripper end effector matters. SO-101's stock gripper is a simple parallel-jaw claw. It is adequate for the pick-and-place tasks most published SO-101 datasets target, but it is not a substitute for a dexterous or force-sensing end effector if your task actually needs one — swapping the gripper is a common early modification, and it changes the action space, so track it in your dataset metadata the same way you would track a different arm revision.
If SO-101 is one of several rigs you run — alongside heavier arms or robots your team already owns — the same recording discipline (one clock, per-camera calibration, episode-level task labels) is what bring your own rig is built around, so a dataset collected on SO-101 slots into the same pipeline as one collected on anything else.