Pular para o conteúdo principal

Estágio 3 · Capítulo 13 · Prática

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​

Configuração

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​

Câmeras

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".
Câmeras superior e de punho

13.3 Encontrando os Nomes dos Dispositivos de Câmera​

Dispositivos

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-cameras antes 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​

Sincronizaçã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:

Fluxo de câmera de dentro da caixa de coleta

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 formato YUYV, mas isso reduzirá a resolução e o FPS, causando engasgos no braço. Atualmente o formato MJPG suporta 3 câmeras em resolução 1920×1080 mantendo 30 FPS.

13.5 Criar Dataset do LeRobot​

Dataset

13.5 Criar Dataset do LeRobot

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âmetroSignificadoRecomendação
--dataset.repo_idNome 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_taskDescrição da tarefa (armazenada no dataset)Em inglês, correspondendo à descrição da tarefa
--dataset.num_episodesQuantos Episódios gravarTeste: 5; formal: 50 (padrão é 50)
--dataset.push_to_hubSe deve enviar para o Hub após a gravaçãofalse = não enviar
--dataset.episode_time_s=30Tempo de gravação por EpisódioAjustar com base na complexidade da tarefa
--dataset.reset_time_s=20Tempo para resetar a cena para a próxima gravaçãoAjustar com base no tempo de reset da cena
--display_data=trueMostrar 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​

Gravação

13.6 Gravando, Pausando e Regravando Episódios

Gravação​

Controles do teclado durante a gravação:

TeclaAçã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
ESCEncerrar toda a sessão de coleta: codificar vídeos, calcular estatísticas, salvar conjunto de dados
atenção

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​

perigo

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​

Reprodução

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​

Edição

13.8 Suplementando e Excluindo Dados

  • Checkpoints são criados automaticamente durante a gravação.
  • Adicione --resume=true ao comando original para continuar suplementando dados.
  • Ao retomar, defina --dataset.num_episodes para 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]"
Loading Comments...