File size: 6,642 Bytes
1a59c60 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | # 3. LeRobot Manipulation
last updated Dec/26/2025
## 3-1. Teleoperation
### ์นด๋ฉ๋ผ index, ์คํ, fps ํ์ธ
2๊ฐ ์ด์์ ์นด๋ฉ๋ผ๋ฅผ ์ฐ๊ฒฐํด ๋ฐ์ดํฐ์
๊ตฌ์ถ/๋ชจ๋ธ ์ถ๋ก ์ ํ์ฉํ ์ ์์ต๋๋ค.
PC์ ์ฐ๊ฒฐ๋ ์นด๋ฉ๋ผ์ index, ํด์๋, fps ๋ฑ ์ ๋ณด๋ฅผ ํ์ธํ๋ ค๋ฉด ์๋ ๋ช
๋ น์ด๋ฅผ ์คํํ์ธ์.
```bash
lerobot-find-cameras
```
```bash
# Example print
--- Detected Cameras ---
Camera #0:
Name: OpenCV Camera @ /dev/video0
Type: OpenCV
Id: /dev/video0
Backend api: V4L2
Default stream profile:
Format: 0.0
Fourcc: YUYV
Width: 640
Height: 480
Fps: 30.0
--------------------
Camera #1:
Name: OpenCV Camera @ /dev/video2
Type: OpenCV
Id: /dev/video2
Backend api: V4L2
Default stream profile:
Format: 0.0
Fourcc: YUYV
Width: 640
Height: 480
Fps: 30.0
--------------------
Finalizing image saving...
Image capture finished. Images saved to outputs/captured_images
```
> **TIP**: ์นด๋ฉ๋ผ ์ฐ๊ฒฐ ์์์ ๋ฐ๋ผ index๊ฐ ๋ฌ๋ผ์ง ์ ์์ผ๋, ์คํ ์ ํ๋ก ํญ์ `lerobot-find-cameras` ๋ค์์ `.../lerobot/outputs/captured_images`์์ ์บก์ฒ๋ ์ฌ์ง์ ํตํด ๊ฐ camera์ ํฌํธ๋ฅผ ํ์ธํ์ธ์.
### Teleoperation command
```bash
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/so101_follower \
--robot.id=follower_new_gripper \
--robot.cameras="{
top: {type: opencv, index_or_path: "/dev/video0", width: 640, height: 480, fps: 30},
wrist: {type: opencv, index_or_path: "/dev/video2", width: 640, height: 480, fps: 30}
}" \
--teleop.type=so101_leader \
--teleop.port=/dev/so101_leader \
--teleop.id=leader \
--display_data=true
```
### ์ต์
์ค๋ช
| ์ต์
๋ช
| ์ค๋ช
| ์์ ๊ฐ |
|---|---|---|
| `--robot.type` | follower ๋ก๋ด ํ์
| `so101_follower` |
| `--robot.port` | follower USB ํฌํธ | `/dev/so101_follower` |
| `--robot.id` | follower ๋ก๋ด ๊ณ ์ ID (calibration ๋ ์ค์ ํ ID) |
| `--robot.cameras` | ์นด๋ฉ๋ผ ์ ๋ณด | `lerobot-find-cameras`๋ก ํ์ธํ ๊ฐ |
| `--teleop.type` | leader ๋ก๋ด ํ์
| `so101_leader` |
| `--teleop.port` | leader USB ํฌํธ | `/dev/so101_leader` |
| `--teleop.id` | leader ์ด๋ฆ | `leader` |
---
## 3-2. Record
### HuggingFace ๊ณ์ ์ค์
```bash
# HuggingFace CLI ํ ํฐ ๋ก๊ทธ์ธ
hf auth login --token ${YOUR_TOKEN_HERE} --add-to-git-credential
# ๋ก๊ทธ์ธ ํ์ธ
HF_USER=$(hf auth whoami | head -n 1)
export HF_USER=$(python -c "from huggingface_hub import whoami; print(whoami().get(\"name\", \"\"))")
# (Optional) ์๊ตฌ ํ๊ฒฝ ๋ณ์ ์ค์
echo 'export HF_USER=$(python -c "from huggingface_hub import whoami; print(whoami().get(\"name\", \"\"))")' >> ~/.bashrc
source ~/.bashrc
echo ${HF_USER}
# Task Name ํ๊ฒฝ ๋ณ์ ์ค์
echo export ${TASK_NAME}=TASK_NAME >> ~/.bashrc # Task ๋ฐ๋ ๋๋ง๋ค ์๋ก ์ค์
#-------------------------------------------------------------------
# Huggingface ๋ก๊ทธ์ธ ํ์ง ์๊ณ ๋ก์ปฌ์์ ์งํํ๋ ๊ฒฝ์ฐ
echo export ${HF_USER}=YOUR_NAME >> ~/.bashrc
echo export ${TASK_NAME}=TASK_NAME >> ~/.bashrc
source ~/.bashrc
echo ${HF_USER} && echo ${TASK_NAME}
```
- HuggingFace [ํ ํฐ ์ค์ ํ์ด์ง](https://huggingface.co/settings/tokens)์์ ์ ํ ํฐ ์์ฑ
- ๊ถํ: `Write` ์ ํ (๋์ค์ pretrained model์ ํ์ต์ํค๋ ๊ฒฝ์ฐ `Read` ๊ถํ๋ ํ์ํ๋ฏ๋ก `Fine-grained` ์ ํ ์ถ์ฒ)
- ์์ฑ๋ ํ ํฐ์ ์ ๋ช
๋ น์ด์ `YOUR_TOKEN_HERE`์ ์
๋ ฅ
### Record command
```bash
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=follower_new_gripper \
--robot.cameras="{
top: {type: opencv, index_or_path: "/dev/video0", width: 640, height: 480, fps: 30},
wrist: {type: opencv, index_or_path: "/dev/video2", width: 640, height: 480, fps: 30}
}" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=leader \
--dataset.single_task="make a cup of coffee." \
--dataset.repo_id=${HF_USER}/${TASK_NAME} \
--dataset.num_episodes=10 \
--dataset.episode_time_s=1200 \
--dataset.reset_time_s=3 \
--display_data=true \
--dataset.push_to_hub=true \
--resume=true # ์ด๋ฏธ ์์ฑ๋ ๋ฐ์ดํฐ์
repo์ ์ถ๊ฐ๋ก ๋ฐ์ดํฐ ์์งํ๋ ๊ฒฝ์ฐ
```
### ์ฃผ์ Record ์ต์
| ์ต์
| ์ค๋ช
|
|------|------|
| `--robot.type` | follower ๋ก๋ด ํ์
|
| `--robot.port` | follower USB ํฌํธ |
| `--robot.id` | follower ๋ก๋ด ๊ณ ์ ID (calibration ๋ ์ค์ ํ ID) |
| `--robot.cameras` | ์นด๋ฉ๋ผ ์ ๋ณด |
| `--teleop.type` | leader ๋ก๋ด ํ์
|
| `--robot.port` | leader USB ํฌํธ |
| `--teleop.id` | leader ๋ก๋ด ๊ณ ์ ID (calibration ๋ ์ค์ ํ ID) |
| `--dataset.single_task` | language instruction |
| `--dataset.repo_id` | ๋ฐ์ดํฐ์
repo ์ด๋ฆ |
| `--dataset.num_episodes` | ์์งํ ์ํผ์๋ ์ |
| `--dataset.episode_time_s` | ๊ฐ ์ํผ์๋ ๋
นํ ์๊ฐ |
| `--dataset.reset_time_s` | ์ํผ์๋ ๊ฐ ๋ฆฌ์
์๊ฐ |
| `--display_data` | ์ค์๊ฐ ๋ฐ์ดํฐ ์๊ฐํ ์ฌ๋ถ (`Rerun`) |
| `--dataset.push_to_hub` | Huggingface ์๋ ์
๋ก๋ ์ฌ๋ถ |
### Record ์ ํค๋ณด๋ ๋จ์ถํค
| ํค | ๊ธฐ๋ฅ |
|----|------|
| โ | ์ํผ์๋ ์กฐ๊ธฐ ์ข
๋ฃ |
| โ | ์ํผ์๋ ์ฌ๊ธฐ๋ก |
| ESC | Command ์ข
๋ฃ ๋ฐ ์
๋ก๋ |
### FileExistsError
๋ฐ์ดํฐ์
repo๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ฉด ๊ธฐ์กด ๋๋ ํ ๋ฆฌ๋ฅผ ๋ฎ์ด์ฐ์ง ์๊ณ FileExistsError๊ฐ ๋ฐ์ํ๋ฏ๋ก ๊ธฐ์กด repo๋ฅผ ์ญ์ ํ๊ฑฐ๋ `--resume=true` ์ต์
์ผ๋ก ๊ธฐ์กด repo์ ์ด์ด์ ์์งํด์ผ ํฉ๋๋ค.
```bash
FileExistsError: [Errno 17] File exists: '/home/.../so101_pickplace'
```
**ํด๊ฒฐ ๋ฐฉ๋ฒ:**
```bash
rm -rf ~/.cache/huggingface/lerobot/${HF_USER}/${TASK_NAME}
```
---
## 3-3. Replay
```bash
lerobot-replay \
--robot.type=so101_follower \
--robot.port=/dev/so101_follower \
--robot.id=follower \
--dataset.repo_id=${HF_USER}/${TASK_NAME} \
--dataset.episode=0
```
### ์ฃผ์ ์ต์
| ์ต์
| ์ค๋ช
|
|------|------|
| `--dataset.repo_id` | ์ฌ์ํ ๋ฐ์ดํฐ์
repo ์ด๋ฆ |
| `--dataset.episode` | ์ฌ์ํ ์ํผ์๋ ๋ฒํธ |
| `--dataset.fps` | ์ฌ์ ์๋ |
---
## 3-4. Visualization (๋ฐ์ดํฐ์
ํ์ธ)
### ๋ฐฉ๋ฒ 1: HuggingFace ์น์์ ํ์ธ
[LeRobot Dataset Visualizer](https://huggingface.co/spaces/lerobot/visualize_dataset) ํ์ด์ง์์ ๋ฐ์ดํฐ์
repo๋ฅผ ์
๋ ฅ ํ ํ์ธ
### ๋ฐฉ๋ฒ 2: ๋ก์ปฌ ์๊ฐํ
```bash
lerobot-dataset-viz \
--repo-id=${HF_USER}/${TASK_NAME} \
--episode-index=0 # visualizeํ ์ํผ์๋ ๋ฒํธ
```
- Rerun ๋ทฐ์ด ์๋ ์คํ
- ์นด๋ฉ๋ผ ์์, ๋ก๋ด ์ก์
, ์ํ ์ ๋ณด ํ์ธ ๊ฐ๋ฅ
---
|