Vermessungsingenieure verwenden differenzielle GPS-Systeme, um genaue Standorte zu erhalten. Ein stationäres GPS und ein Rover zusammenarbeiten, um einige Fehler auszugleichen.Ich dachte, ich könnte mit zwei preiswerten GPSs ein differentielles GPS für Arme bauen, indem ich die Daten von beiden sammle und die Bewegungsvektoren des stationären Geräts vom Rover subtrahiere. Dies funktioniert jedoch nicht mit Consumer-GPS. Wenn ich würde erstmal nachlesen , ich wäre vielleicht direkt zu...
Die Mittelung mehrerer GPS-Ausgaben von benachbarten Geräten liefert eine bessere Antwort als ein einzelnes Gerät.Ich landete mit drei auf einer Fensterbank und fütterte eine Linux-Maschine über USB-Ports.
USB GPSs in a windowUSB GPSs in a windowUSB GPSs in a windowUSB GPSs in a windowUSB-GPSs in einem Fenster
Ich habe einen weiteren Fehler gemacht, als ich den Python-Code geschrieben habe, der die Geräte gegen Ende liest:
### edited for presentation, may not be functional without some TLC
# dmesg after plug in gives usb port info
import serial
import math
import re
import datetime
import sys
# https://github.com/Knio/pynmea2/blob/master/pynmea2/nmea_utils.py
def timestamp(s):
'''
Converts a timestamp given in "hhmmss[.ss]" ASCII format to a
datetime.time object
'''
ms_s = s[6:]
ms = ms_s and int(float(ms_s) * 1000000) or 0
t = datetime.time(
hour=int(s[0:2]),
minute=int(s[2:4]),
second=int(s[4:6]),
microsecond=ms)
return t
def datestamp(s):
'''
Converts a datestamp given in "DDMMYY" ASCII format to a
datetime.datetime object
'''
return datetime.datetime.strptime(s, '%d%m%y').date()
def dm_to_sd(dm):
'''
Converts a geographic coordiante given in "degres/minutes" dddmm.mmmm
format (ie, "12319.943281" = 123 degrees, 19.953281 minutes) to a signed
decimal (python float) format
'''
# '12319.943281'
if not dm or dm == '0':
return 0.
d, m = re.match(r'^(\d+)(\d\d\.\d+)$', dm).groups()
return float(d) + float(m) / 60
ser0 = serial.Serial('/dev/ttyACM0', 2*9600)
ser1 = serial.Serial('/dev/ttyACM1', 2*9600)
ser2 = serial.Serial('/dev/ttyACM2', 2*9600)
lat0=0
lon0=0
lat1=0
lon1=0
lat2=0
lon2=0
time = ""
while True :
state=ser0.readline().split(",")
if state[0]=="$GPRMC":
lat0 = dm_to_sd(state[3])
lon0 = -dm_to_sd(state[5])
time = datetime.datetime.combine(datestamp(state[9]), timestamp(state[1]))
state=ser1.readline().split(",")
if state[0]=="$GPRMC":
lat1 = dm_to_sd(state[3])
lon1 = -dm_to_sd(state[5])
time = datetime.datetime.combine(datestamp(state[9]), timestamp(state[1]))
state=ser2.readline().split(",")
if state[0]=="$GPRMC":
lat2 = dm_to_sd(state[3])
lon2 = -dm_to_sd(state[5])
time = datetime.datetime.combine(datestamp(state[9]), timestamp(state[1]))
print time.strftime("%Y-%m-%dT%H:%M:%S")+","+str(lat0)+","+str(lon0)+","+str(lat1)+","+str(lon1)+","+str(lat2)+","+str(lon2)
sys.stdout.flush()
Der Code wiederholt sich für immer, liest jedes der drei Geräte und sucht nach dem GPRMC Nachricht, die die interessanten Daten enthält, und Drucken einer formatierten Nachricht in die Ausgabedatei. Im Nachhinein hätte diese einfache Druckanweisung die Daten so formatieren sollen, dass sie die Form haben, die ich letztendlich wollte. Was ich habe, ist eine Datei wie
2017-06-29T13:59:59, 35.111,-78.222,35.112,-78.223,35.113,-78.224
wobei 35 und -78 ungefähr Breite und Länge sind. Aber was ich will, ist ziemlich umgestellt:
2017-06-29T13:59:59, 35.111,-78.222,1
2017-06-29T13:59:59, 35.112,-78.223,2
2017-06-29T13:59:59, 35.113,-78.224,3
wobei die nachgestellten 1,2,3 den Sensor identifizieren. Da ich die Daten möglicherweise erneut importieren muss, habe ich diese JSL geschrieben, um die Konvertierung durchzuführen. (Eigentlich dient der größte Teil des Codes dazu, die Bilder zu erzeugen, Notizen am Ende.)
colors={{255,0,0},{0,255,0},{0,0,255},{0,0,0}};
ipicture=1e7; // sequence number with leading digit
path="H:\GPSWander\images\";
takePicture = function({},
// {filename=path||"gps"||char(ipicture++)||".png"},
// Report( gb )[framebox( 1 )]<<SAVEPICTURE>= .003, trans = trans * .80,
Report( gb )[framebox( 1 )] << Transparency( trans );
takePicture();
);
Report( gb )[framebox( 1 )] << Transparency( 1.0 );
Report( gb )[framebox( 1 )] << Marker Size( 2 );
dt << selectrows( 5 :: N Rows( dt ) );
dt << hide( 1 );
dt << clearselect;
step = N Rows( dt ) / 10000; // frames in video
For( i = 1, i < N Rows( dt ), i += step,
dt << selectrows( i :: i + step + step + step + step ); // trail
dt << hide( 0 );
takePicture();
dt << hide( 1 );
dt << clearselect;
);
</SAVEPICTURE>
Suchen Sie nach der Open-Funktion für "gpsLog3.txt". Es hat das Skript, das ich aus einer Datentabelle kopiert habe, bei der mir die Importvorschau geholfen hat. Die nächsten Zeilen löschen einige Zeilen mit ungültigen Daten. Es gab nur 6 schlechte; Ich bin mir nicht sicher, warum das GPS auf Kanal 2 0,0 gemeldet hat.
Die nächsten paar Zeilen erzeugen lat9,lon9 als Durchschnitt von lat1,2,3 und lon1,2,3. Eine <
Der nächste Schritt erstellt Teilmengen mit nur den zu verkettenden Spalten, benennt sie um und fügt die ID-Variable hinzu. Dann werden die Tabellen verkettet, nicht benötigte Tabellen geschlossen.
Die als nächstes generierte Übersichtstabelle wird verwendet, um Reflines und Achsenbegrenzungen im folgenden GraphBuilder festzulegen. Dann gibt es einige Schleifen, um eine Animationssequenz im Graph Builder zu steuern (und die seltsame Funktion am Anfang, um Bilder aufzunehmen.)
- Ich habe mir etwas Github-Code ausgeliehen, um einige der NMEA-GPS-Probleme zu lösen, danke Knio!
- Wenn Sie dies versuchen, benötigen Sie wahrscheinlich auch "sudo adduser $USER dialout", schlagen Sie nach.
Explaining the density ellipse in the videoExplaining the density ellipse in the videoExplaining the density ellipse in the videoExplaining the density ellipse in the videoErklärung der Dichteellipse im Video
Der GPS-Wanderung Video.