banner
Heim / Blog / So verwenden Sie Lidar mit dem Raspberry Pi
Blog

So verwenden Sie Lidar mit dem Raspberry Pi

Nov 29, 2023Nov 29, 2023

Die Möglichkeit, den Abstand zwischen einem autonomen Fahrzeug oder Roboter und nahegelegenen Objekten kostengünstig, aber genau zu messen, ist für Hacker ein herausforderndes Problem. Die Kenntnis der Entfernung ist der Schlüssel zur Vermeidung von Hindernissen. Mit einem kleinen Roboter auf etwas zu stoßen mag ein triviales Problem sein, bei einem großen Roboter wie einem autonomen Fahrzeug kann es jedoch tödlich sein.

Mein Interesse an der Entfernungsmessung zur Vermeidung von Hindernissen geht auf meine Teilnahme am NASA Sample Return Robot (SRR)-Wettbewerb 2013 zurück. Ich habe eine Webkamera zur Bildverarbeitung verwendet und verschiedene visuelle Techniken zur Durchführung von Messungen ausprobiert, ohne großen Erfolg. Beim Wettbewerb nutzten zwei Teilnehmer scannende Lidars, was mein Interesse an ihnen weckte.

Ein Lidar ist ein Laserentfernungsmessgerät. Der Name ist eine Kombination der Begriffe LIght und raDAR und nicht, wie allgemein angenommen, ein Akronym, das in ähnlicher Weise wie sein Vorgänger „RAdio Detection And Ranging“ abgeleitet ist. Laut Merriam-Webster wurde der Begriff erstmals 1963 verwendet. Zu den frühen Einsatzmöglichkeiten von Lidar gehörte die Messung von Wolken und der Mondoberfläche bei Apollo 13. Mit der Verkleinerung der Laser wurden andere Einsatzmöglichkeiten gefunden, unter anderem als Entfernungsmesser für militärische Zwecke.

Ein einzelner Laserstrahl kann nur die Reichweite zu einem einzelnen Objekt liefern. So wie ein Flugzeugkontrollradar einen Strahl durch den Himmel schwenkt, schwenkt ein scannendes Lidar den Laser. Die Anwendung von Lidar für autonome mobile Geräte erfordert das Scannen eines großen Bereichs sowohl vertikal als auch horizontal, um eine Punktwolke mit Entfernungsmessungen bereitzustellen. Etwas Ähnliches könnte mit einem Infrarotsensor erreicht werden, wie wir bereits gesehen haben, aber die Genauigkeit ist nicht so gut wie mit einem Laser.

Die Entfernungsmessung kann auf verschiedene Weise erfolgen, es gibt jedoch zwei grundsätzliche Methoden. Einer misst die Flugzeit eines Laserpulses, der andere nutzt den Ablenkwinkel des Laserstrahls.

Sie sind mit der grundlegenden Funktionsweise von Radar und Sonar vertraut: Senden Sie einen Impuls aus und messen Sie die Zeit, die benötigt wird, um das Rückkehrsignal zu empfangen. Die Zeit dividiert durch die Licht- oder Schallgeschwindigkeit ergibt die Entfernung, die das Signal hin und zurück zurückgelegt hat. Teilen Sie das durch zwei, um die Entfernung zum Objekt zu erhalten. Das ist die Flugzeitmessung (ToF).

Wie Sie vielleicht vermuten, wird es angesichts der Lichtgeschwindigkeit schwierig. Konteradmiral Grace „Amazing Grace“ Hopper, eine Pionierin im Computerbereich, verteilte 11,80-Zoll-Drahtstücke, um die Entfernung zu demonstrieren, die Licht in einer Nanosekunde im Vakuum zurücklegt. Bei Robotern ist das die Größe der Entfernung, die wir messen möchten. Das ist es Es ist schwierig, weniger als einen Meter zu messen, der nur einen Impuls aussendet und das Rücksignal zeitlich festlegt, da das Signal in etwa 7 Nanosekunden zurückkehrt.

Eine Technik hierfür besteht darin, das Signal kontinuierlich nach Amplitude oder Frequenz zu modulieren. Der Phasenunterschied zwischen gesendetem und empfangenem Signal ist proportional zur Entfernung zum Objekt. Ein Lidar mit Modulation kann bis auf Zentimeter genau messen.

Es gibt eine Reihe kommerzieller Anbieter von ToF-basierten Scan-Lidars, aber der Preis ist etwas höher, als die meisten Bastler ausgeben würden. Ein relativ neuer Marktteilnehmer, PulsedLight, bot ein Single-Beam-ToF-Lidar an, das in der Preisspanne von Hackern lag, aber seine Lieferanten sind alle im Rückstand.

Das Triangulations-Lidar nutzt die gleiche Technik wie die Infrarot-Entfernungsmesssensoren von Sharp, die Hacker seit Jahren verwenden. Der Sender ist eine einzelne Quelle, aber der Empfänger ist ein ein- oder zweidimensionales Array von Empfängern. Durch den Versatz der Empfängerelemente zum Sender entsteht die Grundlinie eines Dreiecks. Das Hin- und Rücksignal sind die beiden anderen Seiten des Dreiecks. Die einfache Trigonometrie liefert den Abstand von der Grundlinie zum Objekt.

Die Optical Society beschreibt diese und andere Techniken zur Entfernungsmessung.

Was ich bei der Teilnahme am NASA SRR 2013 nicht wusste, ist, dass Neato Robotics 2010 einen Staubsauger auf den Markt brachte, der ein scannendes Lidar nutzte, um die Umgebung des Staubsaugers zu erfassen. Dadurch kann der Roboter Hindernissen ausweichen, anstatt gegen sie zu stoßen, wie es bei früheren Saugrobotern der Fall war.

Sparkfun hat das Vakuum abgebaut und das Lidar untersucht. Im Trossen Robotic-Forum begann im November 2010 eine lange Diskussion, als Hacker das Vakuum mit viel Aufmerksamkeit auf den Lidar zerlegten. Für das Hacken des Lidars wurden sogar kleine Preise ausgelobt.

Leider existieren einige der Links in diesem Thread nicht mehr, aber es lohnt sich trotzdem, ihn zu lesen, da viele Details in den Nachrichten dargelegt werden. Einige andere Threads im Forum enthalten zusätzliche Informationen. Ein besonders interessanter Fund ist ein Forschungsbericht, der dem Neato-Lidar vorausging, aber als Grundlage für das endgültige Design diente. Darin wurden die Details dargelegt, die Neato zur Entwicklung eines technischen Produkts benötigt.

Die gute Nachricht ist, dass es ein Wiki mit einer Zusammenfassung von Informationen über das Vakuum und das Lidar gibt. Einer der aktiven Hacker-Teilnehmer, [Nicolas „Xevel“ Saugnier] hat eine kleine USB-Schnittstellenkarte entwickelt, um den Lidar mit Strom zu versorgen und ihn mit seiner seriellen Schnittstelle zu verbinden. Im Sommer 2014 besorgte ich mir ein paar Lidar-Einheiten und die Platinen, als ich mich auf den Einstieg beim NASA SRR 2015 vorbereitete. Ich habe die Lidar-Einheiten mit der Python-Software und den im Robot Operating System verfügbaren Paketen von [Xevel] zum Laufen gebracht.

Mit dem Scan-Lidar konnte Neato Robotics die simultane Lokalisierung und Kartierung (SLAM) mithilfe der Entfernungsmessdaten implementieren. Dies ermöglicht es dem Roboter, den Reinigungsweg zu planen, anstatt die vorherigen Stöße und zufälligen Bewegungen, einen Drunkard's Walk, früherer Staubsauger zu verwenden. Dadurch kann der Neato einen Raum schneller vollständig abdecken. Beachten Sie in diesem Video einer Neato-Demonstration, wie der Roboter eine Karte erstellt, wo er war und auf welche Hindernisse er stößt. Beachten Sie insbesondere, wie die LIDAR-Daten verwendet werden, um das eine Hindernis sauber zu umrunden.

Ich interessiere mich immer noch sehr für Roboter, obwohl ich den SRR-Wettbewerb aufgegeben habe. Die Lidars standen auf dem Regal und lockten mich wie mythische Sirenen. Ich erlag schließlich ihrem Ruf, als mir klar wurde, dass die serielle Lidar-Schnittstelle perfekt zu einem Raspberry Pi passt, da beide auf 3V3-Ebene arbeiten. Dadurch würde die USB-Schnittstelle entfallen. Ein ähnlicher Versuch wurde 2014 von [Thomas Jesperson] unternommen, der ein STM32F429-Board verwendete und ein Video des Lidars in Aktion produzierte.

Der Lidar ist eine versiegelte Einheit, an deren einem Ende ein Motor hängt. Der Motor treibt einen Revolver an, der sich mit etwa 300 U/min dreht. Der Turm enthält den Laser und den Empfangssensor und ermöglicht durch Drehen einen 360-Grad-Scan der Umgebung. Der Laser und der Empfangssensor verfügen über zwei optische Anschlüsse außerhalb des Turms. Vom Lidar kommen zwei kurze Kabel mit JST-Anschlüssen. Ein zweipoliger Stecker versorgt den Motor mit Strom. Ein vierpoliger Stecker versorgt die Steuerkreise und die serielle 3V3-Schnittstelle mit 5 V Strom. Die Pinbelegungen sind:

Im Vakuum wird der Motor von einer 12-V-Quelle mit PWM mit einem Arbeitszyklus von etwa 25 % gespeist. Das bedeutet, dass der Motor etwa 3 V benötigt, um mit der richtigen Geschwindigkeit zu laufen, und nachfolgende Tests durch die Hacker haben gezeigt, dass dies wahr ist. Die USB-Schnittstellenkarte betreibt den Lidar über den 5-V-Eingang des USB-Anschlusses mittels PWM, gesteuert durch eine PID-Schleife (Proportional Integral Differential), um die Motorgeschwindigkeit aufrechtzuerhalten. Warum PWM und PID verwenden? Um eine konstante Drehzahl des rotierenden Turms aufrechtzuerhalten, während er sich abnutzt und Schmutz, Staub und andere Ablagerungen ansammelt. Bei meinen Tests habe ich festgestellt, dass der Motor den Turm je nach positiver und negativer Verbindung in beide Richtungen dreht. Die Schnittstelle funktioniert immer noch einwandfrei, aber die Reihenfolge der Datenpunkte wird umgekehrt. Normalerweise dreht sich der Turm gegen den Uhrzeigersinn.

Ein Wort zur Vorsicht: In einigen frühen Geräten verwendete die Schnittstelle 3V3, sodass der Anschluss an 5V zur Zerstörung der Schnittstelle führen kann.

Meine ursprüngliche Verbindung zwischen dem Pi und dem Lidar war schnell und schmutzig. Ich habe den Motor an den 3V3-Ausgang des Pi angeschlossen und es hat funktioniert. Der Ausgang des Pi 3V3 ist durch die Spezifikationen auf 50 mA begrenzt und im Lidar-Wiki heißt es, dass der Motor 64 mA verbrauchen würde. Ich habe meines gemessen und es zeichnete deutlich mehr. Ich habe auch den TX-Pin der Schnittstelle mit dem RX des Pi (Pin 10) verbunden. Mit CuteCom unter Raspbian Jessie konnte ich die Daten lesen, wenn der Turm manuell gedreht wurde. Nachdem diese grundlegenden Tests erledigt waren, war es an der Zeit, etwas ernster zu werden.

Ich habe mich für die Verwendung eines Darlington-Transistor-Arrays ULN2803A entschieden, das ich in meinem Teileschrank gefunden habe, um den Motor anzutreiben. Dieser IC verarbeitet problemlos den zum Antrieb des Motors benötigten Strom und enthält die zum Antrieb einer induktiven Last erforderlichen Schutzdioden. Ich hatte nicht vor, den Motor per PWM zu betreiben, wollte ihn aber aus- und einschalten. Ich habe die 5 V des Pi an Pin 2 mit dem roten Kabel am Motorstecker verbunden. Das schwarze Kabel ist über einen 15-Ohm-Widerstand mit dem ULN2803A verbunden, um die Spannung zu senken. Diese Setup-Low-Side-Konfiguration dient zur Steuerung des Motors. Das Schnittstellenkabel wird an die 5V-, Masse- und RX-Pins des Pi angeschlossen.

Um die Motorsteuerung zu testen, habe ich die Zuordnung der GPIO-Pins zum Dateisystemverzeichnis /sys/class/gpio verwendet. Jeder GPIO kann hier gesteuert werden, sobald der Pin exportiert wurde. Befehle können dann die Richtung der Pins festlegen und die Pins ein- und ausschalten. Die von mir verwendeten Befehle steuerten GPIO 18 (Pin 12):

Die „0“ und „1“ schalten bei Echo den Pin aus bzw. ein. Das hat funktioniert und ich konnte die Daten mit CuteCom sehen.

Ein interessantes Ergebnis tritt auf, wenn Sie mit der seriellen Schnittstelle verbunden sind und dann die Schnittstelle mit Strom versorgen. Der Lidar generiert eine Willkommensnachricht:

Piccolo Laser Distanz Scanner Copyright (C) 2009-2011 Neato Robotics, Inc. Alle Rechte vorbehalten. 5295

Wenn Sie den Turm manuell drehen, erscheint außerdem eine Meldung mit der Aufschrift „Spin“ und weist Sie darauf hin, dass eine Befehlsfunktion verfügbar ist, indem Sie eine Pause oder drei Esc-Zeichen senden. Informationen zu den Befehlen finden Sie im Wiki.

Nun muss ich eine grobe Software erstellen, um zu sehen, wie das alles funktioniert. Natürlich habe ich C++ verwendet, also habe ich die Toolkette für den Pi 2 installiert und festgestellt, dass die Kompilierungsgeschwindigkeit für die Entwicklung ausreichend ist. Ich begann, den Geany-Programmiereditor und Makefiles zu verwenden; Ein Setup, das ich kennengelernt habe, als ich mit dem Python-Code für den Lidar gearbeitet habe. Es beherrscht mehrere Programmiersprachen und ich habe es als Allzweck-Texteditor für Ubuntu und Raspian übernommen. Aber ich habe Geany schließlich aufgegeben und Eclipse CDT auf dem Pi installiert, als es den C++-Code nach der Bearbeitung nicht richtig neu formatieren ließ. Eclipse funktioniert auf dem Pi überraschend gut. Eigentlich war ich ein wenig enttäuscht über den Wechsel, da ich mit Geany neu gelernt habe, wie man mit Makefiles arbeitet, eine Fähigkeit, die ich bei der Arbeit mit Eclipse verloren habe.

Auf der Suche nach Informationen zur Programmierung des GPIO mit C++ bin ich auf die WiringPi-Bibliothek von [Gordon Henderson] gestoßen. Es unterstützt nicht nur die reine GPIO-Programmierung, sondern auch viele Pi-Tochterplatinen. Ein zusätzlicher Reiz für mich ist, dass es über eine serielle Schnittstelle verfügt, sodass ich mich unter Linux nicht mit den Details befassen musste, was für mich neu gewesen wäre. Schließlich nutzte ich sogar die einfache Thread-Fähigkeit, um eine absurd minimalistische Benutzeroberfläche zu verwalten. [Gordon] verfügt auch über ein Dienstprogramm, das Sie ausprobieren sollten, um Pins vollständiger über die Befehlszeile zu steuern als über das Schreiben in die Verzeichnisse, wie ich oben gezeigt habe.

Das letzte Element, das ich in WiringPi gefunden habe, ist die Möglichkeit, Hardware-PWM auf dem einen GPIO-Pin auszuführen, der dazu auf dem Pi geeignet ist. Das ist GPIO 18. Ich hatte ursprünglich GPIO 4 (Pin 7) zur Steuerung des Motors verwendet, wechselte aber, als ich diese Funktion entdeckte. Der Code legt derzeit einen konstanten Wert für die PWM fest, aber irgendwann möchte ich eine PID-Regelschleife (Proportional Integral Differential) hinzufügen (und einen Artikel darüber schreiben), um eine konstante Geschwindigkeit aufrechtzuerhalten. Das Einrichten von WiringPi, einem Thread und dem PWM auf GPIO 18 ist einfach:

Der Thread dient lediglich dazu, das Programm zu stoppen, wenn eine beliebige Taste eingegeben wird, und einen Treffer zurückzugeben. Wenn run auf „false“ gesetzt ist, wird der Hauptthread, der die serielle Eingabe liest, beendet und das Programm wird beendet, nachdem der Turm ausgeschaltet wurde. Der eigentliche Thread ist ganz einfach:

Das Lesen der seriellen Eingabe ist einfach, es reicht aus, Zeichen zu lesen, aber die Daten selbst sind zwar unkompliziert, erfordern aber ein wenig Knallen. Es gibt 360 Samples pro Umdrehung des Revolvers, sodass die Datenmenge bei 5 Umdrehungen pro Sekunde enorm ist. Es gibt 90 Pakete mit jeweils vier Datenpunkten. Jeder Punkt wird durch vier Datenbytes dargestellt: Entfernung, Signalstärke, ungültiges Entfernungsbit und ungültiges Stärkebit. Darüber hinaus beginnt jedes Paket mit einem Startbyte, einem Indexbyte, das die Paketnummer angibt, und zwei Bytes für die Drehgeschwindigkeit des Turms. Das Paket endet mit zwei Prüfsummenbytes. So habe ich diese Daten in Strukturen abgebildet:

Ich habe mich nicht damit beschäftigt, die Datenpakete zu speichern, sondern sie nur zu melden, um sicherzustellen, dass ich gute Daten sehe und meine Berechnungen gut aussehen. Die Entfernungsdaten sind eine Ganzzahl in Millimetern, die ich in Zoll umgewandelt habe. Der Code für die Prüfsumme ist im Wiki, aber ich habe ihn noch nicht implementiert.

Dies ist erst der Anfang der Arbeit mit dem Neato Lidar, aber ein guter. Die Hardware funktioniert gut und die Grundlagen der Software sind vorhanden. Ich kann die Daten abrufen und sehen, dass sie gültig sind. Die WiringPi-Bibliothek ist eine gute Ergänzung, um meine Bemühungen mit dem Pi fortzusetzen.

Die nächsten Schritte bestehen darin, die Prüfsummenroutine zum Laufen zu bringen, die sogenannte Benutzeroberfläche zu erweitern, um die Steuerung des Turmbetriebs zu ermöglichen, und eine PID-Schleife hinzuzufügen, um eine konstante Rotationsgeschwindigkeit aufrechtzuerhalten. Da der UNL2803A-Chip vorhanden ist, werde ich ihn verwenden, um die Stromversorgung der Schnittstelle zu steuern. Ich möchte auch versuchen, den Code von meinem Desktop aus zu kompilieren und Remote-Debugging durchzuführen. Während ich diese Änderungen vornehme, organisiere ich den Code in Klassen und schaue, wie ich ihn auf einem Roboter verwenden kann.

Motorkabel-Schnittstellenkabel