主题
5 分钟快速理解 sim2lerobot
一句话:这个项目在做什么?
把 IsaacLab 仿真环境里的机器人轨迹数据,转换成 NVIDIA GR00T 模型能直接训练的格式。
数据流全景图
┌─────────────────────────────────────────────────────────────────────┐
│ 你的目标:训练一个 GR00T 模型,让机器人学会 pick-and-lift │
└─────────────────────────────────────────────────────────────────────┘
▲
│ 需要
│
┌───────────────┴────────────────┐
│ LeRobot v2 Dataset │
│ (GR00T 1.7 能读的格式) │
│ │
│ meta/info.json │
│ meta/stats.json │
│ data/chunk-000/ │
│ videos/ │
└───────────────▲────────────────┘
│
│ L3 convert.py
│ (格式转换)
┌───────────────┴─────────────────────────────┐
│ HDF5 中间产物 │
│ (IsaacLab 官方格式) │
│ │
│ data/lift_cube/scripted/{run_id}/episodes.hdf5 │
│ data/lift_cube/rl/{run_id}/episodes.hdf5 │
│ data/lift_cube/teleop/{run_id}/episodes.hdf5 │
└───────────────▲─────────────────────────────┘
│
│ L2 数据生成
│ (三种来源)
┌───────────────┴────────────────┐
│ IsaacLab 仿真环境 │
│ Isaac-Lift-Cube-Franka-*-v0 │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 🤖 Franka│ │ 📦 Cube │ │
│ └──────────┘ └──────────┘ │
└────────────────────────────────┘你现在在哪里? 👉 L2 数据生成层(把仿真轨迹录成 HDF5)
为什么要这么做?
问题 1:GR00T 为什么不能直接读 IsaacLab 的数据?
答:格式不兼容。
- IsaacLab 输出:HDF5(嵌套 dict,每个 episode 一个 group)
- GR00T 期望:LeRobot v2(parquet 表格 + 全局 stats.json + 视频)
所以需要 L3 转换层。
问题 2:为什么要三种数据源(scripted / RL / teleop)?
答:数据金字塔——不同来源覆盖不同分布。
| 来源 | 量级 | 优势 | 劣势 |
|---|---|---|---|
| Scripted | 10⁵+ 条/天 | 量大、稳定、GPU 并行 | 轨迹单调,缺少 recovery |
| RL | 10³–10⁴ 条 | 自然产生 recovery / 长尾轨迹 | 需要训练时间,成功率不稳定 |
| Teleop | 10²–10³ 条 | 高质量 ground truth | 慢(人工操作),需要硬件 |
混合训练时,GR00T 会对 teleop 上采样(因为质量高但量少)。三种来源合到同一个 dataset,用 episodes.jsonl 的 source 字段区分。
问题 3:为什么 L2/L3 要拆成两个 venv?
答:依赖冲突。
- L2 需要 IsaacSim 6.0.0(强绑定
torch==2.10.0 cu128) - L3 需要
lerobot==0.3.3(依赖跟 IsaacSim 冲突)
用 HDF5 文件作为两个 venv 之间的边界,L2 写、L3 读。
最小可跑通路径(10 分钟)
bash
# 0. 装 L2 venv(只跑一次,~5 分钟)
cd l2 && uv sync && cd ..
# 1. 验证环境(30 秒)
uv run verify_isaac
# 2. 用 scripted SM 采 10 条轨迹(30 秒)
uv run sim2lerobot scripted collect --num_demos 10 --num_envs 4
# 3. 看数据统计(秒级)
uv run h5_inspect data/lift_cube/scripted/{run_id}/episodes.hdf5 --stats
# 4. 可视化一条轨迹(秒级)
uv run visualize_episode data/lift_cube/scripted/{run_id}/episodes.hdf5 --episode demo_0
# 输出: episode_demo_0.png(3D 轨迹 + action 时序图)
# 5. 转成 LeRobot v2(需要切 L3 venv,~1 分钟)
cd l3 && uv sync
uv run python convert.py ../data/lift_cube/scripted/{run_id}/episodes.hdf5 ../data/lerobot/lift_cube_v0/
# 输出: data/lerobot/lift_cube_v0/(GR00T 能读的格式)恭喜! 你已经跑通了 L2 → L3 的完整流程。现在 data/lerobot/lift_cube_v0/ 可以直接喂给 GR00T 训练。
下一步往哪走?
如果你想深入理解 Scripted 数据源
→ 阅读 Scripted 数据采集
- 状态机怎么写的?
- 为什么用 Warp kernel?
- 怎么扩展到其他任务?
如果你想深入理解 RL 数据源
→ 阅读 RL 数据采集
- PPO 训练的 reward 是什么?
- 为什么训练用 joint_pos 但写盘用 IK-abs?
- 怎么监控训练进度?
如果你想深入理解 Teleop 数据源
→ 阅读 Teleop 数据采集
- 键盘怎么控制机器人?
- 怎么接 SpaceMouse / VR?
如果你想深入理解 L3 转换层
→ 阅读 L3 转换器文档(位于仓库根目录 l3/README.md)
- LeRobot v2 的 schema 是什么?
- GR00T 1.7 有哪些特殊约束?
- 怎么合并三种来源到同一个 dataset?
如果你想深入理解整个 8 层 pipeline
- L0–L7 每一层在做什么?
- 本仓库在整个 pipeline 的哪个位置?
常见困惑 FAQ
Q1: 我只想要 scripted 数据,能跳过 RL 和 teleop 吗?
A: 可以。三个数据源是独立的。
Q2: 我没有 GPU,能跑吗?
A: 不能。IsaacSim 强依赖 NVIDIA GPU(CUDA)。最低要求 RTX 3060 或更高。
Q3: 我想用自己的任务(不是 lift cube),怎么改?
A:
- 在 IsaacLab 里注册你的任务(参考
IsaacLab/source/isaaclab_tasks/.../manipulation/) - 修改
src/sim2lerobot/sources/scripted/env_cfg.py的TASK_ID - 修改
src/sim2lerobot/sources/scripted/state_machine.py的状态机逻辑 - 其他步骤不变
Q4: 我想加相机观测(RGB 图像),怎么做?
A:
- 在
env_cfg.py加scene.front_cam = CameraCfg(...) - 在
observations.policy加front_cam = ObsTerm(...) - L3 转换时会自动把图像写到
videos/目录
详见 src/sim2lerobot/sources/scripted/env_cfg.py:20-23 的 TODO 注释。
Q5: 数据质量怎么检查?
A: 用我们提供的工具:
bash
# 统计分析(数值范围、NaN 检查、成功率)
uv run h5_inspect data/lift_cube/scripted/{run_id}/episodes.hdf5 --stats
# 可视化轨迹(3D 图 + 时序图)
uv run visualize_episode data/lift_cube/scripted/{run_id}/episodes.hdf5 --episode demo_0详见 数据检查与可视化。
关键概念速查
| 术语 | 含义 |
|---|---|
| L2 | Layer 2 数据生成层(IsaacLab 仿真 → HDF5) |
| L3 | Layer 3 数据处理层(HDF5 → LeRobot v2) |
| HDF5 | 中间产物格式(IsaacLab 官方 schema) |
| LeRobot v2 | 最终产物格式(GR00T 能读的 schema) |
| IK-abs | Inverse Kinematics Absolute(7d EE pose + 1d gripper) |
| joint_pos | Joint Position(9d 关节角度) |
| episode | 一条完整轨迹(从 reset 到 done) |
| success | episode 是否成功(cube 到达目标位置) |
| RecorderManager | IsaacLab 自动录制 HDF5 的基础设施 |
项目结构一览
sim2lerobot/
├── l2/ # L2 数据生成层(共享 venv)
│ ├── scripted/ # 来源 #1:手写 SM
│ ├── rl/ # 来源 #2:PPO 训练 + rollout
│ ├── teleop/ # 来源 #3:人类遥操作
│ └── visualize_episode.py # 可视化工具
├── l3/ # L3 数据处理层(独立 venv)
│ └── convert.py # HDF5 → LeRobot v2
├── tools/ # 跨 venv 小工具
│ └── h5_inspect.py # HDF5 检查 + 统计
├── docs/ # 文档
│ ├── guide/ # 入门指南
│ ├── schema/ # 格式定义
│ └── research/ # 调研留痕
└── data/ # 产物(gitignored)
├── scripted/ # L2 来源 #1 产物
├── rl/ # L2 来源 #2 产物
├── teleop/ # L2 来源 #3 产物
└── lerobot/ # L3 最终产物下一步阅读
- 想快速上手? → 直接跑"最小可跑通路径"(上面 10 分钟那段)
- 想理解设计决策? → 看
docs/research/(为什么这么设计?踩过哪些坑?) - 想查格式定义? → 看
docs/schema/(HDF5 / LeRobot v2 / GR00T 1.7 约束)