Ruta de construcciónAvanzadoVarios fines de semana

Construye un robot ROS 2 que localiza marcadores visuales

Un robot que detecta un marcador óptico en la sala, estima su posición 3D relativa y se acopla perpendicularmente, estructurado en un grafo de nodos ROS 2.

Esquema técnico de Construye un robot ROS 2 que localiza marcadores visualesPOSE → STANDOFF → DOCK

Qué vas a construir

Un robot que se coloca en algún punto de una habitación, gira hasta encontrar un marcador impreso en una pared y se acerca hasta él —parándose a medio metro, escuadrado respecto a la cara del marcador y no simplemente cerca de él.

Todas las demás construcciones de este sitio ejecutan un programa en un microcontrolor. Esta es un ordenador con ruedas, y eso cambia en qué consiste el proyecto. Las partes difíciles ya no son la temporización y el cableado: son saber dónde están las cosas unas respecto a otras, y mantener honestas entre sí a varias piezas de software mientras todas corren a la vez.

Por qué este robot necesita un ordenador

Un Arduino no puede hacer esto, y la razón merece precisión. No es la velocidad bruta: es que un fotograma de cámara es un cuarto de megabyte, la detección de ArUco quiere álgebra lineal en coma flotante, y todo eso tiene que ocurrir mientras las ruedas todavía reciben órdenes a 50 Hz. Eso es un trabajo para un sistema operativo con memoria real y planificación real.

Lo que gana a cambio esa caja con Linux es la capacidad de mirar dentro de un robot en funcionamiento. Cada mensaje entre cada parte es un topic al que puedes suscribirte desde un portátil. Cuando el robot pasa de largo el marcador en vez de ir a él, no añades prints y recompilas: haces ros2 topic echo de la pose y la ves estar mal en tiempo real.

La forma del grafo de nodos

Cinco responsabilidades, un nodo cada una:

Nodo Publica Trabajo
camera /image_raw, /camera_info Saca fotogramas del bus CSI
aruco_detector TF camera_link → marker_7 Encuentra la etiqueta y resuelve su pose
docking_controller /cmd_vel Decide hacia dónde conducir
diff_drive serie hacia el Arduino Convierte un Twist en velocidades de rueda
odometry TF odom → base_link Integra los pulsos del encoder

Las interfaces son lo que hace que valga la pena estructurarlo así. El controlador nunca toca una cámara ni un motor: consume una transformada y produce un Twist. Eso significa que puedes conducir el mismo robot con teleoperación de teclado, probar el controlador contra una transformada falsa sin hardware alguno, y más adelante colocar un stack de navegación que publique el topic idéntico.

Lee nodos, topics, servicios y acciones antes de dibujar tu propia versión de esa tabla. El error más común en esta etapa es hacer el controlador de acoplamiento un servicio: es un objetivo de larga duración que tienes que poder cancelar, y eso es exactamente para lo que existe una acción.

Lista de materiales

Este es el robot de dos cerebros, y la lista de piezas lo refleja: un ordenador para la percepción y un microcontrolador para lo que un ordenador no puede hacer de forma fiable.

Componente Cant. Coste aprox. Notas
Raspberry Pi 4, 4 GB 1 $55 4 GB es el suelo práctico para ROS 2 más visión. Con 1 GB empieza a intercambiar y muere
Módulo de cámara Pi 3 1 $25 La variante Wide es mejor para navegación: 102° en vez de 66°
microSD de clase A2, 32 GB 1 $8 O arrancar desde un SSD USB, que es realmente más rápido
Disipador o ventilador 1 $5 Una Pi 4 se estrangula a 80 °C, y una Pi estrangulada pierde fotogramas
Arduino Uno o Nano 1 $5 Encoders y control de motores: la mitad de tiempo real
Motores N20 con encoder 2 $16
TB6612FNG 1 $3
Chasis 2WD 1 $12 Sitio para una Pi, un mástil de cámara y una batería
Pack de baterías 1 $15 3S con regulador de 5 V conmutado dimensionado para 3 A
Marcadores ArUco impresos — $0 Imprímelos, mide el tamaño impreso y usa la medida

Total: unos $145–175. Este es, con diferencia, el proyecto más caro del sitio, y casi todo es la Pi.

La alimentación es donde fallan estos robots, y el fallo es caro. Un apagón durante una escritura en la tarjeta SD corrompe la imagen completa del sistema. Usa un regulador conmutado dimensionado muy por encima del consumo de la Pi, nunca compartas el raíl con los motores, y comprueba vcgencmd get_throttled: cualquier valor distinto de cero significa que la alimentación es insuficiente y que se avecina una tarjeta corrupta.

Mide tus marcadores impresos. La solución de pose de un ArUco escala directamente con el tamaño de marcador que declaras. Un marcador impreso al 95 % por el “ajustar a la página” de una impresora da poses un 5 % equivocadas a cualquier distancia, y nada en la cadena te lo va a decir.

Orden de construcción

1 — Pon ROS 2 en marcha y demuestra la red. Sigue instalar ROS 2 en una Raspberry Pi. No avances hasta que ros2 topic echo en tu portátil muestre un topic publicado en el robot. El descubrimiento por Wi-Fi es, con diferencia, lo más probable que te coma una tarde, y quieres que te la coma ahora y no mientras depuras visión.

2 — Haz que las ruedas obedezcan a un Twist. Cablea el Arduino, los encoders y el TB6612FNG, y monta el puente de cmd_vel. Hito: la teleoperación de teclado desde el portátil conduce el robot real. Calibra aquí la separación de las ruedas: todo lo de después la hereda.

3 — Calibra la cámara. Bien, con un objetivo real, siguiendo calibración de cámara y pose ArUco. Una cámara sin calibrar produce poses que parecen plausibles y están equivocadas en decenas de porcentaje en los bordes del fotograma, que es el peor modo de fallo disponible.

4 — Publica el marcador como transformada. No como un mensaje propio con una x y una y dentro. Publicar camera_link → marker_7 en TF2 significa que el controlador puede preguntar “¿dónde está el marcador, en base_link?”, y la respuesta tiene en cuenta exactamente cómo está montada tu cámara, incluido el hecho de que está inclinada, que lo está.

5 — Conduce hacia el marcador. Un controlador proporcional sobre el rumbo: gira hacia él, avanza, para en la distancia de standoff. Esto funciona, y llega con un ángulo, que es precisamente el punto del paso siguiente.

6 — Acércate siguiendo la normal. En vez de dirigir al marcador, calcula un waypoint apartado de la cara del marcador a lo largo de su normal, conduce hasta él, y solo entonces entra recto. Esta es la diferencia entre llegar al muelle y atracar. También es donde empieza a importar la orientación del marcador —la parte de la pose que no necesitabas hasta ahora— y donde te encontrarás con la ambigüedad de pose.

7 — Envuélvelo en una máquina de estados. Buscar, aproximar, alinear, final, hecho, más las transiciones de salida de cada uno cuando se pierde el marcador. Las máquinas de estados finitos para el comportamiento de un robot cubren la estructura; lo concreto que este robot necesita es un tiempo de espera por pérdida de marcador que vuelva a buscar en vez de seguir con la última pose conocida.

Notas de hardware que importan

Monta la cámara rígidamente, y mide cómo. Toda pose que el robot calcula es relativa a la cámara, y TF2 la convierte en una pose relativa al robot usando la transformada que tú declaras de base_link a camera_link. Una cámara en un soporte flexible convierte esa transformada declarada en una mentira que varía con la aceleración.

Inclina la cámara hacia abajo, y dilo. Una cámara apuntando al horizonte pierde el marcador justo cuando el robot se acerca. De diez a quince grados hacia abajo la mantiene en el fotograma durante el acercamiento final, y esa inclinación va en la transformada estática, no en un factor de corrección dentro del controlador.

Mide el marcador con un calibre. La escala de pose es directamente proporcional al tamaño de marcador que le digas al solucionador. Imprimir al 96 % porque la impresora ajustó a la página hace que cada distancia esté un 4 % equivocada, en silencio y de forma consistente.

Alimenta la Pi por separado de los motores. Un motor que se bloquea hunde el raíl, y donde un Arduino se reiniciaría sin daño, una Pi corrompe su sistema de archivos. O un regulador separado o un pack separado: este no es el sitio para ahorrar un componente.

Mantiene el cable plano de la cámara lejos de los cables de motor. Es un enlace de alta velocidad sin blindaje. El ruido de motor acoplado en él aparece como fotogramas corruptos, que aparecen como detecciones que parpadean sin ninguna razón visible.

Qué significa hacerlo bien

Medida Típico en una Pi 4
Captura de cámara a 640×480 30 fps
Detección de ArUco, 640×480 25–30 fps, usando el 40–60 % de un núcleo
Detección de ArUco, 1920×1080 5–8 fps, y cada fotograma está obsoleto
Alcance de detección del marcador (marcador de 100 mm, 640×480) 1.5–2.5 m
Precisión de pose a 1 m ±2–5 cm en posición, ±3–5° en orientación
Latencia total de imagen a decisión 60–120 ms
Lazo de control de motores, en el Arduino 100–200 Hz
Latencia de topic ROS 2, de la Pi al Arduino por serie 5–15 ms

Dos filas llevan la lección de todo el proyecto.

La resolución no es gratis, y subirla suele empeorar las cosas. Pasar de 640×480 a 1080p cuesta 4–6× el procesamiento para aproximadamente 1.7× el alcance de detección. A menos que necesites ver un marcador más lejos de forma específica, el fotograma más pequeño te da una respuesta más rápida y más fresca, y la frescura importa más que la precisión en un lazo de control.

La fila de latencia es la razón de la división en dos cerebros. A 0.3 m/s, 100 ms de latencia de visión son 3 cm de recorrido; girando a 90°/s son 9° de rotación. Toda medida de visión describe dónde estaba el robot anteriormente. Ciérrala directamente como un lazo rápido y oscilará. La estructura que funciona es la que usa este robot: el Arduino ejecuta el lazo rápido con los encoders, y la visión lo corrige despacio — exactamente la misma forma que fusionar GPS con odometría en el rover de waypoints, y por exactamente el mismo motivo.

Rolling shutter, si el robot se mueve mientras mira

Los módulos de cámara estándar de la Pi tienen obturador rolling: las filas se exponen una tras otra, así que la parte superior de un fotograma se captura unos milisegundos antes que la inferior. Quieto, esto es invisible. Girando a 90°/s, las cuatro esquinas de un marcador ArUco se capturaron en cuatro orientaciones distintas del robot, y la pose resuelta a partir de ellas está equivocada de una manera que la calibración no puede arreglar.

Si el robot tiene que hacer visión mientras se mueve, para eso está el módulo Global Shutter. Si puede permitirse parar, mirar y luego moverse, el módulo más barato es perfectamente suficiente, y parar para mirar es una decisión de diseño legítima, no un apaño.

Cuando va mal

Síntoma Causa habitual
El portátil no ve ningún topic Multicast bloqueado por el punto de acceso, o ROS_DOMAIN_ID distinto
Marcador detectado, el robot no se mueve Twist publicado contra un suscriptor de TwistStamped
La distancia se desvía siempre en unos pocos puntos porcentuales Tamaño de marcador equivocado, o la impresora escaló la página
La pose tiembla mucho a distancia Marcador demasiado pequeño en el fotograma: acércate o imprime más grande
La normal del marcador se voltea de un lado a otro Ambigüedad de pose: acércate fuera del eje o usa un tablero ChArUco
El robot llega cerca del marcador pero torcido Está dirigiendo al marcador en vez de a lo largo de su normal
Se pasa de largo en el acercamiento final Está guiándose por una pose de 50–100 ms de antigüedad: reduce al final
Sigue avanzando cuando el marcador sale del fotograma No hay tiempo de espera por pérdida de marcador en la máquina de estados

La distribución de esa tabla conviene apreciarla antes de empezar: casi nada de ella es visión por computador. Es redes, fotogramas, unidades y control, que es lo que construir un robot ROS 2 te enseña de verdad, y por eso la ruta de fundamentos de ROS 2 dedica su tiempo a patrones de comunicación y marcos de referencia más que a OpenCV.

Si esto es un paso demasiado lejos, el micromouse enseña mapeo y planificación en un microcontrolador sin nada de Linux, y el robot controlado por teléfono cubre la mitad “las órdenes llegan por una red” de este problema por una fracción de las piezas.

Hoja de ruta del proyecto

La ruta de construcción

Sigue el árbol tecnológico desde las piezas hasta un robot que funciona. Cada nodo se desbloquea cuando completas sus requisitos previos, y tu progreso se guarda en este dispositivo.

0 / 19 completados

100%
Componente

Añade actuación en tiempo real

Component

Ver componente
Componente

Añade el controlador de motores

Component

Ver componente
Ruta de aprendizaje

Fundamentos de ROS 2

Learning path

Abrir ruta
Ruta de aprendizaje

Control de motores

Learning path

Abrir ruta
Tutorial

Estructura los sistemas de coordenadas

20 min

Abrir tutorial
Montaje

Condúcelo desde el portátil

Build

Montaje

Aproximación por la normal

Build

Objetivo

Acoplamiento repetible sobre marcador

Goal

Componentes

Tutoriales de esta ruta

Preguntas frecuentes

¿Por qué utilizar ROS 2 en lugar de un único script en Python?

Para una prueba elemental aislada, un script monolítico en Python funcionaría y sería más breve; sin embargo, resulta inviable al escalar el sistema. En el instante en que el procesamiento visual, el lazo de control de tracción y la máquina de estados deben ejecutarse a frecuencias asíncronas sin bloquearse mutuamente, un script único degenera en un complejo problema de concurrencia artesanal. ROS 2 aporta aislamiento de procesos, serialización estandarizada y la capacidad fundamental de inspeccionar cualquier topic desde tu ordenador de desarrollo mediante herramientas como 'ros2 topic echo' mientras el robot opera en tiempo real.

¿Es imprescindible acoplar un Arduino junto a la Raspberry Pi?

No de forma estricta, pero optimiza radicalmente la fiabilidad del control motor. Raspberry Pi opera bajo un núcleo Linux de propósito general donde el planificador de procesos puede demorar la ejecución de los lazos motrices decenas de milisegundos. Esta fluctuación es inocua para el procesamiento de imagen pero perjudicial para un control PID de velocidad en bucle cerrado. Desacoplar la arquitectura (Raspberry Pi para percepción y planificación deliberativa; microcontrolador dedicado para conteo de encoders y generación de PWM determinista) constituye el estándar industrial en robótica móvil.

¿Por qué usar marcadores ArUco en lugar de detección de objetos reales?

Porque un marcador fiducial ArUco proporciona una pose tridimensional completa con 6 grados de libertad a partir de un único fotograma sin requerir redes neuronales pesadas ni introducir ambigüedad semántica. Detectar una silla señala aproximadamente su ubicación espacial; detectar una etiqueta ArUco entrega traslación y orientación exactas en metros y radianes respecto a la cámara. Por este motivo, las bases de recarga autónoma, flotas logísticas en almacenes y plataformas de aterrizaje de drones emplean marcadores fiduciales.

¿Por qué oscila erráticamente la orientación estimada del marcador?

Se debe a la ambigüedad geométrica de pose, inherente a la perspectiva óptica y no a un fallo de software. Un plano cuadrado observado casi frontalmente genera dos proyecciones tridimensionales proyectadas sobre píxeles casi idénticos en el plano focal, por lo que el ruido de discretización hace oscilar al algoritmo entre ambas soluciones. La distancia euclídea permanece estable pero el vector normal estimado salta abruptamente. Se resuelve empleando marcadores de mayor dimensión física, aproximándose con un ligero ángulo oblicuo o recurriendo a tableros ChArUco.

¿Qué tolerancia de precisión se obtiene en el acoplamiento?

Con cámara intrínsecamente calibrada y la dimensión física del marcador medida al milímetro con calibre, se consiguen precisiones de 1 a 2 cm a una distancia de medio metro. Las fuentes principales de desviación son: introducir una medida incorrecta del marcador (que escala proporcionalmente toda la estimación espacial) y la latencia del procesado de imagen (la pose recibida representa la posición del robot de hace 50–100 ms). Reducir la velocidad en los últimos 30 cm de aproximación mitiga este desfase temporal.

¿Puede implementarse en una Raspberry Pi Zero 2 W?

No es aconsejable para este proyecto específico. Aunque una Pi Zero 2 W puede ejecutar ROS 2 y decodificar vídeo, la detección continua de etiquetas ArUco satura completamente sus núcleos reduciendo la tasa de fotogramas, y la compilación del espacio de trabajo de colcon resulta excesivamente lenta. Se recomienda una Raspberry Pi 4 de 4 GB o una Pi 5 para disponer de suficiente memoria RAM y procesamiento.