Robodrohne- Software

 

Software Beschreibung
Bezugsquelle
Ubuntu Auf dem Entwicklungsrechner / Sender www.ubuntu.com
Windows XP Auf dem Entwicklungsrechner / Sender. vorinstalliert
Linux Das Betriebssystem des SBC. Spezielle Distribution. vorinstalliert
IntelliJ IDEA Community Edition 9.0.4 Java IDE. http://www.jetbrains.com/idea/index.html
IntelliJ IDEA ULTIMATE 10 preview
Für die UML Diagramme http://www.jetbrains.com/idea/index.html
JDK 1.6.0_xx Das Java Developement Kit. http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html
JDK 1.5 Zum entwickeln des Empfängers. http://www.oracle.com/technetwork/java/javase/downloads/index-jdk5-jsp-142662.html
jamVM Auf dem SBC. Spezielle Virtuelle Maschine für eingebettete Systeme. vorinstalliert.
http://jamvm.sourceforge.net/
GNU Classpath Auf dem SBC. Freie Klassenbibliothek, wird von jamVM benutzt. vorinstalliert.

http://www.gnu.org/software/classpath/classpath.html

Phidget 21 Treiber Treiber zum ansteuern der Phidgets. http://www.phidgets.com/drivers.php
phidget21.jar Java API, Aufsatz auf die C Bibliothek des Treibers. http://www.phidgets.com/programming_resources.php
DejaVu Schriftsatz mit dem wir Text im Sender (Cockpit) darstellen. http://dejavu-fonts.org/wiki/Main_Page
Filter.jar Bei Verlust der WLAN Verbindung wird das Cockpit grau dargestellt. Wir benutzen dafür einen Graufilter. http://www.jhlabs.com/
jscience.jar Java API für Mathematisch / wissenschaftliche Zwecke. Wird bei uns zur einheitlichen Behandlung von Werten und Maßeinheiten benutzt. In diesem Projekt nur eingeschränkt möglich, da auf dem SBC nicht lauffähig. http://jscience.org/
TableLayout-bin-jdk1.5-2007-04-21.jar Layoutmanager, der Swing Komponenten tabellarisch anordnet. https://tablelayout.dev.java.net/
eventbus-1.4.jar
Kommunikation zwischen Java Objekten. Ersetzt das Listener Konzept in Swing. Ermöglicht Kommunikation zwischen Nicht-Swing Komponenten. Fördert lose Kopplung von Objekten. https://eventbus.dev.java.net/
http://www.eventbus.org/
ProGuard4.5 Erzeugt jar Dateien, optimiert und obfuskiert *.class Dateien http://proguard.sourceforge.net/
VirtualBox Virtualisierungssoftware. Virtualisiert Ubuntu auf Windows XP. http://www.virtualbox.org/

 

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.

alt

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.

alt

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

.alt

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.

alt  

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

.
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.

alt

Robotik in Java.