Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektewise1718:derbecherpublic:start

Dokumentation DerBecher

Die Fangkonstruktion
Abbildung 1: Die Fangkonstruktion

Einleitung


Unsere ursprüngliche Idee war es, einen Roboter zu bauen, der mit Hilfe eines Becher wie beim Bierpong den geworfenen Ball fängt. Allerdings stellte sich das als zu kompliziert heraus, weshalb wir uns für die Konstruktion mit Ring als fangendes Element entschieden haben. Einen entsprechenden Becher kann man in den Ring stellen. Unser grundsätzlicher Anspruch an den Roboter war es, dass dieser Kameraaufnahmen auswerten und so mit einem Objekt interagieren kann. Dies wurde durch unsere Projektidee erfüllt, da der Ball erfasst, seine Zielkoordinaten berechnet und der Roboter zur richtigen Position bewegt werden muss.

Die Wurfkurve des Balles wird dabei von zwei Kameras ermittelt und anschließend seine Zielkoordinaten ausgerechnet. Durch eine Achsenvorrichtung wird der fangende Ring an die richtige Position gebracht, so dass der Ball aufgefangen wird.

Dabei war unser Ziel, dass der Roboter die Daten lesen und auswerten muss, sowie den Ring auf der Konstruktion bewegen muss. Eine möglichst hohe Fangquote sollte auch erreicht werden, wobei aber das Problem besteht, dass die Drehleistung der Steppermotoren nicht für die benötigte Geschwindigkeit ausreicht.

Ähnliche Projekte: ähnlicher Aufbau der Fangkonstruktion beim xy-Core (3D-Drucker)

Überblick über das Gesamtsystem


Der Roboter besteht aus zwei großen Teilbereichen, die jeweils zur Lösung der Teilaufgaben dienen, dabei haben wir unsere Gruppe in zwei Teilgruppen geteilt.

Erfassung und Berechnung der Flugbahn und Datenkommunikation

Die Flugbahn des Balles wird durch zwei Kameras erfasst und mit einem selbstgeschriebenen Programm wird die Flugbahn und Zielkoordinaten im Fangbereich berechnet und dann über die serielle Kommunikation an die Fangmaschine übermittelt. Da die Software nicht vervollständigt werden konnte sind gibt es keine „Master“ Datei die alle Funktionen vereinigt.

Übersicht Aufbau
Abbildung 2: Übersicht Aufbau

Ringbewegung

Der fangende Ring wird durch eine gebaute Konstruktion zur richtigen Position bewegt.

Die Teilbereiche lassen sich in Informationserfassung und -verarbeitung (Software), mechanische Konstruktion (Mechanik und Elektronik) und anschließende Ringbewegung (Software und Mechanik) einteilen.

Einige Anforderungen haben wir schon früh verworfen, da sie unser Projekt deutlich verkompliziert hätten. Dazu gehört die zusätzliche Bewegung der Konstruktion im Raum, weil so der Fangbereich deutlich größer wäre und die Bewegung der gesamten Roboterkonstruktion zu lange dauern würde. Dazu käme, dass der Roboter dann Hindernissen im Raum ausweichen müsste, weswegen wir darauf verzichtet haben. Außerdem haben wir unsere ursprüngliche Idee eines Bechers als Fangobjekt verworfen, denn die Befestigung des Bechers auf der Konstruktion, sowie die zusätzliche Höhe des Bechers erhöht die mechanischen Anforderungen zusätzlich. Am Anfang hatten wir auch einen deutlich größeren Fangbereich eingeplant, da sich die Motoren aber zu langsam bewegen, haben wir diesen auf 60*60 cm eingegrenzt.

Detailbeschreibung der Systembestandteile


Berechnung der Flugbahn

Allgemein

Zur Erfassung/Berechnung der Flugbahn haben wir uns für die C++ Bibliothek OpenCv entschieden, da wir gehört hatten, dass OpenCv besonders gut in Live Berechnungen ist und wir gehofft hatten, unser C++ Wissen aus unserem Informatik Modul anwenden zu können. Kompiliert haben wir unsere Programme mit gcc und cmake und haben uns dabei an diese Tutorial gehalten. Um gut arbeiten zu können, empfehlen wir die aktuelle Dokumentation herunterzuladen. Als Kameras haben wir zwei Playstation Eye Kameras benutzt, die eine Auflösung von 640×480 bei 60Hz und 320×240 bei 120Hz Кангбаши Berechnung der Flugbahn

Zu Beginn stellten wir uns die Frage, ob wir das Problem des fleigenden Balls wie ein Mathematiker oder wie ein Physiker lösen. Der Weg des Mathematikers wäre den Ball an drei Punkten zu erkennen und dann daraus eine Funktion zu errechnen mit der wir dann den Landepunkt berechnen. Der Weg den ein Physiker nehmen würde hat als Ansatz die Formel einer Wurfparabel für einen schrägen Wurf, da unsere Abwurfhöhe nicht 0 war, und mussten somit 3 bzw. 4 Variablen der Formel bestimmen. Das Ziel der Formel war dabei, den eigentlichen Endpunkt (wo Y = 0 ist) zu berechnen, um dann „vorhersagen“ zu können, wo der Ball landen wird. Die Variablen waren dabei : 1. Abwurfhöhe, 2. Abwurfwinkel und 3. die Anfangsgeschwindigkeit des Balls. Wir entschieden uns für den Weg des Physikers.

Um diese Variablen nun zu errechnen, haben wir nach jedem gemessenem Frame, bei dem der Ball erkannt wurde, die Position des Balls gespeichert. Dies ermöglichte uns zum einen sofort die Abwurfhöhe zu bestimmen, und zum anderen eine Strecke vom Anfangspunkt bis zum Punkt des nächsten gemessenem Frames zu erhalten. Aus dieser Strecke konnten wir mit Hilfe des Weg-Zeit Gesetzes die Geschwindigkeit in X- und in Y-Richtung bestimmen. Somit hatten wir fast alle Variablen bis auf den Abwurfwinkel. Da wir jedoch die Geschwindigkeit in zwei Richtungen aufgeteilt haben, fällt der Abwurfwinkel aus der Formel heraus und wir haben eine Funktion um den Endpunkt der Flugbahn zu berechnen.

Abbildung 3: Schräger Wurf Formel

Quelle des Bildes

Erfassung des Balls

Für uns ergaben sich zwei Möglichkeiten den Ball überhaupt zu erkennen. Entweder wir schauen nach einer runden Anordnung ähnlich farbiger Pixel oder wir schauen nach einer speziellen Farbe. Wir haben uns für letzteres entschieden, da wir uns erhofft hatten, dass dies einfacher zu programmieren ist. Wenn man sich nun für einen Weg entschieden hat, dann kann man noch entscheiden, ob man jeweils das gesamte Sichtfeld absucht oder erst Bereiche, wo man annimmt, dass der Ball dort sein könnte. Wir haben uns für das Absuchen des gesamten Sichtfeldes entschieden, wieder weil es uns einfacher zu realisieren schien.

Also suchen wir immer das volle Sichtfeld nach einer Farbe ab und ermitteln dann den Mittelpunkt dieser Anordnung um die Mitte des Balls zu finden. Der Farbwert ist ein HSV-Wert, den wir entweder manuell durch herumprobieren oder mithilfe eines Programms rausgesucht haben. Hier ein Programm zum manuellen Einstellen des Farbwerts (1_cam_config) und eines zum automatischen Herausfinden mit Hilfe eines Bildes (1_pic_hsv_finder).

1_cam_config.zip

1_pic_hsv_finder.zip

Quelle des HSV-Finders

Problem der falschen Daten

Im Laufe der Entwicklung sind wir auf ein Problem gestoßen. Die Daten, die wir ausrechnen, scheinen keinen Sinn zu ergeben, da laut ihnen der Ball in gleicher Zeit unterschiedliche x-Strecken zurücklegt, was ja eigentlich nicht möglich sein kann. Das folgende Video demonstriert dies, der Ball fliegt von links nach rechts und die X-Achse verläuft genauso. Das von uns benutzte Programm dafür ist dieses: 1_cam_trajectory.zip.

Abbildung 4: Horizontaler Wurf mit Linien

mögliche Fehlerquellen:

  • Erkennnungs-Algorithmus erkennt, wenn der Ball zu schnell fliegt, mal die linke und mal die Rechte Seite - wurde ausgeschlossen, indem die einzelnen Frames überprüft worden, wo der Ball erkannt wurde.
  • Der Luftwiderstand stoppt den Ball - wurde erstmal ausgeschlossen, da die Daten nicht typisch für Luftwiderstand waren und wir davon ausgehen, dass ein Ball in so einem Wurf kaum vom Luftwiderstand beeinflusst wird.
  • Fehler in der Programmierung - wurde erstmal ausgeschlossen, da der Code auch mit Hilfe anderer überprüft wurde
  • Die Art, wie das Programm Zeit misst, ist fehlerhaft - wurde noch nicht komplett ausgeschlossen

Datenkommunikation

Allgemein

Um die berechneten Koordinaten von dem Computer zu dem Arduino zu bringen, welcher die Motoren bewegt, muss es einen Kommunikationsweg geben. Wir haben uns für die serielle Kommunikation über den USB Port entschieden. Diese Erklärung ist für C/C++ und ein Linux Betriebssystem geschrieben (hier ubuntu 16.02).

Übersicht der Kommunikatio
Abbildung 5: Übersicht der Kommunikation

Linux behandelt serielle Geräte so ähnlich wie Textdateien, also haben wir eigentlich ein C++ Programm geschrieben, welches die Nachricht in eine Textdatei schreibt. Der Pfad zu dem Arduino ist unter ubuntu irgendwo in /dev/ hat einen Namen wie z.B. „ttyUSB0“. Wir haben die baudrate, mit welcher der Computer zu dem Arduino nicht geändert und haben uns danach gerichtet, was standardmäßig eingestellt war, herausgefunden haben wir, dass mit dem Befehl stty -F pfad_zum_arduino also z.B. stty -F /dev/ttyUSB1. Meistens war es 9600 oder 57600.

Das C++ Programm

Es ist zu beachten, dass wenn man die Arduino „Datei“ zum editieren öffnet, der Aduino neugestartet wird und man ein paar Sekunden warten muss ihn booten zu lassen. Hier ein kleines Beispiel Programm, welches nur einmal eine „0“ über ein ofstream Objekt sendet.

computer_arduino_beispiel_c_code.zip

Der Arduino Sketch

Der Arduino muss zum Einem warten bis eine Nachricht komplett gesendet wurde, was mit Hilfe der Serial.available() Funktion geschieht, und zum Anderen wird, wenn wie in dem Beispiel Programm „0“ gesendet wird, der dezimale Ascii Wert des besagten Zeichen empfangen. Nach der Tabelle ist der Wert „48“.

Hier ein einfaches Beispiel Programm, welches wenn eine „0“ empfangen wird, eine Led basierend auf dem Blink Sketch an Pin 9 für 1 Sekunde zum Leuchten bringt.

computer_arduino_example_arduino.zip

Abbildung 6: Arduino Beispiel einfache Nachrichten

Wenn man aber mehrere Nachrichten auf diese Art versenden will und der Arduino nicht nur überprüfen soll, ob etwas spezielles gesendet wurde, sondern allgemein zuhören soll, wird es etwas komplizierter.

Zum Einem muss man herausfinden, wann genanu die Nachricht gesendet wird, bei einer einzelnen Nachricht ist das egal, weil das Programm die Datei schließt und die Nachricht dann automatisch sendet. Aber wenn man jetzt Nachrichten senden will, während die Datei noch geöffnet ist, muss man überlegen, wann der Buffer (Englisch) geleert wird. Wir haben dann auf Website des C++ Kompilers GCC herausgefunden, dass es für C++ der Fall ist, wenn eine neue Zeile beginnt, also wenn endl verwendet wird.

Zum Anderen muss man beachten, dass nicht nur die Nachricht selbst, sondern noch andere Informationen übertragen werden. Für die Baudrate von 9600 ist es der ascii Code für den Zeilenvorschub welcher eine neue Zeile signalisiert und der Wagenrücklauf welcher signalisiert an den Anfang einer Zeile zu gehen. Bei einer Baudrate von 57600 ist es wiederum nur der Zeilenvorschub. Diese Informationen müssen dann natürlich rausgefiltert werden.

Hier ein Beispiel, welches zwei LED's an den Pins 9 und 10 so oft leuchten lässt, wie der Wert der ersten und zweiten Nachricht. Geschrieben ist es für eine Baudrate von 9600 und basiert darauf, dass die Daten in einem Zweiertakt übermittelt werden. In der Zip-Datei ist der C und Arduino Code.

computer_arduino_mehre_nachrichten_c_arduino.zip

Abbildung 7: Arduino Beispiel mehrere Nachrichten

Bewegung des Rings

Für die Bewegung des Ringes zur errechneten Position brauchten wir eine Konstruktion, die das fangende Element mit möglichst wenig Zeitverlust bewegt. Dabei sind wir bei Recherchen im Internet auf ähnliche Projekte gestoßen, die ein System mit Zahnriemen benutzen. Die Idee hierbei ist, dass mithilfe von nur zwei Motoren jeder Punkt auf der Fangfläche vom fangenden Ring erreicht werden kann. Für unseren Roboter brauchten wir also zuerst einen Rahmen, der die Fangfläche begrenzt. Wir entscheiden uns für einen Holzrahmen mit 90*90 cm Umfang, der eine Fläche von 60*60 cm komplett abdeckt.

Für die Bewegung des Ringes nach oben und unten (y-Richtung), bzw. zur Seite (x-Richtung, aus der Sicht der Zeichnung, fertigten wir eine Plattform mit Loch, die auf dem Rahmen mithilfe von vier Rädern läuft. Dadurch entsteht die Bewegung nach oben und unten. Der Ring selber wird durch die Zahnriemen auf der Plattform in x-Richtung bewegt. Nach unserer ersten Idee sollte sich die Plattform ebenfalls durch Zahnriemen bewegen, die Konstruktion mit den Rädern lies sich aber leichter verwirklichen und auch die ersten Bedenken eventueller Zeitverluste durch Reibung bewahrheiteten sich nicht. Die beiden Stepper-Motoren haben Aufsätze mit Zähnen, die die Zahnriemen bewegen. Dabei ist die Anzahl der Umdrehungen wichtig, damit der Ring zur berechneten Stelle kommt.

Abbildung 8: Bauplan Fangmaschine

Die unterschiedlichen Farben kennzeichnen die zwei Zahnriemen, die durch die Motoren bewegt werden und somit den Ring bewegen.

Umrechnung von Koordinaten in Umdrehungen

Das Drehen eines einzelnen Motors bewirkt eine diagonale Bewegung. Um den Ring jedoch gerade nach oben/unter oder nach rechts/links zu bewegen, müssen beide Motoren gleichzeitig angetrieben werden. Falls Motor1 (der linke Motor) in negativer Richtung (nach links) und Motor2 in positiver Richtung (nach rechts) gedreht wird, entsteht eine Bewegung nach oben (1+; 2- bewirkt eine Bewegung nach unten). Wenn der Ring auf der X-Richtung bewegt werden soll, müssen die Motoren in dieselbe Richtung gedreht werden (1-; 2- = nach rechts | 1+; 2+ = nach links).

Wie können wir nun die Koordinaten die wir von den Kameras in Zentimetern bekommen werden, in Umdrehungen für Motor1 und Motor2 umrechnen?
In unserem gedachten Koordinatensystem des Rahmens kann eine gerade, zum Ziel gerichtete Bewegung in zwei einzelne Bewegungen aufgeteilt werden; die X und die Y-Bewegung. Nehmen wir an, der Ring muss sich um 10cm in X-Richtung und um 20cm in Y-Richtung bewegen.

X-Bewegung: Motor1 eine -10cm, und Motor2 eine -10cm Bewegung machen (Falls X=-10 ⇒ M1=10; M1=10)
Y-Bewegung: Motor1 eine -20cm, und Motor2 eine 20cm Bewegung machen (Falls Y=-20 ⇒ M1=20; M2=-20)

nun haben wir also eine X und Y-Bewegung für Motor1 sowie eine X und Y-Bewegung für Motor2!
Diese können wir laut der VektorAddition addieren und bekommen die insgesamt benötigten Drehungen für Motor1 und Motor2.

Folgende Formeln können für den folgenden Code also verwendet werden:
Motor1: [(-x)/4,6] + [(-y)/3,5]
Motor2: [(-x)/4,6] + [(+y)/3,5]
(4,6 und 3,5 sind Faktoren zum Umrechnen von cm in Umdrehungen. 30cm zur Seite entsprechen 6,5 Umdrehungen (30/6,5 = 4,6)
30cm nach unten/oben entsprechen 8,5 Umdrehungen (30/8,5 = 3,5). Da bei den beiden Bewegungsarten auf der x- oder der y-Achse verschiedene mechanische Vorgänge beweltigt werden (drehung der Motoren in die gleiche/entgegen gesetzte Richtung) kommen unterschiedliche Faktoren zustande)

Die Programmierung

ringbewegung.zip

Die Motoren werden über einen Arduino gesteuert. Daher bewegen sich beide Motoren gleichzeitig, mit gleicher Geschwindigkeit. Jedoch ist es sehr unwahrscheinlich, dass beide Motoren die gleiche Anzahl an Umdrehungen liefern müssen. Somit müssen sich beide Motoren drehen, bis einer der beiden seine Aufgabe erfüllt hat; danach dreht sich der andere Motor weiter bis zu seinem Ziel. Zu dieser Schwierigkeit kommt noch dazu, dass ein Motor sich negativ und der der andere sich positiv drehen könnte.
So entstehen ca. 10 Fälle, je nachdem welcher Motor positiv, welcher negativ ist und welcher sich länger drehen muss!

Der Großteil des Programms besteht also aus sehr vielen, in einander verschachtelten If-Abfragen um zunächst heraus zu finden um welchen Fall es sich handelt und danach die Motoren zu bewegen.
Die Bewegung findet in zwei for-Schleifen statt. Zunächst drehen sich beide Motoren gleichzeitig; wenn die Abbruchbedingung erreicht ist (Die Anzahl der Umdrehungen des sich weniger drehenden Motors), wird die zweite for-Schleife ausgeführt, bis der sich alleine drehende Motor seine Aufgabe erfüllt hat.
Nach 10 Sekunden wird die Bewegung mit umgekehrter Richtung wiederholt, um zur AusgangsStellung zurück zu kehren.
Bevor das Programm jedoch in die Bewegung geht, werden die Koordinaten der Kameras übernommen und mit der Formel in Umdrehungen umgerechnet. Diese Umdrehungszahl, welche auch die eben angesprochene Abbruchbedingung darstellt, wird nun nochmal mit 200 multipliziert da die 200fache Ausführung der for-Schleife einer kompletten Umdrehungen entspricht.

Anschluss der Motoren mit dem Arduino

Abbildung 9: Schaltplan Fangmaschine

Beide Motoren sind über separate Treiber mit dem Arduino verbunden. Zusätzlich werden beide Treiber und Motoren über einer externe Spannungsquelle versorgt.

Ergebnis und Diskussion

Der Endstand des Projektes ist das der Hardware Teil des Projektes funktioniert, aber vielleicht für die volle Benutzung etwas zu langsam ist, und das der Software Teil nur teilweise funktioniert. Die Software erkennt zwar einen fliegenden Ball aber nur in einem zwei Dimensionalen Raum und führt noch keine Berechnnung durch. Diese Aufgaben sind im Prinzip durchdacht wurden aber noch nicht realisiert, wofür zum Teil das Bereits beschriebene Problem verantwortlich ist da die Suche nach einer Lösung viel Zeit gekostet hat und man nicht an anderen Projekten weiterarbeiten wollte ohne das gelöst zu haben.

Verbesserungsmöglichkeiten sind also:

- Geschwindigkeit der Fangkonstruktion

- Beenden der fehlenden Funktionen

Ausblick

Wir können einer anderen Gruppe nur empfehlen dieses Projekt weiterzuführen da wir denken das man mit unserer Basis es schaffen würde das Projekt zu beenden.

Dabei empfehlen wir zu überlegen die Bilderfassung in Processing zu machen da dies eventuell mehr beim Programmieren unterstützt und es mehr Beispiele im Internet/Dokuwiki gibt. Dies ist uns erst mitten in der Entwicklung aufgefallen wo wir nicht mehr unsere Entwicklungsart ändern wollten.

Hinzu kommt das wir empfehlen das jemand der dieses Projekt aufnimmt etwas programmier Erfahrung haben sollte,da wir mit kaum Programmiererfahrung etwas Probleme hatten die OpenCV Dokumentation und Internet Beispiele zu verstehen.

Das in diesem Projekt erlernte Wissen wird uns auf jedenfall im Laufe unseres Studiums weiterbringen und eventuell arbeiten wir an dem Projekt in unserer Freizeit noch weiter da wir das Gefühl haben das man mit mehr Zeit noch viel erreichen könnte.

projektewise1718/derbecherpublic/start.txt · Zuletzt geändert: 2018/05/17 00:35 von d.golovko