Instructions to use CodeChild/pi05-so101-erythromycin-tea with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use CodeChild/pi05-so101-erythromycin-tea with LeRobot:
- Notebooks
- Google Colab
- Kaggle
SO-101 pi0.5 训练与真机部署交接
更新时间:2026-08-04 状态:8000-step 微调和离线评估已完成;尚未进行真机闭环验证。
本文是当前 checkpoint 的权威交接说明。文中将训练时已经确定的事实和首次上真机的建议明确分开。任何真机客户端都必须先读完“动作语义”和“首次上机流程”,尤其不能把服务端返回值再次当作 delta 累加。
1. 一页摘要
| 项目 | 当前结果 |
|---|---|
| 任务 | Pick up the red erythromycin ointment box and place it on top of the green Rizhao tea tin. |
| 模型 | OpenPI pi0.5 base,全参数微调 |
| 最终 checkpoint | checkpoints/pi05_so101_erythromycin/pi05_so101_stage1_wandb/7999 |
| 训练量 | 8000 次 optimizer update,batch size 8 |
| 推理参数 | EMA 参数,ema_decay=0.99 |
| 训练数据 | clean_train:67 episodes / 15070 frames |
| 验证数据 | clean_val:18 episodes / 3972 frames |
| 未使用数据 | recovery:5 episodes / 1515 frames |
| 相机 | 固定相机 fixed + 腕部相机 wrist,RGB 640x480 @ 30 FPS |
| 状态/动作 | 6 维 SO-101 校准后位置空间 |
| 动作表示 | 前 5 维在模型内部为相对当前 state 的 delta;第 6 维夹爪为 absolute |
| 服务端输出 | (50, 6),已经还原为 SO-101 绝对目标 |
| 数据/控制频率 | 30 Hz,约 33.33 ms/step |
| 预测 horizon | 50 steps;50 个控制 tick 约 1.667 s |
| 首次真机建议 | 30 Hz 执行,每次只执行前 5 steps 后重规划;这是建议,不是已验证参数 |
| W&B | https://wandb.ai/99087192-zhejiang-university/openpi/runs/xgk0h74f |
最重要的三点:
- policy server 返回的动作已经是 absolute,机器人端不要
cumsum,也不要再次加当前 state。 - 训练数据是 30 Hz。不能把 50 个目标按 10 Hz 执行,否则同一段轨迹会被拉长约 3 倍。
- 50 是预测长度,不代表首次测试应开环执行完整 50 steps。先执行 5 steps 后重新观测和规划。
2. Artifact 和代码来源
仓库:
/home2/czj/AutoResearch/real_machine/so_arm101/openpi_so101_pi05
最终 checkpoint:
/home2/czj/AutoResearch/real_machine/so_arm101/openpi_so101_pi05/checkpoints/
pi05_so101_erythromycin/pi05_so101_stage1_wandb/7999
目录内容和磁盘占用:
| 目录 | 用途 | 大小 |
|---|---|---|
params/ |
推理必需;保存的是 EMA 参数 | 约 12 GiB |
assets/ |
推理必需;包含仅由 clean_train 计算的 norm stats |
约 16 KiB |
train_state/ |
仅继续训练需要;包含 optimizer state 等 | 约 31 GiB |
| 全部 | 可推理并可续训 | 约 42 GiB |
7999 是从 0 开始计数的最终保存 step,对应已经完成 8000 次更新。checkpoint 保存逻辑在存在 EMA 时会将 EMA 参数放进 params/,所以 policy server 加载的就是 EMA 推理权重。
当前 OpenPI 上游基准 commit:
15a9616a00943ada6c20a0f158e3adb39df2ccac
可移植性提醒: SO-101 policy、数据 split 读取和训练脚本目前包含本地尚未提交的适配代码。仅上传权重并指向干净的上游 commit,不能保证能识别 pi05_so101_erythromycin 配置。上传 Hugging Face 前,应把这些修改形成一个可检出的 Git commit/tag,或随模型仓库提供完整 patch,至少覆盖:
src/openpi/policies/so101_policy.py
src/openpi/training/config.py
src/openpi/training/data_loader.py
scripts/compute_so101_norm_stats.py
scripts/eval_so101_checkpoint.py
scripts/run_so101_training.sh
scripts/so101_preflight.py
3. 数据、划分和任务
数据包:
/home2/czj/AutoResearch/real_machine/so_arm101/
so101_erythromycin_on_tea_grid90_v2_portable
总数据为 90 episodes / 20557 frames / 685.233 s,SO-101 follower,单一语言任务,两路原始 AV1 视频。训练必须以此文件为准:
splits/split_manifest.json
实际划分:
| split | episodes | frames | 是否用于本次训练 |
|---|---|---|---|
clean_train |
67 | 15070 | 是;也只用它计算 norm stats |
clean_val |
18 | 3972 | 只用于离线验证 |
recovery |
5 | 1515 | 否;保留给后续 recovery 实验 |
绝不能直接使用 dataset/meta/info.json 中的 train: 0:90。 那是原始录制范围,不是实验划分;使用它会把 validation 和 recovery 都混入训练。
clean_val 是六个完整 held-out layout settings:setting_01、setting_09、setting_12、setting_17、setting_21、setting_29。当前没有独立 test split,clean_val 仍可能参与 checkpoint 选择,因此不能把它称为最终无偏测试集。
任务 prompt 必须保持完全一致:
Pick up the red erythromycin ointment box and place it on top of the green Rizhao tea tin.
4. 输入 schema 和相机处理
policy server 的单次输入:
observation = {
"observation/state": state_float32_6,
"observation/fixed_image": fixed_rgb_uint8_hwc,
"observation/wrist_image": wrist_rgb_uint8_hwc,
"prompt": "Pick up the red erythromycin ointment box and place it on top of the green Rizhao tea tin.",
}
约束:
state_float32_6.shape == (6,)。- 图像使用 RGB,而不是 OpenCV 默认的 BGR。
- 最稳妥的图像格式是
uint8、HWC、范围[0, 255];分辨率按采集配置为 640x480。 fixed必须对应训练时的固定相机视角,wrist必须对应腕部视角,不得互换、镜像或旋转。- OpenPI 内部使用等比例
resize_with_pad变成 224x224,不应在客户端做会改变宽高比的强制拉伸。 - pi0.5 需要三个图像槽;SO-101 适配会把第三个
right_wrist_0_rgb塞零并设置mask=false。客户端不需要发送第三路图像。
训练中实际使用的图像增强
本次没有添加 SO-101 专用的自定义增强,但 OpenPI 的标准 JAX 训练预处理在 train=True 时确实启用:
- 固定相机:95% 随机裁剪后 resize、随机旋转
[-5 deg, +5 deg]、颜色扰动; - 腕部相机:颜色扰动,不做上述随机裁剪和旋转;
- 颜色扰动参数:brightness
0.3、contrast0.4、saturation0.5; - 离线评估和 policy inference 使用
train=False,不做随机增强。
因此复现实验时不能将本次训练描述成“完全无图像增强”。
5. 状态、动作顺序和校准
state 和 action 的六维顺序完全相同:
| index | LeRobot 名称 | 含义 |
|---|---|---|
| 0 | shoulder_pan.pos |
shoulder pan |
| 1 | shoulder_lift.pos |
shoulder lift |
| 2 | elbow_flex.pos |
elbow flex |
| 3 | wrist_flex.pos |
wrist flex |
| 4 | wrist_roll.pos |
wrist roll |
| 5 | gripper.pos |
gripper |
这些值不是电机原始 encoder tick,而是 LeRobot SO-101 校准后的 position space:前五维按关节角度使用,夹爪使用线性校准空间,通常映射到约 [0, 100]。部署机器必须使用与采集机器一致的关节顺序、方向、零点、角度定义和夹爪标定。
不要只因为数值“看起来在范围内”就假设两台机器人标定一致。首次连接时应逐关节读取 state,与已知安全姿态和采集数据样本对照;发现符号、offset 或夹爪开合方向不一致时禁止下发模型动作。
6. Delta 的精确定义
训练配置中的 mask 是:
delta_action_mask = (True, True, True, True, True, False)
设发起推理时当前状态为 s,数据中的第 t 个绝对目标为 a[t]。训练输入模型前执行:
d[t, 0:5] = a[t, 0:5] - s[0:5]
d[t, 5] = a[t, 5]
这里 50 个未来目标全部减去同一个当前状态 s。它不是:
a[t] - a[t-1]
也不是每步速度。因此绝对不能沿时间轴对模型结果做 cumulative sum。
推理时 OpenPI 的输出 transform 会执行相反操作:
a_hat[t, 0:5] = d_hat[t, 0:5] + s[0:5]
a_hat[t, 5] = d_hat[t, 5]
随后移除模型内部 padding,只返回前 6 维。所以外部收到:
result["actions"].shape == (50, 6)
result["actions"] 已经是机器人校准空间中的 absolute position targets。机器人客户端只需验证、限幅并按顺序下发;不要再次加 state,不要 cumsum。
7. 30 Hz 和 50-step action chunk
训练 action chunk 按数据集的 30 Hz 采样:
control period = 1 / 30 s = 33.33 ms
action horizon = 50 steps
50 control ticks = 1.667 s
last sampled target offset = 49 / 30 s = 1.633 s
已确定的事实
- 模型每次预测 50 个顺序目标。
- 每个相邻目标的训练时间间隔是 33.33 ms。
- policy 不会自动决定机器人端执行其中多少个动作。
- 50-step prediction horizon 不等于必须 50-step open-loop execution。
首次真机建议,尚未验证
- 机器人目标下发循环保持 30 Hz。
- 初始设置执行前缀
K=5,即每次预测后执行约 167 ms,再用新图像和新 state 重规划。 - shadow 和低速测试稳定后,可根据实测推理延迟尝试
K=5..10;不要一开始开环执行完整 50 steps。 - 若采用异步推理,记录 observation timestamp、response timestamp、p50/p95 round-trip latency 和实际控制 jitter。执行前缀至少应覆盖正常的 p95 推理时间;可用
ceil(p95_latency_seconds * 30)估算最低 K,再留少量调度余量。 - 如果覆盖 p95 延迟所需的 K 已经大于 10,首次上机不应简单增大开环窗口来掩盖问题;应先降低推理/网络延迟,或采用可安全 hold 的同步流程。
- 丢弃明显过期、乱序或基于旧 observation 的 response。切换到新 chunk 时记录其 observation 序号,避免旧结果覆盖新结果。
- 不要按 10 Hz 直接执行这 50 个动作;那会把约 1.67 s 的训练轨迹拉成约 5 s。
K=5 是保守起点,不是已经通过真机成功率验证的超参数。最终 K 应由推理延迟、安全性和真实 rollout 数据共同决定。
8. Policy server 启动
在 145 上先检查 GPU,再选择空闲设备:
nvidia-smi
从仓库根目录启动:
CUDA_VISIBLE_DEVICES=<GPU_ID> .venv/bin/python scripts/serve_policy.py \
policy:checkpoint \
--policy.config pi05_so101_erythromycin \
--policy.dir checkpoints/pi05_so101_erythromycin/pi05_so101_stage1_wandb/7999
部署前至少做一次 motors-off 请求,并断言:
actions = np.asarray(result["actions"])
assert actions.shape == (50, 6)
assert np.isfinite(actions).all()
若从 Hugging Face 下载的是 inference-only snapshot,snapshot 根目录应直接包含 params/ 和 assets/,此时 --policy.dir 指向 snapshot 根目录即可。
9. 真机安全门和首次 rollout 流程
以下保护应在机器人客户端实现,不能依赖模型自己学会:
- 形状和数值检查: 必须是
(50, 6)且全部 finite;出现 NaN、Inf、缺帧或超时立即 hold/stop。 - 硬件绝对限位: 按该台 SO-101 的校准和物理限制 clamp 五个关节;夹爪限制在有效线性标定区间。训练集 q01/q99 不是硬件安全限位。
- 单步变化限制: 对每个相邻 absolute target 应用
max_relative_target或等价检查,拒绝突跳;同时限制速度和必要的加速度。 - 工作空间约束: 禁止桌面穿透、自碰撞、相机线缆拉扯和进入人员区域。
- 时序保护: 30 Hz monotonic scheduler;监测 missed deadline、queue underrun、过期 chunk 和相机/state 时间差。
- 失联行为: policy server、相机或网络超时后进入定义好的 safe hold/stop,而不是继续无限执行旧 chunk。
- 现场保护: 低速/低力矩起步、急停可触达、单人专职观察、首次 rollout 不无人值守。
推荐按以下顺序放行:
阶段 A:离线接口检查
- 用一条已录制 observation 请求模型;保存输入图像、state 和
(50, 6)输出。 - 检查 RGB/BGR、相机顺序、图像方向和 prompt。
- 画出六维 action chunk,并比较
actions[0, :5] - state[:5];确认没有明显跳变。
阶段 B:shadow inference,电机不执行
- 真机按 30 Hz 采集相机和 state,但仅打印/记录模型动作。
- 统计各维 min/max、最大单步变化、相对当前 state 的最大偏差和推理 p95 latency。
- 人工确认夹爪开合方向、所有关节符号和目标姿态合理。
阶段 C:低速闭环
- 从安全 home pose 开始,桌面清空危险障碍物。
K=5,30 Hz,开启全部限位和急停,人工全程监护。- 先做短时运动并主动停止,再做完整任务。
阶段 D:正式评估
- 固定初始姿态、物体布局、光照和相机位置,并记录每次实验配置。
- 每个 layout 做多次独立 rollout;建议至少 10 次,报告成功数和总次数,而不只展示最好视频。
- 同时记录抓取成功、最终放置稳定、掉落、碰撞、人工干预、超时和完成时间。
10. 离线评估结果
评估脚本使用 batch size 4、固定随机 seed、无随机图像增强。结果如下:
| 模型 | split | 实际样本数 | flow-matching loss |
|---|---|---|---|
| 原始 pi0.5 base | clean_val |
3972 | 0.04753249 |
| 最终微调模型 | clean_train |
15068 | 0.00407172 |
| 最终微调模型 | clean_val |
3972 | 0.01467515 |
说明:
clean_train原有 15070 frames;评估按完整 batch 统计,因此使用 15068 个样本。- 相对原始 pi0.5 base,微调模型的 validation loss 降低约 69.126%。
- 微调模型的 val/train loss 比约为 3.604,存在明显泛化差距。
- validation 是完整 held-out settings,不与 train 重叠;但没有独立 test split。
- flow-matching loss 衡量训练目标,不等于抓取成功率、放置成功率或安全性。
- 在完成受控真机 rollout 前,不能声称该模型已经可以可靠完成任务。
复现最终模型离线验证:
CUDA_VISIBLE_DEVICES=<GPU_ID> .venv/bin/python scripts/eval_so101_checkpoint.py \
--checkpoint-dir checkpoints/pi05_so101_erythromycin/pi05_so101_stage1_wandb/7999 \
--split-name clean_val
11. 训练配置记录
W&B run 中记录的实际运行参数优先于源码中的默认值:
| 参数 | 值 |
|---|---|
| base weights | gs://openpi-assets/checkpoints/pi05_base/params |
| fine-tuning | full parameters,freeze_filter=Nothing() |
| updates | 8000 |
| batch size | 8 |
| seed | 42 |
| precision | bfloat16 |
| optimizer | Adam,b1=0.9,b2=0.95,gradient clip 1.0 |
| LR | warmup 1000,peak 2.5e-5,配置的 decay horizon 30000 |
| EMA | 0.99 |
| checkpoint interval | 1000;manager 只保留最新 regular checkpoint |
| W&B run ID | xgk0h74f |
训练只运行到 8000 updates,因此 30000-step LR decay schedule 没有完整走完。源码默认训练步数后来仍可显示 30000,不要据此误称本 checkpoint 已训练 30000 steps。
12. Hugging Face 发布建议
推荐默认:inference-only,约 12 GiB
模型 repo 根目录至少包含:
params/
assets/
_CHECKPOINT_METADATA # 建议保留原始 checkpoint 元数据
README.md # Hugging Face model card
SO101_PI05_HANDOFF.md
LICENSE_GEMMA.txt
NOTICE
LICENSE_OPENPI.txt # 或等价保留 OpenPI Apache-2.0 文本
还应提供一个可复现的 OpenPI code commit/tag 或 patch。该 checkpoint 是 Orbax/OpenPI 格式,不是可直接用 transformers.AutoModel.from_pretrained() 加载的标准 Transformers 权重;model card 必须明确要求通过 OpenPI policy loader 使用。
可选:resumable,约 42 GiB
只有在确实需要继续训练时才额外上传:
train_state/
上传 train_state 会增加约 31 GiB,并且仍需完全匹配的代码、配置和 optimizer 定义。默认不建议为了推理上传它。
许可证和数据权限
- OpenPI 代码为 Apache-2.0。
- 权重由包含 Gemma 的 pi0.5 派生,发布时不能把整个模型简单标成纯 Apache-2.0。
- HF model card 建议使用
license: other,正文同时说明 OpenPI Apache-2.0 和 Gemma Terms。 - 分发时保留完整
LICENSE_GEMMA.txt,并在NOTICE中包含:
Gemma is provided under and subject to the Gemma Terms of Use found at ai.google.dev/gemma/terms
- 数据包当前明确写着“未分配数据许可证”。除非数据拥有方确认可再分发,否则不要顺手把原始双相机视频或整个数据集上传到公开 HF repo。
- 发布前由发布者确认 Gemma 条款和数据授权;本文不构成法律意见。
上传前需要确认的信息
- HF namespace:使用个人账号
CodeChild,还是某个 organization。 - model repo 名,例如
pi05-so101-erythromycin-tea。 - repo 是
public还是private。 - 上传 inference-only(约 12 GiB,推荐)还是 resumable(约 42 GiB)。
- model card 上的作者、机构、联系方式和希望展示的模型名称。
- 是否有允许公开链接的数据集 repo;若没有,model card 只描述数据,不上传原始数据。
- 是否确认按 Gemma Terms 分发派生权重并保留要求的 notice。
- SO-101 适配代码是发布为 Git commit/tag,还是随模型提供 patch。
本机已检测到可用的 Hugging Face 登录,当前身份为 CodeChild。不要在聊天中粘贴 access token;如果要换账号,应在本机运行 hf auth login,并使用具有目标 namespace write 权限的 token。
13. 发布和上机前最终 checklist
- HF repo 中同时有
params/和assets/,norm stats 没有遗漏。 - code commit/tag 或 patch 可以构造
pi05_so101_erythromycinpolicy。 - model card 明确 Orbax/OpenPI 加载方法、delta 语义、30 Hz 和 50-step horizon。
- model card 不把 flow-matching loss 写成真机成功率。
- Gemma license 和
NOTICE完整,数据发布权限已确认。 - 真机校准、关节顺序、方向和 gripper range 与采集端一致。
- fixed/wrist 图像为 RGB、方向正确、时间同步。
- 客户端确认输出是 absolute,没有二次加 state 或
cumsum。 - 30 Hz 调度、
K=5初始前缀、超时 hold、限位和急停均已实现。 - 完成 motors-off shadow inference 后才进入低速真机测试。
- 真机结果按多次 rollout 的成功/失败和安全事件完整记录。