13. Configuração de Câmera e Coleta de Dados com LeRobot
Capítulo 13 do Curso para Iniciantes em IA Física da Seeed — configuração com uma ou duas câmeras, localização dos nomes dos dispositivos de câmera, sincronização imagem/ação, criação de um dataset, gravação e regravação, visualização e complementação ou exclusão de dados.
13.1 Configuração com Uma Câmera vs Duas Câmeras
13.1 Configuração com Uma Câmera vs Duas Câmeras
- Configuração com uma câmera: apenas a câmera superior conectada. Boa para uma primeira execução do pipeline e verificação do ambiente — uma câmera a menos significa uma variável a menos na depuração.
- Configuração com duas câmeras (caminho principal do curso, para coleta formal): superior + punho; o modelo ACT também usa por padrão dois fluxos de entrada. Você também pode escolher superior + vista lateral.
Três ou quatro câmeras também podem ser usadas para treinamento e coleta. O próprio ACT não tem limite rígido de quantidade de câmeras: cada fluxo de imagem passa por um backbone ResNet18 compartilhado para produzir uma sequência de tokens de características, que é concatenada no codificador Transformer. O artigo original do ACT (ALOHA dual-arm) usou 4 câmeras (2 superiores + 2 no punho).
- Custo: cada câmera adicional aumenta aproximadamente de forma linear o uso de VRAM e o custo computacional, e também aumenta a necessidade de dados (mais pontos de vista significam mais coisas para aprender); cada fluxo deve manter sincronização e posicionamento fixo.
13.2 Câmeras Superior e de Punho
13.2 Câmeras Superior e de Punho
- Câmera superior (frontal): fixa em um suporte com vista de todo o espaço de trabalho; informa ao modelo "onde está o alvo e o estado geral do braço".
- Câmera de punho (punho): montada na extremidade do braço, acompanhando o gripper; informa ao modelo "a posição relativa entre o gripper e o alvo, e se deve fechar".

13.3 Encontrando os Nomes dos Dispositivos de Câmera
13.3 Encontrando os Nomes dos Dispositivos de Câmera
Para verificar os índices das câmeras, primeiro execute:
lerobot-find-cameras opencv
Você verá Id: 0, onde 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 ...)
Ele lista o nome, o ID e a resolução padrão de cada câmera. Você pode encontrar ~/rebot_lerobot/outputs/captured_images/ no diretório para visualizar as imagens capturadas por cada câmera, verificando se o posicionamento das câmeras está correto e adequado.
Observe também: se estiver usando um laptop, a câmera integrada será escaneada; você precisará desconectar/reconectar para encontrar os índices corretos das câmeras superior e de punho. A câmera integrada do laptop geralmente é o índice 0.
- A ordem de conexão altera os índices. Hoje a câmera superior é 0; amanhã, após reconectar, pode mudar. Gaste 10 segundos reexecutando
lerobot-find-camerasantes de cada sessão de gravação para confirmar. - Câmeras USB devem ser conectadas diretamente ao computador, não por meio de um dock. Contenção de largura de banda em hubs passivos se manifesta diretamente como imagens ilegíveis ou quadros perdidos; idealmente, as duas câmeras devem ser conectadas a controladores USB diferentes.
13.4 Sincronização de Imagem e Ação
13.4 Sincronização de Imagem e Ação
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
Se você tiver mais câmeras, pode adicioná-las alterando o parâmetro --robot.cameras. Observe o formato de index_or_path, que é determinado pelo último dígito do ID da câmera exibido pelo comando python -m lerobot.find_cameras opencv.
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
Você pode ver que esta é a imagem de dentro da caixa de coleta de dados:

Parâmetros recomendados: 640 × 480 @ 30 fps, fourcc: "MJPG". Cada um dos três parâmetros é importante:
- Resolução 640×480: um equilíbrio entre clareza e desempenho em tempo real. Dobrar a resolução quadruplica a largura de banda USB e o overhead de armazenamento, enquanto a entrada do modelo já redimensiona as imagens de qualquer forma — benefício limitado.
- FPS 30: corresponde ao FPS de coleta. Se o FPS da câmera for menor, a gravação reutilizará repetidamente quadros antigos.
fourcc: "MJPG": a imagem é comprimida antes da transmissão, reduzindo a pressão de largura de banda USB em uma ordem de grandeza. Você pode, claro, tentar imagens no formatoYUYV, mas isso reduzirá a resolução e o FPS, causando engasgos no braço. Atualmente o formatoMJPGsuporta 3 câmeras em resolução 1920×1080 mantendo 30 FPS.
13.5 Criar Dataset do LeRobot
13.5 Criar Dataset do LeRobot

Antes de executar o comando abaixo, esteja pronto para gravar dados; haverá um aviso sonoro ao entrar na fase de gravação. Se não houver, verifique as mensagens no terminal para ver se iniciou.
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
Há vários parâmetros relacionados ao próprio dataset:
| Parâmetro | Significado | Recomendação |
|---|---|---|
--dataset.repo_id | Nome do dataset (também o nome da pasta local) | Nomes separados para conjuntos de teste e formais, por exemplo, rebot_b601/grab_cube_test / rebot_b601/grab_cube_v1 |
--dataset.single_task | Descrição da tarefa (armazenada no dataset) | Em inglês, correspondendo à descrição da tarefa |
--dataset.num_episodes | Quantos Episódios gravar | Teste: 5; formal: 50 (padrão é 50) |
--dataset.push_to_hub | Se deve enviar para o Hub após a gravação | false = não enviar |
--dataset.episode_time_s=30 | Tempo de gravação por Episódio | Ajustar com base na complexidade da tarefa |
--dataset.reset_time_s=20 | Tempo para resetar a cena para a próxima gravação | Ajustar com base no tempo de reset da cena |
--display_data=true | Mostrar o fluxo da câmera em tempo real | - |
Depois disso, o conjunto de dados será salvo no diretório home em ~/.cache/huggingface/lerobot. A pasta acima será criada em seeed_rebot_b601_rs/test.
13.6 Gravando, Pausando e Regravando Episódios
13.6 Gravando, Pausando e Regravando Episódios
Gravação
Controles do teclado durante a gravação:
| Tecla | Ação |
|---|---|
| → (Seta para a direita) | Encerrar o Episódio atual mais cedo, prosseguir para reset/próximo |
| ← (Seta para a esquerda) | Descartar o Episódio atual, regravar este |
| ESC | Encerrar toda a sessão de coleta: codificar vídeos, calcular estatísticas, salvar conjunto de dados |
Se as teclas não responderem, é um problema de versão do pynput; faça o downgrade: pip install pynput==1.6.8.
Regravação
Após gravar 5 Episódios e verificar a reprodução, para a coleta formal: altere repo_id para o nome formal, num_episodes=50 para o valor formal e siga o método do lápis de cinco pontos do Capítulo 12 — 1 Episódio por ponto, 5 pontos por rodada, 10 rodadas no total.
Pausando a Gravação
Não pressione Ctrl+C para pausar a gravação — pressione Esc, caso contrário ela será encerrada de forma anormal.
13.7 Visualizando e Reproduzindo um Conjunto de Dados
13.7 Visualizando e Reproduzindo um Conjunto de Dados
Visualizando um Conjunto de Dados
Se você enviou os dados, também pode visualizá-los 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 e não enviou os dados, também pode visualizar localmente 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
Aqui, seeed_rebot_b601_rs/test é o nome de conjunto de dados personalizado da coleta (repo_id).
Reproduzindo um Conjunto de Dados
Agora, tente reproduzir o primeiro conjunto de dados no seu robô: --dataset.episode=0 significa reproduzir o primeiro conjunto de dados coletado, e assim por diante.
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
O robô agora deve executar as mesmas ações que você gravou durante a teleoperação.
13.8 Suplementando e Excluindo Dados
13.8 Suplementando e Excluindo Dados
- Checkpoints são criados automaticamente durante a gravação.
- Adicione
--resume=trueao comando original para continuar suplementando dados. - Ao retomar, defina
--dataset.num_episodespara o número de Episódios adicionais a serem gravados (não o total desejado no conjunto de dados). - Para começar do zero, exclua manualmente o diretório do conjunto de dados.
Use o seguinte comando para excluir Episódios: --operation.episode_indices "[0]" exclui o primeiro Episódio, e assim por diante. Tenha paciência durante a exclusão e modifique o nome do conjunto de dados conforme necessário.
lerobot-edit-dataset \
--repo_id rebot_b601/grab_cube_v1 \
--operation.type delete_episodes \
--operation.episode_indices "[0]"