Repository navigation
feat: add Elite/Rebot robot support, extend XTac-UMI training, and clean up JAX attention - #24
Conversation
…orm stats Include Elite CS66 runtime, bench recipes, policy adapters, training config registration and tests, plus Elite egg-carton and Flexiv strap-tape training configs. Revert UMI-specific normalization changes and import training loaders only for Torch/RLDS paths so parquet statistics work with the local lerobot-xense implementation.
Handle lerobot-xense builds without dataset_reader and filter video timestamps on the dataset for their legacy getitem path. Preserve reader filtering for implementations that delegate reads to DatasetReader. Exercise both installed API variants, including actual frame reads with default, selected, and empty video whitelists.
Retire unsafe XLA collective launch flags and document the findings. Include the whiteboard inspection config, remove the obsolete box assembly config, and preserve current prompt formatting updates.
Vertax42
left a comment
There was a problem hiding this comment.
Code review(Claude Code 自动审读,未跑测试验证)。共 10 条,建议合并前至少处理 🔴 两条和 🟠 两条(真机安全)。
🔴 norm stats 在错误空间计算(scripts/compute_norm_stats.py 的 _STATE_ACTION_TRANSFORM_TYPES,该行不在 diff 中故放这里)
默认 parquet 统计路径只应用 DeltaActions / SubsampleActions,跳过了本 PR 新增的 XtacUmiStateActions(去头部位姿 29D→20D)和 XtacUmiRelativeActions(相对 TCP 动作 + 仅夹爪 2D state)。
后果:compute_norm_stats.py --config-name pi05_base_bi_flexiv_umi_g1_clean_plates_1011_h100(drop_head_pose + use_relative_pose_actions)写出的是 29D 绝对位姿统计。训练时 Normalize 按 mean[..., :x.shape[-1]] 截取,于是 2D 夹爪 state 用了左臂 TCP x/y 的统计,相对动作用了绝对位姿统计——不报错,训练静默使用尺度错误的输入和目标。XtacUmiRelativeActions 的 docstring 声称支持 norm-stats batch,但这条路径从未调用它。
其余问题见行内评论。
| return FakeDataset(model_config, num_samples=1024) | ||
|
|
||
| dataset_meta = lerobot_dataset.LeRobotDatasetMetadata(repo_id) | ||
| dataset_meta = lerobot_dataset.LeRobotDatasetMetadata(repo_id, root=data_config.dataset_root) |
There was a problem hiding this comment.
🔴 数据集路径在统计与训练之间不一致
训练读新增的 DataConfig.dataset_root,但 compute_norm_stats 只认 --dataset-root / OPENPI_LEROBOT_DATASET_ROOT;而训练又不认这个环境变量——1011 的 yaml 恰恰让用户设它。
场景:按 yaml 设 OPENPI_LEROBOT_DATASET_ROOT=/data/ds → 统计来自 /data/ds,训练 LeRobotDataset(root=None) 去读 HF cache 或从 Hub 拉。反过来只在 config 设 dataset_root 则颠倒。两边可能用的是不同的数据。建议两处共用同一个解析函数(config 优先、环境变量兜底)。
| time.sleep(0.001) | ||
| while self.robot.rt_moving: | ||
| if time.time() - t0 > _RESET_TIMEOUT_S: | ||
| logger.warn("Reset motion timeout, proceeding anyway") |
There was a problem hiding this comment.
🟠 reset 失败仍继续开跑(真机安全)
reset 动作 1s 内未开始或 15s 内未完成时只打 warning 继续;另外 go_to_start=False 时也总会调 reset_to_initial_position。
场景:手臂故障/卡在半路,episode 照常开始,策略从任意(可能仍在运动的)姿态输出笛卡尔 servo 目标,首个增量动作基于模型没见过的状态。同 PR 里 Rebot env 在 reset 失败时会明确拒绝继续,建议对齐为 raise。
|
|
||
| def disconnect(self) -> None: | ||
| """Disconnect both arms, grippers, and cameras.""" | ||
| if self.robot.is_connected: |
There was a problem hiding this comment.
🟠 部分连接时资源不释放
仅当 robot.is_connected 才调 robot.disconnect()。
场景:左臂连上、右臂失败,或一只臂运行中掉线 → 双臂 facade 的 is_connected 为 False,disconnect 被跳过,已连接那只臂的 servo 循环、夹爪串口、相机都不释放/不回零。本 PR 中 Rebot env 的注释正好提到这个情况并总是调用 facade 的 disconnect,建议同样处理。
| out.reset_index(drop=True).to_parquet(dst / "data/chunk-000/file-000.parquet", index=False) | ||
|
|
||
| episodes = pd.concat([pd.read_parquet(p) for p in sorted((src / "meta/episodes").rglob("*.parquet"))]) | ||
| episodes = episodes[episodes["episode_index"].isin(kept)].sort_values("episode_index").copy() |
There was a problem hiding this comment.
🟡 per-episode stats 未随 rebase 更新
episodes 元数据从源复制,只改了索引列;stats/observation.state/*、stats/action/* 仍是源数据 29D、Pico 坐标系的统计,而 info.json 已声明 20D 特征。
场景:任何聚合 per-episode stats 的 LeRobot 路径(merge/aggregate、从 episodes 重算 meta/stats)都会拿到维度和坐标系都不对的统计 → shape 不匹配或归一化错误。建议删除这些列或按新数据重算。
| # Sessions are detected over all episodes: a dropped one still sits in the recording order. | ||
| starts = np.stack([states[rows[e][0]] for e in episode_ids]) | ||
| if args.session_starts is not None: | ||
| session_of = np.searchsorted(np.asarray(args.session_starts), episode_ids, side="right") - 1 |
There was a problem hiding this comment.
🟡 --session-starts 未校验
直接传给 np.searchsorted,不排序,也不检查首个起点 ≤ 最小 episode 编号。
场景:--session-starts 15 0(无序)或 episode 从 0 开始却传 --session-starts 5 → session id 为 -1 或错误,episode 被静默分到错误的 anchor/yaw 下。建议排序 + 断言 starts[0] <= min(episode_index)。
| delta_timestamps=self.delta_timestamps, | ||
| image_transforms=self.image_transforms, | ||
| ) | ||
| selective_reader.hf_dataset = reader.hf_dataset |
There was a problem hiding this comment.
🟢 _ensure_reader 重建 SelectiveVideoDatasetReader 时只复制了 hf_dataset 和 _absolute_to_relative_idx。如果某个 LeRobot 版本的 DatasetReader 在 __init__ 后还持有其它状态(lazy-load 标志、视频路径缓存等),重建后的行为会不同(例如每个 worker 重新加载 parquet)。单测只覆盖了这两个属性。可以考虑改 __class__ 或复制完整 __dict__ 再覆盖需要的字段。
| @@ -0,0 +1,52 @@ | |||
| # Launch template (8xH100, hb-openpi env). Do not set XLA_FLAGS: the retired collective | |||
| # combining/pipelining flags corrupted FSDP gradients; see docs/training-optimization.md. | |||
| # python scripts/compute_norm_stats.py --config-name pi05_base_bi_elite_egg_carton_to_tray_1012_h100 | |||
There was a problem hiding this comment.
🟢 注释里的启动命令写的是 pi05_base_bi_elite_egg_carton_to_tray_1012_h100,但文件/config 名是 ..._1016_h100,照抄会报 unknown config。
| @@ -151,7 +166,6 @@ class Args: | |||
| # Runtime settings | |||
| runtime_hz: float = _TRAINING_HZ | |||
| num_episodes: int = 1 | |||
There was a problem hiding this comment.
🟢 删掉了 max_episode_steps(Args 和 Runtime 调用里都删了),其它机器人示例都还保留。传了 max_episode_steps: 200 的 run 文件(各 dry-run.yaml 的写法)会解析失败;没有它,真机运行只能靠 Ctrl+C 停,少了按步数的安全上限。如果是有意为之,建议在 PR 描述里说明。
| "Set `tactile: true` under the data config's `base_config` to decode them." | ||
| ) | ||
| return decode_keys | ||
| required_video_keys = _repack_source_keys(data_config) & set(video_keys) |
There was a problem hiding this comment.
🟢 _repack_source_keys(data_config) & set(video_keys) 算了两次(missing 检查一次、required_video_keys 一次),可以算一次复用,避免两处以后不一致。
…ot resolution - compute_norm_stats parquet path now applies XtacUmiStateActions and XtacUmiRelativeActions, so drop_head_pose / use_relative_pose_actions configs get 2D gripper-state and relative-action stats instead of 29D absolute-pose stats that Normalize silently truncated. - Add config.resolve_dataset_root (DataConfig.dataset_root first, OPENPI_LEROBOT_DATASET_ROOT fallback), used by both training and compute_norm_stats so they read the same dataset. --dataset-root stays a one-off override and warns when it differs from the training root. - Add scripts/compute_norm_stats_test.py covering both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
已修改,改法: 在 src/openpi/training/config.py 新增一个共用函数 resolve_dataset_root(data_config),按评审的建议:config 里的 dataset_root
|
|
感谢修复!
以下问题这次 commit 还没涉及,麻烦看一下(修复或回复说明即可): 🟠 建议合并前处理(真机安全)
🟡 数据工具
🟢 次要(可后续 PR)
细节见上一轮的行内评论。 |
Vertax42
left a comment
There was a problem hiding this comment.
norm stats 和数据集路径两处已修好,感谢。合并前还需要处理两条真机安全问题:
examples/bi_elite_cs66_rt/real_env.py:136:reset 失败(1s 未开始或 15s 未完成)时只打 warning 继续,应改为 raise;go_to_start=False时不应调用reset_to_initial_position。examples/bi_elite_cs66_rt/real_env.py:151:只连上一部分时disconnect()被跳过,已连接那只臂的 servo 循环、夹爪串口和相机不会释放。应总是调用 facade 的 disconnect(参考同一 PR 里 Rebot env 的写法)。
另外请对 rebase_umi_dataset.py 的两条问题(per-episode stats 未更新、--session-starts 未校验)修复或说明。🟢 次要问题可以放到后续 PR。详见之前的行内评论和跟进评论。
|
@Hubo1231 @Ding-YF 跟进一下这个 PR 的进度。 目前 PR 因 changes requested 被阻塞,合并前需要处理两条 Elite 真机安全问题(详见上面的 review):
@Ding-YF 注意到 另外 |
|
修改内容: • Elite reset:1 秒未启动或 15 秒未完成时抛出 TimeoutError;go_to_start=False 时跳过复位。 |
Vertax42
left a comment
There was a problem hiding this comment.
LGTM,已核对 d0990368 和 bb538359:
- ✅ Elite reset 失败抛
TimeoutError,go_to_start=False跳过复位 - ✅ disconnect 总是调用 facade,connect 失败时也清理
- ✅ rebase 后 per-episode stats 按 20D 输出重算;
--session-starts排序去重并校验 - ✅ 本地 Elite env / rebase / norm-stats 测试 16 passed, 1 skipped;CI 通过
剩余 🟢 次要问题(_ensure_reader 状态复制、1016 yaml 注释中的 config 名、max_episode_steps、重复的集合交集)留给后续 PR。
@Ding-YF 本 PR 合并后请把 feat/elite-rerun rebase 到 main(real_env.py 两边都改过,试合并无冲突)。
本 PR 新增 Elite CS66 和 Rebot B601 双臂机器人的训练与推理支持,扩展 XTac-UMI 数据处理,并清理 JAX attention 实现及训练配置。
主要变更
兼容性与迁移
use_cudnn_attention、cudnn_attention_dtype必须删除,旧字段会导致配置加载失败。测试
新增或扩展了机器人数据配置、策略变换、RTC、LeRobot 视频筛选及 UMI 数据重定位的回归测试。