π0.5 LoRA fine-tuned on a bimanual SO-101 (XLeRobot: two follower arms, omni
base, pan/tilt camera head) for one task:
Pick up the watermelon and place in the blue plate
Trained from pi05_base — not from an existing SO-101 checkpoint — on 50
episodes recorded on the robot itself.
Result
On 2026-08-15 this checkpoint put the watermelon in the blue plate in 4 of 5
attempts on real hardware, across five scenes it had never seen: object on
either side, plate moved, and an orange plate, a banana and a red pepper added as
distractors.
The evidence that it is not replaying a memorised trajectory: the arm it uses
tracks the watermelon's side on every run — left, left, right, right, left —
and the idle arm's joints never exceed 0.8°. A replayed trajectory cannot select
an arm from pixels. The blue plate moved on three of the runs and the fruit went
to it each time; the orange plate was ignored twice, once sitting nearer the arm
than the blue one.
What this does not establish: a success rate. Those are five different
scenes, which measures generalisation, not reliability. And all 50 episodes were
trained on — there is no held-out split, so the loss curve cannot separate
fitting from memorising, and 14999 is not established as the best of the 15
checkpoints. The curve was still descending at the end and weight decay is
effectively zero (1e-10).
The ten arm joints are deltas, the two grippers absolute
(make_bool_mask(5, -1, 5, -1)). The AbsoluteActions output transform adds
state back, so what comes off the wire is already absolute joint targets in
degrees. You can see it in assets/.../norm_stats.json: actions.mean is ~0 for
the arm joints but 10.67 / 9.40 for the grippers, matching state.mean exactly.
Contents
params/ (6.7 GB) and assets/ only. train_state/ is deliberately not
published — 5.8 GB of optimizer state that inference never reads; you would
need it only to resume training.
assets/local/watermelon_plate/norm_stats.json is small but load-bearing: it is
what client-side q01/q99 range clamping is measured against. A copy of this
checkpoint without it will serve and produce plausible numbers with no range
guard at all.
This will not reproduce the hardware result on your robot
The policy emits absolute joint targets in one specific robot's calibration
frame. Another SO-101's homing offsets differ, so identical numbers mean a
different physical pose. Feeding this checkpoint to a differently-calibrated arm
is not a degraded version of the experiment — it is an unrelated one.
If you have a bimanual SO-101, the honest path is to retrain on the dataset: one
11-hour run. See the repo's projects/vla_pi05/README.md, "Reproducing this from
a fresh clone".
It moves real hardware. The client requires an explicit --engage flag, and
nothing moves without it. Keep the workspace clear.