
Bolting an arm onto a mobile base adds three action dimensions, swaps position control for velocity control and breaks table-top policies. What that costs, and how to fix it.
A table-top arm rests on one quiet assumption: the world holds still unless the gripper moves it. The camera sees the same background in frame 1 and frame 900, and a shoulder angle of 42 degrees means the same point in space every time. Much of the imitation learning stack leans on that without saying so.
Put the arm on wheels and it is gone. The background becomes a function of where you drove, joint angles no longer pin down a point in the room, and a new channel appears in the action vector that behaves nothing like the other six. What changes, using the LeKiwi implementation in LeRobot and the published results, and why the policy you trained on a fixed table will not carry over.
What you need to know
- •A LeKiwi frame has 9 channels, not 6: six arm positions plus x.vel, y.vel and theta.vel, mixing positions and velocities in one vector.
- •The base is commanded and read back in velocity. LeRobot never integrates it into a pose, so the dataset holds no absolute base position.
- •Mobile ALOHA measured the cost: 20 replays of one 6 second episode with a 180 degree turn landed about 10 cm off, along a 20 cm line.
- •SmolVLA and Pi0.5 pad state and action to 32 dims, so 9 fits untouched. ACT sizes its heads from your dataset instead.
- •GR00T needs a NEW_EMBODIMENT modality config with a third key group for the base.
- •Co-training is the key result: mixing fixed-table episodes into a mobile dataset lifted ACT sub-task success from 0 to 80 percent.
The action vector gets longer, and that is the smallest problem
In LeRobot 0.6 the LeKiwi class defines one state feature dictionary and reuses it for both the action space and the non-camera half of the observation. Since LeRobot dataset columns come straight from these keys, it is the fastest way to see what a mobile episode contains.
# src/lerobot/robots/lekiwi/lekiwi.py (lerobot main, read 2026-08-24)
@property
def _state_ft(self) -> dict[str, type]:
return dict.fromkeys(
(
"arm_shoulder_pan.pos",
"arm_shoulder_lift.pos",
"arm_elbow_flex.pos",
"arm_wrist_flex.pos",
"arm_wrist_roll.pos",
"arm_gripper.pos",
"x.vel",
"y.vel",
"theta.vel",
),
float,
)
@cached_property
def action_features(self) -> dict[str, type]:
return self._state_ft # action space == state spaceSix of those behave like a fixed SO-100: write a goal, the servo goes there, read back where it is. The last three do not. x.vel is a rate. Writing 0.25 does not mean go to 0.25, it means keep moving until told otherwise. Where the robot ends up is the integral of everything you wrote, plus whatever the floor did to the wheels.
| Property | SO-100 on a table | LeKiwi (arm plus 3-wheel base) |
|---|---|---|
| Channels in state and action | 6 | 9 |
| Control mode | position for all 6 | position for 6, velocity for 3 |
| Units in one vector | degrees only | degrees, m/s and deg/s mixed |
| Read back | Present_Position | Present_Position and Present_Velocity |
| Absolute pose in the dataset | implicit | none, only rates are stored |
| Cameras | wherever you clamped them | bolted to the robot |
| Error accumulates over an episode | no | yes, on the base |
The LeRobot guide says it plainly: The wheel motors don't have to be calibrated. Arm calibration maps raw ticks onto a shared joint convention so a network trained on one arm works on another. A rotating wheel has no home position, so nothing guarantees two LeKiwis turn the same commanded x.vel into the same distance. Wheel wear, floor friction and battery charge all get a vote.
Velocity, not position: why drift is structural
LeKiwi's base observation is not a pose estimate. get_observation sync-reads Present_Velocity from wheel IDs 7, 8 and 9 and pushes the speeds through the inverse of a 3x3 matrix built from the mounting angles (240, 0, 120 degrees offset by -90), wheel radius 0.05 m, base radius 0.125 m. Nothing integrates the result into a pose, and the schema has no place to put one.
So the network never learns where the robot is. It learns what the wheels were doing and infers position from the image alone. Every source of base error is invisible to the state vector and gets corrected visually, or not at all.
Mobile ALOHA replayed a 300 step (6 second) demonstration containing a 180 degree turn of roughly 1 m radius, 20 times, objects restored to identical positions. All 20 end-effector landings sat about 10 cm to the left of the original, along a 20 cm line. Their summary: open-loop replaying a demonstration with objects restored to the same configurations will achieve zero whole-task success. On a base, replay tells you nothing.
The paper blames "the stochasticity of the ground contact and low-level controller", and states the general case up front: a small deviation in base pose leads to large drifts in the arm's end effector pose. The trigonometry is unforgiving. A 2 degree heading error is about 3.5 cm of lateral offset per metre of standoff, and centimetres are the difference between grasping a handle and knocking it over.
- Wheel slip. Omni wheels are rollers on a hub, built to slide sideways, which is what makes dead reckoning from wheel speed optimistic.
- Command latency. Mobile ALOHA measured a delay between target and actual base velocity far larger than on the arms. The two halves of your action vector do not land together.
- Loop jitter. The host runs at max_loop_freq_hz = 30, with a comment telling you to lower it if the robot jitters. Every overrun is distance nobody accounted for.
| System | Base representation | Total action dims | Mobile data used |
|---|---|---|---|
| Mobile ALOHA (2401.02117) | linear and angular velocity | 16 (14 arm plus 2 base) | 50 demos per task, 20 for two tasks |
| Pi0.5 (2504.16054) | linear 2D plus angular 1D velocity | 18 or 19, includes a torso lift | about 400 hours across about 100 homes |
| LeKiwi (LeRobot 0.6) | x.vel, y.vel, theta.vel | 9 (6 arm plus 3 base) | your call, docs suggest 50 episodes |
Three groups, three budgets, one design decision. Mobile ALOHA concatenates 14 joint positions with the base's linear and angular velocity into a 16-dimensional action, reusing existing imitation code almost unchanged. Pi0.5 does the same at 18 or 19 dims, adding a torso lift. The flow-matching action expert that consumes those dimensions is taken apart in the pi-zero write-up. None of the three feeds the policy an absolute pose.

Can the five policies even eat a 9-dimensional action?
Answer this before recording anything. Two pad the vector, one sizes itself from your data, two need a config edited by hand. Widths below come from the LeRobot and Isaac-GR00T sources read on 2026-08-24; episode counts and GPU tiers from the policy pages.
| Policy | How the wider vector is handled | Min episodes | GPU tier |
|---|---|---|---|
| ACT | no padding fields, heads sized from the dataset | 50 | RTX 4090 or any 24 GB card |
| SmolVLA | max_state_dim 32, max_action_dim 32, so 9 is padded | 30 | RTX 4090 or any 24 GB card |
| Pi0.5 | same 32-dim padding | 50 | A100 80 GB or H100 80 GB |
| GR00T N1.7 | NEW_EMBODIMENT config declaring the extra key group | 50 | A100 80 GB or H100 80 GB |
| GR00T N1.5 | same, and no LeKiwi guide exists for it here | 50 | A100 80 GB or H100 80 GB |
That padding is why SmolVLA and Pi0.5 are the least painful start: nine channels plus 23 zeros is a 32-vector, and the same checkpoint shape covers both. ACT is the opposite: the docs say it "will automatically adapt to the number of motor states, motor actions and cameras of your robot ... which have been saved in your dataset", which is convenient until you run a LeKiwi checkpoint on a plain SO-100 and the head has three columns too many.
Fine-tuning takes --embodiment-tag NEW_EMBODIMENT with --modality-config-path, and the shipped SO100 example declares exactly two state and two action keys: single_arm and gripper. A LeKiwi dataset has a third group it knows nothing about. Declare it in your config and in meta/modality.json, or you train on a slice of your data. GR00T also wants LeRobot v2.x, so a v3.0 dataset must be converted to v2.1, its own failure mode.
# examples/SO100/so100_config.py in NVIDIA/Isaac-GR00T (read 2026-08-24)
so100_config = {
"video": ModalityConfig(delta_indices=[0], modality_keys=["front", "wrist"]),
"state": ModalityConfig(delta_indices=[0],
modality_keys=["single_arm", "gripper"]),
"action": ModalityConfig(
delta_indices=list(range(0, 16)), # 16-step horizon
modality_keys=["single_arm", "gripper"],
action_configs=[
ActionConfig(rep=ActionRepresentation.RELATIVE, # delta from current state
type=ActionType.NON_EEF, format=ActionFormat.DEFAULT),
ActionConfig(rep=ActionRepresentation.ABSOLUTE, # gripper target
type=ActionType.NON_EEF, format=ActionFormat.DEFAULT),
],
),
"language": ModalityConfig(delta_indices=[0],
modality_keys=["annotation.human.task_description"]),
}
register_modality_config(so100_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT)Note the two ActionConfig entries. The arm is RELATIVE, a delta from the current state, and NON_EEF, which the file itself comments as joint-space rather than end-effector; the gripper is ABSOLUTE. N1.7's headline relative end-effector action space is the other setting of that type field, not what the SO100 example uses. A base group forces the same call, and RELATIVE is wrong there: x.vel is already a rate, so a delta from it is an acceleration. Get that backwards and the model trains cleanly, then drives inexplicably.
What breaks when you move a table-top policy onto a base
| What you see | Mechanism | What to do |
|---|---|---|
| Checkpoint refuses to load | head is 6 wide, robot wants 9 | retrain, no reshaping trick is worth trusting |
| It loads but the base never moves | base columns were zero in every training frame | record mobile episodes, padding creates no behaviour |
| Arm looks right, robot drifts out of reach | no pose in the state, camera moved with the base | vary the standoff across episodes |
| Works in one room only | background was constant, so the model used it as a position sensor | record in several locations |
| Grasp 2 to 3 cm off in one direction | heading error times reach length | keep the wrist camera in the observation |
| Base surges then stops | base velocity lags the arm command inside a chunk | stagger the base slice of the chunk |
Row four deserves a moment. The LeRobot advice for a fixed arm, "Keep the cameras fixed and maintain consistent grasping behavior throughout the recordings", is right for a table and also produces a dataset where the background pixel at (10, 10) predicts the joint angle. On wheels that shortcut is harmful: the pixel now encodes where you drove, not where the object is. The fixed-arm version is at policy only works in one setup.
- A workspace measured in rooms, not centimetres of reach
- Tasks impossible on a clamped arm, such as fetching a towel from another surface
- A base that backs away while both grippers hold something, which is how Mobile ALOHA opens a two-door cabinet
- Every fixed-arm checkpoint you own is now the wrong shape
- Open-loop replay, your cheapest debugging tool, stops being informative
- Drift is a property of velocity control on wheels, not a bug you fix once
- The dataset must cover locations as well as object positions
The manual path: recording a whole-body LeKiwi dataset
This describes LeRobot main at 0.6.2; the latest tagged release when this was written was v0.6.1, 3 August 2026. LeKiwi splits across two machines: a Raspberry Pi 5 owning the servo bus and cameras, and your laptop owning the leader arm and the policy, over ZeroMQ on ports 5555 and 5556. The arm half of it is the ordinary SO-100 procedure, walked through end to end in the SO-100 setup guide.
- 1Install the LeKiwi extra on both machines
It pulls in the Feetech SDK and ZeroMQ. Both ends of the link are LeRobot code.
bashpip install -e ".[lekiwi]" - 2Set motor IDs, arm first then wheels
One control board carries everything. The command walks the arm from 6 down to 1, then the wheels as 9, 8, 7. The order is not optional.
bashlerobot-setup-motors \ --robot.type=lekiwi \ --robot.port=/dev/ttyACM0 - 3Calibrate the arms, skip the wheels
Over SSH on the Pi for the follower, then on the laptop with --teleop.type=so100_leader. Middle of range, Enter, then sweep every joint.
bashlerobot-calibrate \ --robot.type=lekiwi \ --robot.id=my_awesome_kiwi - 4Start the host on the robot
This process owns the bus and both cameras. Its config carries a 500 ms watchdog that stops the base when no command arrives.
bashpython -m lerobot.robots.lekiwi.lekiwi_host \ --robot.id=my_awesome_kiwi - 5Teleoperate both channels at once
Set remote_ip and port in the example first. The leader arm drives six joints, w/a/s/d the base, z/x rotate, r/f step through three speed modes. The docs table lists them as 0.4, 0.25 and 0.1 m/s; lekiwi_client.py defines 0.1, 0.2 and 0.3 and starts slow. Believe the code.
bashpython examples/lekiwi/teleoperate.py - 6Record with both teleoperators in one loop
The example instantiates an SO100Leader and a KeyboardTeleop and feeds both into record_loop. Defaults are small: NUM_EPISODES 2, FPS 30, EPISODE_TIME_SEC 30.
bashpython examples/lekiwi/record.py - 7Train, then roll out
lerobot-train reads the shape of your dataset, so the nine columns propagate on their own. lerobot-rollout needs the robot as well or it has nothing to drive: lekiwi_client takes the same remote_ip the teleop example uses. For slow VLAs, --inference.type=rtc keeps chunked execution smooth on the rollout side.
bashlerobot-train \ --dataset.repo_id=${HF_USER}/lekiwi_pick \ --policy.type=act \ --output_dir=outputs/train/act_lekiwi \ --policy.device=cuda lerobot-rollout \ --strategy.type=base \ --policy.path=${HF_USER}/act_lekiwi \ --robot.type=lekiwi_client \ --robot.remote_ip=<your_pi_ip> \ --task="Fetch the cube from the side table" \ --duration=60
SO-100 class arms run Feetech STS3215 at 7.4 V, and 12 V destroys them. LeKiwi ships as three builds and the bill of materials makes the split explicit: the 5 V and the wired build buy 7.4 V STS3215 units, while the 12 V build buys 12v ST3215 units for everything, 3 for the wheels and 12 for the two arms. It is not a mixed-rail chassis, it is a different parts list. One Motor Control Board carries all nine motors on the robot, so one supply feeds the whole bus. The expensive mistake is spares: dropping a 7.4 V STS3215 from an SO-100 parts bag into a 12 V chassis kills it on the first power-up. Check /robots/lekiwi against the build you actually bought.
Recording control-flow keys work everywhere including headless SSH, but keyboard teleoperation of the base needs a global key backend: X11, Windows, or macOS with Accessibility granted. If the arm follows the leader and the base will not move, this is why.

Co-training: the result that made mobile imitation work
Your old fixed-table data is worthless as a checkpoint and valuable as a co-training ingredient. The Mobile ALOHA recipe is almost insultingly simple: sample 0.5 from the static dataset and 0.5 from the mobile one, zero-pad the base columns of the static episodes, normalise on the mobile statistics alone, batch size 16. No image tricks, no domain adaptation, even though the static data was shot on a black tabletop with the arms facing each other.
| Task and sub-task (ACT, 50 demos) | Co-trained | Not co-trained |
|---|---|---|
| Rinse Pan: turn on faucet | 80% | 0% |
| Call Elevator: press button | 100% | 5% |
| Call Elevator: enter elevator | 95% | 0% |
| Call Elevator: whole task | 95% | 0% |
| Wipe Wine: whole task | 95% | 50% |
| Push Chairs: 5th chair (out of distribution) | 89% | 0% |
| Use Cabinet: whole task | 85% | 85% |
Two things matter more than the headline. The gains sit in the precision sub-tasks: a faucet knob 0.7 cm in diameter, a 2 cm by 2 cm elevator button, the steps where the arm must visually servo to compensate for base error. And the last row is flat, 85 percent either way. Co-training fixes a specific weakness rather than multiplying performance, and reporting the row where it did nothing is why it is credible.
Fixed SO-100 episodes for a similar task are training data for your mobile policy. Pad the three base columns with zeros, mix at roughly 50/50, normalise on the mobile set. Cheaper than recording 50 more mobile episodes. Borrow from the dataset directory; the workflow is at /learn/record-your-first-dataset.
Pi0.5 publishes the scaling curve: about 400 hours of mobile manipulator data from about 100 homes, yet 97.6 percent of first-stage training examples come from elsewhere, including non-mobile robots and web images. Their ablation trained on 3, 12, 22, 53, 82 and 104 environments, and average performance improves with more training locations, with the 104-location model matching a control trained directly on the test homes. Diversity of place bought the generalisation, which is why how you collect the data outranks which model you pick.
Two routes to a trained mobile policy
- Build the base. The LeKiwi bill of materials, read 2026-08-24, totals $482 for the 12 V build, $499 for 5 V and $184 for a wired base without arms.
- Flash the Pi, enable SSH, install LeRobot and the lekiwi extra on both machines.
- Set motor IDs, calibrate both arms, leave the wheels alone.
- Record, budgeting for locations and not object positions alone. The guidance of 50 episodes with 10 per location is optimistic once the base moves.
- Pick a policy your GPU can hold: ACT and SmolVLA fit 24 GB, GR00T and Pi0.5 want 80 GB.
- For GR00T, write your own modality config with the base key group and regenerate meta/modality.json.
- Train, then evaluate with lerobot-rollout. Do not use lerobot-replay as a success metric.
Not in the training. It goes into the two-machine setup, the ZMQ link, and camera indices that shuffle between reboots. See /fix/camera-not-detected.
- Start at /compare/arms/so-100-vs-lekiwi, which puts the fixed arm and the mobile one side by side with parts cost and support level.
- Open your exact combination from the matrix at /train: ACT, SmolVLA, GR00T N1.7 or Pi0.5 on LeKiwi.
- Bring a dataset: a Hugging Face repo id, one from the public directory, or one from the desktop client.
- Pick model and hyperparameters. The backend rents a GPU on a spot market sized by required VRAM and writes checkpoints to object storage.
- Serve it through the inference pod endpoint and point your robot client at it. Pods carry an idle watchdog and destroy themselves, so nothing bills silently.
- Check /arena for what the model scored on published benchmarks first.
| Tier | Models | Run time | Cost per run |
|---|---|---|---|
| A100 80 GB or H100 | GR00T N1.7, GR00T N1.5, Pi0.5 | 3 to 6 h at 1.20 to 2.00 USD/h | about 4 to 12 USD |
| RTX 4090 or any 24 GB card | SmolVLA, ACT | 2 to 5 h at 0.30 to 0.60 USD/h | about 1 to 3 USD |
LeKiwi is listed as compatible, not the reference arm. The plumbing does not care how many action columns you have, but nothing here gives you localisation, mapping or odometry correction: the drift above is yours to handle in the data. The free arm at /live is a fixed SO-100, not a mobile robot.
Latency stops being an abstraction when the robot is moving
On a fixed arm, inference latency costs smoothness. On a moving base it costs position. Check which speed you are actually getting before you do this arithmetic: the LeRobot LeKiwi page prints a table of 0.4, 0.25 and 0.1 m/s, while lekiwi_client.py defines speed_levels of 0.1, 0.2 and 0.3 m/s and starts at the slow one. The wheels follow the code. The table below uses the code's fast mode of 0.3 m/s and its slow mode of 0.1 m/s, multiplied by the per-step inference time from the policy specs.
| Policy | Per action step | Distance at 0.3 m/s (fast) | Distance at 0.1 m/s (slow) |
|---|---|---|---|
| ACT | 20 ms | 0.6 cm | 0.2 cm |
| GR00T N1.7 | 152 ms | 4.6 cm | 1.5 cm |
| GR00T N1.5 | 165 ms | 5.0 cm | 1.7 cm |
| SmolVLA | 245 ms | 7.4 cm | 2.5 cm |
| Pi0.5 | 485 ms | 14.6 cm | 4.9 cm |
Those are multiplications, not measurements, and action chunking cuts both ways. SmolVLA and Pi0.5 predict 50 steps per call and ACT predicts 100, so the model is not consulted every step and the figure is amortised. What chunking does not fix is staleness: the last action in a 50-step chunk came from an observation 50 frames old, taken somewhere else in the room. That is why Mobile ALOHA staggers a chunk, executing the first k minus d arm actions alongside the last k minus d base actions.
The control loop is 20 to 485 ms per action step depending on the model, and public-internet round trips turn a working policy into a hesitant one. Remote inference is viable for slow pick-and-place, not for a robot translating at 0.3 m/s while it decides. Pick ACT or SmolVLA and run them next to the servos.
Before you record 50 episodes
- Confirm all nine keys appear in a recorded frame. Constant zero in x.vel means the keyboard teleoperator never connected, and you are recording a fixed-arm dataset with three dead columns.
- Record in more than one location even when the task is identical.
- Keep the wrist camera in the observation set. It is what lets the arm correct base error visually.
- Keep a fixed-table dataset for the same task. You are going to co-train with it.
Every model and arm combination has its own guide
LeKiwi is a column in the training matrix, so ACT, SmolVLA, GR00T N1.7 and Pi0.5 each have a guide written for that exact arm: GPU tier, dataset format, the defaults the trainer really sends, and what a run costs.
Open the training matrixQuestions people actually ask
Can I fine-tune my existing SO-100 checkpoint on LeKiwi data?▾
Not directly. A fixed SO-100 policy has 6 output channels and a LeKiwi dataset needs 9. For SmolVLA and Pi0.5 the padding to 32 dimensions makes the shapes match, but the base columns were zero in every frame the model saw, so it outputs zero there. The usable version is co-training: mix the old episodes in with the base columns zero-padded and sample roughly 50/50.
How many episodes does a mobile task need?▾
More than the fixed-table version, and nobody has published a clean number for a LeKiwi. The platform floor is 50 episodes for ACT, Pi0.5 and both GR00T variants, 30 for SmolVLA. Mobile ALOHA used 50 demonstrations per task and still needed co-training to clear 80 percent. Treat locations as a second axis: at 10 per location, 50 episodes buys 5 locations.
Does the desktop client record the base channel?▾
The client records LeRobot format datasets, episodes, camera streams and joint states, from a teleoperation session. For the base velocity channel specifically, the documented path is the upstream LeKiwi client scripts, which wire a leader arm and a keyboard teleoperator into one record loop. Bring the finished dataset to the training form by repo id.
Which model should I try first on a mobile base?▾
SmolVLA, for reasons that have little to do with quality: fewest episodes at 30, padding to 32 dimensions so the wider vector needs no config work, and a 24 GB card at roughly 1 to 3 USD per run. ACT is far faster at inference at 20 ms per step, which matters on a moving base, but it trains from scratch with no base model.
Why does replaying a recorded episode no longer reproduce it?▾
Because the base is velocity controlled and nothing corrects its position. Mobile ALOHA quantified it: 20 replays of one 6 second episode, objects restored, every landing about 10 cm off in the same direction, and zero whole-task success across seven tasks. Replay is a hardware smoke test now; judge a policy with a closed-loop rollout.
Sources
Sources
- Mobile ALOHA: Learning Bimanual Mobile Manipulation with Low-Cost Whole-Body Teleoperation (Fu, Zhao, Finn, arXiv 2401.02117, January 2024)
- Pi0.5: a Vision-Language-Action Model with Open-World Generalization (Physical Intelligence, arXiv 2504.16054, April 2025)
- Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (Zhao, Kumar, Levine, Finn, arXiv 2304.13705), the ACT paper
- LeRobot docs: LeKiwi assembly, calibration, teleoperation, recording and speed modes
- LeRobot docs: imitation learning on real-world robots (record, train, rollout)
- lerobot/robots/lekiwi/lekiwi.py: state features, wheel kinematics, observation and action
- lerobot/robots/lekiwi/config_lekiwi.py: watchdog, ZMQ ports, camera and teleop key defaults
- lerobot examples/lekiwi/record.py: leader arm and keyboard teleoperator in one record loop
- SmolVLA configuration: chunk_size, max_state_dim and max_action_dim
- ACT configuration: chunk_size 100, n_action_steps 100, no dimension padding
- LeKiwi bill of materials with 5 V, 12 V and wired build totals
- Isaac-GR00T SO100 modality config, the file you copy to add a base key group
- lerobot/robots/lekiwi/lekiwi_client.py: speed_levels, keyboard-to-base-velocity mapping
- Pi0.5 configuration in lerobot: chunk_size 50, max_state_dim and max_action_dim 32
- lerobot_rollout.py: strategy types, sync and rtc inference backends, required robot arguments
Sources
- Mobile ALOHA: Learning Bimanual Mobile Manipulation with Low-Cost Whole-Body Teleoperation (Fu, Zhao, Finn, arXiv 2401.02117, January 2024)
- Pi0.5: a Vision-Language-Action Model with Open-World Generalization (Physical Intelligence, arXiv 2504.16054, April 2025)
- Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (Zhao, Kumar, Levine, Finn, arXiv 2304.13705), the ACT paper
- LeRobot docs: LeKiwi assembly, calibration, teleoperation, recording and speed modes
- LeRobot docs: imitation learning on real-world robots (record, train, rollout)
- lerobot/robots/lekiwi/lekiwi.py: state features, wheel kinematics, observation and action
- lerobot/robots/lekiwi/config_lekiwi.py: watchdog, ZMQ ports, camera and teleop key defaults
- lerobot examples/lekiwi/record.py: leader arm and keyboard teleoperator in one record loop
- SmolVLA configuration: chunk_size, max_state_dim and max_action_dim
- ACT configuration: chunk_size 100, n_action_steps 100, no dimension padding
- LeKiwi bill of materials with 5 V, 12 V and wired build totals
- Isaac-GR00T SO100 modality config, the file you copy to add a base key group
- lerobot/robots/lekiwi/lekiwi_client.py: speed_levels, keyboard-to-base-velocity mapping
- Pi0.5 configuration in lerobot: chunk_size 50, max_state_dim and max_action_dim 32
- lerobot_rollout.py: strategy types, sync and rtc inference backends, required robot arguments
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started