ฯ0.5-DROID fine-tuned on the bussing task
Fine-tuned from pi05_droid on Sombit/bussing_task_new (real-robot table
bussing, "put the vegetables in the bowl"). Built to drop straight into the
existing DROID deployment โ stock architecture, stock data config, stock DROID
normalization statistics. Nothing custom to install.
Deploy
hf download <REPO_ID> --local-dir ./bussing_droid
# paste the TrainConfig from train_config_snippet.py into
# openpi/src/openpi/training/config.py
python scripts/serve_policy.py \
--policy.config=pi05_droid_bussing \
--policy.dir=./bussing_droid
In pi0_robot.yaml, point at this checkpoint and keep everything else:
policy_config:
autoclass: examples.pi0.pi0.PizeroPolicy
model_config:
model_id: pi05_droid_bussing # contains "droid", passes the assert
checkpoint_dir: /path/to/bussing_droid
flip_gripper: False # <-- MUST be False, see below
action_space: joint_velocities # unchanged
โ ๏ธ Set flip_gripper: False for this checkpoint
flip_gripper: True exists to convert this robot's gripper convention into
DROID's for the stock pi05_droid model. This checkpoint was fine-tuned on
the raw recorded values, so it already speaks the robot's convention โ 1.00 =
open, ~0.3 = closed on an object (verified: all 38 episodes start at exactly
1.00 and dip to 0.26-0.30 at the grasp).
Leaving the flip on would invert the gripper twice over โ once on the observation fed to the model, once on the action sent to the arm โ so it would open on the object and close on empty air. With the flip off, input and output both match what the model was trained on.
Interface
Exactly the standard DROID contract โ no conversion step, unlike the previous end-effector-pose version.
| observations | observation/exterior_image_1_left, observation/wrist_image_left, observation/joint_position (7), observation/gripper_position (1), prompt |
| actions | 8-d: 7 joint velocities (rad/s) + gripper position |
| action horizon | 16 |
| norm stats | the original DROID statistics, reused (not recomputed) |
Training data
38 recorded episodes; 33 used for training, 5 held out for evaluation (episodes 2, 4, 10, 20, 21 โ excluded programmatically, not by convention).
Converted with openpi's own DROID LeRobot layout: images re-decoded from source
to 320ร180, joint velocities derived as (q[t+1] โ q[t]) / 0.2.
The recording is 5 Hz and the controller runs at 15 Hz โ this is fine and
needs no rescaling. Velocity commands are rate-independent: the arm moves at
the commanded rad/s regardless of the sampling rate the data was captured at.
The only consequence is that a chunk is consumed in 0.53 s rather than 1.6 s,
i.e. the policy replans about 3ร more often than the demonstration cadence.
Measured joint velocities peak at 0.607 rad/s, comfortably inside the
controller's [-1, 1] clip, so nothing is truncated.
Known limits
- 33 episodes of a single task. Do not expect generalization to new objects, new layouts, or rephrased instructions.
- Our joint velocities have ~5ร smaller spread than DROID's average (std 0.03โ0.05 vs 0.15โ0.31) โ this teleoperation is slower and smoother than DROID's. State scales match well (0.6โ1.08ร). The DROID normalization is reused per openpi's guidance, which means our actions occupy a compressed part of the normalized range.
- Trained on data where the arm always starts from โ the same home pose (1 cm spread across all 38 episodes). Starting far from it is out of distribution.
Supersedes
An earlier upload trained absolute end-effector poses from pi05_base. That
was the wrong action space for this stack โ JointVelocitiesAction(velocities= action[:7]) read those metres as rad/s โ and it could not reach objects. Do not
use it.