Skip to content

Commit 333d320

Browse files
committed
Add Pico sim2real recording support
1 parent 48b35a6 commit 333d320

19 files changed

Lines changed: 1288 additions & 16 deletions

File tree

AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ target_dof_pos = clip(action, -10, 10) × action_scale + default_dof_pos
146146
- `ARMS` entering/exiting/resume resets policy/reference alignment and uses Kp ramp; offline BVH sim2real does not use `ARMS`, and Unitree remote `B` remains BVH replay
147147
- Realtime mode switches and pause/resume use a retargeter-preserving soft reset: policy/reference state, smoothers, and reference alignment are reset, while the GMR IK warm-start is retained
148148
- Optional LinkerHand control uses `hands.enabled=true`, `hands.driver=linkerhand_l6|linkerhand_o6`, and `hands.mode=gripper|vr_hand_pose`; default is disabled
149+
- Optional Pico sim2real LeRobot v3 recording uses `--config-name sim2real_record` or `recording.enabled=true`; it requires `input.provider=pico4`, `input.video.enabled=true`, `input.video.source=realsense`, an interactive terminal, and the `recording` extra
150+
- Recording is manual only: terminal `R` starts an episode, `S` saves, `D` discards the active episode, and `Q` shuts down; `STANDING`, `MOCAP`, `ARMS`, and paused mocap are recordable
151+
- Recording captures `observation.images.d435i_rgb` RealSense RGB video at 30Hz plus `observation.state(68)`, `observation.mode(1)`, and `action(36)`; RealSense capture lives in `pico_input` through the normal `input.video` path
149152
- `gripper` mode reuses `Pico4InputProvider.get_controller_snapshot()` for Pico grip/trigger open-close control and supports LinkerHand L6 and O6
150153
- `vr_hand_pose` mode reuses `Pico4InputProvider.get_hand_snapshot()` and somehand 0.2.0 public `somehand.api` for continuous Pico hand-pose retargeting; do not start a second `PicoBridge` for hand control
151154
- Teleopit owns Pico 26-joint hand-state to 21-landmark conversion; do not import `somehand.pico_input`

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,23 @@ python train_mimic/scripts/data/build_dataset.py \
8484
--spec data/pico_motion/pico_recorded.yaml --force
8585
```
8686

87+
## Sim2Real LeRobot Recording
88+
89+
Pico sim2real can also record manual LeRobot v3 episodes from the real G1:
90+
91+
```bash
92+
pip install -e '.[recording]'
93+
python scripts/run/run_sim2real.py --config-name sim2real_record \
94+
controller.policy_path=track.onnx \
95+
recording.task="walk forward"
96+
```
97+
98+
Recording uses the terminal controls `R` start, `S` save, `D` discard, and `Q`
99+
shutdown. `STANDING`, `MOCAP`, `ARMS`, and paused mocap can be recorded. The
100+
dataset schema is `observation.images.d435i_rgb` video at 30 Hz,
101+
`observation.state(68)`, `observation.mode(1)`, and `action(36)` as the aligned
102+
reference qpos sent to the policy path.
103+
87104
## Documentation
88105

89106
Full docs at **[BotRunner64.github.io/Teleopit](https://BotRunner64.github.io/Teleopit/)**, covering installation profiles, all tutorials, configuration reference, and architecture.
@@ -95,6 +112,7 @@ Full docs at **[BotRunner64.github.io/Teleopit](https://BotRunner64.github.io/Te
95112
- Added Pico sim2real `ARMS` mode: Pico/controller `B` toggles between whole-body `MOCAP` and stand-pose body/legs with live retargeted arms.
96113
- Bumped Pico input support to pico-bridge 0.2.1 and its corrected tracking pose semantics.
97114
- Added optional LinkerHand L6 sim2real modes under `hands.*`: `gripper` from Pico grip/trigger and `vr_hand_pose` from Pico hand pose through somehand 0.2.0 public API.
115+
- Added manual Pico sim2real LeRobot v3 recording with RealSense D435i RGB video, 68D robot state, mode labels, and 36D reference-qpos action labels.
98116
- Added LinkerHand O6 support for Pico `gripper` mode with an O6-specific grasp pose.
99117
- Set LinkerHand L6 `vr_hand_pose` control to maximum speed while keeping `gripper` at the configured default speed.
100118
- Switched default `vr_hand_pose` to a low-latency somehand path with 60 Hz hand retargeting and reduced smoothing.

docs/docs/configuration/config-reference.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,48 @@ calling somehand 0.2.0 through `somehand.api` only.
151151
| `hands.somehand.temporal_filter_alpha` | somehand input landmark smoothing alpha; `1.0` disables smoothing delay | `1.0` |
152152
| `hands.somehand.output_alpha` | somehand qpos output smoothing alpha; `1.0` disables smoothing delay | `1.0` |
153153

154+
### LeRobot Recording (Pico sim2real)
155+
156+
`recording.enabled=true` is supported only with `input.provider=pico4`,
157+
`input.video.enabled=true`, `input.video.source=realsense`, and an interactive
158+
terminal. The recorder is manual: `R` starts an episode, `S` saves the active
159+
episode, `D` discards the active episode, and `Q` shuts down. `STANDING`,
160+
`MOCAP`, `ARMS`, and paused mocap can be recorded.
161+
162+
`sim2real_record.yaml` enables both recording and the required RealSense
163+
`input.video` path. Recording does not open a second camera; it consumes the
164+
same frames produced by `pico_input`.
165+
166+
| Field | Description | Default |
167+
|-------|-------------|---------|
168+
| `recording.enabled` | Enable manual LeRobot v3 recording | `false` |
169+
| `recording.output_dir` | Dataset root directory | `data/lerobot` |
170+
| `recording.repo_id` / `dataset_name` | LeRobot dataset identity | `null` |
171+
| `recording.task` | Task string stored with frames | `demo` |
172+
| `recording.fps` | Recording/video clock rate | `30` |
173+
| `recording.min_episode_seconds` | Discard saved episodes shorter than this duration | `1.0` |
174+
| `recording.record_modes` | Modes that allow recording start and frame writes | `[standing, mocap, arms, pause]` |
175+
| `recording.camera.key` | LeRobot video feature key | `observation.images.d435i_rgb` |
176+
| `recording.camera.width` / `height` / `fps` | RealSense RGB capture settings | `640` / `480` / `30` |
177+
| `recording.camera.device` | Optional RealSense serial | `null` |
178+
179+
Camera failure behavior is controlled by `input.video.fail_on_error`.
180+
181+
LeRobot features:
182+
183+
```text
184+
observation.images.d435i_rgb video [480,640,3] uint8
185+
observation.state float32[68]
186+
observation.mode float32[1]
187+
action float32[36]
188+
```
189+
190+
`observation.state` is ordered as `joint_pos(29)`, `joint_vel(29)`,
191+
`base_quat_wxyz(4)`, `base_ang_vel(3)`, and `projected_gravity(3)`.
192+
`observation.mode` is a numeric categorical: `standing=0`, `mocap=1`,
193+
`arms=2`, and `pause=3`. `action` is the current reference qpos:
194+
`root_pos(3) + root_quat_wxyz(4) + joint_pos(29)`.
195+
154196
## Critical: `default_dof_pos`
155197

156198
The RL policy outputs action **offsets** relative to the default standing pose, not absolute joint angles:

docs/docs/getting-started/installation.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ scripts/setup/download_somehand_l6_assets.sh
7373

7474
This extra is only required when `hands.enabled=true`.
7575

76+
### Sim2Real Recording
77+
78+
```bash
79+
pip install -e '.[recording]'
80+
```
81+
82+
Adds the Pico sim2real stack plus LeRobot, RealSense, and video encoding
83+
dependencies used by `sim2real_record.yaml`.
84+
7685
## Verify Installation
7786

7887
```bash

docs/docs/tutorials/pico-sim2real.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,30 @@ python scripts/run/run_sim2real.py \
9595
real_robot.network_interface=eth0
9696
```
9797

98+
## Optional LeRobot Recording
99+
100+
Install the recording extra on the machine that owns Pico input and RealSense:
101+
102+
```bash
103+
pip install -e '.[recording]'
104+
```
105+
106+
Run the recording config:
107+
108+
```bash
109+
python scripts/run/run_sim2real.py \
110+
--config-name sim2real_record \
111+
controller.policy_path=track.onnx \
112+
real_robot.network_interface=enp130s0 \
113+
recording.task="walk forward"
114+
```
115+
116+
Terminal controls are `R` start episode, `S` save, `D` discard, and `Q`
117+
shutdown. `STANDING`, `MOCAP`, `ARMS`, and paused mocap can be recorded;
118+
saved episodes cannot be discarded afterward. The v1 schema records
119+
`observation.images.d435i_rgb`, `observation.state(68)`,
120+
`observation.mode(1)`, and `action(36)` at 30 Hz.
121+
98122
## Operator Flow
99123

100124
Keep the Unitree remote in hand. `L1+R1` is the emergency stop path into

docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/configuration/config-reference.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,43 @@ Teleopit 会先将 Pico 手部状态转成 21 个 landmarks,再只通过 someh
169169
| `hands.somehand.max_iterations` | `vr_hand_pose` 的 somehand solver 迭代上限 | `12` |
170170
| `hands.somehand.temporal_filter_alpha` | somehand 输入 landmarks 平滑 alpha;`1.0` 表示关闭平滑延时 | `1.0` |
171171
| `hands.somehand.output_alpha` | somehand qpos 输出平滑 alpha;`1.0` 表示关闭平滑延时 | `1.0` |
172+
173+
### LeRobot 录制(Pico sim2real)
174+
175+
`recording.enabled=true` 只支持 `input.provider=pico4`
176+
`input.video.enabled=true``input.video.source=realsense`,并且需要交互式终端。
177+
录制是手动控制:`R` 开始 episode,`S` 保存当前 episode,`D` 丢弃当前 episode,
178+
`Q` 关闭。可以录制 `STANDING``MOCAP``ARMS` 和暂停状态的 mocap。
179+
180+
`sim2real_record.yaml` 会同时启用录制和必需的 RealSense `input.video`
181+
路径。录制不会打开第二路相机,而是消费 `pico_input` 已经产生的同一批帧。
182+
183+
| 字段 | 说明 | 默认值 |
184+
|---|---|---|
185+
| `recording.enabled` | 启用手动 LeRobot v3 录制 | `false` |
186+
| `recording.output_dir` | 数据集根目录 | `data/lerobot` |
187+
| `recording.repo_id` / `dataset_name` | LeRobot 数据集标识 | `null` |
188+
| `recording.task` | 写入 frame 的任务字符串 | `demo` |
189+
| `recording.fps` | 录制/视频主时钟频率 | `30` |
190+
| `recording.min_episode_seconds` | 保存时短于该时长的 episode 会被丢弃 | `1.0` |
191+
| `recording.record_modes` | 允许开始录制和写帧的模式 | `[standing, mocap, arms, pause]` |
192+
| `recording.camera.key` | LeRobot 视频 feature key | `observation.images.d435i_rgb` |
193+
| `recording.camera.width` / `height` / `fps` | RealSense RGB 采集设置 | `640` / `480` / `30` |
194+
| `recording.camera.device` | 可选 RealSense 序列号 | `null` |
195+
196+
相机失败时的行为由 `input.video.fail_on_error` 控制。
197+
198+
LeRobot features:
199+
200+
```text
201+
observation.images.d435i_rgb video [480,640,3] uint8
202+
observation.state float32[68]
203+
observation.mode float32[1]
204+
action float32[36]
205+
```
206+
207+
`observation.state` 的顺序是 `joint_pos(29)``joint_vel(29)`
208+
`base_quat_wxyz(4)``base_ang_vel(3)``projected_gravity(3)`
209+
`observation.mode` 是数值类别:`standing=0``mocap=1`
210+
`arms=2``pause=3``action` 是当前 reference qpos:
211+
`root_pos(3) + root_quat_wxyz(4) + joint_pos(29)`

docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/getting-started/installation.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ scripts/setup/download_somehand_l6_assets.sh
7272

7373
只有在 `hands.enabled=true` 时才需要安装这个 extra。
7474

75+
### Sim2Real 录制
76+
77+
```bash
78+
pip install -e '.[recording]'
79+
```
80+
81+
该配置包含 Pico sim2real 栈,以及 `sim2real_record.yaml` 使用的 LeRobot、
82+
RealSense 和视频编码依赖。
83+
7584
## 验证安装
7685

7786
```bash

docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/tutorials/pico-sim2real.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,29 @@ python scripts/run/run_sim2real.py \
9191
real_robot.network_interface=eth0
9292
```
9393

94+
## 可选 LeRobot 录制
95+
96+
在负责 Pico 输入和 RealSense 的机器上安装 recording extra:
97+
98+
```bash
99+
pip install -e '.[recording]'
100+
```
101+
102+
运行录制配置:
103+
104+
```bash
105+
python scripts/run/run_sim2real.py \
106+
--config-name sim2real_record \
107+
controller.policy_path=track.onnx \
108+
real_robot.network_interface=enp130s0 \
109+
recording.task="walk forward"
110+
```
111+
112+
终端控制为:`R` 开始 episode,`S` 保存,`D` 丢弃,`Q` 关闭。可以录制
113+
`STANDING``MOCAP``ARMS` 和暂停状态的 mocap;已经保存的 episode 不支持再丢弃。
114+
v1 schema 以 30 Hz 记录 `observation.images.d435i_rgb``observation.state(68)`
115+
`observation.mode(1)``action(36)`
116+
94117
## 操作流程
95118

96119
始终把 Unitree 遥控器拿在手里。`L1+R1` 是进入 `DAMPING` 的急停路径。

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ pico4 = [
5353
"pico-bridge[camera] @ https://github.com/BotRunner64/pico-bridge/releases/download/v0.2.1/pico_bridge-0.2.1-py3-none-any.whl",
5454
"teleopit[sim2real]",
5555
]
56+
recording = [
57+
"teleopit[pico4]",
58+
"lerobot",
59+
"pyrealsense2",
60+
"opencv-python",
61+
"imageio[ffmpeg]",
62+
]
5663
dexhand = [
5764
"linkerhand-python-sdk @ file:third_party/linkerhand-python-sdk",
5865
"somehand @ file:third_party/somehand",

teleopit/configs/pico4_sim2real.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@ reference_anchor_velocity_smoothing_alpha: 0.25
1818
reference_steps: [0]
1919
reference_debug_log: false
2020

21+
recording:
22+
enabled: false
23+
format: lerobot_v3
24+
output_dir: data/lerobot
25+
dataset_name: null
26+
repo_id: null
27+
task: demo
28+
fps: 30
29+
control: terminal
30+
min_episode_seconds: 1.0
31+
discard_on_shutdown: true
32+
record_modes: [standing, mocap, arms, pause]
33+
camera:
34+
enabled: true
35+
key: observation.images.d435i_rgb
36+
source: realsense
37+
width: 640
38+
height: 480
39+
fps: 30
40+
device: null
41+
2142
runtime:
2243
host: 127.0.0.1
2344
base_port: 39700

0 commit comments

Comments
 (0)