Skip to content

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 默认绑定):

操作按键
平移 ±XW / S
平移 ±YA / D
平移 ±ZQ / E
转动 roll (绕 X)Z / X
转动 pitch (绕 Y)T / G
转动 yaw (绕 Z)C / V
切换 gripper (开/关)K
重置当前 episode (丢弃 buffer)R
暂停录制 (只渲染)N
恢复录制M

操作技巧

  1. 先移到 cube 上方(WASD + QE)
  2. 下降到 cube(E 键)
  3. 合拢夹爪(K 键)
  4. 举起(Q 键)
  5. 移到目标(WASD)
  6. 放下(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.pySe3Keyboard.advance() 的 7d delta 复合到当前 EE pose,产 8d IK-abs action

关键函数

  • record.py:main() — 主循环:读键盘 → 复合 → step → 判定 success → export
  • record.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/steprot_sensitivity=0.02 rad/step。按住 W 不放 ~30Hz × 0.005 ≈ 15 cm/s,够用又不会冲过去。觉得太慢调高 --pos_sensitivity
  • 上手顺序:scripted → RL → teleop。teleop 实操最容易卡(键盘节奏感+视角),先把前两个跑通能极大缩短调试时间

当前实现范围

教学最小版,只支持 keyboard

  • Se3Keyboard(IsaacLab 自带)出 7d SE3 delta + gripper
  • keyboard_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:同上

参考