主题
Teleop 数据采集
L2 数据生成层最珍贵的一支:人通过键盘实时控制机器人,录下高质量的人类示教轨迹。
数据金字塔角色:量级最小(10²–10³ 条),但语义最准——VLA 训练通常对 teleop 数据上采样。
核心原理
键盘按键(WASDQE / ZXTGCV / K)
↓
Se3Keyboard 解析成 7d SE3 delta
↓
复合到当前 EE pose(IK-rel → IK-abs)
↓
env.step(8d IK-abs action)
↓ 同时
RecorderManager 写 (obs, action) 到 HDF5关键特点:
- 高质量:人类的意图最准确
- 语义丰富:隐含任务理解
- 可处理复杂场景:人能应对意外
- 慢:人手响应 30 Hz,操作耗时
使用方法
bash
# 基础录制(5 个 demo,需要 GUI)
uv run sim2lerobot teleop record --task lift_cube --num_demos 5
# 录制视频(每 2 个 episode 录一个)
uv run sim2lerobot teleop record --task lift_cube --num_demos 10 --video --video_interval 2
# 检查 schema
uv run h5_inspect data/lift_cube/teleop/{run_id}/episodes.hdf5按键(Se3Keyboard 默认绑定):
| 操作 | 按键 |
|---|---|
| 平移 ±X | W / S |
| 平移 ±Y | A / D |
| 平移 ±Z | Q / E |
| 转动 roll (绕 X) | Z / X |
| 转动 pitch (绕 Y) | T / G |
| 转动 yaw (绕 Z) | C / V |
| 切换 gripper (开/关) | K |
| 重置当前 episode (丢弃 buffer) | R |
| 暂停录制 (只渲染) | N |
| 恢复录制 | M |
操作技巧:
- 先移到 cube 上方(WASD + QE)
- 下降到 cube(E 键)
- 合拢夹爪(K 键)
- 举起(Q 键)
- 移到目标(WASD)
- 放下(E 键)
关键设计:IK-rel → IK-abs 转换
为什么需要转换
问题:三来源要合到同一个 dataset,action 表示必须一致。
Scripted: 8d IK-abs [x, y, z, qx, qy, qz, qw, gripper]
RL: 8d IK-abs(写盘时重写)
Teleop: 7d IK-rel [dx, dy, dz, drx, dry, drz, gripper] ← 不一致!解决:在脚本侧把 IK-rel 复合成 IK-abs。
python
# 读当前 EE pose
ee_pos_curr, ee_quat_curr = read_ee_frame_sensor(env)
# 复合
abs_pos = ee_pos_curr + delta[:3]
abs_quat = quat_mul(delta_quat, ee_quat_curr)
# 写盘
action = [abs_pos, abs_quat, gripper] # 8d IK-abs为什么不让 controller 做?
- 如果用 IK-rel controller,写盘的
actions列就是 7d delta - L3 转换层就要按 source 分支处理(scripted/rl 用 8d,teleop 用 7d)
- 在脚本侧复合 → 三来源 schema 完全一致
详见 Obs/Action 对齐 "三来源转换义务"。
人类 vs 机器的控制方式
┌─────────────────────────────────────────────────────────────┐
│ Scripted(机器) │
└─────────────────────────────────────────────────────────────┘
思维:规则("如果 cube 在这,就去那")
输出:绝对位姿("EE 去 (0.5, 0.0, 0.3)")
频率:50 Hz(物理仿真频率)
特点:精确、快速、但死板
┌─────────────────────────────────────────────────────────────┐
│ Teleop(人类) │
└─────────────────────────────────────────────────────────────┘
思维:增量("往前一点、往左一点")
输出:相对增量("dx=+0.01, dy=-0.005")
频率:30 Hz(人手响应延迟)
特点:灵活、能应对意外、但慢为什么人类用增量控制?
- 人脑不擅长计算绝对坐标("EE 去 (0.5, 0.0, 0.3)" 很难想象)
- 人脑擅长相对调整("再往前一点" 很直观)
- 键盘 / SpaceMouse 天然输出增量(按住 W = 持续 +dx)
Success 判定
连续 N 步 + 手动 export:
python
if object_reached_goal(env):
success_counter += 1
if success_counter >= 10: # 连续 10 步(0.33s)
env.unwrapped.recorder_manager.export_current_episode(success=True)
env.reset()为什么不用 TerminationManager?
- 避免 cube 抖动瞬时进圈触发 auto-reset 把 episode 切短
- 连续 N 步(0.33s)+ 手动 export 更稳
- 这是 IsaacLab 官方
record_demos.py的做法
代码结构
| 文件 | 作用 |
|---|---|
src/sim2lerobot/sources/teleop/record.py | 主入口:启动 sim、起 Se3Keyboard、跑 30Hz 录制 loop |
src/sim2lerobot/sources/teleop/env_cfg.py | 基于 Isaac-Lift-Cube-Franka-IK-Abs-v0,关 time_out、挂 RecorderManager |
src/sim2lerobot/sources/teleop/keyboard_adapter.py | 把 Se3Keyboard.advance() 的 7d delta 复合到当前 EE pose,产 8d IK-abs action |
关键函数:
record.py:main()— 主循环:读键盘 → 复合 → step → 判定 success → exportrecord.py:object_reached_goal()— 判断 cube 是否到达目标(距离 < 阈值)keyboard_adapter.py:keyboard_delta_to_ik_abs()— IK-rel delta → IK-abs action
常见问题
Q: 为什么不直接用 IsaacLab 的 IK-rel controller?
A: 如果用 IK-rel controller,写盘的 actions 列就是 7d delta(不是 8d abs),跟 scripted/rl 的 schema 不一致。L3 转换层就要按 source 分支处理。把复合做在脚本侧能保证三来源 schema 对齐。
Q: 为什么 time_out=None?
A: keyboard 操作慢,默认 episode_length_s=5.0 太短,容易在用户还没完成动作时被强制 reset。给人留足够时间。
Q: 为什么 num_envs=1?
A: 人一次只能控一台机器人。多 env 会让 keyboard 的单 7d action broadcast 变得别扭(所有 env 同步动作)。
Q: 怎么接 SpaceMouse?
A: 把 Se3Keyboard 替换成 Se3SpaceMouse,其他代码不变(接口同形,都是 7d SE3 delta + gripper)。需要硬件验证。
数据价值
/\
/ \ Teleop (10²–10³ 条)
/ 高质\ 人类意图最准确
/ 量少 \
/--------\
/ RL \ (10³–10⁴ 条)
/ recovery \ 自然产生 recovery
/--------------\
/ Scripted \ (10⁵+ 条)
\________________/ 量大,覆盖底座
混合训练时:
- Scripted 提供量(覆盖常见场景)
- RL 提供 recovery(处理意外)
- Teleop 提供质量(人类意图 ground truth)
→ GR00T 对 teleop 上采样(因为质量高但量少)Teleop 的价值:
- 语义最准确:人知道"为什么这么做"(隐含任务理解)
- 处理复杂场景:cube 卡住了 → 人能调整策略;scripted 会卡死
- 提供 ground truth:BC 模型的"黄金标准"
为什么量少但重要?
- 10 条高质量 teleop > 1000 条低质量 scripted
- VLA 训练时,teleop 数据的 loss 权重通常更高
- 混合训练的"锚点":其他来源向 teleop 对齐
注意事项
- Sim 需要 GUI 才能拿键盘焦点,
record.py强制args.headless = False num_envs=1是硬约束——人一次只能控一台机器人- 灵敏度建议:默认
pos_sensitivity=0.005 m/step、rot_sensitivity=0.02 rad/step。按住 W 不放 ~30Hz × 0.005 ≈ 15 cm/s,够用又不会冲过去。觉得太慢调高--pos_sensitivity - 上手顺序:scripted → RL → teleop。teleop 实操最容易卡(键盘节奏感+视角),先把前两个跑通能极大缩短调试时间
当前实现范围
教学最小版,只支持 keyboard:
Se3Keyboard(IsaacLab 自带)出 7d SE3 delta + gripperkeyboard_adapter把 delta 复合到ee_frame当前 pose,产出 8d IK-abs action- HDF5 schema 与
src/sim2lerobot/sources/scripted/src/sim2lerobot/sources/rl严格对齐
不在范围:
- SpaceMouse:接口跟 keyboard 一样是 7d SE3 delta,把
Se3Keyboard替成Se3SpaceMouse即可,但需要硬件验证 - VR / OpenXR / handtracking:需要 CloudXR + 头显,工程复杂度高
- Apple Vision Pro / leader-follower:同上
参考
- L2 三种轨迹来源 §3
- Obs/Action 对齐 "三来源转换义务"
- 快速开始