
Running a semester robotics course on the SO-100 arm: cost per seat from the published bill of materials, a 14-week plan, five exercises that teach, and the honest limits.
A robotics course lives or dies on whether the hardware survives twenty students. The SO-100 is one of the few arms cheap enough for a department to buy a set and open enough that a broken gripper costs an evening of printing, not a purchase order. What follows is a course plan: what a seat costs, what a student finishes in fourteen weeks, and which exercises teach.
Software here describes LeRobot v0.6.1, released 3 August 2026, read from the upstream docs in August 2026. Upstream moves: the inference entry point went from lerobot-record --policy.path in v0.5.1 to a dedicated lerobot-rollout, and the install was split into optional extras. Pin a version in the syllabus and date it, or week 9 goes on debugging a command that no longer exists.
The short version
- •One teleoperation seat costs EUR 226.30 or USD 229.88 in parts, per the published SO-ARM100 bill of materials. Filament, cameras and a host machine are extra.
- •A seat serves two to three students. A cohort of 20 needs 7 to 10 arm pairs, not 20.
- •Six weeks gets a team from a box of servos to a policy that picks up a cube. The other eight are where the learning is.
- •ACT is the right first policy: about 80 M parameters, 20 ms per action step, roughly 1 to 3 USD per run on a 24 GB card.
- •The fastest way to destroy a set of arms is voltage. STS3215 servos run on 7.4 V; 12 V kills the whole bus at once.
- •Budget more lab time for calibration, USB ports and camera indices than for training.
Why the SO-100 is a teaching arm, not a research arm
Six degrees of freedom, bus servos that report their own position, a printed frame, a two-finger end effector. No absolute encoders, no torque sensing, no compliance control. Every omission makes the arm poor for research and good for teaching: the failure modes are large and mechanically obvious. A student who watches the follower miss a cube by two centimetres can usually name the cause without instrumentation. On a 30,000 EUR collaborative arm the same failure hides behind a controller nobody may open.
| Course objective | Served? | Why |
|---|---|---|
| Teleoperation and demonstration quality | Yes | The mapping is direct, so sloppy habits show up at once. |
| Imitation learning end to end | Yes | Record, train, deploy is four commands. |
| Dataset design, bias, coverage | Yes | Real cameras and lighting leak in ways simulation will not. |
| Kinematics and control | Partly | Six joints and a URDF, no torque control or force feedback. |
| Repeatability engineering | No | Backlash sets the floor; experiments measure the printer. |
| Safety, interlocks, certification | No | A hobby arm lacks everything a real cell needs. |
Upstream now documents the SO-101 as the main build and marks the SO-100 page deprecated. The SO-101 has improved wiring and needs no gear removal during assembly, worth half a lab session per team. Both work here, so buy SO-101 and keep calling it an SO-100 course, since that is what the tutorials and datasets are named after: SO-100 vs SO-101.
Cost per seat, worked out
The published bill of materials totals USD 229.88 or EUR 226.30 for a leader and follower pair: twelve STS3215 servos across three gear ratios, two control boards, two power supplies, cables and clamps. A follower alone is USD 121.94 or EUR 124.30, and filament, cameras and the host machine are outside that. This site lists SO-100 parts at 110 to 150 EUR and SO-101 at 130 to 170 EUR per arm.
| Line item | EU | US | Note |
|---|---|---|---|
| Leader + follower BOM | EUR 226.30 | USD 229.88 | SO-ARM100 repo, read 24 Aug 2026 |
| Follower only | EUR 124.30 | USD 121.94 | A policy-only fleet for semester two. |
| Printed parts | filament | filament | PLA+, 0.4 mm nozzle, 0.2 mm layers, 15 percent infill |
| Two USB webcams | 20 to 60 | 20 to 60 | Not in the BOM. Rigid mounts beat resolution. |
| Training run, ACT or SmolVLA | - | 1 to 3 USD | 24 GB card, 2 to 5 h at 0.30 to 0.60 USD/h |
| Training run, GR00T or Pi0.5 | - | 4 to 12 USD | 80 GB card, 3 to 6 h at 1.20 to 2.00 USD/h |
Fleet arithmetic matters more than unit price. One seat serves two to three students in rotation, because recording is a single-operator job while the others audit footage, write the LeRobot dataset card and prepare the next reset. For 20 students, 7 pairs works and 10 is comfortable: roughly 1,600 to 2,300 EUR. Add a spare follower per five seats, because something snaps in week 3.
The SO-100 uses Feetech STS3215 bus servos on a 7.4 V rail. Feetech sells a 12 V variant of the same body: the upstream BOM records 16.5 kg.cm stall at 6 V for the 7.4 V part against 30 kg.cm for the 12 V part, and warns that the 12 V motors need their own 12 V 5A+ supply. They look identical in a drawer. Putting 12 V into 7.4 V servos destroys them, and since they share one daisy-chained bus it takes all six at once. Label every brick and make the voltage check a graded item: servo not responding.

What a student can build in fourteen weeks
The realistic deliverable for one semester: a working leader-follower rig, a 50-episode dataset with a data card, one trained policy that completes one tabletop task at some measured rate, and a report explaining three ablations. One task, honestly measured, failures documented. Teams that aim higher deliver less.
| Week | Topic | Deliverable |
|---|---|---|
| 1 to 2 | Print, assemble, wire, set servo IDs | Both arms move. Voltage check signed off. |
| 3 to 4 | Calibration, teleoperation, cameras | Ten minutes of clean teleop; two fixed cameras with pinned indices. |
| 5 to 6 | Record the first dataset | 50 episodes, 10 per object location, plus a data card. |
| 7 | Dataset audit | Defects found by watching recordings, not by reading a loss curve. |
| 8 | Train ACT | One run to completion, config committed with the report. |
| 9 | Deploy and measure | 20 scored rollouts under a fixed protocol, with a denominator. |
| 10 to 11 | Ablations: drop a camera, move the setup | Retrain once, re-measure twice. Which sensor carried the task? |
| 12 | A second policy for contrast | SmolVLA, or a smaller episode budget. Same protocol. |
| 13 to 14 | Failure taxonomy and defence | Failures named and attributed. The demo is worth little; the defence is everything. |
Half the semester happens before a network is trained and a third after. That ratio is correct and students will resist it. Here, SO-100 getting started covers weeks 1 to 3, record your first dataset covers 4 to 6, and train your first policy plus run your first policy cover 8 and 9. The free Hugging Face robotics course is a usable lecture spine: 30 to 45 minute units needing no hardware, so a student who misses a lab keeps up.

Five exercises that actually teach something
1. Calibrate, then break the calibration on purpose
Most courses treat calibration as setup. It is the best teaching artifact on this arm, because getting it wrong is immediate and recoverable. Calibrate correctly, verify by teleoperation, then deliberately mis-calibrate one joint and describe what the leader-follower mapping does.
- 1Find the two serial ports
Run with both arms connected, unplug one when prompted. Students find out for themselves that port numbers are not stable across reboots.
bashlerobot-find-port - 2Write motor IDs into servo EEPROM
One motor at a time, gripper first. Written to EEPROM, so once per arm. Where teams learn a bus needs unique addresses.
bashlerobot-setup-motors \ --robot.type=so101_follower \ --robot.port=/dev/ttyACM0 lerobot-setup-motors \ --teleop.type=so101_leader \ --teleop.port=/dev/ttyACM1 - 3Calibrate both arms with stable ids
Centre every joint, press enter, sweep each through its full range. The id string is how LeRobot finds the calibration file; renaming it breaks every later command.
bashlerobot-calibrate \ --robot.type=so101_follower \ --robot.port=/dev/ttyACM0 \ --robot.id=lab03_follower lerobot-calibrate \ --teleop.type=so101_leader \ --teleop.port=/dev/ttyACM1 \ --teleop.id=lab03_leader - 4Verify, then break it
Teleoperate with both cameras and the Rerun viewer on. Then recalibrate the shoulder with the arm parked 20 degrees off centre and drive again. Write down the offset and which joints amplified it.
bashlerobot-teleoperate \ --robot.type=so101_follower \ --robot.port=/dev/ttyACM0 \ --robot.id=lab03_follower \ --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \ --teleop.type=so101_leader \ --teleop.port=/dev/ttyACM1 \ --teleop.id=lab03_leader \ --display_data=true
What it teaches: a network trained on one robot transfers to another only because calibration made them agree on what joint angle zero means. That lands harder after watching a 20 degree offset propagate down the chain. When ports refuse to appear, arm not detected and joint stops early cover the usual causes.
2. Record 50 episodes, then audit them before training
Upstream guidance for a first grasping task is 50 episodes, about 10 per object location, cameras fixed and grasp behaviour consistent. Its rule of thumb is the useful part: you should be able to do the task yourself from the camera images alone. If you cannot, neither can the policy.
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=lab03_follower \
--robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=lab03_leader \
--dataset.repo_id=${HF_USER}/lab03_cube_in_bowl \
--dataset.num_episodes=50 \
--dataset.single_task="put the red cube in the bowl" \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=15 \
--display_data=true- Watch all 50 episodes at speed. Count how many the operator would fail if graded.
- Count episodes where the object starts outside the region the policy will be tested in.
- Check whether the gripper closes to the same width every time, or the operator got lazy after episode 30.
- Look for camera drift. If the wrist camera moved at episode 13, the dataset holds two tasks.
- Write a one-page data card: task, objects, locations, lighting, operator, defects. Graded.
LeRobot derives a frame timestamp from its index. If the loop actually ran at 25 Hz because the cameras were slow, the dataset still declares 30 fps and the recorded motion is faster than reality. Policies trained on it inherit that distortion and later overshoot. Since v0.6, lerobot-record prints a cadence report per episode: effective Hz against target, ticks over budget, and which loop step consumed the time. Make reading it a required line in the lab notebook. Usually observe is the offender, and the fix is fewer camera streams, not a faster GPU.
3. Train, then distrust the loss curve
ACT is the right first model: about 80 M parameters, trained from scratch on the student's data, with an action chunking head that predicts a whole sequence at once. It wants 50 episodes and any 24 GB card, at roughly 1 to 3 USD a run. Platform defaults: batch size 8, learning rate 1e-5, 100,000 max steps, chunk size 100, 100 action steps.
lerobot-train \
--dataset.repo_id=${HF_USER}/lab03_cube_in_bowl \
--policy.type=act \
--output_dir=outputs/train/act_lab03 \
--job_name=act_lab03 \
--policy.device=cuda \
--policy.repo_id=${HF_USER}/act_lab03 \
--steps=20000 \
--wandb.enable=trueThe exercise is not to get a low loss. It is to write down beforehand what a low loss would and would not prove. A training step count that looks healthy on a chart is fully compatible with an arm that sits still, because imitation loss is measured against demonstrations, not task success. It has its own page: loss falls, policy does nothing. Requiring the prediction in advance turns a plotting exercise into an epistemic one.
4. The ablation that produces the grade
One trained policy is an anecdote. Three policies differing in exactly one input are an experiment. This is the part that transfers to everything else the student does, and it is cheap here: a retrain costs a couple of dollars, not a grant.
- Drop the wrist camera and retrain. Grasping usually degrades more than the overhead view suggests, which shows which sensor carried the task.
- Halve the dataset to 25 episodes. Plot success against episode count, then argue honestly about what two points support.
- Keep the policy, move the table 15 cm, change the lamp. No retraining. The answer is humbling: policy only works in one setup.
- Swap the red cube for a blue one of the same shape, then a red one of a different shape. Which hurts more, and what does that say about what the network keyed on?
- Re-record 10 episodes with a second operator and mix them in. Operator style is a confound nobody warns undergraduates about.
5. Replay, to separate the arm from the policy
Before blaming a model, replay a recorded episode straight back onto the hardware. The arm executes the recorded action sequence with no network in the loop. If replay does not reproduce the original motion, the problem is mechanical or calibration-related and no training fixes it. Five minutes here saves whole weeks.
lerobot-replay \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=lab03_follower \
--dataset.repo_id=${HF_USER}/lab03_cube_in_bowl \
--dataset.episode=0Two ways to run the course
The same fourteen weeks run either on department hardware or with the cloud parts outsourced. The trade is not quality, it is which failures the students own. Self-hosting teaches CUDA drivers alongside robotics, which is either valuable or eight lost lab hours.
Print, assemble, install LeRobot from source, record to the Hugging Face Hub, train on a lab GPU, deploy from the same machine.
conda create -y -n lerobot python=3.12
conda activate lerobot
conda install ffmpeg -c conda-forge
git clone https://github.com/huggingface/lerobot.git
cd lerobot
pip install -e ".[core_scripts,training,feetech]"
hf auth login- You own printer time, servo procurement, USB chaos, a 24 GB GPU, drivers and episode storage.
- Marginal cost per training run is near zero, which matters when students retry six times.
- It teaches the full stack, unglamorous half included. Some cohorts need that; most have only fourteen weeks.
- Where it hurts: one broken CUDA install blocks every team on that machine, usually in deadline week.
The desktop client on the download page records LeRobot-format datasets straight from a teleop session, so the recording half is identical. Training is a form: pick model, dataset and hyperparameters, and the backend rents a GPU by required VRAM and writes checkpoints to object storage. What the form sends is in the training docs.
- You own the arms, the cameras and the task. Nobody in the room maintains a GPU.
- 1 to 3 USD per ACT or SmolVLA run, 4 to 12 USD per GR00T or Pi0.5 run on the published spot ranges. See pricing.
- Inference pods auto-provision and carry an idle watchdog that destroys them after an idle period, which is what you want when a student shuts a laptop.
- Students without hardware can drive a real arm at the live queue with no signup, so a remote week is not dead.
- The same operations exist at the CLI and the MCP server if you want scripted grading.
- Where it hurts: less infrastructure learned, and a third-party dependency in deadline week.

Which policy to teach with
Five policies are trainable here and two belong in an undergraduate course. The rest are worth a lecture and a table, not a lab, because inference latency and GPU tier decide what a student can debug alone.
| Policy | Params | GPU tier | Latency | Min episodes | Cost per run |
|---|---|---|---|---|---|
| ACT | about 80 M | RTX 4090 or any 24 GB | 20 ms | 50 | 1 to 3 USD |
| SmolVLA | about 450 M | RTX 4090 or any 24 GB | 245 ms | 30 | 1 to 3 USD |
| GR00T N1.7 | about 3 B, 40 M trained | A100 or H100 80 GB | 152 ms | 50 | 4 to 12 USD |
| GR00T N1.5 | about 3 B | A100 or H100 80 GB | 165 ms | 50 | 4 to 12 USD |
| Pi0.5 | about 3 B, PaliGemma | A100 or H100 80 GB | 485 ms | 50 | 4 to 12 USD |
Teach ACT first. It trains from scratch on the student's own data, so the link between demonstration quality and behaviour is not diluted by a pretrained prior. There is no base ACT model at all, only the one the class produces, which is what a first imitation learning unit wants. Contrast with SmolVLA: 30 episodes minimum and a pretrained backbone, so the same data goes further. The ACT vs SmolVLA comparison is the slide, and the arena lists 85 vision-language-action model entries with 332 benchmark results, each linked to its paper.
ACT, SmolVLA and Pi0.5 take LeRobot v3.0 datasets. GR00T N1.7 and N1.5 take v2.0 or v2.1, and a v3.0 dataset crashes the GR00T loader outright. NVIDIA ships scripts/lerobot_conversion/convert_v3_to_v2.py in Isaac-GR00T, whose SO100 example is the reference workflow. When a team tries GR00T mid-semester on data recorded for ACT, this is where their Tuesday goes: dataset rejected, wrong version. GR00T fine-tuning also exposes no random seed, so those runs are not bit-for-bit reproducible; LeRobot defaults to seed 1000.
Honest limits, including where a platform does not help
- Under 230 EUR per seat fits a consumables budget without a capital request.
- Every structural part is printable, so a snapped gripper costs an evening, not a lead time.
- Record, train, deploy is four commands, so the semester goes on science, not build systems.
- Failures are visible and traceable to a camera angle or a demonstration habit.
- Datasets use a standard format, so next year's cohort starts from this year's data.
- Apache 2.0 throughout: nothing in the syllabus rides on a licence renewal.
- Assembly is real work: two lab sessions per team, three if printing is in-house.
- Calibration drifts and must be redone; there is no absolute encoder to fall back on.
- No force or torque sensing, so contact-rich manipulation is out of scope.
- Backlash in printed parts sets a hard floor on repeatability.
- Cloud spend scales with students times retries, and students retry a lot.
- Anything above SmolVLA needs an 80 GB card, which most departments lack on site.
- USB. Six teams, twelve serial devices, one hub. Plan for it or lose a session.
The latency limit constrains course design. Inference has to sit next to the servos for anything fast: the control loop is 20 to 485 ms per action step depending on the model, and public-internet round trips on top turn a working policy into a hesitant one. Fine for slow pick and place, not for anything reactive.
Teleoperation and recording over the internet are fine, and a queue-based live arm covers students who cannot reach campus. Closed-loop execution is different: the round trip adds to a budget already down to 20 ms for ACT. Design remote weeks around recording, auditing and training, and keep deploy-and-measure weeks with the hardware.
Some things no platform fixes. It will not print your parts, stop a student remounting the wrist camera each session, or turn 30 sloppy episodes into a working policy. Cloud training removes the driver problem and nothing about data quality. Assign collecting high-quality VLA training data in week 4, before the first recording session, and pair it with the complete SO-100 setup guide as the build-week reference.
Grade the report, not the demo
Success rate here varies between teams for reasons unrelated to effort: a better print, a stiffer camera mount, an object with more contrast. Grading demo-day success rewards luck and pushes teams to cherry-pick the lighting that works. Grade the epistemics instead.
| Component | Weight | What earns the marks |
|---|---|---|
| Dataset and data card | 25 percent | Coverage argued in advance; defects found by the team. |
| Evaluation protocol | 20 percent | Trial count and scoring rule fixed before the first rollout. |
| Ablations | 25 percent | Three single-variable changes, one protocol, honest interpretation. |
| Failure taxonomy | 20 percent | Failures named, counted and attributed, with evidence. |
| Demonstration | 10 percent | It runs. That is all it should be worth. |
Two failure modes to pre-empt in the brief. Teams that spend eleven weeks assembling and two learning: set a week 4 cutoff, after which any team without a working rig switches to a public dataset from the dataset directory and continues on software. And teams reporting a single number: demand a denominator. The failure-mode index gives shared vocabulary for a policy that freezes mid-motion or an arm that twitches then sags.
Everything for the SO-100 in one place
Setup, teleoperation, dataset recording, per-model training guides and the failure-mode pages, with the GPU tier, latency and minimum episodes each policy needs.
Open the SO-100 hubQuestions course leads ask
How many SO-100 arms does a 20-student course need?▾
Seven to ten leader-follower pairs, plus a spare follower per five seats. One seat serves two to three students in rotation, because recording is a single-operator activity while the others audit footage and prepare resets. That is roughly 1,600 to 2,300 EUR in parts, before filament and cameras.
Can students complete the course without a local GPU?▾
Yes for training, no for deployment. An ACT or SmolVLA run on a rented 24 GB card costs about 1 to 3 USD over 2 to 5 hours, and LeRobot can dispatch a run to Hugging Face Jobs with --job.target. Deployment has to sit next to the servos, but at 20 ms per action step ACT is fine on a modest laptop GPU.
How many episodes before a policy does anything useful?▾
Upstream guidance for a first grasping task is at least 50 episodes, about 10 per object location. The stated minimums here are 50 for ACT, GR00T N1.5, GR00T N1.7 and Pi0.5, and 30 for SmolVLA. Below that you are testing luck, not the model.
Can the whole course run remotely?▾
Partly. Teleoperation and recording work over the internet, and a queue-based live arm lets students without hardware drive a real one. Closed-loop execution does not survive public-internet round trips on a 20 to 485 ms control budget, so keep evaluation weeks on site.
What breaks most often in a teaching lab?▾
In order: USB serial ports changing identity between sessions, camera indices shifting when a different device is plugged in first, calibration drifting after a servo is forced by hand, gripper fingers snapping, and eventually one team feeding 12 V into 7.4 V servos. A checklist fixes the first three.
Sources
- TheRobotStudio/SO-ARM100: Standard Open SO-100 and SO-101 Arms, bill of materials and print settings
- LeRobot docs: SO-101 assembly, motor setup and calibration
- LeRobot docs: imitation learning on real-world robots, recording defaults and cadence reporting
- LeRobot cheat sheet: every CLI command in one place
- LeRobot installation guide: Python 3.12, ffmpeg and the feature extras
- huggingface/lerobot: the library, Apache 2.0
- LeRobot v0.6.1 release notes, 3 August 2026
- Cadene et al., LeRobot: An Open-Source Library for End-to-End Robot Learning, ICLR 2026
- Zhao et al., Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (ACT), 2023
- Shukor et al., SmolVLA: A Vision-Language-Action Model for Affordable and Efficient Robotics, 2025
- Mitre, TARA: A Low-Cost 3D-Printed Robotic Arm for Accessible Robotics Education, 2025
- Jenkins et al., The Michigan Robotics Undergraduate Curriculum, 2023
- Hugging Face Robotics Course, unit 0
- NVIDIA Isaac-GR00T: SO100 fine-tuning example and the v3 to v2 dataset conversion script
- Waveshare wiki: SO-ARM100 and SO-ARM101 servo voltage and stall torque variants
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started