RoboCup 2014: Überarbeiteter Roboter Teil 2: Software

Nachdem die Hardware überarbeitet wird, wird natürlich (zwangsläufig?) auch die Software aktualisiert und verbessert. Zum Glück können wir da noch Einiges im alten Roboter machen und müssen nicht auf die Fertigstellung des neuen Roboters warten. Im Folgenden listen wir alle Ziele dieser Saison auf.
Achtung, alles sehr schwierig in wenig Worten zu erklären, weshalb das wahrscheinlich nicht für alle sofort verständlich sein wird :(

Zur Hilfe und vielleicht zum Verständnis deshalb hier die aktuellen Regeln (englisch).

 

Boot

Boot: Logo, Versionsanzeige, Status (Kalibrierung der IMU) und die Resetquelle (ResSRC); in diesem Fall PORF, also Power-On-Reset-Flag. Hier wird angezeigt, ob der Roboter zuletzt normal ausgeschaltet wurde, die Batterie zu leer war oder ob ein anderer Reset ausgelöst wurde.

  1. [Erledigt] Verbesserung des User Interfaces
    Für ein vernünftiges Debugging Menü hatten wir bis jetzt keine Zeit, lediglich die Temperaturwerte ließen sich am Display ausgeben und die Schwellwerte über eine Variable einstellen. Wenn man nun beim Start des Roboters die Enter Taste gedrückt hält, kommt man ins Setup- und Debuggingmenü:

    Setup- und Debuggingmenü. Der Pfeil zeigt an, was gerade geändert werden kann, wird auch noch einmal durch die beiden Nullen unten links angezeigt.

    Oben sieht man immer noch die Statusleiste (die wird immer angezeigt, die hatten wir auch schon immer vorher), in der Fehlermeldung, Informationen etc. angezeigt werden. Darunter dann die Menüeinträge:

    IR links [Ist-Wert] [Schwellwert] Einstellen des Schwellwerts für diesen Temperatursensor. Wert wird nach Änderung im EEPROM des Mikrocontrollers gespeichert und bleibt deshalb auch nach Neustart bestehen.
    IR rechts [Ist-Wert] [Schwellwert] ––––––––––––––––––––––––“––––––––––––––––––––––––––––
    Tarry [Ist-Wert] Wird der Algorithmus zum Abfahren des Labyrinth genutzt oder wird die rechte Hand Regel angewandt? Wird auch im EEPROM gespeichert.
    View Hier werden alle Sensorwerte auf einem Bildschirm dargestellt. Besonders die Entfernungssensoren lassen sich so gut darstellen und debuggen.
    ok Setup beenden
  2. View

    View: Darstellung aller Sensoren, in der Mitte der Roboter und die Entfernungssensoren als Striche

    [Erledigt] Speicherung der Karte
    Das war ein relativ großes Problem bei den deutschen Meisterschaften. Um Arbeitsspeicher zu sparen, war das Array, in dem die Karte gespeichert wurde, nur so groß, wie es sein musste. Die Startposition des Roboters mussten wir deshalb auch manuell einstellen. Das ist dann ein Problem, wenn der Roboter auf einmal im Labyrinth neu starten sollte oder mitten im Labyrinth gestartet werden sollte (theoretisch nach neuen Regeln möglich). Wir haben uns darüber recht viele Gedanken gemacht (dynamische Arrays, Verschiebung des Arrayinhalts etc.), aber nichts ist so unkompliziert, wie ein simpler offset: Sobald der Roboter vom Rand des Speichers fährt, wird eine Variable hochgezählt und es wird am anderen Speicherrand weitergemacht. Bei der Darstellung wird dieser Offset einfach aufaddiert und die Karte entsprechend zurück verschoben. Das Ganze braucht insgesamt ca. 50 Zeilen Code.

  3. [Erledigt] Darstellung der Karte
    Bei großen Labyrinthen braucht man einen großen Speicher. Bis jetzt haben wir immer den gesamten Speicher auf dem Display dargestellt. Das Display beansprucht die meiste Zeit des Programmdurchlaufs (Programmdurchlauf: bei normaler Größe des Labyrinths, d.h. 10x5x2 Fliesen ca. 12ms, Display 8ms), davon wiederum die Darstellung der Karte das meiste (ca. 5ms). Bei größerer Karte, wenn zum Beispiel zwei Räume in beide Richtungen nebeneinander liegen, die Karte also 10x10x2 Fliesen groß ist, beansprucht das Display weitere 5ms (es muss ja jede Wand aus dem Array ausgelesen und dargestellt werden). Das ist nicht so schön, weshalb wir uns einen zweiten Darstellungsmodus für die Karte überlegt haben: Es werden immer nur die nächsten 4 Fliesen in jede Richtung um den Roboter dargestellt. So müssen nur 64 Fliesen, also 192 Wände und Untergründe (für die schwarzen Flächen) anstatt im schlimmsten Fall 600 Wände und Untergründe dargestellt werden. Somit brauchen wir für einen Hauptschleifendurchlauf nur noch 10ms.

    Hauptansicht: Kartenmodus 0. Man sieht den gesamten Speicher der unteren Etage (z-Position 0). Ganz rechts die Zeit für einen Schleifendurchlauf: 14ms.

    Kartenmodus 1: Hier wird ein Ausschnitt von 6 Fliesen um den Roboter angezeigt. Die Dauer eines Schleifendurchlaufs beträgt 2ms weniger. Das ist zwar nicht viel, aber es ist besser.

  4. [Erledigt] Watchdog
    Wir kommen nochmal auf das „immer vom schlimmsten Fall ausgehen zurück: Das allerschlimmste, was passieren könnte, ist, dass der Roboter sich aufhängt, warum also auch immer das Programm einfriert. Damit hatten wir letztes Jahr Probleme, haben es auch mit einem Watchdog gelöst. Ein Watchdog wird in der Hauptschleife immer wieder gesetzt. Wenn er aber eine definierte Zeit (bei uns 120ms) nicht gesetzt wird, das Programm also eingefroren ist, resetet sich der Roboter automatisch (hier kommt wieder Punkt 2: Der Roboter befindet sich dann sehr wahrscheinlich irgendwo im Labyrinth und hätte Probleme mit dem Speicher, wenn er losfahren würde). Jetzt wird so eine Situation erkannt und auch, nachdem der Roboter neugestartet ist, angezeigt. Dieser Status lässt sich in Zukunft vielleicht auch von anderen Teilen des Programmes erkennen und diese könnten dann in einen bestimmten Modus springen (vielleicht ja die Karte in Zukunft auf einer SD Speicherkarte speichern und ggf. wiederherstellen?).
  5. Schwarze Fliesen
    Zusammen mit dem neuen Sensor zur Erkennung der schwarzen Fliesen muss auch die Programmierung daran angepasst werden. Was genau wir da machen, wissen wir noch nicht, dazu dann wenn es so weit ist noch ein Artikel.
  6. Rampe
    Bis jetzt haben wir die Rampe ganz einfach über die Position des Roboters in der Karte erkannt. Das ist aber keine 100%ig saubere Lösung, wenn die Rampe an einer anderen Position ist, kann der Roboter sie nicht vernünftig fahren (Problem bei der Rampe ist, dass sie ein eigenes Unterprogramm zum Fahren braucht und nicht Fliesenweise abgefahren werden kann, da die Rampe ja geneigt ist und es deshalb unter Umständen Konflikte mit den Maßen der Karte geben kann). Deshalb muss die Rampe nun über den Neigungssensor der IMU erkannt werden und die Position der Rampe in der Karte gespeichert werden. Wo die Rampe in der oberen Etage aufhört spielt dank Punkt 2 keine Rolle mehr, lediglich die Position muss dann gespeichert werden.
  7. Lack of Progress, Eingriff
    Auch, wenn das nachher noch so unwahrscheinlich ist, muss das vorgesehen werden… Genau, immer vom schlimmsten Fall ausgehen. Der Roboter muss aufgrund des Navigationsalgorithmus’ Markierungen in der Karte machen. Wenn der Roboter nun irgendwo hängen bleiben sollte, stimmt die Position und somit die Markierungen nicht mehr mit dem Roboter überein, evtl. bleibt der Roboter dann stehen. Das gleiche passiert (aber dann beabsichtigt), wenn der Roboter das Labyrinth einmal komplett durchfahren hat. Nach den neuen Regeln muss er dann nur noch 5 Sekunden auf der Startplatte stehen bleiben, anstatt komplett. Das können wir ausnutzen, um das Programm neu zu starten bzw. die Karte „auszuradieren”. Wenn das Programm also richtig funktioniert und der Roboter normal am Eingang für 5 Sekunden stehen bleibt, ist der Wertungslauf beendet und es gibt den Punktebonus, wenn zuvor ein Fehler passiert ist, bleibt der Roboter irgendwo im Labyrinth stehen, wartet 5 Sekunden (oder etwas mehr) und fängt dann von vorne an (und hier kommt erneut Punkt 2 mit der dynamischen Karte, wenn der Roboter nämlich irgendwo mitten im Labyrinth stehen bleibt). Das Einzige, was dann passiert, ist, dass es eventuell nicht den Startbonus gibt.
    Wenn man das nicht möchte, kann man einen Eingriff machen. Das gibt einen Punktabzug, aber man darf dafür dem Roboter die neue Position mitteilen (dabei wird er auch an einen bestimmten Punkt zurückgesetzt). Dann stimmen natürlich trotzdem die bereits gespeicherten Markierungen für den Algorithmus, weshalb der Roboter quasi seinen Pfad speichern muss, damit er weiß, bis zu welchem Punkt die Markierungen zurückgesetzt bzw. nicht beachtet werden müssen.
  8. Update der I²C-Kommunikations Bibliothek
    Wir haben festgestellt, dass wir einen Bug in der Programmbibliothek zur Kommunikation mit den Wärmesensoren haben. Die Ursprungsbibliothek ist voll mit Schleifen, die auf ein Ereignis warten, also für unseren Roboter tötlich, wenn mal keine Antwort kommen soll. Deshalb wird in den Schleifen eine Variable hochgezählt und die Schleife abgebrochen, wenn ein Schwellwert erreicht wird. Ganz einfach. Leider funktioniert das noch nicht 100%ig und das gesamte I²C Modul des Mikrocontrollers schmiert ab, wenn abgebrochen wird, weshalb wir da noch etwas optimieren müssen.
  9. Hindernisumfahrung
    Last but not least das i-Tüpfelchen: Wenn noch genug Zeit bleibt (und ich bin mir sicher, es bleibt noch genug Zeit bis zum Wettbewerb), implementieren wir auch noch die Hindernisumfahrung. Laut Regeln kann es vorkommen, dass ein Hindernis im Parcours platziert wird. Ein Hindernis darf eine bestimmte Größe nicht überschreiten, hat jedoch eine Mindestgröße und darf jede beliebige Form haben. Es ist garantiert, dass neben dem Hindernis min. 30cm, also eine Fliese, Platz für den Roboter zur ungehinderten Wegfindung bleiben. Das Hindernis kann also so aussehen (hellblau, rote Wände erstmal unwichtig):

    Hindernis

    Parcours: Hellblau: Hindernis

    Man sieht also, dass das Hindernis in diesem beispiel 4 Fliesen belegt, aber um das Hindernis noch ein pfad zum Vorbeifahren bleibt. Unsere Idee ist es, den Roboter normal fahren zu lassen, wenn aber plötzlich ein Hindernis erkannt wird, er die bis dahin gefahrene Distanz zurückfährt und eine „virtuelle” Wand einzeichnet (rot). So sperrt er nach und nach das Gebiet mit dem Hindernis.

Das war es vorerst – sicherlich werden wir nach uns nach auf weitere kleine Probleme stoßen, die wir in die Programmierung einbauen müssen. Auch dazu dann ggf. mehr.

Der Termin für die German Open 2014 wurden übrigens schon bekanntgegeben: Vom 3. bis zum 5. April findet der Wettbewerb wieder in Magdeburg statt. Wann die Vorqualifikationen stattfinden, wurde allerdings noch nicht verkündet.