Views
No views yet
Evaluating this model and getting bad/lost behavior? ReadEVAL_FIX.mdand userobodyna_policy.py(both in this repo). The weights are verified good (reproduces training actions at correlation ~0.9997); "lost" behavior is an input-format bug — almost always images passed as HWC instead of CHW(3,H,W), or a missing repack transform.
pi05_base (openpi), full finetune (all parameters).params/). Training was still in progress when exported.pi05_robodyna_full.⚠️ This is a training checkpoint, not a converged final model. It reproduces the training-data action distribution well but has not been validated on rollouts. Evaluate on-sim before trusting it.
params/ # EMA model weights (orbax checkpoint) — this is the model
assets/robodyna_merged/norm_stats.json # state/action normalization stats — REQUIRED for inferencetrain_state/ (optimizer state, resume-only) is intentionally not included.| Robot | dual-arm UR5 — two 6-DoF arms, each with a gripper |
| State | 14-dim joint vector: [L_joint0..5, L_gripper, R_joint0..5, R_gripper] |
| Action | 14-dim, same layout, action horizon = 50 (model predicts a 50-step chunk) |
| Cameras | head (overhead/base), left_wrist, right_wrist — RGB, 240×320 native |
| Control rate | 16.67 Hz (dataset fps) |
Robot vs. data format. The physical robot is a dual-arm UR5. The demonstrations are stored in the LeRobot aloha 14-dim layout and the model was trained through openpi's Aloha data pipeline (AlohaInputs/AlohaOutputs, cameras mapped tocam_high/cam_left_wrist/cam_right_wrist). So you will see "aloha" naming in the openpi config and transforms below — that is the data/adapter convention, not the arm hardware.
policy.infer(obs) a flat dict with these exact keys (this is the LeRobot column layout the
model trained on):1obs = {
2 # IMAGES ARE CHANNEL-FIRST (C,H,W) uint8 — NOT (H,W,C). Verified against openpi make_aloha_example.
3 "observation.images.head": np.uint8, # (3, H, W), RGB, CHW
4 "observation.images.left_wrist": np.uint8, # (3, H, W), RGB, CHW
5 "observation.images.right_wrist": np.uint8, # (3, H, W), RGB, CHW
6 "observation.state": np.float32,# (14,) current joint positions (dataset convention)
7 "prompt": str, # the task instruction (see task list below)
8}(3, H, W). If your sim gives (H, W, 3), transpose:
img.transpose(2, 0, 1). Feeding HWC either crashes the resize or silently transposes your image
into noise — this was the #1 eval bug (a mislabeled earlier version of this card said HWC).img[::-1] on the channel axis).norm_stats.json. Do not pre-normalize.1result = policy.infer(obs)
2actions = result["actions"] # np.float32, shape (50, 14)(action_horizon=50, 14). Already un-normalized and converted delta → absolute, so
each row is a directly-commandable 14-dim absolute joint target.[L_j0, L_j1, L_j2, L_j3, L_j4, L_j5, L_gripper, R_j0, R_j1, R_j2, R_j3, R_j4, R_j5, R_gripper].1CHUNK_EXECUTE = 25 # execute the first K of the 50 predicted steps, then re-infer
2while not done:
3 obs = get_observation() # RGB images + 14-dim joint state + prompt
4 actions = policy.infer(obs)["actions"] # (50, 14) absolute joint targets
5 for a in actions[:CHUNK_EXECUTE]:
6 step_sim(a) # command a as absolute joint positions
7 if done: breakCHUNK_EXECUTE to your control rate.1import numpy as np
2from openpi.training import config as _config
3from openpi.policies import policy_config
4import openpi.transforms as T
5
6cfg = _config.get_config("pi05_robodyna_full")
7
8# REQUIRED: create_trained_policy defaults to an EMPTY repack, so you MUST pass one, and at
9# inference it must NOT include the "actions" key (there are no future actions to look up).
10infer_repack = T.Group(inputs=[T.RepackTransform({
11 "images": {"cam_high": "observation.images.head",
12 "cam_left_wrist": "observation.images.left_wrist",
13 "cam_right_wrist": "observation.images.right_wrist"},
14 "state": "observation.state",
15 "prompt": "prompt",
16})])
17
18policy = policy_config.create_trained_policy(
19 cfg,
20 checkpoint_dir="/path/to/this/download", # dir containing params/ and assets/
21 repack_transforms=infer_repack, # <-- do not omit this
22)
23
24obs = {
25 "observation.images.head": head_rgb_chw_uint8, # (3, H, W) CHW, RGB
26 "observation.images.left_wrist": left_rgb_chw_uint8, # (3, H, W)
27 "observation.images.right_wrist": right_rgb_chw_uint8, # (3, H, W)
28 "observation.state": joint_state_14.astype(np.float32), # (14,)
29 "prompt": "hold the cup, wait for a gap in the swaying curtain ...",
30}
31actions = policy.infer(obs)["actions"] # (50, 14) absolute joint targetscreate_trained_policy loads params/ and reads assets/robodyna_merged/norm_stats.json
automatically. Verified: on real training frames in this exact format the policy reproduces the
dataset actions with MAE ~0.01 and correlation ~0.9998 — if your eval looks lost, the mismatch is in
how the obs is built (CHW vs HWC, missing repack, wrong/empty prompt, or BGR), not the weights.pi05_robodyna_full maps head→cam_high, left_wrist→cam_left_wrist,
right_wrist→cam_right_wrist, uses use_delta_joint_actions=True, prompt_from_task=True, and
quantile normalization. If evaluating with stock openpi, register a TrainConfig with these fields
(pi05=True, action_horizon=50) or reuse the one from the training fork.| id | prompt (abbreviated) |
|---|---|
| 0 | press the button matching the target marble color … trapdoor |
| 1 | catch the red ball rolling off the ramp with the cup; ignore blue distractor |
| 2 | close the gripper around the rat/mouse when it pops up (catch_two_mice → both arms) |
| 3 | slide the bowl along the belt to catch the marble off the shelves |
| 4 | place a cup beyond the red line to catch the red ball off the valley ramp |
| 5 | pass the cup through a gap in the swaying curtain into the moving slot |
| 6 | place the square blocker in the green zone to keep the ball out of goal |
| 7 | attach the dart inside the yellow center of the moving target board |
| 8 | drop the ball into a wagon of the circling toy train (opt1: red wagon only) |
| 9 | press left/right to tilt the shelf so the marble lands in the bowl |
| 10 | set the tall block onto the moving conveyor without tipping |
| 11 | strike the red ball into the target pocket with the cue (no robot-ball contact) |
| 12 | press the matching red/green key per tile; skip black distractors |
| 13 | drop shaped blocks into matching holes on the rotating sorter cap |
| 14 | hold the ping-pong bat so the red ball hits the bat head |
| 15 | press each mole when it pops up; avoid rabbits (distractors) |
meta/tasks.jsonl
(Hoshipu/robodyna-lerobot-suite).
Use the exact prompt string the model was trained on for best results.[L_j0..5, L_gripper, R_j0..5, R_gripper]), aloha-format data pipeline.pi05_base.