GPS-USB

Einleitung

Anfangs hauptsächlich noch für militärische Zwecke gedacht findet das „Global Positioning System“ (kurz: [GPS] ) seit seiner Einführung im Jahr 1995 auch zunehmend im zivilen Bereich Anwendung. Die Verbesserung des GPS selbst sowie die Entwicklung von Technologie, welche dieses nutzt, führt zu einer immer flexibleren und genaueren Positions - und Uhrzeitbestimmung. So ist es mittlerweile möglich, kontinentenweit die Position mittels GPS auf einen Meter genau zu bestimmen, mit speziellen Verfahren (wie z.B. Differential-GPS) auch auf Werte im Zentimeter-Bereich. Mit der Zeit erhöhte sich vor allem auch die Flexibilität und Handlichkeit von GPS-Empfängern, wodurch er mittlerweile möglich ist mittels eines USB-Sticks überall da, wo ein USB-Anschluss vorliegt, GPS-Signale zu empfangen. Im vorliegenden Projekt soll dokumentiert werden, wie man sein System für solch einen solchen USB-Sticks (hier einer der Firma U-blox7) konfiguriert, Signale empfängt und sie anzeigt. Obendrein soll ein kleines Programm einen kurzen Einblick in die Verarbeitung dieser Daten geben, um z.B. Entfernungen zu anderen Objekten zu bestimmen. Zuvor jedoch folgt eine kurze Erläuterung des Funktionsprinzips des GPS sowie die technischen Daten und Funktionsweise eines solchen GPS - Empfängers im USB-Stick-Format.

Das Global - Positioning - System

Das GPS umfasst 24 Satelliten, welche jeweils zu viert auf 6 verschieden hohen Umlaufbahnen die Erde umkreisen. Diese senden konstant ein codiertes Radiosignal, welches Position sowie Sendezeitpunkt des Signals des Satelliten beinhaltet. Zur Bestimmung der Position müssen dabei mindestens 3 Satelliten zur Berechnung herangezogen werden, wobei mit steigender Anzahl der verendetetn Satellitensignale die Genauigkeit der Positionsbestimmung steigt. . Da die Position des Empfängers für jeden Satelliten eine Kugel mit dem Radius der Entfernung darstellt, reichen 3 Satelliten, um aus dem Schnittbild dieser 3 Kugeln die Position des Empfängers zu bestimmen.

Abb.Nr.1: Trilateration zur Positionsbestimmung / Quelle: https://gisgeography.com/trilateration-triangulation-gps/

Aufbau von GPS - Daten

Das für zivile Einheiten relevante L1 - Signal, welches vom GPS gesendet wird, verwendet den sogenannten C/A - Code. Dieser stellt eine pseudozufällige Reihe von 1023 Bits dar. Jeder Satellit sendet dabei einen eigenen solchen Code aus, welcher im Aufbau recht komplex ist. Diese Komplexität stellt sicher, dass Streusignale anderer Quellen nicht für GPS - Signale gehalten werden sowie Satelliten des GPS eindeutig voneinander unterschieden werden können. Jeder Satellit sendet diesen Code mit einer eigenen Codephasenverschiebung aus. Dies stellt sicher, dass diese trotz gleicher gesendeter Frequenz eindeutig unterschieden werden können.

Der GPS - Receiver VK-172

Dieser Empfänger aktualisiert seine Position in einem Bereich von 1 - 10 Hertz. Die Genauigkeit der Positionsbestimmung beträgt weniger als 2,5 Meter. Bei der Messung von Geschwindigkeiten kann auf weniger als 0,02 m/s gemessen werden, die Änderung der Richtung kann auf weniger als 0,5 Grad genau bestimmt werden. Da das Modul A-GPS unterstützt, ist es möglich das Modul auch in einem mit WLAN - Funknetz ausgestatteten Gebäude zu verwenden, da hier die Funknetzdaten zusätzlich zur Positionsbestimmung herangezogen werden können.

ISS-Tracker

Ein interesannter Versuch mit einem solchen Usb Dongle ist, die eigenen Koordinaten mit anderen Koordinaten zu vergleichen. Um das ganze nun interessanter zu machen vergleichen wir unsere Koordinaten mit denen der ISS. Diese sind im Internet frei verfügbar und können durch eine bereitgestellte [API] von jedem abgefragt werden. Die API die hier benutzt wird findet man unter: http://api.open-notify.org/iss-now.json

Alternativ kann man auf dieser Seite: https://www.astroviewer.net/iss/de/ genau sehen über welchem Kontinent sich die Raumstation befindet.

Abb.Nr.2 Flugbahn der ISS / Quelle: https://www.esa.int/Science_Exploration/Human_and_Robotic_Exploration/International_Space_Station/Where_is_the_International_Space_Station

Unsere eigene Position wird mit hilfe des USB-Sticks ausgegeben. Wir benutzen den Deamon [gpsd] welcher uns ohne Datenverlust die empfangenen Daten der Satelliten bereitstellnt. Dieser lässt sich einfach über das Terminal mit $ sudo apt install gpsd gpsd-clients installieren. Nun kann man mit Programen wie cgps oder gpsmon schon seine eigenen Koordinaten ausgeben lassen. Um aber gpsd in seinem eigenen code verwenden zu wollen, muss man die Libary gps in sein script einbinden.

from gps import *

running = True
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)

In meinem Code wird die Libary eingebunden und die classe gpsd initialisiert. Die Funktion für die Abfrage der Koordinaten sieht dann wie folgt aus.

1
2
3
4
5
6
7
8
9
def getmy():
    now = gpsd.next()
    if now['class'] == 'TPV':
        latM = (getattr(now,'lat'))
        lonM = (getattr(now,'lon'))
    else:
        latM = 51.48
        lonM = -0.01
    return latM, lonM

In Zeile 3 wird überprüft ob das richtige Protokoll der Satelliten ausgelesen wird, denn Latitude und Longitude stehen in TPV. TPV steht für Time Position Velocity und gibt uns hier die nötigen Informationen mit Zeile 4 und 5. getattr(now,'lat') gibt uns also einen String mit den gpsd Daten über Latitude aus. Sollte es nicht der Fall sein das wir guten Empfang haben oder ein anderes Protokoll gerade übertragen wird schreiben wir in unsere Latitude und Longitude Variablen die Koordinaten von Greenwich. Anderfalls würde 0 oder „unknown“ übergeben werden. Zum Schluss wird ein Tuple zurückgegeben.

Die Funktion für die Koordinaten der ISS funktioniert etwas anders, weil auf die API zugegriffen werden muss.

1
2
3
4
5
6
7
8
9
def getiss():
    url = "http://api.open-notify.org/iss-now.json"
    response = urllib.request.urlopen(url)
    result = json.loads(response.read())
    issPos = result["iss_position"]
    latI = issPos['latitude']
    lonI = issPos['longitude']

    return latI,lonI

In Zeile 2 wird zuerst die URL der API übergeben und in Zeile 2-3 die Antwort der API abgefragt. Wenn man auf den Link klickt kann man sehen unter welcherm Namen die nötigen Daten zu finden sind. In unseren Fall unter iss_position und wieder latitude beziehungsweise longitude. Zurückgegeben wird wieder ein Tuple.

Bevor nun die Schleife losgeht hab ich noch eine Funktion zum ermitteln der Distanz zwischen ISS und der Eigenen Position geschrieben.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def getdistance(latI,lonI,latM,lonM):
    latI = float(latI)
    lonI = float(lonI)
    latM = float(latM)
    lonM = float(lonM)
    dy = 111.3 * (latI - latM)
    lat = (latI + latM) / 2 * 0.01745
    dx = 111.3 * np.cos(lat) * (lonI - lonM)
    distance = np.sqrt(dx*dx + dy*dy)
    distance = round(distance,2)
return distance

Zuerst müssen die ganzen Übergeben Strings zu Floats gecastet werden. Anders lässt sich nicht mit den Werten rechnen. Danach funktioniert alles ähnlich wie beim Pythagoras, da die Erde wie ein Koordinatensystem aufgeteilt ist. Hierbei gibt es allerdings eine Schwierigkeit. Der Abstand zwischen zwei Breitenkreisen ist immer konstant 111.3 km. Allerdings ist der Abstand zwischen Längenkreisen nicht konstant. Am Äquator ist dieser zwar auch 111.3km an den Polen ist dieser allerdings annähernd 0. Die Formel für die Berechnung sieht so aus: 111.3 * cos(latitude). Die cos() funktion erwarten jetzt aber einen Wert im Bogenmaß. Also müssen wir den wert der Latitude mit 0.01745 multiplizieren was 1° entspricht.

Das einzige was jetzt noch fehlt ist die Schleife und die Ausgabe.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
while running:
    latI, lonI = getiss()
    latI = round(float(latI),2)
    lonI = round(float(lonI),2)
    iss = str(latI)+"/"+str(lonI)
    latM, lonM = getmy()
    latM = round(float(latM),2)
    lonM = round(float(lonM),2)
    my = str(latM)+"/"+str(lonM)
    distance = getdistance(latI,lonI,latM,lonM)

    print("ISS = [" + str(iss) + "]  My = [" + str(my)+"]  Distanz = " + str(distance) + " km   ",end = "\r")
    time.sleep(1)

Hier werden die Tuple der Funktion getiss() und getmy() entpackt und die Werte für die Distanzfunktion gerundet und gecastet. Anschließend wird ein String erstellt welche die Koordinaten formatiert wiedergibt. In einer print Ausgabe wird dann Alles zusammengesetzt. Das fertige Programm läuft dann wie folgt und um zu beweisen das es funkioniert sieht man im Video die aktuelle Position der ISS über die Website: https://www.astroviewer.net/iss/de/

Video Nr.1 Funktion des ISS-Trackers

Fazit

Die Handlichkeit und Stromversorgung über USB machen diesen Stick für viele Use - Cases zum perfekten GPS - Empfänger. Eine relativ hohe Genauigkeit bei Positions- Geschwindigkeits- sowie Richtungsbestimmung führen zu einem breiten Anwendungsspektrum im Hobbybereich, wobei die sehr unkompliziert gehaltene Einrichtung und Verwendung mittels eines Desktoprechners oder Laptops sowie der geringe Preis wohl die Hauptargumente für die Verwendung dieses Moduls darstellen dürften. Ein weiterer interessanter Use - Case stellt den Empfang der Satelliten - Zeit des GPS dar. Da der Empfänger über mindestens 4 Satelliten, welche allesamt über eine Atomuhr verfügen, die Zeit bezieht kann diese auch vom eigenen System verwendet werden und weist i.d.R. eine höhere Genauigkeit als die Zeitangaben anderer Quellen auf.

Literaturangaben

[gpsd]Wiki zu gpsd (besucht am 5.12.21) https://gpsd.gitlab.io/gpsd/
[API]Erklärung zum Begriff API (besucht am 5.12.21) https://www.mulesoft.com/de/resources/api/what-is-an-api
[GPS]Erläuterung des GPS https://www.trimble.com/gps_tutorial/howgps-measuring.aspx