Coleta de Dados Multi-View
Configure uma ou duas câmeras, identifique dispositivos, grave demonstrações LeRobot, visualize e reproduza conjuntos de dados e adicione ou remova episódios.
- Configuração de câmera
- Gravação de dados
- Visualização e reprodução
- Adicionar e remover episódios
Configurações com Uma e Duas Câmeras
-
Uma câmera: use apenas a câmera superior. Isso é útil para uma verificação inicial do ambiente, pois remove uma variável da solução de problemas.
-
Duas câmeras (a configuração principal para este curso): superior + punho. A configuração ACT também usa essas duas entradas por padrão.
- Uma visão superior + lateral é outra opção.
Você também pode coletar dados e treinar com três ou quatro câmeras. O próprio ACT não impõe uma contagem fixa de câmeras: cada visão passa por um backbone ResNet18 compartilhado para produzir uma sequência de tokens de características, e as sequências são concatenadas para o codificador Transformer. A configuração bimanual ALOHA do artigo original do ACT usou quatro câmeras: duas superiores e duas no punho.
- Custo: a memória e a computação da GPU crescem aproximadamente de forma linear com a contagem de câmeras, e visões adicionais podem aumentar os requisitos de dados. Mantenha cada visão sincronizada e sua posição de montagem fixa.
Câmeras Superior e de Punho
-
Câmera superior (
front): fixa em um suporte acima da área de trabalho, mostrando ao modelo onde está o alvo e a configuração geral do braço. -
Câmera de punho (
wrist): montada perto do efetuador final e se movendo com a garra, mostrando sua posição em relação ao alvo e quando fechar.

Encontrar IDs de Dispositivo das Câmeras
Primeiro, execute o seguinte comando para encontrar os índices das câmeras:
lerobot-find-cameras opencv
A saída mostra Id: 0; aqui, 0 é o índice da câmera.
--- Detected Cameras ---
Camera #0:
Name: OpenCV Camera @ 0
Type: OpenCV
Id: 0
Backend api: AVFOUNDATION
Default stream profile:
Format: 16.0
Width: 1920
Height: 1080
Fps: 15.0
--------------------
(more cameras ...)
O comando lista o nome, o ID e a resolução padrão de cada câmera. As imagens capturadas são salvas em ~/rebot_lerobot/outputs/captured_images/. Inspecione-as para verificar a posição e o enquadramento da câmera.
Em um laptop, a varredura também detecta sua câmera integrada, geralmente no índice 0. Desconecte e reconecte as câmeras externas para identificar os índices corretos da câmera superior e da câmera de punho.
-
Reconectar câmeras pode alterar seus índices. Uma câmera que hoje é 0 pode receber um índice diferente da próxima vez. Execute
lerobot-find-camerasantes de cada sessão de gravação para confirmar. -
Conecte câmeras USB diretamente ao computador. Evite hubs: disputa de largura de banda em um hub sem alimentação pode causar perda de imagens e quadros descartados. Se possível, conecte as duas câmeras a controladores USB diferentes.
Sincronizar Imagens e Ações
- Para uma câmera:
Versão RS:
lerobot-teleoperate \
--robot.type=seeed_b601_rs_follower \
--robot.port=can0 \
--robot.id=follower1 \
--robot.can_adapter=socketcan \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=rebot_arm_102_leader \
--teleop.port=/dev/ttyUSB0 \
--teleop.id=rebot_arm_102_leader \
--display_data=true
Versão DM:
lerobot-teleoperate \
--robot.type=seeed_b601_dm_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=follower1 \
--robot.can_adapter=damiao \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=rebot_arm_102_leader \
--teleop.port=/dev/ttyUSB0 \
--teleop.id=rebot_arm_102_leader \
--display_data=true
Versão SO-ARM:
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm \
--display_data=true
Para adicionar mais câmeras, edite --robot.cameras. Defina index_or_path usando o ID da câmera informado por python -m lerobot.find_cameras opencv.
- Para duas câmeras:
Versão RS:
lerobot-teleoperate \
--robot.type=seeed_b601_rs_follower \
--robot.port=can0 \
--robot.id=follower1 \
--robot.can_adapter=socketcan \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=rebot_arm_102_leader \
--teleop.port=/dev/ttyUSB0 \
--teleop.id=rebot_arm_102_leader \
--display_data=true
Versão DM:
lerobot-teleoperate \
--robot.type=seeed_b601_dm_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=follower1 \
--robot.can_adapter=damiao \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=rebot_arm_102_leader \
--teleop.port=/dev/ttyUSB0 \
--teleop.id=rebot_arm_102_leader \
--display_data=true
Versão SO-ARM:
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm \
--display_data=true
A pré-visualização mostra as visões das câmeras dentro do sandbox de coleta.

Configurações recomendadas: 640 × 480 a 30 fps, fourcc: "MJPG". Cada configuração tem um propósito:
-
Resolução 640 × 480 equilibra detalhes e desempenho em tempo real. Dobrar ambas as dimensões quadruplica a largura de banda USB e os custos de armazenamento, enquanto o modelo redimensiona as entradas de qualquer maneira, limitando o benefício.
-
30 fps: combine com a taxa de coleta (a Seção 12.3 explica carimbos de tempo lógicos). Se a câmera funcionar mais lentamente, a gravação reutilizará repetidamente quadros antigos.
-
fourcc: "MJPG"comprime as imagens antes da transferência e reduz substancialmente o uso de largura de banda USB. Você pode tentarYUYV, mas seus requisitos maiores de largura de banda podem forçar resoluções ou taxas de quadros menores e causar travamentos. A configuração descrita aqui suporta três câmeras em1920*1080e30FPScomMJPG.
Criar um Conjunto de Dados LeRobot

Esteja pronto para demonstrar a tarefa antes de executar o comando a seguir. Um aviso de áudio sinaliza a gravação; se o som não estiver disponível, observe o terminal para ver quando a gravação começa.
Versão RS:
lerobot-record \
--robot.type=seeed_b601_rs_follower \
--robot.port=can0 \
--robot.id=follower1 \
--robot.can_adapter=socketcan \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=rebot_arm_102_leader \
--teleop.port=/dev/ttyUSB0 \
--teleop.id=rebot_arm_102_leader \
--display_data=true \
--dataset.repo_id=seeed_rebot_b601_rs/test \
--dataset.num_episodes=5 \
--dataset.single_task="Grab the crayfish into the box" \
--dataset.push_to_hub=false \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=20
Versão DM:
lerobot-record \
--robot.type=seeed_b601_dm_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=follower1 \
--robot.can_adapter=damiao \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=rebot_arm_102_leader \
--teleop.port=/dev/ttyUSB0 \
--teleop.id=rebot_arm_102_leader \
--display_data=true \
--dataset.repo_id=seeed_rebot_b601_dm/test \
--dataset.num_episodes=5 \
--dataset.single_task="Grab the crayfish into the box" \
--dataset.push_to_hub=false \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=20
Versão SO-ARM:
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.can_adapter=damiao \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm \
--display_data=true \
--dataset.repo_id=seeed_soarm101/test \
--dataset.num_episodes=5 \
--dataset.single_task="Grab the crayfish into the box" \
--dataset.push_to_hub=false \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=20
Os seguintes parâmetros controlam o conjunto de dados e a sessão de gravação:
| Parâmetro | Significado | Recomendação |
|---|---|---|
--dataset.repo_id | Nome do conjunto de dados e nome da pasta local | Use nomes separados para teste e produção, como rebot_b601/grab_cube_test e rebot_b601/grab_cube_v1. |
--dataset.single_task | Descrição da tarefa armazenada no conjunto de dados | Escreva uma descrição precisa em inglês. |
--dataset.num_episodes | Número de episódios a serem gravados | Use 5 para um teste e 50 para a coleta completa; 50 é o padrão. |
--dataset.push_to_hub | Se deve fazer upload após a gravação | false mantém o conjunto de dados local. |
--dataset.episode_time_s=30 | Tempo de gravação por episódio | Ajuste conforme a complexidade da tarefa. |
--dataset.reset_time_s=20 | Tempo para redefinir a cena entre episódios | Reserve tempo suficiente para restaurar a cena inicial. |
--display_data=true | Mostrar visualizações da câmera em tempo real |
O conjunto de dados é armazenado em ~/.cache/huggingface/lerobot, na pasta especificada, como seeed_rebot_b601_rs/test.
Fazer upload para o Hugging Face Hub (Opcional)
Para gerenciar conjuntos de dados no Hugging Face Hub, faça login com um token que tenha permissão de escrita. Crie um em Hugging Face settings.
huggingface-cli login --token ${HUGGINGFACE_TOKEN} --add-to-git-credential
Salve seu nome de usuário do Hugging Face em uma variável para comandos posteriores:
HF_USER=$(huggingface-cli whoami | head -n 1)
echo $HF_USER
Execute novamente o comando de coleta com duas alterações: --dataset.repo_id=${HF_USER}/grab_cube_v1 e --dataset.push_to_hub=true. A gravação então faz upload do resultado para o seu repositório no Hub. Use esse nome de repositório com lerobot-dataset-viz --repo-id para visualizá-lo.
Dica: O upload é opcional. Conjuntos de dados locais gravados com
push_to_hub=falsepodem ser usados diretamente para treinamento no Capítulo 16. O upload altera onde os dados ficam armazenados, não se eles podem ser usados para treinamento.
Gravar, Parar e Regravar Episódios
Gravação
Controles de teclado durante a coleta:
| Tecla | Ação |
|---|---|
| → (Seta para a direita) | Encerra o episódio atual mais cedo e prossegue para o reset / próximo episódio. |
| ← (Seta para a esquerda) | Descarta o episódio atual e o grava novamente. |
| ESC | Encerra a sessão de coleta, codifica os vídeos, calcula estatísticas e salva o conjunto de dados. |
Se as teclas não responderem, a versão do pynput pode ser a causa. Faça downgrade com pip install pynput==1.6.8.
Regravação
Depois de gravar cinco episódios de teste e verificar que a reprodução funciona, inicie a coleta completa. Altere repo_id para o nome final do conjunto de dados e defina num_episodes=50. Siga o método de cinco pontos marcado a lápis no Capítulo 12: um episódio por ponto, cinco pontos por rodada e dez rodadas.
Parando a gravação
Use Esc, em vez de Ctrl+C, para parar a gravação; interromper com Ctrl+C pode causar uma saída anormal.
Visualizar e Reproduzir um Conjunto de Dados
Visualizar o conjunto de dados
Se você fez upload do conjunto de dados, visualize-o localmente com:
echo ${HF_USER}/rebot_test
lerobot-dataset-viz \
--repo-id ${HF_USER}/rebot_test \
--episode-index 0 \
--display-compressed-images=false
Se você usou --dataset.push_to_hub=false, visualize o conjunto de dados local com:
Versão RS:
lerobot-dataset-viz \
--repo-id seeed_rebot_b601_rs/test \
--episode-index 0 \
--display-compressed-images=false
Versão DM:
lerobot-dataset-viz \
--repo-id seeed_rebot_b601_dm/test \
--episode-index 0 \
--display-compressed-images=false
Versão SO-ARM:
lerobot-dataset-viz \
--repo-id seeed_soarm101/test \
--episode-index 0 \
--display-compressed-images=false
Aqui, seeed_rebot_b601_rs/test é o repo_id escolhido durante a gravação.
Reproduzir um conjunto de dados
Agora reproduza o primeiro episódio no seu robô. --dataset.episode=0 seleciona o primeiro episódio gravado; incremente o índice para reproduzir os demais.
Versão RS:
lerobot-replay \
--robot.type=seeed_b601_rs_follower \
--robot.port=can0 \
--robot.can_adapter=socketcan \
--robot.id=follower1 \
--dataset.repo_id=seeed_rebot_b601_rs/test \
--dataset.episode=0
Versão DM:
lerobot-replay \
--robot.type=seeed_b601_dm_follower \
--robot.port=/dev/ttyACM0 \
--robot.can_adapter=damiao \
--robot.id=follower1 \
--dataset.repo_id=seeed_rebot_b601_dm/test \
--dataset.episode=0
Versão SO-ARM:
lerobot-replay \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--dataset.repo_id=seeed_soarm101/test \
--dataset.episode=0
O robô deve reproduzir os movimentos gravados durante a teleoperação.
Adicionar e Remover Episódios
-
Checkpoints são criados automaticamente durante a gravação.
-
Adicione
--resume=trueao comando original para continuar gravando dados adicionais. -
Ao retomar, defina
--dataset.num_episodespara o número de episódios adicionais, em vez do tamanho total desejado do conjunto de dados. -
Para recomeçar, exclua manualmente o diretório do conjunto de dados.
Use os seguintes comandos para remover episódios selecionados. --operation.episode_indices "[0]" remove o primeiro episódio; altere os índices conforme necessário. Substitua o nome do conjunto de dados e aguarde o término da operação.
Versão RS:
lerobot-edit-dataset \
--repo_id seeed_rebot_b601_rs/test \
--operation.type delete_episodes \
--operation.episode_indices "[0]"
Versão DM:
lerobot-edit-dataset \
--repo_id seeed_rebot_b601_dm/test \
--operation.type delete_episodes \
--operation.episode_indices "[0]"
Versão SO-ARM:
lerobot-edit-dataset \
--repo_id seeed_soarm101/test \
--operation.type delete_episodes \
--operation.episode_indices "[0]"