Experimente

Experimente: LDV Bot und Python:

 

Hardware:

 

Der LDV Bot wird von einem Computer aus über das Funkmodul nRF24L01+ angesprochen.Dabei werden von der Python Konsole eines beliebigen Python Editors aus Daten über das erste Funkmodul (angesteuert über einen Arduino, in diesem Fall Arduino Leonardo) an das zweite Funkmodul am Roboter geschickt (Arduino Pro Mini). Der Roboter führt anschließend den entsprechenden Befehl aus und sendet gegebenenfalls eine Antwort zurück.

 

nRF24L01+ Funkmodul und Arduino Leonardo:

Wird ein Arduino Leonardo in Verbindung mit dem Funkmodul verwendet, gibt es hier eine kleine Anleitung zur Verkabelung:

https://arduinoexamples.wordpress.com/2012/11/11/nrf24l01-com-arduino-leonardo-nrf24l01-with-arduino-leonardo/

Um mit dem Roboter zuverlässig kommunizieren zu können ist es jedoch noch nötig, einen Kondensator zwischen dem 3.3V und dem GND Pin parallel zu schalten. Hier wurde ein Elko 10µF 63V verwendet.

 

Python Umgebung:

Der nachfolgende Python Code und das dazugehörige Framework sind in Python 2.7 geschrieben.

Folgendes wird benötigt um eine kompatible Python Programmierumgebung für dieses Projekt zu schaffen:

- Python 2.7: Interpreter (https://www.python.org/download/releases/2.7)

- Ein Python kompatibler Editor: Hier wurde die Community Edition von PyCharm verwendet (https://www.jetbrains.com/pycharm/download

- PySerial: Zur Unterstützung von seriellen Ports (http://pyserial.sourceforge.net/pyserial.html)  

Nachdem die oben genannten Programme/Module installiert wurden, kann der Python Code nun ausgeführt werden.

 

Python Framework:

Es gibt drei Dateien, die jeweils verschiedene Funktionen enthalten bzw. erfüllen:

- functions.py: Diese Datei beinhaltet die Grundbefehle/Funktionen um über einen seriellen Port kommunizieren zu können.

- robofunc.py: Das eigentliche Framework, hier gibt es die Funktionen die dem Roboter sagen was er tun soll (drive, led an/aus, Sensordaten auslesen etc.)

- roboxperiment.py: Das eigentliche Experiment. Hier wurden verschiedene Algorithmen implementiert und ausprobiert. Diese Datei beinhaltet unter anderem Experimente zum Line Following und Maze Solving.

Alle genannten Dateien wurden auf GitLab veröffentlicht und können von dort aus bezogen werden.

 

Ausführen der Funktionen:

Um Funktionen aus den oben genannten Programmen ausführen zu können öffnet man zunächst die Konsole, unter PyCharm: => Tools => Python Console. Die Python Console wird geöffnet und man kann mit der Eingabe der Befehle loslegen.

Bevor man eine der Funktionen ausführen kann, muss zunächst noch die Datei in der sich diese Funktion befindet importiert werden. Dies geschieht ganz einfach in dem man „from DATEI_NAME import *“ in die Konsole eingibt. Möchte man zum Beispiel die Funktion drive(…) ausführen, würde der Importbefehl folgendermaßen aussehen:

from robofunc import *. Zu beachten ist, dass der Arduino mit dem Funkmodul schon an den USB Anschluss angeschlossen und vom Computer erkannt wurde, da beim Importieren auch gleich der definierte Port geöffnet wird. Nun wurde die robofunc.py Datei importiert und ist dem Interpreter bekannt und alle darin enthaltenen Funktionen können nun direkt ausgeführt werden.

 

Häufige Fehlermeldungen:

1.

 

Wird die Fehlermeldung: „Windows Error 5, access denied“ ausgegeben, liegt das meistens daran, dass mehrere Prozesse gleichzeitig versuchen auf den seriellen Port zu zugreifen. Task Manager starten und den Prozess von Hand beenden sollte das Problem beheben. Danach die Python Console neu starten, da diese nun, nachdem der python.exe Prozess beendet wurde nicht mehr reagiert.

 2.

„Windows Error 2, not found“, bekommt man diese Fehlerausgabe zu Gesicht, wird der Arduino an dem definierten USB Port nicht erkannt. Ein- und ausstecken des Arduino Leonardo und ein Neustart der Python Console sollte das Problem in den meisten Fällen beheben. Wird dieser Fehler weiterhin ausgegeben sollte sichergestellt werden, dass der serielle Port richtig angegeben wurde.

Den Port kann man in der Datei functions.py anpassen.

 

Experimente:

 

Line Following:

Ein Teil des Roboter Experiments war es, dem Roboter beizubringen, einem vorgegebenen Weg folgen zu können, in diesem Fall einer schwarzen Linie. Dazu wurden mehrere Teststrecken angefertigt, die jeweils unterschiedliche Eigenschaften aufweisen:

- Two Lines: Teststrecke für erste Erfahrungen mit Hardware und Kommunikation

- Long path: Gerade Strecken mit rechtwinkligen Kurven/Streckenabschnitten

- Short path: Gerade Strecken mit rechtwinkligen und schrägen Streckenabschnitten

- Circle path: Kreisartige Strecke mit unterschiedlich starken Kurvenausprägungen

Zu Testzwecken wurden mehrere Programme geschrieben, die jeweils anders auf Änderungen der Sensordaten reagieren und es somit starke Schwankungen in der Effizienz der jeweiligen Programme auf den verschiedenen Strecken gibt.

Im Folgenden wird kurz näher auf die einzelnen Algorithmen/Programme eingegangen, diese befinden sich alle in der Datei roboxperiment.py.

1. Travel to Line:

def traveltoline(runs=1):  # Experiment #1: Let the robot travel between two markings [0]

Strecke: Two Lines

Das erste Programm ist im eigentlichen Sinne kein Line Following Programm, sondern diente allein dazu, erste Erfahrungen mit der zur Verfügung stehenden Hardware des Roboters zu machen. Der Roboter fährt bei dieser Funktion zwischen den zwei Linien hin und her.

Im Code auffallend sind die häufig verwendeten time.sleep(0.1) Anweisungen. Recht schnell wurde schon beim ersten Versuch  klar, dass der Roboter bei Sensorabfragen entweder gar nicht oder nur sehr unzuverlässig antwortet. Nach weiteren Tests erkannte man, dass Delays nötig sind um die Hardware zuverlässig anzusprechen. Dieser Umstand lässt sich so erklären, dass der Roboter bei vielen Befehlen erst interne Berechnungen abschließen muss, bevor dieser wieder ansprechbar ist und neue Befehle verarbeiten kann. Auch anzumerken ist die Tatsache, dass die Hardware es anscheinend nicht schafft, laufend Sensorwerte auszulesen und dabei zeitgleich mit Volllast die Motoren zu betreiben. (Unregelmäßiges Fahren und ‚zucken’ der Motoren) Aus diesem Grund wurde der Parameter ‚speed’ in der drive Funktion auf den Wert 80 heruntergeschraubt.

 

2. Walk the Line:

 

Strecken:

Circle Path:                                                 Long Path:                                         

Short Path:

Anmerkungen:

Es gibt drei Bodensensoren, sind alle auf der schwarzen Linie wird als Sensorwert ‚000’ zurückgegeben. Bei weisem Untergrund, also off the line, wird „111“ (HIGH) detektiert.

Sensorwert       Bedeutung (in Fahrtrichtung)

000   Komplett auf der Linie

111   Komplett außerhalb der Linie

011   Stark nach rechts abgedriftet (mit dem rechten und mittlerem Sensor nicht auf der Linie)

001   Nach rechts abgedriftet (mit dem rechten Sensor nicht auf der Linie)

100   Nach links abgedriftet (mit dem linken Sensor nicht auf der Linie)

110   Stark nach links abgedriftet (mit dem linken und mittlerem Sensor nicht auf der Linie)

Geht der Roboter in einen neuen Zustand über und ist dabei auf die neuen Umstände zu reagieren, leuchtet solange bis die Korrektur/Änderung abgeschlossen ist und die Fahrt wieder aufgenommen wird die blaue LED.

Als Endmarkierung wurde rotes Isolierband über die schwarze Linienmarkierung geklebt. Dies hat einen Bodensensoranalogwert von 280 – 480 zur Folge.

Da es auch Fälle gibt, in denen dieser Wert auch detektiert wird, ohne das die Endmarkierung wirklich erreicht wurde, muss dieser Wert mindestens zwei mal detektiert werden um in den Zielzustand über zu gehen.

Wird in den Zielzustand übergegangen, blink die blaue LED sechs mal schnell auf und in der Python Console werden ermittelte Streckenwerte ausgegeben.

 

def walktheline():  # Experiment #2: Let the robot travel on the line [1]         

Hier beginnt das eigentliche Line Following Experiment. Das erste Programm ist in seiner Ausführung noch sehr undynamisch. Es werden die Bodensensoren ausgelesen und sobald der Roboter zu stark in eine Richtung abweicht und die Linie verlässt stoppt der Roboter und je nach Fall wird die Ausrichtung und Fahrtrichtung korrigiert. Kommt der Roboter so stark von der Strecke ab, dass von den drei vorhandenen Bodensensoren gleich zwei Sensoren auf HIGH stehen (off the line) wird stärker in die Gegenrichtung entgegengelenkt, als wenn nur ein Sensor von der Linie runter gefahren ist. Dabei wird jeder Fall explizit unterschieden und ggf. mit einem fixen Winkelwert entgegengelenkt bzw. korrigiert. Nachteilig bei dieser Methode
ist auch die Tatsache, das öfter gestoppt und korrigiert werden muss, bis die gewünschte Fahrtrichtung wiederhergestellt wurde.

Fährt der Roboter auf einmal komplett von der Linie ist das ein Zeichen dafür, dass die Linie abrupt endet und hier eine andere Richtung eingeschlagen werden muss. Der Algorithmus geht hier nach dem Ausschlussverfahren vor. Endet die Linie, muss um 90° gedreht werden. Die Sensorwerte werden erneut ausgelesen. Sind alle Sensoren wieder auf der Linie, kann die Fahrt wieder aufgenommen werden. Befinden sich die Sensoren jedoch immer noch außerhalb der Linie, wird um 180° gedreht. Hier muss es nun weitergehen, da man die Richtung aus der man gekommen ist, als fortführenden Weg ausschließen kann, die Richtung, wegen der man als erstes gestoppt hat ebenfalls und die Richtung in die man um 90° gedreht hat um nach einem neuen Weg zu suchen sich auch als Sackgasse erwies. Nach dem Ausschlussverfahren kann es also nur noch in eine Richtung weitergehen, da bei rechtwinkligen Streckenverläufen es nur vier mögliche Bewegungsrichtungen gibt.

Auf den folgenden Animationen ist der walktheline() Algorithmus auf den verschiedenen Strecken zu sehen. Zusätzlich können noch Werte wie Drehungen, Stops, Anzahl der Nachkorrekturen und die verstrichene Zeit des Roboters auf der Strecke verglichen werden.

Circle Path:             

Short Path:

Long Path:

 

def walktheline_ex():  # Experiment #2: Let the robot travel on the line [2] [UNIVERSAL ALGORITHM]

Der walktheline_ex() Algorithmus ist universell anwendbar, d.h. auf kurvenartigen und rechtwinkligen und geraden Streckenverläufen. Falls der Weg, der gerade beschritten wird plötzlich endet (auf geraden und rechtwinkligen Strecken), wird nach dem gleichen Muster verfahren wie im vorherigen Algorithmus (Ausschlussverfahren). Die entscheidende Verbesserung jedoch ist, dass der Ablauf wesentlich dynamischer realisiert wurde. Kommt der Roboter seitlich von der Linie ab, wird dies detektiert und so lange in die Gegenrichtung gedreht bis alle Sensoren wieder komplett auf der Linie sind. Im Vergleich zum vorherigen Algorithmus gibt es also keine komplette Fallunterscheidung mehr und auch die fixen Winkel für das nachkorrigieren wurden durch das dynamische Verfahren ersetzt.

Circle Path:

Short Path:

Long Path:

 

3. Travel on the Circle:

def walkthecircle():  # Experiment #3: Let the robot travel on the circle [1]

Dieser Algorithmus ist nur für kurvenartige/kreisartige Streckenverläufe ausgelegt. Ursprünglich sollte dieses Programm dazu dienen erste Versuche auf nicht geraden Strecken zu absolvieren. Dieser Code beinhaltet wie der walktheline() Algorithmus nur eine Korrektur mit fixem Winkel und eine vollständigen Fallunterscheidung. Kommt der Roboter also von der Linie ab, wird abhängig davon wie viele Sensoren beim letzen Sensorencheck auf HIGH waren nach vorgegebenem fixen Winkelwert stärker oder schwächer entgegengelenkt.

Circle Path:

 

 

def walkthecircle_ex():  # Experiment #3: Let the robot travel on the circle [2]

Dieser Algorithmus ist im Gegensatz zum vorherigen Code wieder dynamischer in seiner Fahrtrichtungskorrektur ausgelegt. Zu vergleichen mit dem Code walktheline_ex() wird hier im Falle eines Abkommens von der Linie so lange in die andere Richtung entgegengedreht, bis alle Sensoren wieder auf der Linie sind. Dieses Programm ist ebenfalls wieder nur für kurven-/kreisartige Streckenverläufe ausgelegt.

 

Maze Solving:

 

Simple Wall Following:

def solvethemaze():  # Experiment #3: Let the robot solve the maze [1] [Simple Wall Following Algorithm]

Dieser Algorithmus ist der erste Versuch den Roboter auf eine labyrinthartige Umgebung reagieren zu lassen. Im Gegensatz zu den Line Following Experimenten wird hier mit den Analogwerten der Sensoren gearbeitet und nicht mit den HIGH und LOW Binärwerten, die durch die eingestellten Schwellenwerte zustande kommen.

Sensoren (in Fahrtrichtung):

Dieses Programm ist im Prinzip sehr simpel. Man legt wie in diesem Code z.B. die rechte Hand bzw. den rechten Sensor an die Wand und tastet sich fortlaufend an dem Hindernis entlang. In der Theorie findet man so, unter der Voraussetzung, dass das Labyrinth zusammenhängend ist den Ausgangspunkt, oder falls nicht vorhanden wieder zum Startpunkt zurück. Kommt der Roboter zu weit von der Wand ab, wird in die Gegenrichtung nachgedreht und wieder Richtung Wand gefahren bis die Sensoren den Gegenstand wieder „ertasten“ können. Kommt der Roboter der Wand zu nah oder berührt sie sogar, wird dem ebenfalls mit einer Drehung dynamisch in Gegenrichtung entgegengewirkt, bis die Sensoren wieder akzeptable analog Abstandswerte liefern. Stößt man frontal an ein Hindernis, wird um 90° nach links gedreht, damit der rechte Sensor immer an der Wand bleibt.

 

Pledge Algorithmus:

def solvethemaze_ex():  # Experiment #3: Let the robot solve the maze [2] [Pledge Algorithm]

Wie bereits erwähnt funktioniert der gerade beschriebene, einfache Wall Following Algorithmus nur bei zusammenhängenden Umgebungen. Würde der Roboter an ein Hindernis geraten, das nicht mit dem Rest des Labyrinths zusammenhängt, würde dieser sich fortlaufend and dessen Wand entlang tasten und in einer Endlosschleife gefangen sein. Abhilfe soll eine Erweiterung des Wall Following Algorithmus schaffen, der Pledge Algorithmus.

Bei diesem Algorithmus werden die Rechts- und Linksdrehungen gezählt.

Hier wurde einfach bei jeder Linksdrehung die variable obstacle_control_count dekrementiert und bei jeder Rechtsdrehung inkrementiert. Zu Beginn wird der Wert dieser Variable mit Null initialisiert, dies entspricht also der Fahrtrichtung, die zu Anfang eingeschlagen wurde. Der Roboter tastet sich nun so lange mit seiner rechten Seite am Gegenstand entlang, bis die Ausgangsfahrtrichtung wieder erreicht wurde (also die variable obstacle_control_count wieder gleich Null ist). Ist dies der Fall, hat der Roboter das Hindernis umfahren und kann dieses „loslassen“. (Im Code: release_obstacle = 1). Der Roboter verlässt jetzt also dieses Hindernis und fährt solange geradeaus, bis er frontal wieder an ein neues Hindernis stößt, das der Roboter zu umfahren versucht. Auf diese Weise kann der Roboter den Endlosschleifen, wie sie beim einfachen Wall Following Algorithmus bei nicht zusammenhängenden Hindernissen auftreten können entgehen.

Testen Kann man die Funktionalität dieses Algorithmus z.B. indem man eine G-förmige Testumgebung baut und den Roboter diese lösen lässt. Der Wall Following Algorithmus wird ewig an diesem Hindernis hängen bleiben und sich fortlaufend entlang tasten, wohingegen der Pledge Algorithmus die G-Strecke einmal abfährt und sich sobald der Roboter sich wieder in gleicher Fahrtrichtung wie zu Anfang befindet von dem besagten Hindernis löst. (siehe Grafik)

Visuelle Darstellung der Zähl- und Funktionsweise des Pledge Algorithmus

 

Strecke: Small G-Maze

Nachdem die Funktionalität des Algorithmus festgestellt wurde, können nun weitere Tests in komplexeren Umgebungen angegangen werden.

Es folgt nun ein kleiner Vergleich der beiden vorgestellten Maze Solving Programme in der großen labyrinthartigen Umgebung. (Grüne Fläche = Start | Rote Fläche = Ziel)

 

Das aufgebaute Labyrinth:

 

Wall Following Algorithmus:

 

Pledge Algorithmus:

Man erkennt deutlich den Unterschied zwischen den beiden Algorithmen. Anzumerken ist, dass je nachdem wo die Zielmarkierung positioniert wurde (oder wie der Roboter zu Anfang ausgerichtet wurde), sich das „Abkürzen“ des Pledge Algorithmus auch negativ auf die Effizienz auswirken kann. In diesem Beispiel jedoch kommt uns dieser Umstand sehr entgegen.

 

Pledge Algorithmus in Aktion:


Siehe Anhang...

 

 

 

 

 

 

 

Anhänge:
Diese Datei herunterladen (ldvbot_experiment_big maze_pledge.gif)Pledge Algoritmus in Aktion[Pledge Algorithmus im Labyrinth]%2015-%04-%30 %1:%Apr%+02:00