Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektewise19:rugbotpublic:start

Rugbot Roby

Einleitung

Wir möchten ein Rugbyspiel in der TUB veranstalten. Allerdings mit zwei Robotern, die gegeneinander spielen. Unser Ziel war es also zwei fahrbare Roboter zu bauen, die per Bluetooth vom Rechner gesteuert werden. Doch damit die Roboter nicht ziellos durch die Gegend fahren, müssen sie wissen, wo der Ball und sie selbst sind.
Als Spielfeld verwenden wir einen umgedrehten Tisch aus dem Labor. Um die Positionen der Roboter und des Balls zu bestimmen, wird eine Kamera über dem Spielfeld angebracht, die die Objekte anhand ihrer Farbe beziehungsweise farbigen Markierungen auf den Robotern erkennt. Die Roboter können auf zwei Wege gesteuert werden: vom Computer, der anhand des Kamerabildes die Roboter- und Ballpositionen erkennt und den richtigen Fahrweg berechnet, oder von einem Menschen über die Computertastatur. Die Befehle werden als W,A,S,D (Vorwärts, Links, Rückwärts, Rechts) per Bluetooth an den Arduino gesendet.

Ähnliche Projekte:

Umsetzung

Roboter

Die Roboter selbst bestehen je aus:

Bauteil Anzahl
Arduino Nano 1
Steppermotor2
Pololu DRV8824 Treiber2
Kondensator 100μF1
Bluetooth Modul HC051
Lithium-Ionen Akku (~7,4V)1

die alle über ein Breadboard verbunden sind.

Abbildung 1: Fritzing Zeichnung

Die Steppermotoren sind im Zusammenhang mit den Treibern öfter warm geworden, funktionieren jedoch gut. Wir haben sie aufgrund ihrer Stärke und relativen Genauigkeit gewählt. Der Nachteil ist, dass sie langsam sind. Die Wahl der anderen Bauteile hat sich vor allem nach dieser Entscheidung gerichtet.
Abgesehen von den zwei großen Antriebsrädern, die an den Steppermotoren befestigt sind, befindet sich hinten, auf der Unterseite der Roboter, eine kleine frei bewegliche Rolle, sodass es an genau drei Punkten Bodenkontakt gibt. Da sich die Antriebsräder genau mittig befinden, müssen die Roboter hinten schwerer sein, als vorne. Da sich die Lithiumakkumulatoren welche eine Spannung von rund 7,4 V liefern, hinten befinden ist das kein Problem. Die Karosserie ist rund, damit die Roboter sich nicht ineinander oder an der Wand verhängen. Um einen möglichst wendigen Roboter zu haben, verwenden wir zwei Räder und ein Stützrad. An der Vorderseite ist eine Einbuchtung um den Ball zu schieben. Auf der Oberseite ist ein grünes Quadrat, um den Drehwinkel des Roboters zu bestimmen. Weiterhin ist die Karosserie möglichst klein, damit die Roboter auf das Feld passen. Das Bluetooth-Modul HC-05 bereitete uns, bis auf die Tatsache, dass lange nur eins funktioniert hat, keine Probleme. Der Arduino war leider ein recht fehleranfälliges Bauteil. Häufiger sind sie aus verschiedenen Gründen durchgebrannt. Die Rechenkraft reicht aus. Die Treiber bereiteten ebenfalls Probleme. Häufig sind sie, weil wir die Stromstärk zu hoch eingestellt hatten oder aus anderen uns unbekannten Gründen, zu heiß geworden. Zwei bestellte Treiber (Pololu DRV 8824) funktionieren bisher einwandfrei. Den Kondensator haben wir eingebaut, damit die Stepper besser laufen. Er liefert bei dem plötzlich steigendem Stromverbrauch der Stepper schneller Leistung, als der Akku.

Abbildung 2: Rugby auseinander genommen
Abbildung 3: Rugby, gut zu erkennen das grüne Quadrat über der Vorderseite
Abbildung 4: frei bewegliche Rolle

Greiffunktion

In der letzten Phase unserer Arbeit kam die Idee auf den ganzen Spielablauf dadurch zu vereinfachen, dass wir dem autonomen Roboter die Möglichkeit geben den Ball festzuhalten. Hierfür befestigten wir einen kleinen Holzarm an einem Servomotor auf der Vorderseite des Roboters und implementierten die Verwendung dieses Werkzeuges sowohl in der Pythondatei als auch in dem Arduinoprogramm. Der Roboter sollte den Servomotor dann bewegen und somit den Ball „greifen“ sobald dieser in einem bestimmten Radius zum Roboter war. Dies funktionierte zwar teilweise gut, jedoch gab es Situationen, in denen der Mechanismus versagte, die wir nicht umgehen konnten. Auch um einen unfairen Kampf der Roboter zu verhindern entschieden wir uns schließlich den autonomen Roboter mit zwei unbeweglichen Metallwinkeln eine Art Halterung zu geben, sodass der Roboter den Ball besser fixieren und über das Spielfeld bewegen kann.

Abbildung 5: Servomotor mit Holzarm
Abbildung 6: unbewegliche Metallwinkel

Peripherie

Die Kamera ist eine beliebige Farb-Webcam. Theoretisch könnte man auch seinen Laptop übers Spielfeld halten. Das Spielfeld ist ein umgedrehter Tisch, an dessen Tischbein mit einer Kran-ähnlichen Konstruktion die Kamera befestigt ist. Dabei musste die Höhe genau bestimmt werden. Weiterhin war der Farbunterschied zwischen Tischtennisball und Tischinnenseite zu gering, weswegen diese weiß abgeklebt werden musste.

Abbildung 7: Das Spielfeld


Software

Die Software auf dem Arduino besteht vor allem aus einer selbst geschriebenen Libary, die für die einzelnen Befehle W,A,S,D die Bewegung ausführt. Dabei werden die entsprechenden Output Pins (hier D6, D5, D4) angesteuert. Der Step-Pin (D6) wird abwechselnd mit einem delay von 25000 µs auf High/Low gesetzt. Die Anzahl ans Steps, die nach jeder Bewegungsaufforderung, die der Arduino per Bluetooth bekommt, kann manuell angepasst werden. Sie sollte nicht zu klein gewählt werden, da die Stepper sonst anfangen zu zucken und die Bewegung sehr abgehackt wird. Wird sie hingegen zu groß gewählt kommt es zu Verzögerungen und der Roboter reagiert nicht mehr schnell genug, fährt also über Ziele hinaus. Wir haben uns für 20 Steps je Befehl geeinigt und dies mit Hilfe einer Vorschleife umgesetzt.
Eine Besonderheit unserer Schaltung und Steuerung ist es, dass wir nur über einen Step-Pin verfügen, was bedeutet, dass beide Motoren immer parallel einen Schritt machen. Mit den beiden anderen Pins (D4 und D5) kann die Richtung, in der die Steppermotoren den Schritt machen entschieden werden. Daraus ergeben sich vier mögliche Bewegungen: vorwärtsfahren (W), rückwärtsfahren (S), sich auf der Stelle nach links drehen (A) und sich auf der Stelle nach rechts drehen (D), wobei der autonome Roboter nicht rückwärtsfährt, sondern sich immer in die jeweilige Richtung ausrichtet und dann vorwärtsfährt.

Die Verbindung über Bluetooth mit dem Computer ist seriell. Wir verwenden die Funktion Serial.available() um die Signale, die der Arduino über das Bluetoothmodul empfängt, auszulesen. Wichtig ist es am Ende des Loops die Liste der Empfangenen Daten zu löschen, da der Arduino alle empfangenen Signale nacheinander abarbeitet und es somit zu einem „Datenstau“ kommen kann. Hierfür verwenden wir while(Serial.available() >0){ Serial.read()};.

Für die oben erwähnte Greiffunktion haben wir ebenfalls eine Version geschrieben, in der noch zusätlich die Befehle „G“ für „grap“ und „U“ für „up“ empfangen werden können, die dann den Servomotor steuern können, wofür wir die Servo-Library verwenden.

Python In dieser Sprache sind die eigentlichen Spielzüge programmiert. Wir entschieden uns für diese Programmiersprache, da wir in ihr die OpenCV-Bibilothek für Python verwenden konnten (eigentlich in C/C++ geschrieben). OpenCV ist eine öffentlich zugängliche Bildverarbeitungssoftware, die wir an unsere Bedürfnisse angepasst haben.

OpenCV erkennt die Kreise, die die Roboter bilden sowie das grüne Rechteck auf dem autonomen Roboter, sowie den Ball. Diese Punkte werden in X/Y-Koordinaten angegeben. Aus den Koordinaten berechnet der Computer den Winkel zwischen Robotermitte und grünem Quadrat, sowie den Winkel zwischen Ball und Roboter und bildet die Differenz. Mehr dazu unter dem Punkt Winkelberechnung. Somit sind alle notwendigen Größen zur Wegberechnung bekannt. Zur besseren Anschaulichkeit werden die genannten Objekte farbig auf dem Kamerabild nachgezogen.

Abbildung 8: Das Kamerabild

Damit OpenCV funktioniert haben wir NumPy installiert. NumPy wandelt die Aufnahmen der Kamera in mehrdimensionale Array um, in denen die Informationen zu Farbton, Helligkeit und Sättigung gespeichert werden. Wenn ihr mehr über die Objekterkennung lernen möchtet, könnt ihr euch sehr ausführlichen Dokumentationen aus den letzen Jahren durchlesen, die das Thema allgemeiner beschreiben: CATcher, Rembarntpublic, eine Doktorarbeit von Andreas Cobet

Wir haben zwei verschiedene Versionen des Pythonprogramms. Die Erste ist um einiges komplexer als die Zweite, jedoch weist sie einige Defizite auf und funktioniert nicht einwandfrei. Da wir nicht die Zeit hatten diese Probleme in angemessener Weise zu lösen, haben wir eine zweite, vereinfachte Version entworfen. Wir haben beschlossen euch beide zur Verfügung zu stellen und zu erläutern, da evtl. beide für euch hilfreich sein könnten. Die Abschnitte Spielablauf und Kalibrierung beziehen sich nur auf die komplexere Version, haben es also leider nicht in unser vorläufiges Endprodukt geschafft.

Das erste Pythonprogramm gliedert sich in Folgende Abschnitte:

  1. Setup
    1. Librarys
    2. Variabeln
    3. Bilderkennung
    4. Bluetoothverbindung
  2. Hauptloop
    1. Bilderkennung
    2. Kalibrierung
    3. Steuerung des Autonomen Roboters
      1. Spieldaten
      2. Spielsituationen
      3. Zielpunkte
      4. Ansteuerung der Zielpunkte
      5. Spielende
    4. Steuerung des nicht autonomen Roboters
    5. Ende und Neustart

Das zweite Pythonprogramm funktioniert einwandfrei und schafft glücklicherweise oft sogar mehr, als wir ursprünglich mit dieser Version erreichen wollten.

Winkelberechnung

Die folgende Abbildung zeigt das Spielfeld aus der Sicht des Computers mit den berechneten Winkeln. Der Computer berechnet mit math.atan2 die gezeigten Winkel. Dafür wird durch Subtraktion der X/Y-Koordinaten die Kathetenlängen berechnet (siehe zum Beispiel math.atan2 (Ball Y - Mittelpunkt Y , Ball X - Mittelpunkt X) ). Die Ergebnisse dieser Berechnung liegen immer zwischen -2π und +2π. Die gepunktete Linie ist dabei imaginär und parallel zur X-Achse. Die beiden Winkel werden verglichen und anhand des Ergebnisses die entsprechenden Richtungsbefehle ausgesendet.

Abbildung 9: Die Winkelberechnung

Wie oben erwähnt erfolgt die Winkelberechnung in Python mit der Funktion math.atan2() aus der Math Bibilothek für Python. Dabei ist anzumerken, dass wir eine gewisse Toleranz eingebaut haben. Solange der Roboter eine gewisse Entfernung zum Ball hat, wird der Befehl „Vorwärts“ auch gesendet, wenn der Winkel zwischen Roboter und Ball um +-10° abweicht. Der Roboter kann sich nicht immer 100% genau ausrichten und diese Toleranz verhindert, dass er sich nur ausrichtet und nicht vorwärts fährt.
Je nach dem, was die persönliche Präferenz ist, kann man mit der Funktion math.degrees() Bogen- in Gradmaß umwandeln. Andersherum aber auch mit math.radians() Grad- in Bogemaß.

Spielablauf

Der Spielablauf besteht vor allem aus mehreren Fallunterscheidungen. Mit mehreren if- und elseIf-Bedingungen wird überprüft, in welcher Position der Roboter sich zum Ball befindet. Dabei ist vor allem wichtig, ob der Ball vom Tor aus gesehen vor oder hinter dem Roboter ist, denn im nächsten Schritt wird eine Zielposition für den Roboter festgelegt. Befindet sich Roby (der autonome Roboter) zum Beispiel zwischen Ball und Zieltor würde er, wenn er den Ball direkt anfährt, ins eigene Tor schießen. Stattdessen muss er einmal „hinter“ den Ball, damit der Ball auch im richtigen Tor landet. Die Grafik beschreibt unser Lösung dabei am besten.

Abbildung 10: verschiedene Spielbedingungen

Wenn die konkrete Situation erkannt wurde, werden die entsprechenden Befehle (Vorwärts, Links , Rechts) gesendet. Dabei werden zu keinem Zeitpunkt Daten oder Befehle, die die Spielsituationen betreffen, gespeichert, da die Berechnung immer live erfolgt. Befindet sich der Ball am Spielfeldrand, so fährt Roby zuerst hinter den Ball nahe an den Rand, richtet sich dann aus und schiebt den Ball parallel zur Wand in das Tor. Somit soll verhindert werden, dass der Roboter den Ball einfach an die Wand drückt.

Abbildung 11: verschiedene Fahrwege

Da das Programm mit dieser Version leider nicht funktionsfähig ist, haben wir eine vereinfachte Form bei unserer Vorführung verwendet, die wie folgt funktioniert:
Es gibt zwei Fallunterscheidungen. Ist der Ball am Roboter oder weiter entfernt?

  1. Der Ball ist weiter entfernt: Es wird die oben erwähnte Toleranz mit einbezogen und die Winkel werden verglichen. Stimmen die Winkel bis auf die Toleranz überein, wird „vorwärts“ gesendet. Ansonsten entsprechend „rechts“ oder „links“. Somit steuert der Roboter den Ball an.
  2. Der Ball ist am Roboter: Es gibt keine Toleranz mehr, damit sich der Roboter genau auf das Tor ausrichtet. Nun werden die Winkel zwischen Roboter und Tor auf gleiche Weise verglichen. Somit schiebt der Roboter den Ball in das richtige Tor.

Kalibrierung

Da der autonome Roboter mit Spielsituationen, bei denen sich der Ball am Rand befindet umgehen soll, muss dessen Position bekannt sein. Da sich die Kamera bei Auf- und Abbau des Spielfeldes leicht bewegt, ist es nicht möglich feste Koordinaten einzustellen. Deshalb haben wir eine Kalibrierungsfunktion eingebaut. Bei jedem Spielbeginn wird der Spieler, nach Auswahl der Bluetoothmodule, dazu aufgefordert den Ball erst auf die Spielfeldecke unten links zu platzieren und Enter zu drücken. Das selbe wird dann mit der Ecke oben rechts wiederholt. An den jeweiligen Stellen ist eine Unterlegscheibe befestigt, sodass der Ball nicht wegrollt. Das Pythonprogramm kann nun die Koordinaten des Balls auslesen und diese als Spielecken festlegen. Mit der Funktion cv2.rectangle(frame,(spielbereich_x_min,spielbereich_y_min),(spielbereich_x_max,spielbereich_y_max),(0,255,255), 1) können wir dies auch bildlich darstellen. Diese Funktion findet leider keine Anwendung in der vereinfachten Pythonversion.

Abbildung 12: Unterlegscheibe auf den Spielfeldecken
Abbildung 13: Ball liegt auf Spielfeldecke

Unser Code

In der Folgenden Zip-Datei findet ihr den von uns erarbeiteten Code mit den verschiedenen Versionen:

Rugbot Roby

Projektergebnis

Schwierigkeiten und Probleme

Wir waren mit vier Personen eine relativ große Gruppe, was an sich viele Vor-, aber auch Nachteile mit sich bringt. Einerseits verfügt man über mehr Knowhow und kann sich die einzelnen Aufgabenbereiche, je nach Stärken und Interessen der Personen, besser aufteilen. Andererseits erhöht sich so auch der organisatorische Aufwand, terminliche Probleme entstehen und es wird viel aneinander vorbeigearbeitet. Leider musste ein Teilnehmer die Projektarbeit vorzeitig beenden.

Wir hatten einen relativ straffen Zeitplan, der vor allem durch die Fehleranfälligkeit unserer Hardware, insbesondere der Stepperdriver, nicht eingehalten werden konnte. Im Nachhinein fällt es einem oft leicht die Schwachstelle der Projektplanung zu erkennen. Besonders den Zeitaufwand für die Erarbeitung des Spielablaufes und für das anschließende Testen des Ganzen haben wir unterschätzt. Wir haben gelernt, dass zum Ende einer Projektphase mehr Zeit für unvorhergesehenen Aufgaben und Probleme eingeplant werden sollte.

In unserem Arbeitsprozess haben wir häufig verschiedene Lösungen für Aufgaben entwickelt, von denen wir nicht alle bis zum Ende beibehalten haben. Beispielsweise hatten wir ursprünglich vor die Bilderkennung mit Processing zu verbinden, um dort das Geschehen auf dem Spielfeld zu simulieren und eine ansprechende Benutzeroberfläche zu gestalten. Schnell haben wir diesen Plan verworfen und die Bilderkennung in Python implementiert, da uns dies deutlich praktikabler erschien.

Erst relativ spät haben wir uns hingegen entschieden, die Verarbeitung der Bilddaten und die Berechnung der Bewegung des Roboters nicht auf dem Arduino, sondern in dem Pythonprogramm auf den Laptop durchzuführen, da dieser hierbei deutlich schneller ist und Python eine bessere Grundlage für mathematische Berechnungen bietet.

Ein großes Hindernis war ebenfalls, dass wir zwar vier Laptops zur Verfügung hatten, einer davon jedoch kein Bluetooth hatte und es bei einem weiteren lange nicht möglich war, alle für unser Programm nötigen Libraries zu installieren, sodass wir des Öfteren höchstens einen Laptop hatten, auf dem wir die Programme auch wirklich testen konnten.

Endergebnis

Bis zum Ende unserer Projektphase habe wir es leider nicht geschafft alles umzusetzen, was wir uns vorgenommen haben.

Was wir erreicht haben:

  • ein praktisches und funktionierendes Spielfeld mit Markierungen und Kameraarm
  • zwei (meistens) funktionstüchtige Roboter (R.)
  • stabile Bilderkennung des Balls und eines R.
  • funktionierende Bluetooth-Verbindung mit einem R.
  • der R. kann mit einer einfacheren Variante des Codes den Ball (fast) immer ins Ziel bringen

Was wir gerne noch geschafft hätten:

  • Funktionsfähigkeit der erweiterten Python-Version (mit Analyse der Spielsituationen)
  • Steuerung des zweiten R. durch einen Spieler
  • Möglichkeit, dass beide R. autonom gegeneinander spielen
  • angenehme Spieloberfläche und evtl. Geräuschkulisse am Laptop

Ausblick

Bei einer möglichen Weiterentwicklung wäre unser erstes Ziel die Bilderkennung für zwei Roboter gleichzeitig anzupassen, sodass zwei Roboter autonom gegeneinander Spielen können. Aufgrund der knappen Zeit konnten wir diese Funktion bisher nicht implementieren. Außerdem könnten wir speziell die Spielsteuerung verbessern. Hierzu haben wir bereits wie erwähnt eine zweite Programmversion entworfen, jedoch noch nicht komplett fertig entwickelt. Diese Version könnte ein verbessertes Spielverhalten liefern und Funktionen wie zum Beispiel rückwärtsfahren einbauen.
Zusätzlich könnte eine andere Auswahl an Bauteilen, wie anderen Motoren, die Zuverlässigkeit erhöhen. Nicht notwendig aber optisch schöner wäre eine rundum Verkleidung der Roboter aus Pappe oder als 3D Druck, wobei auf eine mögliche Überhitzung insbesondere der Motoren geachtet werden müsste. Weiterhin wäre die oben erwähnte Geräuschkulisse umsetzbar.

Weiterführende Informationen

projektewise19/rugbotpublic/start.txt · Zuletzt geändert: 2020/04/07 14:03 von d.golovko