BouwrouteExpertEen paar weekenden

Bouw een ROS 2-robot die een marker ziet en er naartoe rijdt

Een robot die een marker in een ruimte opmerkt, bepaalt waar de marker ten opzichte van hem staat en er recht van voren naartoe rijdt — opgebouwd als een echte ROS 2-nodegraph.

Technisch schema: Bouw een ROS 2-robot die een marker ziet en er naartoe rijdtPOSE → STANDOFF → DOCK

Wat u bouwt

Een robot die ergens in een ruimte wordt neergezet, draait tot hij een afgedrukte marker op een muur vindt en rijdt daar naartoe — hij stopt een halve meter ervoor, recht op het vlak van de marker in plaats van alleen in de buurt.

Elke andere build op deze site draait één programma op een microcontroller. Deze is een computer op wielen, en dat verandert waar het project over gaat. De moeilijke onderdelen zijn niet langer timing en bekabeling; het gaat erom te weten waar dingen ten opzichte van elkaar staan en meerdere softwareonderdelen op elkaar afgestemd te houden terwijl ze allemaal tegelijk draaien.

Waarom deze robot een computer nodig heeft

Een Arduino kan dit niet en de reden verdient precisie. Het gaat niet om pure snelheid — een camerabeeld is een kwart megabyte, ArUco-detectie heeft lineaire algebra met drijvende komma nodig en het geheel moet gebeuren terwijl de wielen nog met 50 Hz worden bestuurd. Dat is een taak voor een besturingssysteem met echt geheugen en echte taakplanning.

In ruil voor die Linux-doos kunt u in een werkende robot kijken. Elk bericht tussen elk onderdeel is een topic waarop u vanaf een laptop kunt abonneren. Rijdt de robot langs de marker in plaats van naar de marker toe, dan voegt u geen printopdrachten toe en brandt u geen firmware opnieuw — u voert ros2 topic echo uit op de stand en ziet hem in realtime fout gaan.

De vorm van de nodegraph

Vijf verantwoordelijkheden, elk in een eigen node:

Node Publiceert Taak
camera /image_raw, /camera_info Beelden ophalen van de CSI-bus
aruco_detector TF camera_link → marker_7 De tag vinden en de stand bepalen
docking_controller /cmd_vel Bepalen waar er gereden moet worden
diff_drive serieel naar de Arduino Van Twist naar wielsnelheden
odometry TF odom → base_link Encoderticks integreren

De interfaces maken de moeite waard om dit zo te structureren. De controller raakt nooit een camera of motor aan — hij verbruikt een transformatie en produceert een Twist. Daardoor kunt u dezelfde robot met toetsenbordbesturing besturen, de controller zonder enige hardware tegen een neptransformatie testen en later een navigatiestack inzetten die exact hetzelfde topic publiceert.

Lees nodes, topics, services en actions voordat u uw eigen versie van die tabel tekent. De meest voorkomende fout in deze fase is de dockingscontroller als service maken — het is een langdurig doel dat u moet kunnen annuleren, en dat is precies waarvoor een action bestaat.

Materialenlijst

Dit is de robot met twee hersenen, en dat komt tot uiting in de onderdelenlijst: een computer voor visuele waarneming en een microcontroller voor de dingen die een computer niet betrouwbaar kan doen.

Onderdeel Aantal Geschatte kosten Opmerkingen
Raspberry Pi 4, 4 GB 1 $55 4 GB is de praktische ondergrens voor ROS 2 en visuele waarneming. Met 1 GB gaat hij naar de wisselschijf en loopt vast.
Pi Camera Module 3 1 $25 De variant Wide is beter voor navigatie — 102° in plaats van 66°
microSD van A2-klasse, 32 GB 1 $8 Of start vanaf een USB-SSD, wat werkelijk sneller is
Koellichaam of ventilator 1 $5 Een Pi 4 verlaagt bij 80 °C zijn klokfrequentie en een door warmte afgeremde Pi laat beelden vallen
Arduino Uno of Nano 1 $5 Encoders en motorbesturing — de realtimehelft
N20-motoren met encoder 2 $16
TB6612FNG 1 $3
2WD-onderstel 1 $12 Ruimte voor een Pi, cameramast en accu
Accupack 1 $15 3S met een schakelende 5 V-regelaar van 3 A
Afgedrukte ArUco-markers — $0 Print, meet de afgedrukte afmeting en gebruik die meting

Totaal: ongeveer $145–175. Dit is met ruime marge het duurste project op de site, en het grootste deel daarvan is de Pi.

Voeding is waar dit soort robots kapotgaat, en de storing is duur. Een brown-out tijdens een SD-kaartschrijfactie beschadigt de hele systeemimage. Gebruik een schakelende spanningsregelaar met een ruime marge boven het verbruik van de Pi, deel nooit de spanningsrail met de motoren en controleer vcgencmd get_throttled — alles wat niet nul is betekent dat de voeding onvoldoende is en er een beschadigde kaart aankomt.

Meet uw afgedrukte markers. De oplossing voor de ArUco-stand schaalt rechtstreeks met de afmeting van de marker die u opgeeft. Een marker die door de printer op 95% wordt geschaald via “aan pagina aanpassen” levert op elke afstand een stand op die 5% fout is, en niets in de pipeline waarschuwt u.

Bouwvolgorde

1 — Laat ROS 2 draaien en bewijs dat het netwerk werkt. Volg ROS 2 installeren op een Raspberry Pi. Ga niet verder voordat ros2 topic echo op uw laptop een topic toont dat op de robot wordt gepubliceerd. Ontdekking via wifi kost het vaakst een hele avond, en u wilt dat nu meemaken in plaats van tijdens het debuggen van visuele waarneming.

2 — Laat de wielen een Twist opvolgen. Bekabel de Arduino, encoders en TB6612FNG en bouw de cmd_vel-brug. Mijlpaal: toetsenbordbesturing vanaf de laptop bestuurt de echte robot. Kalibreer hier de wielafstand — alles downstream erft die waarde.

3 — Kalibreer de camera. Grondig, met een echt doel, volgens camerakalibratie en ArUco-stand. Een niet-gekalibreerde camera levert standen op die er geloofwaardig uitzien, maar aan de randen van het beeld tientallen procent fout zijn. Dat is de slechtste storingsmodus die u hier kunt krijgen.

4 — Publiceer de marker als transformatie. Niet als een eigen berichttype met daarin een x en een y. camera_link → marker_7 publiceren in TF2 betekent dat de controller kan vragen: “waar is de marker in base_link?” Het antwoord houdt dan precies rekening met de manier waarop uw camera is gemonteerd — ook met het feit dat die gekanteld is, en dat is zo.

5 — Rij op de marker af. Een proportionele regelaar op basis van de richting: draai ernaartoe, rij vooruit en stop op de gewenste naderingsafstand. Dit werkt, maar de robot komt scheef aan, en dat is het doel van de volgende stap.

6 — Nader langs de normaal. Bereken in plaats van rechtstreeks op de marker te sturen een waypoint op naderingsafstand van het markervlak langs de normaal, rij daarheen en rij pas daarna recht naar voren. Dit is het verschil tussen bij het dock komen en daadwerkelijk aanlopen. Hier wordt ook de oriëntatie van de marker — het deel van de stand dat u tot nu toe niet nodig had — belangrijk en komt u dubbelzinnigheid van de stand tegen.

7 — Verpak alles in een toestandsmachine. Zoeken, naderen, uitlijnen, aanlopen, klaar, plus de overgangen uit elke toestand wanneer de marker verdwijnt. Toestandsmachines voor robotgedrag behandelt de structuur; wat deze robot specifiek nodig heeft, is een time-out voor een verloren marker die terugkeert naar zoeken in plaats van op de laatst bekende stand door te werken.

Hardware-opmerkingen die ertoe doen

Monteer de camera stevig vast en meet hoe. Elke stand die de robot berekent is relatief ten opzichte van de camera, en TF2 zet die om in een stand ten opzichte van de robot met de transformatie die u van base_link naar camera_link opgeeft. Een camera op een flexibele beugel maakt van die opgegeven transformatie een leugen die met de versnelling verandert.

Kantel de camera naar beneden en geef dat aan. Een camera die op de horizon gericht staat, verliest de marker precies wanneer de robot dichtbij komt. Tien tot vijftien graden naar beneden houdt de marker tijdens de laatste nadering in beeld — en die kanteling hoort in de statische transformatie, niet als correctie in de regelaar.

Meet de marker met een schuifmaat. De schaal van de stand is recht evenredig met de afmeting van de marker die u aan de oplosser geeft. Een afdruk op 96%, omdat de printer schaalde om op de pagina te passen, maakt elke afstand stilzwijgend en consistent 4% fout.

Voed de Pi apart van de motoren. Een motor die vastloopt laat de spanningsrail inzakken, en waar een Arduino zonder gevolgen zou resetten, beschadigt een Pi zijn bestandssysteem. Gebruik een aparte spanningsregelaar of een apart accupack — dit is niet de plek om op een onderdeel te bezuinigen.

Houd de lintkabel van de camera weg van de motordraden. Het is een onafgeschermde snelle verbinding. Motorruis die erin terechtkomt, verschijnt als beschadigde beelden en dus als detecties die om onverklaarbare redenen flikkeren.

Zo ziet goed eruit

Meting Typisch op een Pi 4
Camera-opname bij 640×480 30 fps
ArUco-detectie, 640×480 25–30 fps, waarbij 40–60% van één kern wordt gebruikt
ArUco-detectie, 1920×1080 5–8 fps — en elk beeld is verouderd
Detectiebereik van markers (marker van 100 mm, 640×480) 1,5–2,5 m
Nauwkeurigheid van de stand op 1 m ±2–5 cm positie, ±3–5° oriëntatie
Totale latentie van beeld tot beslissing 60–120 ms
Motorbesturingslus op de Arduino 100–200 Hz
Latentie van ROS 2-topic, Pi naar Arduino via serieel 5–15 ms

Twee rijen dragen de les van het hele project.

Resolutie is niet gratis en hoger is vaak slechter. De overstap van 640×480 naar 1080p kost 4–6 keer de verwerking voor ongeveer 1,7 keer het detectiebereik. Tenzij u een marker op grotere afstand moet zien, geeft het kleinere beeld een sneller en actueler antwoord — en in een regellus is actualiteit belangrijker dan precisie.

De latentierij verklaart waarom de splitsing in twee hersenen bestaat. Bij 0,3 m/s betekent 100 ms visuele latentie 3 cm rijafstand; bij een draaisnelheid van 90°/s is dat 9° draaiing. Elke visuele meting beschrijft waar de robot was. Sluit daar een snelle lus rechtstreeks op aan, dan gaat hij oscilleren. De werkende structuur is degene die deze robot gebruikt: de Arduino draait de snelle lus op basis van de encoders en visuele waarneming corrigeert die langzaam — precies dezelfde opbouw als GPS samenvoegen met odometrie op de waypoint-rover, en om precies dezelfde reden.

Rolsluiter als de robot beweegt terwijl hij kijkt

De standaard Pi-cameramodules hebben een rolsluiter: rijen worden na elkaar belicht, waardoor de bovenkant van een beeld enkele milliseconden vóór de onderkant wordt vastgelegd. Voor een stilstaande robot is dat onzichtbaar. Bij 90°/s werden de vier hoeken van een ArUco-marker bij vier verschillende robotoriëntaties vastgelegd — en de daaruit berekende stand is fout op een manier die kalibratie niet kan corrigeren.

Moet de robot visuele waarneming tijdens het bewegen uitvoeren, dan is dat waarvoor de Global Shutter-module bedoeld. Kan hij eerst stoppen, kijken en daarna bewegen, dan is de goedkopere module prima — en stoppen om te kijken is een legitieme ontwerpkeuze, geen noodoplossing.

Wanneer het misgaat

Symptoom Meestal
Laptop ziet geen topics Multicast wordt door het toegangspunt geblokkeerd, of ROS_DOMAIN_ID komt niet overeen
Marker gedetecteerd, robot beweegt niet Twist gepubliceerd op een abonnee die TwistStamped verwacht
Afstand is steeds enkele procent fout Verkeerde afmeting van de marker, of de printer heeft de pagina geschaald
Stand trilt heftig op afstand Marker te klein in beeld — ga dichterbij of print groter
Normaal van de marker wisselt heen en weer Dubbelzinnigheid van de stand — nader iets uit de as, of gebruik een ChArUco-bord
Robot komt in de buurt van de marker maar scheef Sturen op de marker in plaats van langs de normaal
Schiet over bij de laatste nadering Sturen op een stand van 50–100 ms oud — vertraag aan het einde
Rijdt door nadat de marker uit beeld verdwijnt Geen time-out voor een verloren marker in de toestandsmachine

Kijk naar de verdeling in die tabel voordat u begint: vrijwel geen ervan is computervisie. Het gaat om netwerken, frames, eenheden en regeling — en dat leert u werkelijk door een ROS 2-robot te bouwen. Daarom besteedt het leerpad ROS 2-basis zijn tijd aan communicatiepatronen en coördinaatframes in plaats van aan OpenCV.

Gaat dit te ver voor u, dan leert de micromouse kaarten en plannen op een microcontroller zonder Linux, en behandelt de robot die met een telefoon wordt bestuurd voor een fractie van de onderdelen de helft van dit probleem waarin “opdrachten komen binnen via een netwerk”.

Projectroadmap

De bouwroute

Volg de techboom van onderdelen tot een werkende robot. Elk knooppunt wordt ontgrendeld zodra de voorwaarden klaar zijn, en je voortgang wordt op dit apparaat opgeslagen.

0 / 19 klaar

100%
Bouw

Bestuur hem vanaf een laptop

Bouwstap

Bouw

Nader langs de normaal

Bouwstap

Doel

Herhaalbaar aanlopen op een marker

Doel

Componenten

Tutorials in deze route

Veelgestelde vragen

Waarom ROS 2 gebruiken in plaats van één Python-script?

Voor alleen deze robot werkt één script ook, en dat is korter. Het overleeft de tweede functie echter niet. Zodra de cameralus, de aandrijflus en de beslislogica op verschillende snelheden moeten draaien en blijven werken wanneer een daarvan vastloopt, wordt één script een taakplanningsprobleem dat u zelf moet oplossen. ROS 2 biedt procesisolatie, een wireformaat tussen de onderdelen en — en dat merkt u direct — de mogelijkheid om vanaf een laptop elk topic te bekijken terwijl de robot draait. Dit project is de moeite waard om die structuur aan een klein genoeg probleem te leren.

Heb ik naast de Raspberry Pi ook een Arduino nodig?

Strikt genomen niet, maar de robot is er veel beter mee. Een Pi draait Linux, waardoor uw motorlus samen met al het andere wordt ingepland en af en toe milliseconden te laat is. Dat is onzichtbaar voor visuele waarneming en fataal voor een PID-regelaar van een wiel. De robot opsplitsen — Pi voor waarneming en beslissingen, microcontroller voor de lussen die niet mogen jitteren — is om een goede reden de standaardarchitectuur, en ROS 2 moedigt precies die splitsing ook aan.

Waarom een ArUco-marker in plaats van een echt object detecteren?

Omdat de marker uit één beeld een volledige stand met 6-DOF oplevert, zonder trainingsdata en zonder twijfel over welk object u hebt gevonden. Een stoel detecteren vertelt ongeveer waar een stoel staat; een ArUco-tag detecteren vertelt de positie en oriëntatie ervan in meters, en dat heeft een regelaar werkelijk nodig. Het is ook het eerlijke beginpunt — echte aanloopstations, magazijnrobots en landingsplatformen voor drones gebruiken herkenningsmarkers om dezelfde reden.

Waarom wisselt de oriëntatie van de marker steeds om?

Dit is dubbelzinnigheid van de stand en een eigenschap van de geometrie, geen bug in uw code. Een vierkant stuk papier dat bijna recht van voren wordt bekeken, heeft twee 3D-oriëntaties die op vrijwel dezelfde pixels worden afgebeeld. Daardoor laat minuscule ruis de oplosser tussen beide wisselen. De afstand blijft stabiel terwijl de geschatte normaal heen en weer springt. Gebruik een fysiek grotere marker, nader iets uit de as, zodat de twee oplossingen uiteenlopen, of stap over op een ChArUco-bord of meerdere markers op het dock — al deze opties geven de oplosser meer geometrische informatie, waardoor de twee oplossingen beter uit elkaar te onderscheiden zijn.

Hoe nauwkeurig is het aanlopen?

Met een gekalibreerde camera en een marker die tot op de millimeter is gemeten, is een centimeter of twee bij een afstand van een halve meter realistisch. De dominante fouten zijn niet degene die u verwacht: een verkeerd ingevoerde afmeting van de marker schaalt elke afstandsschatting evenredig, en latentie in de camerapipeline betekent dat de stand waarop u stuurt beschrijft waar de marker 50 tot 100 milliseconden geleden stond. Vertraag in de laatste 30 cm — dat lost het meeste van het tweede probleem gratis op.

Kan ik dit op een Raspberry Pi Zero doen?

Voor dit project niet — niet zonder problemen. Een Zero 2 W kan ROS 2 draaien en een camerastroom decoderen, maar daar ArUco-detectie op een bruikbare beeldfrequentie bovenop draaien laat niets over en een workspace bouwen is er lastig. Gebruik een Pi 4 met 4 GB of een Pi 5. De Zero is een goed bord voor een robot waarvan de Pi alleen opdrachten doorgeeft.