ROBODROHNE – HARDWARE

Im Folgenden zeigen wir euch, wie wir die Hardware der RoboDrohne aufgebaut haben.

Mobirise

Zunächst einmal wurde die Struktur der Drohne in SolidWorks konstruiert, um einen groben Überblick zu haben, wie die Komponenten angeordnet werden sollen. Außerdem wurden Pläne für die Frästeile angefertigt. Diese sind die CenterPlates und die Motorträger. Links ist der zentrale Aluminiumrahmen als CAD-Baugruppe zu sehen. Wie Ihr weiter unten lesen werdet schaut der auch in der Realität genauso aus…

Mobirise

Hier die Einzelteile, aus welchen die Struktur aufgebaut ist. Gut zu sehen die Ausleger in der Mitte. Die Motorplatten und die Centerplates rechts. Links liegen die mit Glasfaser verstärkten Balsaholzplatten, welche die gesamte Elektronik halten. sie wiegen jeweils etwa ein drittel weniger als die Aluminiumplatten

Mobirise

Der zusammengesetzte Rahmen. Wie man sieht sieht er exakt aus wie in der Konstruktion gedacht, und um ehrlich zu sein, es sieht gut aus…

Aber ernsthaft, man sieht unten die mit Abstandshaltern befestigte SBC-Ebene, auf welcher der Rechner sitzen wird. Auf der oberen Centerplate sind noch provisorische Abstandshalter für die Sensorebenen zu sehen, diese werden noch von Schwingungsdämpfern ersetzt.

Mobirise

Und hier der Rahmen, fertig zum Bestücken mit der Elektronik und den Motoren.

Alles weitere kommt mit der Zeit…

Mobirise

Die vier Pichler BOOST 25 Brushless Motoren mit zugehörigen Pichler XQ30 Reglern. Um das Gesamtdrehmoment auf die Drohne auszugleichen, müssen sich jeweils zwei Motoren in entgegengesetzte Richtungen drehen. Deswegen sind je zwei Propeller als Pusher und zwei als Puller ausgelegt.

Mobirise

Links die Sensorebene mit darauf montiertem W-LAN – Stick. Das linke Modul ist der Servocontroller, rechts das Voltmeter. Die Platine rechts ist der SBC mit angeschlossenem Sonar-Sensor (hinter der Antenne). Die USB-Kabel sind selbst gelötet, da die, die man kaufen kann, zu schwer und zu lang sind. Sie sind hier nicht geschirmt, da Übertragungsstörungen bei unseren Längen (10cm) nur gering ausfallen sollten. Für den Fall, dass die Störungen Überhand nehmen, müssen die Kabel noch geschirmt werden.
Das Gyroskop ist Rückseitig auf der Sensorebene Montiert, sodass es möglichst nahe am Scherpunkt der Drohne angeordnet ist. Die gesamte Sensorebene ist später auf Schwingungsdämpfern montiert.

Mobirise

Der Rahmen mit fertig montiertem Kabelbaum. Wir schließen alle Akkus und alle Motoren parallel. Unsere Überlegung dabei: wenn wir die Stromversorgung aufteilen und ein Akku stärker entladen wird als der andere, dann haben nicht alle Motoren dieselbe Arbeitsspannung, was zu einem einseitigen oder diagonalen (je nach Anordnung) Leistungsverlust führen kann (der SBC muss auch versorgt werden). Allerdings haben wir hier das Problem, dass wenn ein Motor plötzlich mehr Strom zieht, dann führt dies zu einem Leistungsverlust bei den anderen dreien und im Endeffekt zum selben Ergebnis, dem Überschlag.
Wir werden sehen, ob es sich bewahrheitet.
Die mit gestreiftem Klebeband abgeklebten Enden werden noch mit Steckern versehen. Dies sind die Zuleitungen von den Akkus.

Mobirise

Die montierten Regler. Sie sind für die ersten Tests noch mit Lüsterklemmen am Kabelbaum befestigt. In späteren Phasen werden sie jedoch angelötet. Die Regler selbst sind mit einer Moosgummiunterlage versehen, um die Elektronik zu schützen. Eine Montage auf den Armen hat den Vorteil, dass die Kühlkörper der Regler direkt von den Propellern angeblasen werden und somit die Kühlung gewährleistet ist.

Mobirise

Die RoboDrohne fertig montiert, bereit für die ersten Tests. Die Propeller sind allerdings auf dem Foto noch nicht richtig angeordnet. Die Drohne soll in X-Konfiguration fliegen und die Antenne ist hinten. Damit ist auch die Flugrichtung definiert und die ersten Tests beginnen.

Damit ist die Sektion Fertigstellung vorübergehend abgeschlossen und wir bringen der RoboDrohne nun das Fliegen bei. Die nächsten Arbeitsschritte sind demnach in den Bereichen “Software” zu finden. Hier gehts dann weiter, wenn wir soweit sind, dass wir Nutzlast transportieren können. Unter Nutzlast verstehen wir Kameras, GPS, Zeitungen, Einkäufe, Wasserbomben… :-)

ROBODROHNE -- Software

Allgemeines

Die hier beschriebene Software hat – wie das gesamte Projekt – experimentellen Charakter. Der Quelltext kann deshalb den Qualitätsanforderungen von Produktivsystemen (Webservern oder wissentschaftliche Applikationen) nicht standhalten. Unser Quelltext sollte deshalb nicht zur Steuerung von Mars-Missionen, Kernkraftwerken oder Toaster verwendet werden!

Nachfolgend möchten wir die Software auszugsweise vorstellen.

Die verwendete Programmiersprache ist Java in den Versionen 1.6 und 1.5 (dazu später mehr).

Die Steuerungssoftware von RoboDrohne ist aufgeteilt in Sender und Empfänger. Die beiden Applikationen kommunizieren bidirektional über WLAN und dem TCP Protokoll. Um unsere Software für spätere Projekte möglichst ohne Änderung wiederverwenden zu können haben wir die Zuständigkeiten und die Funktionalitäten so weit als möglich abstrahiert. Daraus entstanden die beiden wesentlichen Schnittstellen IHost und IModule.



Der Host

Eine IHost Implementierung verwaltet unter Anderem die bei ihm registrierten Module, öffnet und schliesst Socket-Verbindungen, führt asynchrone Aktionen aus, lädt und speichert Daten auf Festplatte. Viele dieser Eigenschaften sind für Sender und Empfänger exakt gleich, deshalb sind sie in der Klasse AbstractHost implementiert. Funktionen die sich im Sender und Empfänger unterscheiden befinden sich in den Klassen TransmitterCore und ReceiverCore. Diese und weitere Klassen wurden in ein eigenes Softwareprojekt ausgelagert das als Basis (Kern) für zukünftige Hardware – Projekte dient.Für unser Projekt RoboDrohne haben wir deshalb in unserer IDE jeweils ein Projekt für den Sender und den Empfänger angelegt. Dies wurde u.A. auch notwendig weil auf dem SBC als Virtuelle Maschine jamVM mit GNU Classpath in
der Java Version1.5 zur Verfügung steht. Der Sender wird mit dem JDK 1.6 entwickelt. Ein drittes Projekt enthält Klassen die sowohl vom Sender als auch vom Empfänger genutzt werden – es wird ebenfalls mit Java 1.5 entwickelt.

Mobirise

Das Modul

Beide Projekte (Sender und Empfänger) enthalten als wesentlichen Bestandteil Implementierungen der Schnittstelle IModule. Auch hier existiert eine Abstraktionsschicht, weil nicht alle Methoden in den Modulen implementiert werden müssen.Ein Modul kann auf vielfältige Weise implementiert werden: Als Initialisierungs – und Verwaltungseinheit eines Phidget Treibers oder als Modul für die Berechnung der Fluglage sowie als generischer Schubhebel der Tastatureingaben entgegennimmt – und vieles mehr.

Mobirise

Kommunikation und Transport

Wie eingangs beschrieben läuft die Kommunikation zwischen Sender und Empfänger über WLAN und dem TCP Protokoll. Java unterstützt uns hierbei sehr gut durch die Klassen java.net.Socket und java.net.ServerSocket. Mit wenigen Zeilen Quelltext ist die Verbindung zwischen zwei Kommunikationsendpunkten aufgebaut und die Daten können ausgetauscht werden. Die oben erwähnten Klassen liefern uns nach erfolgreichem Verbindungsaufbau Referenzen auf einen Eingabe – und Ausgabestrom der auf Byte Ebene arbeitet.Da wir Zahlen, Text sowie Boolesche Werte versenden wäre ist es nicht praktikabel diese Datentypen beim Senden in Bytes zu zerlegen und beim Empfangen wieder in den entsprechenden Datentyp zu konvertieren. Diese Arbeit erledigen für uns die Klassen java.io.DataInputStream und java.io.DataOutputStream. Wir haben diese Klassen erweitert um einfacher Zahlen beliebigen Typs bzw. null versenden zu können: RBBDataOutputStream und RBBDataInputStream. Um Datenstrukturen versenden zu können war es notwendig die Informationen in eine eigene Klasse zu kapseln – in die Klasse AbstractDataPacket. Eine konkrete Implementierung existiert beispielsweise für die Datenerfassung von unserem Messsystem (IMU): IMUDataPacket. Zum Zeitpunkt der Niederschrift dieses Textes ist diese Klasse noch im Beta Stadium und deshalb unkommentiert

Mobirise

Eine weitere wichtige Klasse ist DataPacketFactory. Sie erstellt für uns auf Anfrage Datenpakete eines bestimmten Typs. Sie kommt dort zum Einsatz wo Daten empfangen werden. Ein kurzes Beispiel:
In unserem IMU Modul werden aus dem Messsystem periodisch Daten gelesen. Anschliessend wird ein neues IMUDataPacket erzeugt und die Daten übergeben. Über die Methode IHost.send() wird dieses Paket an ein anderes Modul über das Netz gesendet. Jeder Pakettyp hat eine eindeutige Kennung. Diese Kennung wird beim Versand als erstes mit der Methode AbstractDataPacket.getID() in den Datenstrom geschrieben und beim Empfang als erstes gelesen. Diese ID übergeben wir der DataPacketFactory die uns dann das passende Datenpaket erzeugt und zurückliefert. Das alles geschieht in den Methoden Protocol.outgoing() und Protocol.incoming() womit wir die letzte wichtige Klasse zur Datenübertragung erklärt hätten.

Mobirise

Datenermittlung, Datenhaltung und Auswertung

Die Datenermittlung (Sensorik etc…) und deren Auswertung (Berechnung der Fluglage) wird ausschliesslich auf dem Empfänger durchgeführt. Der Sender überträgt lediglich die Kommandos für Richtung (Joystick) und Schub (Tastatur), sowie Parameter die vor dem Flug gesetzt werden. Die Werte der Sensoren sowie die Leistungsdaten der Motoren schicken die zuständigen Module zum Sender wo sie auf der GUI dargestellt werden (dazu später mehr). Eine Zeitversetzte Auswertung (Blackbox) ist zu einem späteren Zeitpunkt geplant. Spätestens dann kann von einer Telemtrieanwendung gesprochen werden.Diese Daten liegen als Fliesskommazahlen, Ganzzahlen oder Boolesche Werte vor. Das sind unter anderem: Schubhebelposition, Joystickposition, elektrische Spannung, Sonar usw… Auf diese Werte werden mathematische Operationen angewendet – hauptsächlich für die Fluglageregelung. Wir speichern diese Werte deshalb in der Klasse Operand. Operand speichertnicht nur einen Zahlenwert, sondern enthält auch eine Wertespezifikation ValueSpec_15. Sie definiert den Wertebereich, den initialen (Standard) Wert sowie die Enheit. Alle Operanden werden in einem Array in der Klasse FlightLogicUnit gehalten. Über eine entsprechende Methode kann jedes Modul seine Operanden abholen um Werte zu schreiben oder zu lesen. Das Modul FlightLogicUnit ist die übergeordnete Funktionseinheit. Sie steuert das Zusammenspiel aller Module und führt Plausibilitätsprüfungen durch. Es darf beispielsweise nur in den Flug – Modus geschaltet werden wenn die Motorsteller kalibriert sind und der Schubhebel in Leerlaufstellung ist.Befüllen und Auswerten der Operanden:
Module die die Schnittstelle IProcessingModule implementieren werden in einer Schleife aufgerufen. Zuerst die Sensoren die die entsprechenden Operanden mit den aktuellen Werten befüllen, dann die FlightLogicUnit - sie entscheidet anhand der Werte das weitere Vorgehen. Anschliessend wird das Modul FlightControlUnit - unsere zentrale Recheneinheit aufgerufen. Die FlightControlUnit berechnet anhand der Operanden den Schub für jeden einzelnen Motor. Die berechneten Werte werden ebenfalls in vier verschiedene Operanden geschrieben und durch das ServoModule dem AdvancedServoPhidget übergeben. Das Setzen der Steuer – und Schubkommandos geschieht in der Methode setPacket() von FlightLogicUnit

Mobirise

Datenvisualisierung und Benachrichtigungsmechanismus

Wie weiter oben erwähnt schickt der Empfänger diverse Daten (Sensorik, Motordaten usw…) zum Sender zurück. Diese Daten stellen wir in einem Anwendungsfenster dar das einem Flugzeugcockpit ähnelt. Die Applikation besteht im wesentlichen aus Komponenten aus dem Package javax.swing. Das Fenster ist eine Instanz von javax.swing.JFrame. Alle Anzeigen erben von der Klasse javax.swing.JComponent. Sie dient als Basisklasse für zahlreiche Swing Komponenten wie JButton, JTable und andere. Will man eigene Komponenten entwerfen ist JComponent oder JPanel der beste Einstieg. Den Künstlichen Horizont und das Rundinstrument haben wir in Anlehnung an die Instrumente des Airbus A380 entworfen. Da wir auf die sonst übliche Betriebssystemspezifische Darstellung von Komponenten verzichten können, gestaltet sich das Implementieren dieser Anzeigen relativ einfach. Wir wollen dies am Beispiel des Rundinstrumentes erläutern. Unser Rundinstrument visualisiert die Schubhebelstellung, den momentanen Schub und die Begrenzung des Maximalschubes.

Bevor wir loslegen, noch ein paar Sätze zu dem von uns verwendeten Nachrichtenmechanismus:
Grafische Benutzerschnittstellen sind Ereignisgesteuert. Klickt man beispielsweise mit der Maus auf einen Button wird ein Ereignis ausgelöst auf das ein anderes oder mehrere andere Programmteile reagieren können – beispielsweise durch Anzeige einer Dialogbox. Um das Ereignis empfangen zu können müssen sich diese Programmteile bei dem Button bekannt machen (als Zuhörer registrieren). Dieser Mechanismus ist auch bekannt als Beobachter oder Observer Muster (Siehe Buch Design Patterns von Erich Gamma et al.). In Java wir dieses Konzept durch die allgegenwärtigen addXXX() und removeXXX() Methoden und entsprechenden Schnittstellen realisiert. Für einen JButton sind das beispielsweise die Methoden addActionListener(ActionListener l) und removeActionListener(ActionListener l) Für unser Rundinstrument bräuchten wir demnach drei Anmelde – und drei Abmeldemethoden sowie die entsprechnde Logik. Dieser Mechanismus funktioniert sehr gut solange Sender (von Ereignissen) und Empfänger im Quelltext nah beieinander sind. Ist dies – meist bei grösseren Projekten – nicht der Fall muss zusätzlicher Implementierungsaufwand betrieben werden. Durch die Verwendung der EventBus API von Michael Bushe reduziert sich dieser Aufwand deutlich. Da für uns das Experimentieren im Vordergrund steht war es selbstverständlich diese API statt den herkömmlichen Listener Mechanismus zu verwenden. Wir erklären den EventBus anschliessend bei der Vorstellung des Rundinstrumentes.


Datenerfassung und Verarbeitung


Damit die Drohne in der Lage ist sich selbst zu stabilisieren, muss sie Informationen über ihre aktuelle Lage erhalten. Dies passiert bei uns durch kontinuierliches Auslesen der Werte, die die Piezoelemente des Spatial 3/3/3 liefern. Da der Rahmen im Flug niemals still steht, sondern immer mit Vibrationen zu rechnen ist, müssen diese Daten gefiltert werden. Dies passiert bei uns über einen FIR Filter. Die Lage im FLug wird dann über PID-Regler stabilisiert.

Start the Engines!

Das Zusammenspiel der beschriebenen Klassen möchten wir anhand der Abarbeitung eines Joystick Kommandos erläutern.

Unser Cockpit in der Version 1.0.1: Sender und Empfänger erfolgreich gestartet.

Mobirise

© 2022 Robobuam - Michael Tasior, Manfred-Linden-Ring 1, 84100 Niederaichbach, info<at>robobuam<punkt>de