# Coleta de Dados com Participação Humana

A coleta de dados com intervenção humana (Human-In-the-Loop, HIL) permite melhorar uma política treinada ao implantá-la em um robô real, enquanto um operador humano monitora e intervém quando necessário. Os dados de intervenção (movimentos de recuperação e correções) são registrados junto com os segmentos autônomos, gerando um conjunto de dados de treinamento mais rico que ensina a política a lidar com falhas.

---

## Por que Human-In-the-Loop?

O clone comportamental padrão treina políticas apenas em demonstrações bem-sucedidas. Durante a implantação, pequenos erros podem se acumular e levar o robô a estados nunca vistos durante o treinamento (mudança de distribuição). A coleta de dados HIL aborda isso da seguinte forma:

- Executando a política treinada no robô real
- Ter um humano intervindo quando o robô está prestes a falhar
- Registrando a recuperação e a correção do humano como dados de treinamento
- Ajuste fino da política no conjunto de dados combinado

Isso produz uma política que não apenas sabe como executar a tarefa, mas também como se recuperar quando algo dá errado.

---

## Como Funciona

Durante uma sessão de HIL, o operador humano segue este loop dentro de cada episódio:

1. **Assista** à política executar de forma autônoma
2. **Pausa** quando a falha é iminente, o robô mantém sua posição
3. **Assuma o controle** e teleopere o robô de volta a um estado adequado (recuperação), em seguida, corrija o comportamento
4. **Devolver o controle para a política**, a política retoma a execução autônoma
5. Repita as etapas 2–4 quantas vezes forem necessárias durante o episódio
6. **Encerre o episódio** quando a tarefa for concluída, salve e passe para o próximo rollout

Por padrão, apenas os segmentos controlados pelo humano (recuperação e correção) são registrados, e cada correção se torna um episódio próprio. Com `--strategy.record_autonomous=true`, os segmentos autônomos também são registrados: a política e o humano podem alternar o controle várias vezes, e a execução autônoma, a recuperação e a correção são capturadas em uma única trajetória contínua. Em ambos os modos, o robô continua a partir do seu estado atual após cada transferência de controle (nenhum reset é necessário apenas porque uma intervenção ocorreu). Após a coleta, o conjunto de dados combinado (demonstrações originais + dados HIL) é usado para ajustar finamente a política.

Esse processo pode ser repetido iterativamente: implantar, coletar, ajustar finamente, repetir. Cada rodada visa os modos de falha da política atual.

```
┌─────────────────────────────────────────────────────────────────────────┐
│  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)                            │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## Requisitos de Hardware

### Requisitos do Teleoperador

O modo `lerobot-rollout --strategy.type=dagger` requer **teleoperadores com motores ativos** que possam:

- Ativar/desativar torque programaticamente
- Mover para as posições de destino (para espelhar o estado do robô ao pausar)

Quando você pausa, o braço líder se move para corresponder ao robô, de modo que o controle passa entre a política e o humano sem saltos. Saltos acabariam por entrar nas correções gravadas e ensinariam à política trajetórias trêmulas.

**Teleoperadores compatíveis:**

- `bi_openarm_mini` - OpenArm Mini Bimanual
- `so100_leader` / `so101_leader` - braço líder SO100 / SO101
- `bi_so_leader` - Braços líderes bimanuais SO100 / SO101

> [!IMPORTANT]
> Os comandos fornecidos usam `bi_openarm_follower` + `bi_openarm_mini` por padrão. Configurações SO100 / SO101 funcionam da mesma forma, por exemplo, `--robot.type=so101_follower` com `--teleop.type=so101_leader`.

---

## Script

Use `lerobot-rollout` com `--strategy.type=dagger` para coleta de dados HIL. Selecione o backend de inferência com `--inference.type=sync|rtc|remote`:

| Modo                     | Flag                      | Modelos                                                                                                 |
| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------ |
| Padrão (padrão)       | _(nenhuma flag necessária)_        | ACT, Diffusion Policy                                                                                  |
| Chunking em Tempo Real (RTC) | `--inference.type=rtc`    | Pi0, Pi0.5, SmolVLA                                                                                    |
| Remoto                   | `--inference.type=remote` | Checkpoint servido por `lerobot-policy-server`; consulte [requisitos de implantação remota](./remote_inference) |

---

## Guia Passo a Passo

### Etapa 1: Pré-treinar uma Política Base

Primeiro, treine uma política no seu conjunto de dados de demonstração. Este exemplo treina o ACT, que é executado com inferência padrão na etapa 2:

```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
```

### Etapa 2: Coletar dados HIL

**Inferência padrão (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
```

Com `--interpolation_multiplier=N`, o robô recebe `N` comandos interpolados por ação de política (o controle é executado a `fps × N` Hz), enquanto a inferência da política e a gravação do conjunto de dados permanecem em `--fps`, de modo que o conjunto de dados gravado corresponda ao FPS declarado.

**Com RTC para modelos grandes (Pi0, Pi0.5, SmolVLA):**

Para modelos com alta latência de inferência, ative o RTC para uma execução suave. Isso requer uma política base VLA, como Pi0, Pi0.5 ou SmolVLA, em vez da política ACT da etapa 1:

```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
```

**Controles:**

| Chave     | Ação                                                                  |
| ------- | ----------------------------------------------------------------------- |
| `Space` | Pausar a política / retomar a política                                    |
| `Tab`   | Iniciar / parar uma correção (somente enquanto estiver pausado); as correções são gravadas |
| `Enter` | Envie o dataset para o Hub (modo somente correções)                     |
| `ESC`   | Encerrar a sessão                                                        |

Um pedal de USB pode ser usado no lugar do teclado com `--strategy.input_device=pedal`. Consulte [Policy Deployment](./inference) para todas as flags do DAgger.

**O Protocolo HIL:**

1. Veja a política executar de forma autônoma (teleop está ocioso/livre)
2. Quando você perceber uma falha iminente, pressione `Space` para **pausar**
   - Paradas de política
   - Operador remoto se move para corresponder à posição do robô (torque ativado)
   - Nenhum frame registrado durante a pausa
3. Pressione `Tab` para **assumir o controle**
   - Torque do teleoperador desativado, livre para se mover
   - **Recuperação**: Teleopere o robô de volta para um bom estado
   - **Correção**: Corrigir o comportamento
   - Todos os movimentos são registrados
4. Pressione `Tab` novamente para encerrar a correção e, em seguida, `Space` para **devolver o controle à política**
   - A política retoma a execução autônoma a partir do estado atual
   - Você pode intervir novamente a qualquer momento (repita as etapas 2–4)
5. No modo padrão, cada correção é salva como seu próprio episódio. Com `--strategy.record_autonomous=true`, tudo é registrado e dividido em episódios automaticamente
6. Pressione `ESC` para encerrar a sessão

**Configuração do pedal (Linux):**

Ao usar um pedal de USB (PCsensor FootSwitch), garanta o acesso:

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

### Etapa 3: Mesclar os Conjuntos de Dados

`lerobot-rollout` adiciona um timestamp ao nome do dataset, então o dataset HIL da etapa 2 é salvo como `your-username/rollout_hil_dataset_YYYYMMDD_HHMMSS`. Use esse nome completo abaixo.

O conjunto de dados HIL possui uma coluna extra `intervention` que marca os quadros controlados por humanos, e os conjuntos de dados só podem ser mesclados quando possuem os mesmos recursos. Remova a coluna primeiro e, em seguida, mescle os dados HIL com suas demonstrações:

```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']"
```

Ambos os conjuntos de dados também devem usar o mesmo robô, câmeras e fps. Consulte [Usando as Ferramentas de Conjunto de Dados](./using_dataset_tools#merge-datasets) para mais opções de mesclagem.

### Etapa 4: Ajuste fino da Policy

Ajuste fino da política da etapa 1 no conjunto de dados **mesclado**:

```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
```

Em seguida, implante a política ajustada e repita a partir da Etapa 2 para abordar seus modos de falha restantes.

---

## Dicas para uma coleta de HIL eficaz

### Quando intervir

Intervenha quando você vir:

- Robô prestes a cometer um erro irreversível
- Robô hesitando ou exibindo comportamento incerto
- Robô desviando da trajetória esperada

### Recuperação: Teleoperando de volta para um bom estado

Durante a recuperação, teleopere o robô de volta para um estado em que:

- O robô está em uma configuração familiar, dentro da distribuição
- A subtarefa atual ainda pode ser concluída
- A própria trajetória de recuperação é um dado de treinamento informativo

### Qualidade das Correções

Durante a correção:

- Forneça trajetórias **confiáveis e limpas**
- Conclua totalmente a subtarefa atual
- Não exagere na correção nem adicione movimentos desnecessários

---

## Trabalhos Relacionados

Essa abordagem de coleta de dados HIL se baseia em ideias do aprendizado por imitação interativa:

- **DAgger** (Ross et al., 2011) introduziu a ideia central: em vez de treinar apenas com demonstrações de especialistas, consultar o especialista para obter correções nos estados visitados pelo _learner_. Isso quebra o ciclo de erro composto do clonagem comportamental padrão ao coletar iterativamente dados on-policy.

- **HG-DAgger** (Kelly et al., 2019) tornou isso prático para robótica: um especialista humano monitora o robô e intervém apenas quando necessário, em vez de rotular cada estado. O controle de transição entre o controle autônomo e o humano é exatamente o loop de pausa → intervenção → retorno à política usado nos scripts aqui.

- **RaC** (Hu et al., 2025) escala esse loop para tarefas de longo prazo ao decompor explicitamente as intervenções em **recuperação** (teleoperar de volta para um bom estado) e **correção** (demonstrar o comportamento correto a partir daí). Essa decomposição é o protocolo seguido pela estratégia DAgger em `lerobot-rollout`.

- **π0.6/RECAP** (Physical Intelligence, 2025) aplica o mesmo loop iterativo de coleta e ajuste fino em escala com modelos VLA, demonstrando que até mesmo políticas pré-treinadas grandes se beneficiam substancialmente de correções humanas direcionadas aos seus próprios modos de falha. O π0.6 é treinado usando 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}
}
```

