Instructions to use siyuhsu/openpi_lab with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use siyuhsu/openpi_lab with LeRobot:
- Notebooks
- Google Colab
- Kaggle
Model card: cover both robots (G2 + Piper)
Browse files
README.md
CHANGED
|
@@ -6,108 +6,110 @@ tags:
|
|
| 6 |
- openpi
|
| 7 |
- pi0
|
| 8 |
- lerobot
|
| 9 |
-
- bimanual
|
| 10 |
- manipulation
|
|
|
|
| 11 |
library_name: openpi
|
| 12 |
pipeline_tag: robotics
|
| 13 |
---
|
| 14 |
|
| 15 |
-
#
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
camera observations and completes the task.
|
| 20 |
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
-
| | |
|
| 24 |
-
|---|---|
|
| 25 |
-
| Robot | AgiBot G2, dual 7-DOF
|
| 26 |
-
| Action / state | 16-D `[L_j1..
|
| 27 |
-
|
|
| 28 |
-
|
|
| 29 |
-
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
##
|
| 32 |
|
| 33 |
-
```
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
dataset/g2_dualarm_yogurt_rs10/ LeRobot v2.1 — 58 episodes / 48,332 frames / 10 Hz
|
| 38 |
```
|
| 39 |
|
| 40 |
-
##
|
| 41 |
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
dims as deltas, gripper kept absolute, per arm.
|
| 51 |
|
| 52 |
-
|
|
|
|
| 53 |
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
runs at a rock-steady 29.5–29.9 Hz and the cameras at ~30 Hz, but 60–65% of frames are
|
| 58 |
-
dropped before they reach disk. Naive contiguous re-indexing distorts episode duration by
|
| 59 |
-
−18%…+35%; the resampled variant is accurate to +0.06%.
|
| 60 |
-
* **The right gripper's position sensor is dead** (constant 0.2173 across all 60 episodes),
|
| 61 |
-
so both gripper dims come from the *command* boolean, not from a sensor.
|
| 62 |
-
* **Gripper polarity in this dataset: `1.0` = OPEN, `0.0` = CLOSED.** The underlying raw
|
| 63 |
-
field is named `gripper_closed`, and **the name is backwards relative to the physical
|
| 64 |
-
behaviour**. Verified from the physical semantics: in episode 27 the right gripper dim
|
| 65 |
-
flips `1.0 → 0.0` at step 54, exactly as the right arm reaches its deepest point — the
|
| 66 |
-
grasp. If you drive real hardware, confirm your wire convention separately; on this robot
|
| 67 |
-
the DDS tool wire is the opposite (`1.0` = CLOSED), so the mapping is an inversion.
|
| 68 |
-
* 2 of 60 recorded episodes are excluded (camera dropouts mid-episode, broken on the robot).
|
| 69 |
|
| 70 |
-
##
|
| 71 |
|
| 72 |
-
|
| 73 |
|
| 74 |
| metric | value | threshold |
|
| 75 |
|---|---|---|
|
| 76 |
| joint MAE | **0.28°** (worst 0.95°) | < 5° |
|
| 77 |
| gripper agreement | **99.8%** | > 90% |
|
| 78 |
| delta direction cosine | **0.999** | > 0.8 |
|
| 79 |
-
| first-step jump | 1.47° (worst 5.43°) | worst < 15° |
|
| 80 |
-
|
| 81 |
-
On real hardware the policy was validated in four stages — dry-run → ground-truth replay →
|
| 82 |
-
policy-replay on dataset observations → live closed loop — and completes the task in the
|
| 83 |
-
last stage.
|
| 84 |
-
|
| 85 |
-
## Using the weights
|
| 86 |
-
|
| 87 |
-
```bash
|
| 88 |
-
# serve (openpi)
|
| 89 |
-
python examples/g2_dualarm/g2_serve_openpi.py \
|
| 90 |
-
--config pi0_g2_dualarm --ckpt-dir <this repo>/ --port 8000
|
| 91 |
-
```
|
| 92 |
-
|
| 93 |
-
The server publishes the deployment contract in its connect-time metadata:
|
| 94 |
-
`action_chunk_size=50`, `action_rate_hz=10.0`, `robot_servo_hz=30.0`,
|
| 95 |
-
`action_space="absolute_joint_rad_plus_gripper_cmd"`, plus a `reset_pose`.
|
| 96 |
-
|
| 97 |
-
> ⚠️ **Advance the chunk at 10 Hz, not at the servo rate.** Actions are absolute joint
|
| 98 |
-
> targets; stepping them at 30 Hz executes the trajectory 3× too fast.
|
| 99 |
-
|
| 100 |
-
## Caveats
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
## Code
|
| 111 |
|
| 112 |
-
|
| 113 |
-
|
|
|
|
| 6 |
- openpi
|
| 7 |
- pi0
|
| 8 |
- lerobot
|
|
|
|
| 9 |
- manipulation
|
| 10 |
+
- bimanual
|
| 11 |
library_name: openpi
|
| 12 |
pipeline_tag: robotics
|
| 13 |
---
|
| 14 |
|
| 15 |
+
# openpi_lab — real-robot π₀ checkpoints + the datasets they were trained on
|
| 16 |
|
| 17 |
+
Two robots, each with its trained π₀ weights and the exact LeRobot dataset behind them.
|
| 18 |
+
Everything here has been run on real hardware, not only in replay.
|
|
|
|
| 19 |
|
| 20 |
+
```
|
| 21 |
+
g2/model/ π₀, 30k steps g2/dataset/ 58 ep / 48,332 frames / 10 Hz
|
| 22 |
+
piper/model/pi0/ π₀, 30k steps piper/dataset/ 125 ep / 71,702 frames / 30 Hz
|
| 23 |
+
piper/model/pi05/ π₀.₅, 30k steps
|
| 24 |
+
```
|
| 25 |
|
| 26 |
+
| | **G2** | **Piper** |
|
| 27 |
+
|---|---|---|
|
| 28 |
+
| Robot | AgiBot G2, **dual** 7-DOF arm | AgileX Piper, **single** 6-DOF arm |
|
| 29 |
+
| Action / state | 16-D `[L_j1..7, L_grip, R_j1..7, R_grip]` | 7-D `[j1..j6, gripper]` |
|
| 30 |
+
| Action space | absolute joint rad + boolean gripper | joint **delta** from episode start + absolute gripper (m) |
|
| 31 |
+
| Cameras | head + hand_left + hand_right | head + hand |
|
| 32 |
+
| Control rate | **10 Hz** | **30 Hz** |
|
| 33 |
+
| Chunk | 50 | 16 |
|
| 34 |
+
| Tasks | 1 (`Make a yogurt bowl with cereal and fruit.`) | 4 (pen→cup, carrot→bowl, blocks→drawer, stack bowls) |
|
| 35 |
|
| 36 |
+
## Download
|
| 37 |
|
| 38 |
+
```bash
|
| 39 |
+
hf download siyuhsu/openpi_lab --include "g2/model/*" --local-dir ./g2_ckpt
|
| 40 |
+
hf download siyuhsu/openpi_lab --include "piper/model/pi0/*" --local-dir ./piper_pi0
|
| 41 |
+
hf download siyuhsu/openpi_lab --include "g2/dataset/*" --local-dir ./g2_data
|
|
|
|
| 42 |
```
|
| 43 |
|
| 44 |
+
## Serving
|
| 45 |
|
| 46 |
+
```bash
|
| 47 |
+
# G2
|
| 48 |
+
python examples/g2_dualarm/g2_serve_openpi.py --config pi0_g2_dualarm \
|
| 49 |
+
--ckpt-dir ./g2_ckpt/g2/model --port 8000
|
| 50 |
+
# Piper
|
| 51 |
+
python examples/piper/code/piper_serve_openpi.py --config pi0_piper_4task \
|
| 52 |
+
--ckpt-dir ./piper_pi0/piper/model/pi0 --port 8000
|
| 53 |
+
```
|
|
|
|
| 54 |
|
| 55 |
+
Each server publishes its deployment contract in the connect-time metadata
|
| 56 |
+
(`action_chunk_size`, `action_rate_hz`, `robot_servo_hz`, `action_space`, `reset_pose`).
|
| 57 |
|
| 58 |
+
> ⚠️ **Advance the action chunk at the DATASET rate, not the servo rate.** G2 is 10 Hz,
|
| 59 |
+
> Piper is 30 Hz. Actions are absolute (G2) or delta-from-start (Piper) joint targets;
|
| 60 |
+
> stepping G2's chunk at 30 Hz would execute it 3× too fast.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
+
## Results
|
| 63 |
|
| 64 |
+
**G2** — offline replay against a live server, 120 frames / 12 episodes:
|
| 65 |
|
| 66 |
| metric | value | threshold |
|
| 67 |
|---|---|---|
|
| 68 |
| joint MAE | **0.28°** (worst 0.95°) | < 5° |
|
| 69 |
| gripper agreement | **99.8%** | > 90% |
|
| 70 |
| delta direction cosine | **0.999** | > 0.8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
+
Validated on hardware in four stages — dry-run → ground-truth replay → policy-replay on
|
| 73 |
+
dataset observations → live closed loop — and completes the task in the last stage.
|
| 74 |
+
|
| 75 |
+
**Piper** — replay eval, all 4 tasks GO: pi0 joint MAE 0.74° / cos 0.940; pi0.5 0.44° / cos 0.995.
|
| 76 |
+
Real-robot success rates over 160 rollouts (10 per model × task × condition):
|
| 77 |
+
|
| 78 |
+
| model | in-dist | OOD-L1 | overall |
|
| 79 |
+
|---|---|---|---|
|
| 80 |
+
| baseline QwenOFT | 55% | 30% | 42.5% |
|
| 81 |
+
| ctxdemo QwenLAP | 80% | 75% | 77.5% |
|
| 82 |
+
| **π₀** | **85%** | **80%** | **82.5%** |
|
| 83 |
+
| π₀.₅ | 80% | 60% | 70% |
|
| 84 |
+
|
| 85 |
+
## Things that will bite you
|
| 86 |
+
|
| 87 |
+
* **G2 gripper polarity is inverted between dataset and wire.** In the dataset `1.0` = OPEN,
|
| 88 |
+
`0.0` = CLOSED — the raw field is called `gripper_closed` and **the name is backwards**
|
| 89 |
+
relative to the physical behaviour. Verified from physical semantics: in episode 27 the
|
| 90 |
+
right gripper dim flips `1.0 → 0.0` at step 54, exactly as the arm reaches its deepest
|
| 91 |
+
point (the grasp). On that robot's DDS tool wire the convention is the opposite again.
|
| 92 |
+
Confirm your own wire convention before driving hardware.
|
| 93 |
+
* **G2's right gripper position sensor is dead** (constant 0.2173 in all 60 episodes), so
|
| 94 |
+
both gripper dims come from the *command* boolean, not a sensor.
|
| 95 |
+
* **G2 `_rs10` = resampled to a uniform 10 Hz grid.** Raw recordings are badly jittered —
|
| 96 |
+
but the cause is the on-robot **disk writer**, not the cameras or the control loop
|
| 97 |
+
(control runs at a steady 29.5–29.9 Hz; 60–65% of frames never reach disk). Naive
|
| 98 |
+
contiguous re-indexing distorts episode duration by −18%…+35%; resampling is +0.06%.
|
| 99 |
+
* **Do not JPEG-compress observations to save bandwidth.** Measured on the G2 checkpoint,
|
| 100 |
+
q92/q85 flips the *gripper decision* outright (|Δ| = 1.007 on a boolean dim, 3 of 6
|
| 101 |
+
trials) while joint dims move only ~2°. Mean error hides this completely.
|
| 102 |
+
* **These policies are stochastic** (flow matching): identical input gives joint outputs
|
| 103 |
+
differing by ~1.2°. Repeated inference is not a determinism check.
|
| 104 |
+
* Piper's `action` is the recorded teleop target and **leads the state by ~3 frames**;
|
| 105 |
+
G2's satisfies `action[t] == state[t+1]` exactly. Do not assume one convention for both.
|
| 106 |
+
|
| 107 |
+
## Scope
|
| 108 |
+
|
| 109 |
+
Single scene per task, 58 (G2) / 125 (Piper) demonstrations. Expect brittleness outside the
|
| 110 |
+
recorded prop layout.
|
| 111 |
|
| 112 |
## Code
|
| 113 |
|
| 114 |
+
`examples/g2_dualarm/` and `examples/piper/` in the accompanying openpi fork, including the
|
| 115 |
+
real-robot clients, the staged validation tooling and the hardware-verification scripts.
|