IPS-Erweiterungen

 1. Kurswinkelberechnung

 2. XBee

 3. GUI

 4. Änderungen Kurswinkelflug

--------------------------------------------------------------------------------------------------------

Softwareerweiterung

Um das Indoor-Navigationsgerät IPS für den Zeppelinflug nutzen zu können mussten von unserem Team bestimmte Erweiterungen/Änderungen in der ips.py Datei vorgenommen werden vorgenommen werden. Neben der Vervollständigungen der GUI verlangte der bestehende Code noch nach einer geeigneten Auswertung der errechneten Position [posx, posy,posz].

1.Kurswinkelberechnung

Für einen geregelten Flug werden von der Bodenstation an den Zeppelin relative Winkel gesendet, die dieser dann nachregelt. Die Berechnung und das Senden dieser Winkel übernimmt ein eigener von GUI und Arduino unabhängiger Thread:

 
class TeamX(threading.Thread):
 

Wenn in der Main-Klasse der Thread angestoßen wird,

 
self.team.start()
 

wird automatisch die run-Funktion und in dieser die loop-Funktion gestartet, welche die zu wiederholenden Berechnungen und Operationen ausführt, unter der Bedingung, dass  der Thread auch in der GUI gestartet wurde und das Navigationssystem eine neue Position liefert.

 
def run(self):
        while(self.run_):
            self.loop()
    def loop(self):
        if (self.start_):
            if self.newposflag:
                if len(self.alpha_soll) == 0:
                    self.reference_angle()
                    pass
                self.course_angle_pos()
                self.compare()
                self.newposflag = False
                pass
 

Als erstes werden die Winkel der abzufliegenden Wegpunkte, welche vorher manuell in der GUI gesetzt wurden verwendet um die Winkel zwischen diesen zu berechnen. Anfangsposition und Ziel des Zeppelins müssen je erster bzw. letzter Wegpunkt sein.

[list ThreadX.alpha_soll] = reference_angle(list main.waypointlist)

Zur Funktion course_angle_reference(): Die Wegpunkte werden aus dem liststore1 der GUI ausgelesen. Die x- und y-Koordinaten werden jeweils in einer Liste x oder y gespeichert und zur Berechnung des Sollwinkels verwendet.

 

        for i in range(len(self.main.waypointlist)-1):
            self.alpha_soll.append(math.atan2(y[i+1]-y[i],x[i+1]-x[i]))

 

Sobald dies einmalig durchgeführt wurde wird in der compare(self)-Funktion der aktuelle Sollwinkel mit dem in der Funktion course_angle_pos(self) errechneten Winkel verglichen, der den aktuell vom Zeppelin eingeschlagenen Winkel angibt.

[global list poslist, ThreadX.alpha_ist, ThreadX.wp_next] = course_angle_pos(posx,posy,posz)

Wie in der Funktionsdefinition zu sehen ist wird auch eine Positionsliste erstellt um den Weg des Zeppelins nachzuvollziehen. Wobei sich diese Positionen aus dem arithmetischen Mittel oder wahlweise Medain von "b" von der Bodenstationen gestellten Werten errechnen um den Einfluss fehlerhafter Positionsdaten zu verringern. Eine Istwinkelberechnung findet erst statt wenn mehr als zwei gefilterte Positionen zur Verfügung stehen. Über die Flag compareflag wird gewährleistet, dass erst bei einem neuen Istwinkel verglichen wird, da die Flag newposflag sich auf die ungefilterten bezieht und ohne zusätzliche Flag compare ohne neue Daten ausgeführt werden würde. Die letzte Outputvariable wp_next gibt den aktuell nächsten Wegpunkt an, der geändert wird sobald sich der Zeppelin diesem auf einen bestimmten Abstand genähert hat. Wegen der Trägheit des Zeppelins sollte dieser Abstand relativ groß sein.

Nun zur compare()-Funktion: Sollte die Abweichung des Istwinkels vom aktuellen Sollwinkel größer als ein maximaler Wert sein

diff = self.alpha_soll[self.wp_next]-self.alpha_ist
if abs(diff) > (10.0 * math.pi/180.0):  #10Grad maximale Abweichung
 

wird ein neuer Sollwinkel aus dem nächsten Wegpunkt und der aktuellen Position des Zeppelins berechnet. Danach wird ein relativer Winkel mit einer eingeschränkten maximalen Schrittweite an die Gondel geschickt.

 
schrittweite_rad =10.0 * math.pi/180.0
...
...
    if abs(diff) > (schrittweite_rad):
                    data = str(schrittweite_grad)
                    if diff < 0:
                        data = ''.join(['bwi -',data])
                    else:
                        data = ''.join(['bwi ',data])

               if self.XBeeflag:
                        self.XBee_send(data)
                        pass
                    else:
                        print("No XBee connected!")
 

Es wird nicht der komplette Abweichungswinkel gesendet, da das Verhalten der Regelung bei verschiedenen Werten unterschiedlich gut ist und den Winkelflug unvorhersehbar machen würde. Stattdessen wird solange mit dem Schrittwinkel die Bahn des Zepplins angepasst, bis die Abweichung wieder unter den maximalen Wert fällt.

Soweit die Kurswinkelberechnung. Bei jedem neuem gefiltertem Positionswert beginnt die Berechnung von vorn. Folgendes Diagramm stellt anschaulich die im Text erläuterten Schritte dar.

Diagramm der Winkelberechnung mit dem IPS

2.XBee

Die Bodenstationen kommunizieren über NRF-Funkmodule. Das Team benutzt für die Kommunikation mit der Gondel aber XBee-Module. Also musste auch dies im Teamthread des Pythoncodes ergänzt werden.

 
def XBee_init(self):
        tty = glob.glob('/dev/ttyUSB*')
        debug(tty)
        #print(tty)
        
        if(len(tty)<2):
            print("No XBee connected!")
        else:
            for i in tty:
                if i != self.main.ttyport:
                    XBeeport = i
                    self.XBee = serial.Serial(XBeeport, 19200)
                    self.XBeeflag = True
                    debug("XBee initiiert")        
                    pass
    
    def XBee_send(self,data):
        print('Sende: ')
        print(data)
        self.XBee.write(bytes(data,'UTF-8'))
 

 Über die XBee_init()-Funktion wird der Serialport mit dem XBee geöffnet, dabei wird falls nur der Arduino angeschlossen ist eine Fehlermeldung ausgegeben. Dies erfolgt in der Initiierung der TeamX-Klasse. 

Die write()-Funktion des Serials führt in der XBee_send(string data) Funktion das senden der Daten durch, die als String übergeben werden und folgendem Protokoll entsprechen:

"bwii Leerzeichen Vorzeichen Schrittwinkel"

"b" bildet den Beginnbyte des Datenpakets. "wii" ist das Kommando, dass der Winkel geändert werden soll. Andere Befehle siehe "Basisstation Befehle" in der Dokumentation. Getrennt von einem Leerzeichen folgt dann der vorzeichenbehaftete Schrittwinkel. Ein negatives Vorzeichen entspricht in diesem Fall eine Änderung der Flugrichtung nach rechts und ein positives dementsprechend einer Änderung nach links. Genauso ist es möglich einen absoluten Winkel statt das Inkrement zu schicken. Dafür statt "bwii" nur "bwi" und dann die Winkelwerte im Bereich von [-360,360] hochschicken. Dabei steht das negative Vorzeichen für eine Rechtsdrehung und das positive für die Linksdrehung.

 

3.GUI

Wie in der Dokumentation "Gemeinsames IPS" müssen die dort genannten Pythonpakete installiert werden. Wenn man dann die graphische Oberfläche nutzen möchte muss man zunächst die Datei multilat.c, welche die Berechnungen für das Navigationssysstem durchführt wie folgt kompilieren:

 

gcc -c -fPIC -O3 multilat.c

 

gcc -shared -o multilat.so multilat.o
 
Das ist erforderlich, damit das C-Programm für das jeweilige 32 oder 64 Bit System funktioniert. Danach ist es möglich die GUI über die Konsole zu starten. Dazu wechselt man in das Verzeichnis, das die Datei ips.py enthält und führt diese mit Python3  aus. Es ist darauf zu achten nicht "./" zu vergessen.
 
 
 
Daraufhin erscheint das Init-Fenster in dem man den Port wählt an den der Arduino mit der Empfängerantenne angeschlossen ist auf den die base.ino geflasht wurde. Falls man vergessen hat ein Arduino anzuschließen kann man dies nachträglich tun und über den Button "neu laden" die Anzeige aktualisieren. In diesem Fall kann man zwischen zwei Ports wählen, da auch das XBee über den USB-Explorer angeschlossen ist. Dies sollte der Normalfall sein, da die Positionsanzeige zwar auch nur mit dem Arduino funktioniert, aber für das ausführen der Berechnungen für die Gondel des Zeppelins der XBee angeschlossen sein muss.
 
 
Sobald man auf den Button "und los!" drückt öffnet sich die Karte. Falls Daten von den Bodenstationen ankommen wird sofort die Position des Zeppelins angezeigt. Gleichzeitig wird der zurückgelegte Weg blau dargestellt. Links kann man zwischen den Reitern Navigation,CMD und Info wechseln.
In Navigation werden die im ips.py-Code vorinitialisierten Postitionen der Wegpunkte und Bodenstationen angezeigt, welche in der GUI selbst veränderbar sind aber die Werte im Code nicht überschreiben, d.h. bei einem Neustart werden wieder die Werte aus dem Code angezeigt. Wegpunkte werden in der Karte schwarz angezeigt. Bodenstationen werden falls aktiv Werte gesendet werden grün andernfalls rot angezeigt.
 
 
Im Info Reiter werden die aktuellen Positionswerte angezeigt.
Zur Steuerung des Zeppelins dienen die Buttons im CMD wie "commands"-Tab
Mit dem "Radien anzeigen"- Button kann man sich zusätzlich die Abstände der Sender auf der Gondel von den Bodenstationen als Kreise anzeigen lassen. Auf dem Schnittpunkt der Kreise sollte somit der Zeppelin liegen.
 
 
 
Während die Buttons "42" und "Kreis fliegen" nichts bewirken, kann man über "Flugweg zurücksetzen den Flugweg reseten und über den "Wegpunkte+Sollwinkel"-Button sich über die Konsole die genannten anzeigen lassen.
 
 
Über den Start und Stop-Button lässt sich die Kurswinkelberechnung und der Flug des Zeppelins starten bzw. stoppen. Zu beachten ist, das hierfür das XBee angeschlossen sein muss. Gleichzeitig werden folgende Ausgaben erzeugt:
 
 
Man sieht die Befehle, die an den Zeppelin gesendet werden, die aktuelle Postition, den aktuellen Wegpunkt, sowie den Abstand zwischen den letzten beiden Positionen und zum nächsten Wegpunkt.
 
Falls ein Flug erfolgreich alle Wegpunkte abgefahren hat erhält man folgendes Bild. Da mindestens drei Bodenstationen für eine gute Berechnung aktiv sein müssen und die Reichweite ca. 3-5 Meter beträgt gibt es, wie hier zu sehen ist, am Ende große Sprünge in der Position.
 
 
 
In Zukunft soll noch eine farbliche Höhenanzeige, ein Maßstabsbalken, ein eigener Wegpunkteditor und die Möglichkeit des Speicherns hinzugefügt werden.

4. Änderungen Kurswinkelflug

Bei den Test stellte sich heraus, dass die häufige Inkrementierung des Flugwinkels bei einer Abweichung einen negativen Einfluss auf die Regelung hat. Deswegen gingen wir dazu über nicht mehr die Winkel zu inkrementieren, sondern jedes mal wenn der Zeppelin in den Einflussbereich eines Wegpunktes kommt (Kreis mit Radius 60 cm ) den Winkel zwischen der gemessenen Istposition und dem nächsten Wegpunkt als absoluten Winkel an die Bodenstation zu senden. Somit hat die Regelung genug Zeit auf die neuen Winkel anhand der Sensordaten zu reagieren.

Wegen Ungenauigkeiten des Magnetsensors/Kompass auf dem Imu-Board sollten die Wegpunkte nicht zu weit ( ca. max 1,5m) auseinander liegen. Falls Wegpunkte nicht getroffen werden kann falls sich der über das IPS-Navigationssystem gemessene Abstand zum Wegpunkt wieder erhöht, und damit ein Entfernen stattfindet, neue Winkel berechnet werden. 

Drehungen über 90 Grad sind aber nicht zu empfehlen, da die Regelung sonst übersteuern.

IPS-SOFTWARE DOWNLOAD:

Die nötige aktuellste Softwareversion ist unter diesem Link zu finden https://github.com/Daedalus-TUM/ips-indoor-navigation. Bitte das README zum kompilieren beachten und vorher den Artikel "Gemeinsames IPS" durchlesen, in dem die nötigen Pythonpakete angegeben werden.