# ヒューマン・イン・ザ・ループによるデータ収集

Human-In-the-Loop (HIL) データ収集では、訓練済みのポリシーを実際のロボットにデプロイし、人間のオペレーターが監視して必要に応じて介入することで、ポリシーを改善できます。介入データ（回復動作や修正）は自律区間と並行して記録され、ポリシーが失敗をどのように処理すべきかを教える、より充実した訓練データセットが生成されます。

---

## なぜHuman-In-the-Loopなのか？

標準的な行動クローニングは、成功したデモデータのみを用いてポリシーを学習します。デプロイメント時には、小さな誤差が累積し、学習時に一度も見たことのない状態にロボットを押しやる可能性があります（分布シフト）。HILデータ収集は、これに対処するために以下を行います：

- 学習済みポリシーを実際のロボットで実行する
- ロボットが失敗しそうなときに人間が介入する
- 人間の回復と修正をトレーニングデータとして記録する
- 結合データセットでポリシーをファインチューニング

これにより、タスクを実行する方法だけでなく、問題が発生した場合の回復方法も把握したポリシーが生成されます。

---

## 仕組み

HILセッション中、人間のオペレーターは各エピソード内でこのループに従います:

1. **Watch** して、ポリシーが自律的に実行される様子を確認します
2. **Pause** 失敗が迫っている場合、ロボットは現在的位置を保持します
3. **制御を奪取**し、ロボットを良好な状態（リカバリー）に遠隔操作で戻してから、動作を修正します
4. **ポリシーに制御を返す**と、ポリシーは自律的な実行を再開します
5. エピソード中、必要に応じてステップ2〜4を繰り返します
6. タスクが完了したら、**エピソードを終了**し、保存して次のロールアウトに進みます

デフォルトでは、人間が制御するセグメント（リカバリーと修正）のみが記録され、各修正が独立したエピソードとして扱われます。`--strategy.record_autonomous=true` を使用すると、自律セグメントも記録されます。これにより、ポリシーと人間が複数回制御を交代でき、自律実行、リカバリー、修正が1つの連続した軌跡としてキャプチャされます。どちらのモードでも、ロボットは各ハンドオフ後に現在の状態から継続します（介入が発生したという理由だけでリセットは不要です）。収集後、統合されたデータセット（元のデモデータ + HIL データ）を使用してポリシーのファインチューニングが行われます。

このプロセスは反復的に繰り返すことができます：デプロイ、収集、ファインチューニング、繰り返し。各ラウンドでは、現在のポリシーの失敗モードに焦点を当てます。

```
┌─────────────────────────────────────────────────────────────────────────┐
│  Policy v0 (trained on demos)                                           │
│       ↓                                                                 │
│  HIL Collection (target current failure modes) → Fine-tune → Policy v1  │
│       ↓                                                                 │
│  HIL Collection (target new failure modes) → Fine-tune → Policy v2      │
│       ↓                                                                 │
│  ... (repeat until satisfactory performance)                            │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## ハードウェア要件

### テレオペレーター要件

`lerobot-rollout --strategy.type=dagger` モードには、次のことができる**アクティブモーターを備えたテレオペレーター**が必要です:

- トルクのプログラムによる有効化/無効化
- ターゲット位置へ移動する（一時停止時にロボットの状態をミラーリングするため）

一時停止すると、リーダーアームがロボットに合わせて移動するため、制御がポリシーと人間の間でジャンプなく引き継がれます。ジャンプが発生すると、記録された修正に反映され、ポリシーがぎこちない軌道を学習してしまうことになります。

**対応するテレオペレーター:**

- `bi_openarm_mini` - 両手用 OpenArm Mini
- `so100_leader` / `so101_leader` - SO100 / SO101 リーダーアーム
- `bi_so_leader` - 両手SO100 / SO101リーダーアーム

> [!IMPORTANT]
> 提供されているコマンドは、デフォルトで`bi_openarm_follower` + `bi_openarm_mini`を使用します。SO100 / SO101のセットアップも同様に動作し、例えば`--robot.type=so101_follower`に`--teleop.type=so101_leader`を指定します。

---

## スクリプト

HILデータ収集には、`lerobot-rollout`に`--strategy.type=dagger`を付けて使用します。推論バックエンドは`--inference.type=sync|rtc|remote`で選択します:

| モード                     | フラグ                      | モデル                                                                                                 |
| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------ |
| 標準（デフォルト）       | _（フラグは不要）_        | ACT、Diffusion Policy                                                                                  |
| リアルタイムチャンキング（RTC） | `--inference.type=rtc`    | Pi0, Pi0.5, SmolVLA                                                                                    |
| リモート                   | `--inference.type=remote` | `lerobot-policy-server`によって提供されるチェックポイント。[リモートデプロイメントの要件](./remote_inference)を参照してください。 |

---

## ステップバイステップガイド

### ステップ1: ベースポリシーの事前学習

まず、デモデータセットでポリシーを学習します。この例では、ステップ2で標準的な推論を実行できるACTを学習します。

```bash
lerobot-train \
    --dataset.repo_id=${HF_USER}/demo-dataset \
    --policy.type=act \
    --policy.repo_id=${HF_USER}/act_pretrain \
    --output_dir=outputs/pretrain \
    --batch_size=32 \
    --steps=50000
```

### ステップ2: HILデータの収集

**標準的な推論（ACT、Diffusion Policy）:**

```bash
lerobot-rollout --strategy.type=dagger \
    --robot.type=bi_openarm_follower \
    --robot.left_arm_config.port=can1 \
    --robot.left_arm_config.side=left \
    --robot.right_arm_config.port=can0 \
    --robot.right_arm_config.side=right \
    --robot.cameras='{left_wrist: {type: opencv, index_or_path: "/dev/video0", width: 1280, height: 720, fps: 30}, right_wrist: {type: opencv, index_or_path: "/dev/video4", width: 1280, height: 720, fps: 30}, base: {type: opencv, index_or_path: "/dev/video2", width: 640, height: 480, fps: 30}}' \
    --teleop.type=bi_openarm_mini \
    --teleop.left_arm_config.port=/dev/ttyACM0 \
    --teleop.right_arm_config.port=/dev/ttyACM1 \
    --policy.path=outputs/pretrain/checkpoints/last/pretrained_model \
    --dataset.repo_id=${HF_USER}/rollout_hil_dataset \
    --dataset.single_task="Fold the T-shirt properly" \
    --dataset.fps=30 \
    --strategy.num_episodes=50 \
    --interpolation_multiplier=2
```

`--interpolation_multiplier=N` を使用すると、ロボットはポリシーアクションごとに `N` 個の補間コマンドを受信します（制御は `fps × N` Hz で実行されます）。一方、ポリシー推論とデータセットの記録は `--fps` のままなので、記録されたデータセットは宣言された FPS と一致します。

**大規模モデル（Pi0、Pi0.5、SmolVLA）での RTC について:**

推論レイテンシが高いモデルでは、スムーズな実行のためにRTCを有効にしてください。これには、ステップ1のACTポリシーではなく、Pi0、Pi0.5、SmolVLAなどのVLAベースポリシーが必要です:

```bash
lerobot-rollout --strategy.type=dagger \
    --inference.type=rtc \
    --inference.rtc.execution_horizon=20 \
    --inference.rtc.max_guidance_weight=5.0 \
    --inference.rtc.prefix_attention_schedule=LINEAR \
    --robot.type=bi_openarm_follower \
    --robot.left_arm_config.port=can1 \
    --robot.left_arm_config.side=left \
    --robot.right_arm_config.port=can0 \
    --robot.right_arm_config.side=right \
    --robot.cameras='{left_wrist: {type: opencv, index_or_path: "/dev/video0", width: 1280, height: 720, fps: 30}, right_wrist: {type: opencv, index_or_path: "/dev/video4", width: 1280, height: 720, fps: 30}, base: {type: opencv, index_or_path: "/dev/video2", width: 640, height: 480, fps: 30}}' \
    --teleop.type=bi_openarm_mini \
    --teleop.left_arm_config.port=/dev/ttyACM0 \
    --teleop.right_arm_config.port=/dev/ttyACM1 \
    --policy.path=outputs/pretrain/checkpoints/last/pretrained_model \
    --dataset.repo_id=${HF_USER}/rollout_hil_rtc_dataset \
    --dataset.single_task="Fold the T-shirt properly" \
    --dataset.fps=30 \
    --strategy.num_episodes=50 \
    --interpolation_multiplier=3
```

**コントロール:**

| キー     | アクション                                                                  |
| ------- | ----------------------------------------------------------------------- |
| `Space` | ポリシーの一時停止 / ポリシーの再開                                    |
| `Tab`   | 補正の開始/停止（一時停止中のみ）; 補正は記録されます |
| `Enter` | Hub にデータセットをプッシュする（修正のみモード）                     |
| `ESC`   | セッションを停止する                                                        |

`--strategy.input_device=pedal` を使用すると、キーボードの代わりに USB フットペダルを使用できます。DAgger のすべてのフラグについては、[Policy Deployment](./inference)を参照してください。

**HILプロトコル:**

1. が自律的に実行される様子を観察する（teleopはアイドル/フリー状態）
2. 失敗が迫っていると感じたら、`Space`キーを押して**一時停止**してください。
   - ポリシーの停止
   - テレオペレーターがロボットの位置に合わせて移動する（トルク有効）
   - 一時停止中にフレームが記録されていません
3. `Tab`キーを押して**操作を切り替える**
   - テレオペレータのトルクが無効化され、自由に移動できます
   - **リカバリー**：ロボットを良好な状態に戻すために遠隔操作を行う
   - **修正**: 動作を修正する
   - すべての移動が記録されます
4. `Tab`キーをもう一度押して修正を終了し、`Space`キーを押して**制御をポリシーに返します**
   - Policyは現在の状態から自律的な実行を再開します
   - いつでも再度介入できます（手順2〜4を繰り返す）。
5. デフォルトモードでは、各補正が個別のエピソードとして保存されます。`--strategy.record_autonomous=true` を使用すると、すべてが記録され、自動的にエピソードに分割されます。
6. `ESC`キーを押してセッションを停止します

**フットペダルのセットアップ（Linux）:**

USBフットペダル（PCsensor FootSwitch）を使用する場合は、アクセスを許可してください：

```bash
sudo setfacl -m u:$USER:rw /dev/input/by-id/usb-PCsensor_FootSwitch-event-kbd
```

### ステップ3: データセットのマージ

`lerobot-rollout` はデータセット名にタイムスタンプを追加するため、ステップ 2 の HIL データセットは `your-username/rollout_hil_dataset_YYYYMMDD_HHMMSS` として保存されます。以下では、その完全な名前を使用してください。

HILデータセットには、人間が操作したフレームを示す`intervention`という追加の列があります。データセットは、特徴量が同じ場合のみマージできます。まずこの列を削除してから、HILデータをデモデータとマージしてください。

```bash
lerobot-edit-dataset \
    --repo_id ${HF_USER}/rollout_hil_dataset_YYYYMMDD_HHMMSS \
    --new_repo_id ${HF_USER}/hil_dataset_no_intervention \
    --operation.type remove_feature \
    --operation.feature_names "['intervention']"

lerobot-edit-dataset \
    --new_repo_id ${HF_USER}/demo_plus_hil \
    --operation.type merge \
    --operation.repo_ids "['${HF_USER}/demo-dataset', '${HF_USER}/hil_dataset_no_intervention']"
```

両方のデータセットは、同じロボット、カメラ、およびfpsを使用する必要があります。マージオプションの詳細については、[Using Dataset Tools](./using_dataset_tools#merge-datasets)を参照してください。

### ステップ4: ポリシーのファインチューニング

ステップ1のポリシーを、**マージ済み**のデータセットでファインチューニングします:

```bash
lerobot-train \
    --dataset.repo_id=${HF_USER}/demo_plus_hil \
    --policy.path=outputs/pretrain/checkpoints/last/pretrained_model \
    --policy.repo_id=${HF_USER}/act_hil_finetune \
    --output_dir=outputs/hil_finetune \
    --steps=20000
```

その後、ファインチューニングされたポリシーをデプロイし、Step 2 から繰り返して、残りの失敗モードをターゲットにします。

---

## 効果的なHILデータ収集のヒント

### 介入すべきタイミング

次のような状況を確認したら介入してください:

- 取り返しのつかないミスをしようとしているロボット
- ロボットがためらったり、不確実な動作を示したりする
- 想定軌道から逸脱するロボット

### リカバリー: 良好な状態への遠隔操作

回復中、ロボットを以下の状態に遠隔操作で戻します:

- ロボットは、既知の分布内の構成にあります
- 現在のサブタスクは依然として完了できます
- 回復の軌跡自体が有益な学習データです

### 修正の品質

補正中:

- **確実でクリーンな**軌跡を提供します
- 現在のサブタスクを完全に完了してください
- 過剰な修正や不要な動きを加えないでください

---

## 関連する研究

このHILデータ収集のアプローチは、インタラクティブな模倣学習のアイデアを基盤としています:

- **DAgger**（Ross ら、2011 年）は、その核となるアイデアを導入しました。これは、エキスパートのデモデータのみで学習するのではなく、_学習者_が訪れる状態に対してエキスパートに修正を問い合わせるというものです。これにより、オンポリシーなデータを反復的に収集することで、標準的な行動クローニングにおける複合誤りのサイクルを断ち切ります。

- **HG-DAgger**（Kelly ら、2019 年）は、ロボティクスにおいてこれを現実的なものにし、人間のエキスパートがロボットを監視し、すべての状態にラベルを付けるのではなく、必要に応じてのみ介入する方式を採用しました。自律制御と人間による制御の間のゲーティングは、まさに、ここでのスクリプトで使用されている「一時停止 → 引き継ぎ → ポリシーへの復帰」のループです。

- **RaC** (Hu et al., 2025) は、介入を明示的に**recovery**（良好な状態へ遠隔操作で戻すこと）と**correction**（そこから正しい動作を実演すること）に分解することで、このループを長期タスクに拡張します。この分解は、`lerobot-rollout`における DAgger 戦略が採用するプロトコルです。

- **π0.6/RECAP** (Physical Intelligence, 2025) は、VLA モデルに対して同じ反復的な収集とファインチューニングのループを大規模に適用し、大規模な事前学習済みポリシーであっても、自身の失敗モードに対するターゲットを絞った人間の修正から大幅に恩恵を受けることを示しています。π0.6 は RECAP を用いて学習されています。

```bibtex
@article{ross2011dagger,
  title={A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning},
  author={Ross, Stéphane and Gordon, Geoffrey and Bagnell, Drew},
  journal={Proceedings of the Fourteenth International Conference on Artificial Intelligence and Statistics},
  year={2011}
}

@article{kelly2019hgdagger,
  title={HG-DAgger: Interactive Imitation Learning with Human Experts},
  author={Kelly, Michael and Sidrane, Chelsea and Driggs-Campbell, Katherine and Kochenderfer, Mykel J},
  journal={arXiv preprint arXiv:1810.02890},
  year={2019}
}

@article{hu2025rac,
  title={RaC: Robot Learning for Long-Horizon Tasks by Scaling Recovery and Correction},
  author={Hu, Zheyuan and Wu, Robyn and Enock, Naveen and Li, Jasmine and Kadakia, Riya and Erickson, Zackory and Kumar, Aviral},
  journal={arXiv preprint arXiv:2509.07953},
  year={2025}
}

@article{pi2025recap,
  title={π0.6: a VLA That Learns From Experience},
  author={Physical Intelligence},
  year={2025}
}
```

