Percorso di costruzioneAvanzatoAlcuni fine settimana

Costruisci un robot ROS 2 che vede e raggiunge un marcatore

Un robot che individua un marcatore dall'altra parte della stanza, ne calcola la posizione relativa e vi si avvicina frontalmente, strutturato come un vero grafo di nodi ROS 2.

Schema tecnico: Costruisci un robot ROS 2 che vede e raggiunge un marcatorePOSE → STANDOFF → DOCK

Cosa stai costruendo

Un robot posizionato in un punto qualsiasi di una stanza, che ruota finché non trova un marcatore stampato su una parete e lo raggiunge — fermandosi a mezzo metro di distanza, inquadrato rispetto alla faccia del marcatore anziché soltanto vicino.

Ogni altra costruzione di questo sito esegue un programma su un microcontrollore. Questa è un computer con ruote, il che cambia il tema del progetto. Le parti difficili non sono più temporizzazione e cablaggio; sono sapere dove si trovano le cose rispetto alle altre e mantenere coerenti tra loro più componenti software mentre sono tutti in esecuzione.

Perché questo robot ha bisogno di un computer

Un Arduino non può farlo, e il motivo merita di essere precisato. Non è la velocità bruta — è che un fotogramma della camera occupa un quarto di megabyte, il rilevamento ArUco richiede algebra lineare in virgola mobile e tutto deve avvenire mentre alle ruote vengono ancora comandati segnali a 50 Hz. È un lavoro per un sistema operativo con memoria e pianificazione reali.

In cambio di questo sistema Linux ottieni la possibilità di guardare dentro un robot in funzione. Ogni messaggio tra ogni parte è un topic a cui puoi iscriverti da un laptop. Quando il robot passa accanto al marcatore invece di raggiungerlo, non aggiungi istruzioni di stampa e riflashi: usi ros2 topic echo sulla posa e la osservi sbagliata in tempo reale.

La forma del grafo dei nodi

Cinque responsabilità, una per nodo:

Nodo Pubblica Funzione
camera /image_raw, /camera_info Estrae i fotogrammi dal bus CSI
aruco_detector TF camera_link → marker_7 Trova il tag e ne risolve la posa
docking_controller /cmd_vel Decide dove muoversi
diff_drive seriale verso Arduino Da Twist alle velocità delle ruote
odometry TF odom → base_link Integra gli impulsi degli encoder

Le interfacce sono ciò che rende utile strutturare il sistema in questo modo. Il controllore non tocca mai direttamente una camera o un motore: consuma una trasformazione e produce una Twist. Questo significa che puoi guidare lo stesso robot con il telecontrollo da tastiera, provare il controllore mediante una trasformazione finta senza alcun hardware e, in seguito, inserire uno stack di navigazione che pubblica lo stesso identico topic.

Leggi nodi, topic, servizi e azioni prima di disegnare la tua versione di quella tabella. L’errore più comune in questa fase è fare del controllore di aggancio un servizio: è un obiettivo di lunga durata che devi poter annullare, ed è esattamente a questo che servono le azioni.

Elenco dei componenti

Questo è il robot a due cervelli e l’elenco dei componenti lo riflette: un computer per la percezione e un microcontrollore per le cose che un computer non riesce a eseguire in modo affidabile.

Componente Quantità Costo approssimativo Note
Raspberry Pi 4, 4 GB 1 $55 4 GB è il minimo pratico per ROS 2 più la visione. Con 1 GB il sistema effettua swap e si arresta
Pi Camera Module 3 1 $25 La variante Wide è migliore per la navigazione — 102° anziché 66°
microSD di classe A2, 32 GB 1 $8 Oppure avvia da un SSD USB, che è davvero più veloce
Dissipatore o ventola 1 $5 Un Pi 4 riduce la frequenza della CPU quando raggiunge gli 80 °C e un Pi sotto limitazione termica perde fotogrammi
Arduino Uno o Nano 1 $5 Encoder e controllo dei motori — la metà in tempo reale
Motori N20 con encoder 2 $16
TB6612FNG 1 $3
Telaio 2WD 1 $12 Spazio per un Pi, un palo della camera e una batteria
Pacco batteria 1 $15 3S con regolatore a commutazione da 5 V di portata 3 A
Marcatori ArUco stampati — $0 Stampa, misura la dimensione stampata e usa la misurazione

Totale: circa $145–175. È di gran lunga il progetto più costoso del sito e la maggior parte del costo è il Pi.

L’alimentazione è il punto in cui questi robot falliscono, e il fallimento è costoso. Un brownout durante la scrittura su una scheda SD corrompe l’intera immagine di sistema. Usa un regolatore a commutazione con una portata ben superiore al consumo del Pi, non condividere mai la linea di alimentazione con i motori e controlla vcgencmd get_throttled: qualsiasi valore diverso da zero indica un’alimentazione insufficiente e una scheda corrotta in arrivo.

Misura i marcatori stampati. La soluzione della posa ArUco scala direttamente rispetto alla dimensione del marcatore che dichiari. Un marcatore stampato al 95% dalla funzione «adatta alla pagina» della stampante produce posi sbagliate del 5% a ogni distanza, senza che nulla nella catena di elaborazione te lo segnali.

Ordine di costruzione

1 — Fai funzionare ROS 2 e dimostra che la rete funziona. Segui installazione di ROS 2 su un Raspberry Pi. Non andare avanti finché ros2 topic echo sul laptop non mostra un topic pubblicato dal robot. La scoperta tramite Wi-Fi è la causa più probabile di una serata sprecata e vuoi che accada adesso anziché mentre esegui il debug della visione.

2 — Fai in modo che le ruote obbediscano a una Twist. Collega l’Arduino, gli encoder e il TB6612FNG, e costruisci il ponte cmd_vel. Traguardo: il telecontrollo da tastiera sul laptop guida il robot reale. Calibra qui la distanza tra le ruote — tutto ciò che segue la eredita.

3 — Calibra la camera. Correttamente, con un bersaglio reale, seguendo calibrazione della camera e posa ArUco. Una camera non calibrata produce pose che sembrano plausibili ma sono sbagliate di decine di percento ai bordi del fotogramma, il peggior modo di guasto disponibile.

4 — Pubblica il marcatore come trasformazione. Non come messaggio personalizzato con dentro una x e una y. La pubblicazione di camera_link → marker_7 in TF2 permette al controllore di chiedere «dove si trova il marcatore, in base_link?», e la risposta tiene conto esattamente di come è montata la camera, incluso il fatto che è inclinata, cosa che è.

5 — Avanza verso il marcatore. Un controllore proporzionale sull’angolo di puntamento: ruota verso di esso, avanza e fermati alla distanza prevista. Funziona e arriva a un angolo, che è il punto del passo successivo.

6 — Avvicinati lungo la normale. Invece di sterzare verso il marcatore, calcola un punto di passaggio a una distanza prefissata dalla faccia del marcatore lungo la sua normale, recati lì e solo dopo avanza in linea retta. Questa è la differenza tra raggiungere l’aggancio e agganciarsi. È anche il punto in cui l’orientamento del marcatore, la parte della posa di cui non avevi bisogno fino ad ora, inizia a contare e in cui incontrerai l’ambiguità della posa.

7 — Racchiudilo in una macchina a stati. Ricerca, avvicinamento, allineamento, finale, completamento, più le transizioni in uscita da ciascuno quando il marcatore viene perso. Le macchine a stati finiti per il comportamento dei robot descrive la struttura; lo specifico aspetto di cui questo robot ha bisogno è un timeout per marcatore perso che torni alla ricerca anziché continuare dall’ultima posa nota.

Note hardware che contano

Monta la camera rigidamente, e misura il montaggio. Ogni posa calcolata dal robot è relativa alla camera e TF2 la trasforma in una posa relativa al robot mediante la trasformazione che tu dichiari da base_link a camera_link. Una camera su una staffa flessibile rende quella trasformazione dichiarata una menzogna che varia con l’accelerazione.

Inclina la camera verso il basso, e dichiaralo. Una camera puntata verso l’orizzonte perde il marcatore proprio quando il robot si avvicina. Dieci o quindici gradi verso il basso lo mantengono nell’inquadratura durante l’avvicinamento finale, e questa inclinazione va nella trasformazione statica, non in un fattore correttivo nel controllore.

Misura il marcatore con un calibro. La scala della posa è direttamente proporzionale alla dimensione del marcatore che comunichi al risolutore. Stampare al 96% perché la stampante ha adattato la scala rende ogni distanza sbagliata del 4%, in modo silenzioso e coerente.

Alimenta il Pi separatamente dai motori. Un motore in stallo abbassa la tensione di alimentazione e, dove un Arduino si riavvierebbe senza conseguenze, un Pi corrompe il proprio file system. Usa un regolatore separato oppure un pacco batteria separato: non è il posto in cui risparmiare un componente.

Tieni il nastro della camera lontano dai fili dei motori. È un collegamento ad alta velocità non schermato. Il rumore dei motori che si accoppia al nastro si manifesta come fotogrammi corrotti, che appaiono come rilevamenti che lampeggiano senza una ragione visibile.

Come appare un risultato buono

Misura Valore tipico su un Pi 4
Acquisizione della camera a 640×480 30 fps
Rilevamento ArUco, 640×480 25–30 fps, usando il 40–60% di un nucleo
Rilevamento ArUco, 1920×1080 5–8 fps — e ogni fotogramma è vecchio
Portata di rilevamento del marcatore (marcatore da 100 mm, 640×480) 1.5–2.5 m
Precisione della posa a 1 m ±2–5 cm di posizione, ±3–5° di orientamento
Latenza totale da immagine a decisione 60–120 ms
Ciclo di controllo dei motori, sull’Arduino 100–200 Hz
Latenza dei topic ROS 2, dal Pi all’Arduino via seriale 5–15 ms

Due righe racchiudono la lezione dell’intero progetto.

La risoluzione non è gratuita e spesso una risoluzione maggiore è peggiore. Passare da 640×480 a 1080p costa 4–6× la potenza di elaborazione per circa 1.7× la portata di rilevamento. A meno che tu non abbia bisogno specifico di vedere un marcatore più lontano, il fotogramma più piccolo fornisce una risposta più rapida e aggiornata, e l’aggiornamento conta più della precisione in un ciclo di controllo.

La riga sulla latenza spiega l’esistenza della divisione a due cervelli. A 0.3 m/s, 100 ms di latenza visiva corrispondono a 3 cm di percorso; con una rotazione a 90°/s, a 9° di rotazione. Ogni misurazione visiva descrive dove il robot era. Chiudere direttamente su di essa un ciclo rapido lo farà oscillare. La struttura funzionante è quella usata da questo robot: l’Arduino esegue il ciclo rapido sugli encoder e la visione lo corregge lentamente, esattamente come quando si fondono GPS e odometria sul rover con punti di passaggio, e per la stessa identica ragione.

Rolling shutter, se il robot si muove mentre guarda

I moduli camera standard del Pi hanno un rolling shutter: le righe vengono esposte una dopo l’altra, quindi la parte superiore di un fotogramma viene catturata qualche millisecondo prima di quella inferiore. Da fermo, questo non è visibile. Con una rotazione a 90°/s, i quattro angoli di un marcatore ArUco sono stati catturati in quattro diverse orientazioni del robot, e la posa risolta da essi è sbagliata in un modo che la calibrazione non può correggere.

Se il robot deve eseguire la visione mentre si muove, serve il modulo Global Shutter. Se può permettersi di fermarsi, guardare e poi muoversi, il modulo più economico va benissimo, e fermarsi per guardare è una scelta progettuale legittima, non una soluzione provvisoria.

Quando va storto

Sintomo Causa abituale
Il laptop non vede alcun topic Multicast bloccato dal punto di accesso oppure ROS_DOMAIN_ID diverso
Marcatore rilevato, ma il robot non si muove Twist pubblicata verso un sottoscrittore TwistStamped
La distanza è sempre sbagliata di qualche percento Dimensione del marcatore errata oppure pagina ridimensionata dalla stampante
La posa oscilla violentemente a distanza Marcatore troppo piccolo nell’inquadratura — avvicinati o stampane uno più grande
La normale del marcatore si inverte continuamente Ambiguità della posa — avvicinati fuori asse oppure usa una tavoliera ChArUco
Il robot arriva vicino al marcatore ma storto Sta sterzando verso il marcatore anziché lungo la sua normale
Supera il bersaglio durante l’avvicinamento finale Sta sterzando in base a una posa vecchia di 50–100 ms — rallenta vicino alla fine
Continua a muoversi dopo che il marcatore esce dall’inquadratura Nessun timeout per marcatore perso nella macchina a stati

Vale la pena notare la distribuzione in quella tabella prima di iniziare: quasi nulla riguarda la visione artificiale. Riguarda rete, sistemi di riferimento, unità e controllo, che è ciò che costruire un robot ROS 2 insegna davvero e il motivo per cui il percorso sui fondamenti di ROS 2 dedica il proprio tempo agli schemi di comunicazione e ai sistemi di riferimento anziché a OpenCV.

Se questo è un passo troppo avanti, il micromouse insegna mappatura e pianificazione su un microcontrollore senza Linux, mentre il robot controllato dal telefono copre la metà «i comandi arrivano tramite una rete» di questo problema con una frazione dei componenti.

Roadmap del progetto

Il percorso di costruzione

Segui l'albero tecnologico dai componenti fino a un robot funzionante. Ogni nodo si sblocca quando i suoi prerequisiti sono completati, e i tuoi progressi vengono salvati su questo dispositivo.

0 / 19 completati

100%
Costruzione

Guidalo da un laptop

Costruzione

Costruzione

Avvicinati lungo la normale

Costruzione

Obiettivo

Aggancia in modo ripetibile a un marcatore

Obiettivo

Componenti

Tutorial in questo percorso

Domande frequenti

Perché usare ROS 2 per questo invece di un singolo script Python?

Per questo solo robot, uno script singolo funzionerebbe e sarebbe più breve. Non sopravviverebbe però alla seconda funzionalità. Nel momento in cui il ciclo della camera, il ciclo di trazione e la log decisionale devono funzionare a velocità diverse e continuare anche quando uno di essi si blocca, uno script singolo diventa un problema di pianificazione che devi risolvere tu. ROS 2 fornisce separazione dei processi, un formato di scambio tra le parti e — l'aspetto che avverti immediatamente — la possibilità di ispezionare qualsiasi topic da un laptop mentre il robot è in funzione. Il progetto vale la pena di essere realizzato perché insegna quella struttura su un problema abbastanza piccolo da restare comprensibile.

Serve un Arduino oltre al Raspberry Pi?

Non strettamente, ma il robot è molto migliore con uno. Un Pi esegue Linux, il che significa che il ciclo dei motori viene pianificato insieme a tutto il resto e occasionalmente ritarda di alcuni millisecondi. Ciò è invisibile per la visione e fatale per un PID delle ruote. Dividere il robot — Pi per percezione e decisioni, microcontrollore per i cicli che non devono oscillare — è l'architettura standard per una buona ragione, ed è esattamente la divisione che ROS 2 favorisce comunque.

Perché un marcatore ArUco anziché rilevare un oggetto reale?

Perché il marcatore fornisce una posa 6-DOF completa da un singolo frame, senza dati di addestramento e senza ambiguità su quale oggetto hai trovato. Rilevare una sedia ti dice all'incirca dove si trova una sedia; rilevare un tag ArUco ti dà posizione e orientamento in metri, che sono ciò di cui un controllore ha realmente bisogno. È anche un punto di partenza onesto — stazioni di aggancio reali, robot da magazzino e piattaforme di atterraggio per droni usano marcatori fiduciali per la stessa ragione.

Perché l'orientamento del marcatore si inverte continuamente?

È l'ambiguità della posa, una proprietà della geometria anziché un bug del codice. Un quadrato piatto visto quasi di fronte ha due orientamenti 3D che proiettano su pixel quasi identici, quindi anche piccole quantità di rumore fanno saltare il risolutore da uno all'altro. La distanza resta stabile mentre la normale stimata si sposta. Usa un marcatore fisicamente più grande, avvicinati da una posizione leggermente fuori asse, dove le due soluzioni si separano, oppure passa a una tavoliera ChArUco o a più marcatori sull'aggancio: tutte opzioni che forniscono al risolutore più geometria su cui discordare.

Quanto è preciso l'aggancio?

Con una camera calibrata e un marcatore misurato al millimetro, sono realistici uno o due centimetri a una distanza di aggancio di mezzo metro. Gli errori dominanti non sono quelli che le persone si aspettano: una dimensione del marcatore inserita in modo errato scala proporzionalmente ogni stima di distanza, e la latenza della catena di elaborazione della telecamera significa che la posa su cui stai sterzando descrive dove si trovava il marcatore da 50 a 100 millisecondi fa. Rallentare negli ultimi 30 cm elimina gran parte del secondo problema senza alcun costo.

Posso farlo su un Raspberry Pi Zero?

Per questo progetto no, non comodamente. Un Zero 2 W può eseguire ROS 2 e decodificare un flusso video, ma il rilevamento ArUco a una frequenza di fotogrammi utile non lascia risorse, e costruirvi uno spazio di lavoro è fastidioso. Usa un Pi 4 da 4 GB o un Pi 5. Zero è una buona scheda di sviluppo per un robot il cui Pi si limita a ritrasmettere comandi.