Tutorial · Mittelstufe · 35 Min.
Lidar für Roboter: Was ein Scan liefert und wie er zur Karte wird
Wie ein rotierendes Lidar einen Scan aufbaut, warum schnelleres Drehen Winkelauflösung kostet und wie Raycasting Messungen in ein Belegungsraster verwandelt.
Einführung
Ein Entfernungssensor sagt, wie weit ein Ding entfernt ist, entlang einer Linie. Eine Karte sagt die Form eines Raums. Alles Interessante in Navigation lebt in der Lücke zwischen beiden – und um diese Lücke geht es auf dieser Seite.
Beide Enden sind hier bereits abgedeckt: Einzelpunktmessung auf einer Seite, und SLAM sowie A* auf Belegungsraster auf der anderen. Doch die setzen ein bereits existentes Raster voraus. Nichts sagt, woher es kommt – und die Antwort – einen Scan per Raycasting in Zellen gießen – ist simpel wie fallenträchtig.
Ein 2D-Lidar ist ein ToF-Sensor auf Drehteller
Das ist das Nützlichste, was man wissen kann – denn die Entfernungsmessungshälfte versteht man damit bereits.
In einem Hobby-2D-Lidar steckt ein optisches Laufzeit-Entfernungsmessmodul, exakt die Art auf einem VL53-Breakout, seitwärts zeigend und gedreht. Ein Winkelencoder meldet, wohin es bei jeder Messung schaute. Strom und Daten queren die rotierende Grenze per Schleifring oder optisch-induktiver Kopplung.
Ein „Scan“ ist also kein Foto. Es ist eine Liste aus (Winkel, Entfernung)-Paaren, einzeln gesammelt, über eine Umdrehung. Jede Grenze unten folgt aus diesem Satz.
Das erklärt auch, warum Ultraschallsensoren nicht zu Lidaren versponnen werden. Ein Ultraschallstrahl ist Dutzende Grad breit – ihn zu rotieren gewinnt fast nichts: Man würde einen bereits breiten Strahl durch den Raum schmieren. Ein enges optisches Bündel macht Winkelauflösung überhaupt erst sinnvoll. Einen einzelnen ToF-Sensor auf einem Servo zu schwenken, wie im Scan-Ultraschall-Tutorial, ist wirklich ein langsames, niedrigauflösendes Lidar.
Das Abtastbudget ist fest – Auflösung und Frische handeln also
Hier der Teil, der Leute überrascht – und lohnt Verstehen, bevor man irgendetwas kauft.
Das Entfernungsmessmodul hat eine Durchsatzzahl: Wie viele Messungen pro Sekunde es schafft. Am RPLIDAR A1 sind das etwa 8000 Messwerte pro Sekunde – und sie ändert sich nicht, wenn man die Drehrate ändert. Die Drehrate wählt man selbst, typisch 1–10 Hz.
Die Punkte pro Umdrehung sind also schlicht Budget geteilt durch Drehrate:
points per revolution = samples per second ÷ spin rate
angular step = 360° ÷ points per revolution
| Drehrate | Punkte pro Umdrehung | Winkelschritt | Scandauer |
|---|---|---|---|
| 5,5 Hz | 1455 | 0,25° | 182 ms |
| 10 Hz | 800 | 0,45° | 100 ms |
Frische Scans und feine Winkelauflösung zugleich gibt es nicht. Mit 10 Hz drehen halbiert deine Latenz und fast halbiert deine Winkelauflösung. Dieser eine Zielkonflikt entscheidet mehr darüber, wie sich ein Roboter verhält, als die Reichweitenschlagzeile – und er ist das Erste, was man absichtlich setzt statt auf Treiberstandard zu lassen.
Schnell fahrender Roboter im offenen Korridor: schnell drehen – Frische braucht man und Wände sind groß. Langsamer Roboter kartiert vollgestellten Raum: langsam drehen – Detail braucht man und Latenz kann man sich leisten.
Strahlen laufen auseinander – ferne Hindernisse fallen dazwischen
Ein Winkelschritt ist ein Winkel, keine Strecke. Zwei Nachbarstrahlen trennen sich auf dem Weg:
gap between beams ≈ range × angular step (in radians)
Bei 0,45° sind das 7,9 mm Lücke bei einem Meter und 31 mm bei vier Metern. Nichts tastet den Raum dazwischen ab.
Ein 20-mm-Stuhlbein nehmen. Bei 10 Hz drehend passiert die Strahllücke 20 mm bei etwa 2,5 m – dahinter kann das Bein vollständig zwischen zwei Strahlen sitzen und nichts zurückgeben. Bei 5,5 Hz kommt man bis etwa 4,6 m, bevor dasselbe geschieht.
Das erklärt ein Verhalten, das sonst wie ein defekter Sensor aussieht: Dünne Hindernisse erscheinen, während sich der Roboter nähert – tauchen einen, zwei Meter entfernt in der Karte auf. Das Lidar versagte nicht. Das Bein wurde nie abgetastet.
Zwei Folgen, die sich lohnen einzuplanen:
- Keinem einzelnen Scan für dünne Hindernisse trauen. Mehrere Scans in ein Raster zu sammeln, wie unten, findet Tischbeine wirklich – jeder Scan tastet leicht andere Winkel ab.
- Stuhl- und Tischbeine sind der klassische Haushaltsroboterfehler – denn sie sind dünn, liegen exakt auf Lidarhöhe, und der Roboter erfährt erst spät von ihnen.
Ein Scan ist kein Schnappschuss
Die Punkte einer Umdrehung wurden nicht im selben Augenblick gemessen. Bei 5,5 Hz dauert der Schwenk 182 ms – und der Roboter wartet nicht höflich.
- Bei 0,5 m/s Fahrt legt der Roboter während einer Umdrehung 91 mm zurück.
- Bei 1 rad/s Drehung wird der Scan durch 10,4° verschmiert.
Diese Punktliste als starren Schnappschuss einer Pose zu behandeln verbiegt die Welt. Gerade Wände kommen gekrümmt oder verdoppelt heraus – und Scanmatching kämpft Korrekturen, die wirklich die eigene Bewegung sind.
Darum trägt sensor_msgs/LaserScan scan_time und time_increment neben den Entfernungen: Sie lassen einen Verbraucher ausrechnen, wann jeder Strahl aufgenommen wurde. Dafür zu korrigieren – jeden Punkt mit der Pose transformieren, die der Roboter zum Zeitstempel dieses Strahls hielt – heißt Entzerrung oder Bewegungskompensation, und gute SLAM-Frontends tun es für dich.
Was das praktisch heißt: Sind deine Karten im Stand sauber und in Fahrt verschmiert, Entzerrung und Zeitstempel verdächtigen, lange bevor man den Sensor verdächtigt. Und langsamer fahren beim Kartieren. Halbes Tempo ist halbe Verzerrung, gratis.
Eine horizontale Scheibe ist alles, was du bekommst
Ein 2D-Lidar misst eine Ebene. Was über oder unter dieser Ebene sitzt, existiert nicht.
Die klassischen drei:
- Überhänge. Eine Tischplatte bei 700 mm ist für ein Lidar bei 150 mm unsichtbar. Der Roboter fährt selbstbewusst darunter und verkeilt sich.
- Niedrige Hindernisse. Eine Türschwelle, ein Kabel, eine Socke. Alle unter der Ebene.
- Abgründe. Eine absteigende Treppe ist Leere in jeder Richtung, die das Lidar sehen kann. Sie liest sich als wunderschön freier Boden.
Keine Scanverarbeitung behebt das – denn die Information wurde nie erfasst. Echte Roboter behalten Bumper, Abgrundsensoren und oft einen abwärts- oder vorwärtsgeneigten Ranger neben dem Lidar – nicht weil das Lidar schlecht wäre, sondern weil eine Ebene eine Ebene ist. Wenn man liest, ein Saugroboter „habe Lidar und trotzdem Bumper“, darum.
Vom Scan zum Raster: Raycasting
Nun die Kartierungshälfte. Ein Belegungsraster teilt die Welt in quadratische Zellen und speichert pro Zelle, wie stark man glaubt, sie sei belegt.
Die Einsicht, die es funktionieren lässt: Eine Entfernungsmessung sagt etwas über jede Zelle entlang des Strahls, nicht nur die Zelle am Ende. Fuhr ein Strahl 3 m, bevor er etwas traf, muss der durchquerte Raum leer gewesen sein – sonst wäre er früher gestoppt.
Jeder Strahl erzeugt also drei Urteile:
- Zellen, die der Strahl durchquerte → Evidenz für frei. Die Linie von Sensor zu Treffer abgehen und jede Zelle Richtung leer schubsen.
- Die Zelle, in der die Messung landete → Evidenz für belegt. Sie Richtung voll schubsen.
- Zellen jenseits des Treffers → nichts. Der Strahl stoppte. Über das, was hinter dieser Wand liegt, lernte man nichts – diese Zellen muss man also in Ruhe lassen.
Die Linie abgehen ist schlichte Linienrasterung – Bresenham-Algorithmus, derselbe, der eine Linie auf einen Bildschirm zeichnet.
Eine Maximalentfernungsmessung braucht eigene Behandlung. Viele Treiber melden das Maximum oder Unendlich, wenn nichts zurückkam. Das ist nicht „dort bei 12 m steht eine Wand“ – sondern „nichts gefunden“. Den Strahl frei markieren und am Ende keine belegte Zelle markieren.
Log-Odds: warum man addiert statt multipliziert
Man könnte pro Zelle eine Wahrscheinlichkeit speichern und Bayes-Updates multiplizieren. In der Praxis speichern alle stattdessen Log-Odds:
l = ln( p / (1 - p) ) p = 1 / (1 + e^(-l) )
Zwei Gründe: Viele kleine Wahrscheinlichkeiten zu multiplizieren läuft unter; Logs zu addieren nicht. Und es macht das Update zu einer einzigen Addition – billig genug, um es für jede Zelle jedes Strahls jedes Scans zu tun.
Mit p = 0,5 (keine Ahnung) abgebildet auf l = 0 einen Wert für Treffer und einen für Nichttreffer wählen – etwa p_occ = 0,7 (l = +0,847) und p_free = 0,4 (l = −0,405) –, und das Update lautet:
l_cell += l_occ # this beam hit this cell
l_cell -= 0.405 # this beam passed through this cell
Eine Zelle beginnend bei l = 0 nach drei Treffern:
| Beobachtung | Log-Odds | Wahrscheinlichkeit |
|---|---|---|
| Start (unbekannt) | 0,000 | 0,500 |
| Treffer | +0,847 | 0,700 |
| Treffer | +1,695 | 0,845 |
| Treffer | +2,542 | 0,927 |
| Durchquert | +2,136 | 0,894 |
| Durchquert | +1,731 | 0,850 |
Evidenz summiert sich – und Dissens zieht sie zurück. Das ist der ganze Algorithmus.
Die Summen begrenzen. Das zählt mehr, als es aussieht. Zwanzig Folgetreffer ohne Begrenzung setzen eine Zelle auf l = 16,9, also p = 0,999999. Nun rückt jemand den Stuhl weg. Diese Gewissheit rückgängig zu machen braucht 42 freie Beobachtungen. Der Stuhl hinterlässt ein dauerhaftes Phantom – und dein Planer lenkt weiter um nichts herum.
l auf etwa ±3,5 zu begrenzen behebt es: Starke Überzeugung bleibt stark, aber eine Handvoll widersprechender Scans kann sie umstoßen. Sammeln deine Karten Geister verschwundener Objekte, liegt es fast immer hieran.
Unbekannt ist ein dritter Zustand, kein Synonym für frei
Das ist der Fehler, der selbstbewusste, gefährliche Pläne erzeugt.
Ein frisch initialisiertes Raster ist vollständig unbekannt. Behandelt dein Planer Unbekannt als befahrbar, routet er fröhlich durch die Weltteile, die man nie anschaute – und als Unerforschte sind sie exakt dort, wo die Überraschungen leben. Behandelt er Unbekannt als blockiert, verweigert der Roboter am Start jede Bewegung – denn alles ist unbekannt.
Beides ist falsch; die drei Zustände getrennt halten und bewusst entscheiden:
- Belegt – nicht hindurchplanen.
- Frei – hindurchplanen.
- Unbekannt – nur mit Kosten hindurchplanen, oder nur beim bewussten Erkunden.
Frontier-Erkundung – wie ein Roboter wählt, wohin er als Nächstes schaut – baut vollständig auf der Frei/Unbekannt-Grenze. Beide kollabieren lassen und man hat das weggeworfen.
Zellgröße wählen
Die übliche Antwort für Innenraumroboter lautet 5 cm – und es gibt einen Grund, nicht feiner zu gehen, nur weil man kann.
Eine Zelle kleiner als dein Strahlabstand bei typischer Entfernung erfindet Präzision, die du nicht hast – bei 4 m liegen die Strahlen 31 mm auseinander, 1-cm-Zellen lassen also dauerhafte Löcher zwischen Strahlen, die nie zuwachsen. Zellen deutlich größer als dein Roboterfreiheitsmaß lassen andererseits Türen unpassierbar aussehen – denn eine einzelne belegte Zelle kann die Lücke schlucken.
Praktische Regel: Zellgröße etwas kleiner als die engste zu durchfahrende Lücke, und nicht kleiner als dein Strahlabstand dort, wo du wirklich operierst. Dann Hindernisse zur Planungszeit um den Roboterradius aufblähen, statt Zellen zum Ausgleich zu schrumpfen.
Wenn es schiefgeht
| Symptom | Meist |
|---|---|
| Dünne Hindernisse erscheinen erst nah | Strahlabstand überschritt bei Entfernung ihre Breite – erwartet, kein Defekt |
| Wände kurven oder verdoppeln sich während der Fahrt | Scan nicht entzerrt; Punkte als ein Augenblick behandelt |
| Karte im Stand sauber, in Fahrt verschmiert | Dieselbe Ursache; außerdem langsamer kartieren versuchen |
| Roboter fährt unter einen Tisch und verkeilt sich | 2D-Ebene sieht Überhänge nicht; zweiten Sensor brauchen |
| Treppen lesen sich als freier Boden | Abgründe sind für horizontale Ebene unsichtbar; Abgrundsensoren |
| Entfernte Hindernisse bleiben auf der Karte | Log-Odds nicht begrenzt – Gewissheit lässt sich nicht rückgängig machen |
| Ganze Karte füllt sich an den Rändern mit Hindernissen | „Keine Rückkehr“-Maximalmessungen als Treffer markiert |
| Planer routet durch unerforschten Raum | Unbekannt mit frei verwechselt |
| Feines Raster voller Sprenkellöcher | Zellen kleiner als Strahlabstand; nichts tastet zwischen Strahlen ab |
| Glaswände fehlen vollständig | Optische Rückkehr geht glatt hindurch – der eine Ort, wo Ultraschall gewinnt |
Diese letzte Zeile ist der ehrliche Vorbehalt der ganzen Seite. Lidar schlägt Sonar bei Auflösung, Rate und Reichweite – und verliert dann vollständig an einer Glastür, die Schall reflektiert und Licht nicht. Es ist das klarste Argument dafür, nicht einen Sensor zu wählen und das Problem für gelöst zu erklären.
Den Graphen erkunden
Teil dieser Bauprojekte
Projekte und Lernpfade, die dieses Tutorial enthalten.
Weiterführende Literatur