Hallo Habr!
In dieser Veröffentlichung möchte ich darüber sprechen, wie ich eine lokale Cross-Country-Karte für den Roboter erstellt habe. Diese Aufgabe war sowohl notwendig, um die Kenntnisse in der Programmierung und Beherrschung von Sensoren zu verbessern, als auch für die anschließende Implementierung unserer eigenen Algorithmen in der Arbeit von echten Robotern an Robotertests wie Robocross und Robofest.
Dieser Artikel richtet sich an Personen, die gerade erst in die Welt der Robotik einsteigen oder herausfinden möchten, wie eine Cross-Country-Karte erstellt wird. Ich habe versucht, alles in der einfachsten und verständlichsten Sprache zu erklären, die für die meisten Menschen verständlich ist.
Was ist eine lokale Langlaufkarte?
Eine
lokale Cross-Country-Karte sieht der Roboter also zu einem bestimmten Zeitpunkt.
Dies sind die Informationen, die aus den "Augen" des Roboters stammen und anschließend verarbeitet und in einer für uns geeigneten Form angezeigt werden.
Wenn der Roboter stillsteht, bleibt seine lokale Karte unter konstanten Umgebungsbedingungen konstant.
Wenn sich der Roboter bewegt, ändert sich zu jedem Zeitpunkt auch seine Umgebung, und auch die lokale Karte ändert sich.
Die lokale Karte hat normalerweise konstante Größen. Die Größe wird basierend auf der maximalen Länge der vom Entfernungsmesser emittierten Strahlen berechnet. In meinem Fall beträgt diese Länge 6 Meter.
Um die Aufgabe zu vereinfachen, wurde beschlossen, die Karte quadratisch zu machen. Es wurde auch beschlossen, dass sich der bedingte Entfernungsmesser genau in der Mitte der Karte befindet (dieser Ort ist der Punkt, an dem x = y = 0 ist). Das Zentrum wurde auf diese Weise ausgewählt, weil der von mir verwendete Entfernungsmesser Strahlen in der Ebene von mehr als 180 ° aussendet (er sendet Strahlen bei 240 ° aus, aber dazu später mehr), das heißt, einige Strahlen werden sicherlich hinter den Scanner und Wenn Sie das falsche Zentrum wählen, können Sie diese verlieren. Bei richtiger Wahl des Zentrums werden alle Strahlen korrekt angezeigt. Auf dieser Grundlage habe ich die Kartengröße zweimal größer gemacht als die maximale Länge der emittierten Strahlen.
Die Größe meiner Karte beträgt 12 * 12 Meter.

Der Sensor, den ich benutzt habe
Um diese Art von Problem zu lösen, können Sie einen beliebigen Entfernungsmesser verwenden.
Der Entfernungsmesser ist ein Gerät zur Bestimmung der Entfernung zu etwas (in meinem Fall zu einem potenziellen Hindernis).
In der Robotik werden hauptsächlich zwei Arten von Entfernungsmessern verwendet: Ultraschall und Laser.
Ultraschall- Entfernungsmesser sind viel billiger, aber Ultraschallstrahlen sind breit genug und nicht für genaue Messungen geeignet.
Laser- Entfernungsmesser sind teurer, aber genauer, da ihre Strahlen eng fokussiert sind.
Um mein Problem zu lösen, habe ich einen Hokuyo URG-04LX-UG01 Laserscanner verwendet. Dieser Sensor kann Strahlen mit 240 ° emittieren und liefert ziemlich genaue Informationen über die Hindernisse, die den Strahlen im Weg standen. Die maximale Reichweite beträgt 5-6 Meter. Es ist erwähnenswert, dass dieser Entfernungsmesser Strahlen nur in der 2D-Ebene aussendet. Diese Tatsache zwingt Sie dazu, den Sensor an einer bestimmten Stelle am Roboter anzubringen, normalerweise vor der Unterseite des Roboters, um ein genaueres Bild zu erhalten. Auch hier können Sie 3D-Scanner verwenden, die viel genauere und vollständigere Informationen über die Umgebung liefern, aber auch viel mehr kosten.
Ich glaube, dass dieser spezielle Scanner perfekt für das Training im Preis-Leistungs-Verhältnis geeignet ist.
Hokuyo URG-04LX-UG01Kurz zum Prinzip des Laserscanners:Der Entfernungsmesser sendet Strahlen entlang der Ebene aus. Ein Strahl, der auf seinem Weg auf ein Hindernis gestoßen ist, wird von diesem reflektiert und kommt zurück. Anhand der Phasendifferenz zwischen den gesendeten und empfangenen Signalen kann man beurteilen, wie weit sich das Hindernis befindet.
Wenn der emittierte Strahl nicht zurückkehrte, gab es dementsprechend bei 5 bis 6 Metern entlang der geraden Linie seiner Emission entweder keine Hindernisse oder der Strahl konnte nicht richtig reflektieren.
Die folgenden Daten können von einem Laserscanner erhalten werden:Für jeden emittierten Strahl:
- Entfernung zu einem Hindernis
- Emissionswinkel
* Jeder der Parameter wird in einem separaten Array gespeichert und entspricht den Daten für einen der Strahlen.Über das Erstellen von Karten
Um die Karte zu erstellen und zu zeichnen, habe ich die ROS-Tools (Robot Operating System) verwendet, nämlich das Programm Rviz und den Datentyp nav_msgs :: OccupancyGrid. Ich habe einen Herausgeber der lokalen Karte mit dem Nachrichtentyp nav_msgs :: OccupancyGrid unter dem entsprechenden Thema local_map erstellt. In Rviz, das dieses Thema abonniert hat, wurden Daten zur Karte empfangen und in Form des Typs Karte angezeigt.
In Übereinstimmung mit einem solchen Algorithmus war es notwendig, die Verarbeitung von Daten von einem Laserscanner programmgesteuert zu konfigurieren und sie in dem für die Übertragung erforderlichen Format aufzuzeichnen. In OccupancyGrid wird eine Karte in einem eindimensionalen Array gespeichert und übertragen.
Was ist hier los?Für diejenigen, die zum ersten Mal mit dieser Art von ROS-Daten konfrontiert sind: Dies ist ungewöhnlich, da die Karte herkömmlicherweise als zweidimensionales Array mit einer bestimmten Anzahl von Spalten und Zeilen dargestellt wird.
So war es bei mir. Ich speichere die Karte basierend auf den Daten des Scanners in einem zweidimensionalen Array. Wenn ich eine Nachricht zum Senden an Rviz verfasse, konvertiere ich das zweidimensionale Array in das eindimensionale Array, das für OccupancyGrid benötigt wird.
Tatsächlich wird eine Karte in OccupancyGrid nur in einem eindimensionalen Array gespeichert und übertragen. Beim Entschlüsseln der Daten wird automatisch eine quadratische zweidimensionale Karte erstellt.
Damit dies jedoch korrekt geschieht, müssen Sie dieses eindimensionale Array auf eine bestimmte Weise schreiben.
Nämlich: Zeile für Zeile aus dem zweidimensionalen Speicher, um in eine Zeile zu schreiben.
Voila! Das ist das ganze Geheimnis.
Eine Berufung auf ein Element eines solchen eindimensionalen Arrays erfolgt wie folgt:
mapSize - lokale Kartengröße
j ist die Spaltennummer
i - ZeilennummerKartenzellen (wiederum entsprechend dem Datentyp des OccupancyGrid) müssen Werte von 0 bis 100 haben. Je niedriger der Wert, desto größer ist die Wahrscheinlichkeit, dass die Zelle passierbar ist und umgekehrt.
Um die Aufgabe zu vereinfachen, habe ich
3 Primärfarben zum Färben von Zellen ausgewählt.- Weiß - Passierbarer Bereich = 0
- Schwarz - unpassierbarer Bereich = 100
- Grau - unbekannte Zone = 50
Ein wichtiger Punkt!Bevor die Daten vom Scanner eintreffen, ist die Karte vollständig unbekannt (Werte aller Zellen = 50) und wird jedes Mal nach dem Zeichnen erneut in einen unbekannten Zustand aktualisiert. Dies geschieht, damit die Karte keine überflüssigen vorherigen Werte überlagert. Schließlich spiegelt eine lokale Karte den Zustand der Umgebung nur zu einem bestimmten Zeitpunkt wider.
Unbekannte KarteStrahlen werden unter Verwendung einer Transformation aus dem Polarkoordinatensystem (UCS) konstruiert.
zum kartesischen Koordinatensystem (DSC).
$$ display $$ \ left \ {\ begin {collect} x = r * cos φ \\ y = r * sin φ \ end {collect} \ right. $$ display $$
x, y - neue Koordinaten in DSC
r ist der Abstand zum Hindernis
φ ist der Winkel, in dem der Strahl fallen gelassen wurde
r, φ - alte Koordinaten in UCS
Algorithmus zur Verarbeitung von Sensordaten:
Wir durchlaufen die Anordnungen der Abstände r und Winkel φ der Strahlen vollständig (UCS-Daten). Gehen Sie für jeden Artikel wie folgt vor:
- Wir transformieren die Koordinaten von UCS zu DSC für endliches r und φ. Malen Sie die resultierende Zelle schwarz. Dies ist ein Hindernis.
- Wir gehen in einer geraden Linie von der Position des Scanners zur Zelle mit einem Hindernis mit einem bestimmten Schritt, im einfachsten Fall gleich der Zellengröße.
- Wir konvertieren erneut die Daten vom BKS zum DSC und malen die neue Zelle in Weiß. Dies ist eine begehbare Gegend.
Das einfachste Beispiel dafür, wie man einen begehbaren Weg zu einem Hindernis bautWas aber, wenn der emittierte Strahl nicht zurückkehrt?In diesem Fall könnte dies Folgendes bedeuten:
- Der Strahl ist „verloren“, dh er wird nicht vollständig reflektiert oder in die andere Richtung reflektiert
- Es gab keine Hindernisse im Weg des Strahls und aus diesem Grund hatte er einfach nichts zu reflektieren
* Ein Strahl kann normalerweise „verloren gehen“, weil er nicht in einem Winkel von 180 ° reflektiert wurde (dh unter einem Winkel, der nicht nach hinten reicht), da das Hindernis senkrecht zum Strahl stehen könnte. Und wie Sie aus der Physik wissen: Der Einfallswinkel ist gleich dem Reflexionswinkel.

Oder weil das Hindernis zu schwarz war und den größten Teil der Energie des Strahls absorbierte und der Strahl nicht genug Energie hatte, um zurück zu gehen.
Daher ist es unmöglich, völlig sicher zu sein, was passiert ist, wenn der Strahl nicht zurückgekehrt ist.
Was tun in solchen Situationen?Wir machen folgendes:
- Wir betrachten den Abstand zum Hindernis eines solchen Strahls für den Scanner als möglich (in unserem Fall sind es 6 Meter).
- Wir betrachten alle Zellen in einer geraden Linie zum Hindernis als halbpassierbar und weisen ihnen eine Zwischenzahl von 25 zu. Dies sind passierbare Zellen, aber wir sind uns ihrer nicht ganz sicher.
Wir verlieren nichts, wenn die Strahlen wirklich nicht auf Hindernisse treffen und wenn dennoch ein Hindernis aus den „Augen“ des Roboters entweicht, wird es mit Sicherheit sehr schnell erkannt.
Kartenauflösung
Endlich der letzte Schliff!
Jede Karte hat eine Erlaubnis. Einfach ausgedrückt ist dies die Anzahl der Zellen, die in eine Zelle passen können.
Zum BeispielWenn es 1 Zelle in 1 Zelle gibt (der einfachste Fall), dann Auflösung 1.
Wenn eine Zelle 5 Zellen enthält, beträgt die Auflösung 0,2.
Die Auflösung meiner Karte beträgt 0,04. Das heißt, in jeder Zelle gibt es 25 Zellen. Somit beträgt mein Mindestschritt 4 cm. Und 1 Zelle ist 1 m.
Zelle und Zellunterschied auf meiner KarteWas ist das Ergebnis?
Ein Beispiel für die Erstellung einer lokalen Cross-Country-Karte
* Gelbe Farbe zeigt Zellfarben anIch glaube, dass die Arbeit, die ich geleistet habe, im Allgemeinen erfolgreich war, aber ich verstehe, dass der Algorithmus unvollkommen ist und Verfeinerung und Verfeinerung erfordert.