Caminho de construçãoAvançadoAlguns fins de semana

Construa um robô ROS 2 que vê e segue até um marcador

Um robô que localiza um marcador do outro lado de uma sala, descobre onde ele está em relação a si mesmo e chega de frente — estruturado como um grafo real de nós ROS 2.

Esquema técnico de Construa um robô ROS 2 que vê e segue até um marcadorPOSE → STANDOFF → DOCK

O que você está construindo

Um robô colocado em algum lugar de uma sala que gira até encontrar um marcador impresso em uma parede e dirige até ele — parando a meio metro de distância, em ângulo reto com a face do marcador, e não apenas perto.

Todas as outras construções deste site executam um programa em um microcontrolador. Esta é um computador com rodas, e isso muda o assunto do projeto. As partes difíceis não são mais temporização e fiação; são saber onde as coisas estão em relação umas às outras e manter várias partes do software honestas entre si enquanto todas executam ao mesmo tempo.

Por que este robô precisa de um computador

Um Arduino não consegue fazer isso, e vale ser preciso sobre o motivo. Não é a velocidade bruta — é que um quadro de câmera ocupa um quarto de megabyte, a detecção ArUco exige álgebra linear com ponto flutuante e tudo isso precisa acontecer enquanto as rodas ainda estão sendo comandadas a 50 Hz. Esse é um trabalho para um sistema operacional com memória e agendamento reais.

O que você ganha em troca dessa máquina Linux é a capacidade de olhar para dentro de um robô em execução. Cada mensagem entre cada parte é um tópico que você pode assinar de um notebook. Quando o robô passa pelo marcador em vez de ir até ele, você não adiciona mensagens de impressão nem regrava o software — executa ros2 topic echo na pose e a vê errada em tempo real.

A forma do grafo de nós

Cinco responsabilidades, um nó para cada uma:

Nó Publica Tarefa
camera /image_raw, /camera_info Retira quadros do barramento CSI
aruco_detector TF camera_link → marker_7 Encontra o marcador e resolve sua pose
docking_controller /cmd_vel Decide para onde dirigir
diff_drive porta serial para o Arduino Conversão de Twist em velocidades das rodas
odometry TF odom → base_link Integra as contagens dos encoders

As interfaces são o que torna isso valer a pena. O controlador nunca toca em uma câmera ou em um motor — consome uma transformação e produz um Twist. Isso permite dirigir o mesmo robô por teleoperação com teclado, testar o controlador contra uma transformação falsa sem componentes e, depois, inserir uma pilha de navegação que publique exatamente o mesmo tópico.

Leia nós, tópicos, serviços e ações antes de desenhar sua própria versão dessa tabela. O erro mais comum nesta etapa é transformar o controlador de acoplamento em um serviço — ele é um objetivo de longa duração que precisa poder ser cancelado, e é exatamente para isso que serve uma ação.

Lista de materiais

Este é o robô com dois cérebros, e a lista de peças reflete isso: um computador para percepção e um microcontrolador para as coisas que um computador não faz de forma confiável.

Peça Qtd. Custo aproximado Observações
Raspberry Pi 4, 4 GB 1 US$ 55 4 GB é o mínimo prático para ROS 2 mais visão. 1 GB faz troca de memória e morre
Módulo de câmera Pi 3 1 US$ 25 A versão Wide é melhor para navegação — 102° em vez de 66°
microSD classe A2, 32 GB 1 US$ 8 Ou inicialize por um SSD USB, que é realmente mais rápido
Dissipador ou ventilador 1 US$ 5 Um Pi 4 reduz a frequência a 80 °C, e um Pi limitado perde quadros
Arduino Uno ou Nano 1 US$ 5 Encoders e controle de motores — a metade em tempo real
Motores N20 com encoder 2 US$ 16
TB6612FNG 1 US$ 3
Chassi 2WD 1 US$ 12 Espaço para um Pi, uma haste de câmera e uma bateria
Pacote de bateria 1 US$ 15 3S com regulador chaveado de 5 V dimensionado para 3 A
Marcadores ArUco impressos — US$ 0 Imprima, meça o tamanho impresso e use a medida

Total: aproximadamente US$ 145–175. Este é o projeto mais caro do site por uma margem larga, e a maior parte do custo é o Pi.

A alimentação é onde esses robôs falham, e a falha é cara. Uma queda de tensão durante uma escrita no cartão SD corrompe toda a imagem do sistema. Use um regulador chaveado dimensionado bem acima do consumo do Pi, nunca compartilhe o trilho com os motores e verifique vcgencmd get_throttled — qualquer valor diferente de zero significa que a fonte é inadequada e que um cartão corrompido está a caminho.

Meça seus marcadores impressos. A solução da pose ArUco escala diretamente com o tamanho do marcador que você declara. Um marcador impresso a 95% pelo “ajustar à página” de uma impressora produz poses 5% erradas em todas as distâncias, e nada no fluxo de processamento informará isso.

Ordem de construção

1 — Faça o ROS 2 funcionar e prove a rede. Siga instalar o ROS 2 em um Raspberry Pi. Não avance até ros2 topic echo no notebook mostrar um tópico publicado no robô. A descoberta por Wi-Fi é a coisa mais provável de consumir uma noite, e você quer que ela aconteça agora, e não enquanto depura visão.

2 — Faça as rodas obedecerem a um Twist. Conecte o Arduino, os encoders e o TB6612FNG, e construa a ponte cmd_vel. Marco: a teleoperação por teclado do notebook dirige o robô real. Calibre aqui a separação entre rodas — tudo abaixo herda esse valor.

3 — Calibre a câmera. Corretamente, com um alvo real, seguindo calibração de câmera e pose ArUco. Uma câmera não calibrada produz poses que parecem plausíveis e estão erradas dezenas de pontos percentuais nas bordas do quadro, o pior modo de falha possível.

4 — Publique o marcador como uma transformação. Não como uma mensagem personalizada com x e y. Publicar camera_link → marker_7 no TF2 permite que o controlador pergunte “onde está o marcador, em base_link?”, e a resposta considera exatamente como a câmera está montada — inclusive o fato de ela estar inclinada, como está.

5 — Dirija até o marcador. Um controlador proporcional com base na direção medida em relação ao robô: vire em direção a ele, avance e pare na distância de aproximação. Isso funciona, mas chega em ângulo, que é o ponto da próxima etapa.

6 — Aproxime-se ao longo da normal. Em vez de dirigir diretamente ao marcador, calcule um ponto de passagem afastado da face do marcador ao longo de sua normal, vá até ele e só então dirija em linha reta. Esta é a diferença entre alcançar o acoplador e acoplar. É também onde a orientação do marcador — a parte da pose que você não precisava até agora — começa a importar, e onde encontrará a ambiguidade de pose.

7 — Coloque tudo em uma máquina de estados. Procurar, aproximar, alinhar, final, concluído, além das transições de saída de cada estado quando o marcador é perdido. Máquinas de estados finitas para comportamento de robôs cobre a estrutura; o que este robô precisa especificamente é um tempo limite de marcador perdido que volte à busca em vez de continuar pela última pose conhecida.

Observações dos componentes que importam

Monte a câmera rigidamente e meça como ela está. Toda pose que o robô calcula é relativa à câmera, e TF2 a transforma em uma pose relativa ao robô usando a transformação que você declara de base_link a camera_link. Uma câmera em suporte flexível torna essa transformação declarada uma mentira que varia com a aceleração.

Incline a câmera para baixo e registre isso. Uma câmera apontada para o horizonte perde o marcador exatamente quando o robô fica perto. De dez a quinze graus para baixo a mantém no quadro durante a aproximação final — e essa inclinação vai para a transformação estática, não para um fator de correção improvisado no controlador.

Meça o marcador com paquímetro. A escala da pose é diretamente proporcional ao tamanho do marcador que você informa ao solucionador. Imprimir a 96% porque a impressora ajustou à página torna cada distância 4% errada, de forma silenciosa e consistente.

Alimente o Pi separadamente dos motores. Um motor travado derruba o trilho, e onde um Arduino apenas reiniciaria sem dano, um Pi corrompe o sistema de arquivos. Use um regulador separado ou outra bateria — este não é o lugar de economizar uma peça.

Mantenha o cabo da câmera longe dos fios dos motores. É uma ligação de alta velocidade sem blindagem. Ruído dos motores acoplado a ela aparece como quadros corrompidos, que aparecem como detecções piscando sem nenhuma razão visível.

Como fica um bom resultado

Medição Típico em um Pi 4
Captura da câmera a 640×480 30 fps
Detecção ArUco, 640×480 25–30 fps, usando 40–60% de um núcleo
Detecção ArUco, 1920×1080 5–8 fps — e cada quadro está desatualizado
Alcance de detecção do marcador (marcador de 100 mm, 640×480) 1,5–2,5 m
Precisão da pose a 1 m ±2–5 cm de posição, ±3–5° de orientação
Latência total de imagem à decisão 60–120 ms
Laço de controle de motores, no Arduino 100–200 Hz
Latência de tópico ROS 2, do Pi ao Arduino pela porta serial 5–15 ms

Duas linhas carregam a lição do projeto inteiro.

Resolução não é gratuita, e uma resolução maior costuma ser pior. Ir de 640×480 para 1080p custa 4–6× o processamento para cerca de 1,7× o alcance de detecção. A menos que você realmente precise ver um marcador mais distante, o quadro menor oferece uma resposta mais rápida e atual — e atualidade importa mais que precisão em um laço de controle.

A linha de latência explica por que existe a divisão em dois cérebros. A 0,3 m/s, 100 ms de latência de visão são 3 cm de deslocamento; girando a 90°/s, são 9° de rotação. Toda medição de visão descreve onde o robô estava. Feche um laço rápido diretamente nela e ele oscilará. A estrutura que funciona é a que este robô usa: o Arduino executa o laço rápido com encoders, e a visão o corrige lentamente — exatamente a mesma forma de fundir GPS com odometria no rover de pontos de passagem, e pelo mesmo motivo.

Obturador rolante, se o robô se mover enquanto olha

Os módulos de câmera padrão do Pi têm obturador rolante: as linhas são expostas uma após outra, então o topo de um quadro é capturado alguns milissegundos antes da parte inferior. Parado, isso é invisível. Girando a 90°/s, os quatro cantos de um marcador ArUco são capturados em quatro orientações diferentes do robô — e a pose resolvida a partir deles está errada de uma maneira que a calibração não consegue corrigir.

Se o robô precisa fazer visão em movimento, é para isso que existe o módulo Global Shutter. Se ele pode parar, olhar e depois se mover, o módulo mais barato é perfeitamente suficiente — e parar para olhar é uma escolha legítima de projeto, não uma solução improvisada.

Quando algo dá errado

Sintoma Geralmente
O notebook não vê tópicos Tráfego multicast bloqueado pelo ponto de acesso, ou ROS_DOMAIN_ID diferente
Marcador detectado, robô não se move Twist publicado para um assinante de TwistStamped
Distância sistematicamente errada em alguns pontos percentuais Tamanho do marcador errado ou página escalada pela impressora
Pose oscila muito à distância Marcador pequeno demais no quadro — aproxime-se ou imprima maior
A normal do marcador alterna Ambiguidade de pose — aproxime-se fora do eixo ou use uma placa ChArUco
Robô chega perto do marcador, mas torto Está orientando para o marcador em vez de seguir sua normal
Passa do ponto na aproximação final Pilotando por uma pose que tem 50–100 ms — reduza a velocidade perto do final
Continua dirigindo depois de o marcador sair do quadro Não há tempo limite de marcador perdido na máquina de estados

Vale perceber essa distribuição antes de começar: quase nada nela é visão computacional. É rede, referenciais, unidades e controle — é isso que construir um robô ROS 2 realmente ensina, e é por isso que o caminho dos fundamentos do ROS 2 passa o tempo em padrões de comunicação e referenciais, e não em OpenCV.

Se este passo for demais, o micromouse ensina mapeamento e planejamento em um microcontrolador sem Linux envolvido, e o robô controlado por celular cobre a metade de “comandos chegam por uma rede” desse problema com uma fração das peças.

Roteiro do projeto

O caminho de construção

Siga a árvore tecnológica das peças até um robô funcionando. Cada nó é desbloqueado quando seus pré-requisitos são concluídos, e seu progresso fica salvo neste dispositivo.

0 / 19 concluídos

100%
Componente

Adicione atuadores em tempo real

Componente

Ver componente
Tutorial

Instale o ROS 2 e crie um espaço de trabalho

1 h

Abrir tutorial
Componente

Adicione motoresredutores com encoder

Componente

Ver componente
Caminho de aprendizagem

Fundamentos do ROS 2

Caminho de aprendizagem

Abrir caminho
Caminho de aprendizagem

Controle de motores

Caminho de aprendizagem

Abrir caminho
Montagem

Dirija-o de um notebook

Construção

Montagem

Aproxime-se ao longo da normal

Construção

Objetivo

Acople-se a um marcador de forma repetível

Objetivo

Componentes

Tutoriais deste caminho

Perguntas frequentes

Por que usar ROS 2 neste projeto em vez de um único script Python?

Para este robô sozinho, um único script funcionaria e seria mais curto. O que ele não suportaria é a segunda funcionalidade. No momento em que o laço da câmera, o laço de tração e a lógica de decisão precisam rodar em taxas diferentes e continuar funcionando quando um deles trava, um único script se transforma em um problema de agendamento que você mesmo precisa resolver. O ROS 2 oferece separação de processos, um formato de comunicação entre as partes e — a parte que você sente imediatamente — a possibilidade de inspecionar qualquer tópico de um notebook enquanto o robô está rodando. O projeto vale ser feito porque ensina essa estrutura em um problema pequeno o bastante para ainda ser compreendido.

Preciso de um Arduino além do Raspberry Pi?

Não estritamente, mas o robô fica muito melhor com um. O Pi executa Linux, o que significa que seu laço de motores é agendado junto com tudo o mais e ocasionalmente atrasa alguns milissegundos. Isso é invisível para visão e fatal para um PID de roda. Dividir o robô — Pi para percepção e decisões, microcontrolador para os laços que não podem sofrer variação no intervalo de execução — é a arquitetura padrão por um motivo, e é exatamente a divisão que o ROS 2 encoraja.

Por que um marcador ArUco em vez de detectar um objeto real?

Porque o marcador fornece uma pose completa de 6 DOF a partir de um único quadro, sem dados de treinamento e sem ambiguidade sobre qual objeto foi encontrado. Detectar uma cadeira informa aproximadamente onde está uma cadeira; detectar um marcador ArUco informa posição e orientação em metros, que é o que um controlador realmente precisa. É também um ponto de partida honesto — estações de acoplamento reais, robôs de armazém e plataformas de pouso de drones usam marcadores fiduciais pelo mesmo motivo.

Por que a orientação do marcador fica alternando?

Isso é ambiguidade de pose, uma propriedade da geometria e não um erro no código. Um quadrado plano visto quase de frente tem duas orientações 3D que projetam quase os mesmos pixels, então pequenas quantidades de ruído fazem o solucionador alternar entre elas. A distância permanece estável enquanto a normal estimada salta. Use um marcador fisicamente maior, faça a abordagem com um pequeno desvio do eixo para que as duas soluções se separem, ou migre para uma placa ChArUco ou vários marcadores no acoplador — todas opções que dão ao solucionador mais geometria para distinguir as soluções.

Quão preciso é o acoplamento?

Com uma câmera calibrada e um marcador medido até o milímetro, um ou dois centímetros a uma distância de meio metro é realista. Os erros que dominam não são os que as pessoas esperam: um tamanho de marcador inserido errado escala proporcionalmente todas as estimativas de distância, e a latência da cadeia de processamento da câmera significa que a pose usada para dirigir descreve onde o marcador estava 50 a 100 milissegundos antes. Reduzir a velocidade nos últimos 30 cm elimina a maior parte do segundo problema sem custo adicional.

Posso fazer isso em um Raspberry Pi Zero?

Neste projeto, não — ou não com conforto. Um Zero 2 W pode executar ROS 2 e decodificar um fluxo de câmera, mas a detecção ArUco em uma taxa útil sobrecarrega tudo, e criar um espaço de trabalho nele é doloroso. Use um Pi 4 com 4 GB ou um Pi 5. O Zero é uma boa placa para um robô cujo Pi apenas retransmite comandos.