I geometri utilizzano sistemi GPS differenziali per ottenere posizioni precise. Un GPS fisso e un rover lavorare insieme per cancellare alcuni errori.Ho pensato di poter costruire un GPS differenziale per poveri con due GPS economici raccogliendo i dati da entrambi e sottraendo i vettori di movimento del dispositivo fisso dal rover. Ma questo non funziona con i GPS di livello consumer. Se lo farei prima leggi , potrei essere andato direttamente a...
La media di diverse uscite GPS da dispositivi adiacenti produce una risposta migliore rispetto a un singolo dispositivo.Sono finito con tre sul davanzale di una finestra, alimentando una macchina Linux tramite porte USB.
USB GPSs in a windowGPS USB in una finestra
Ho commesso un altro errore quando ho scritto il codice Python che legge i dispositivi, verso la fine:
### 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()
Il codice si ripete all'infinito, leggendo ciascuno dei tre dispositivi, cercando il file GPRMC messaggio che contiene i dati interessanti e stampa un messaggio formattato nel file di output. In retrospettiva, quella semplice dichiarazione di stampa avrebbe dovuto formattare i dati in modo che fossero la forma che alla fine volevo. Quello che ho è un file come
2017-06-29T13:59:59, 35.111,-78.222,35.112,-78.223,35.113,-78.224
dove 35 e -78 sono latitudine e longitudine, approssimativamente. Ma quello che voglio è un po' riorganizzato:
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
dove il finale 1,2,3 identifica il sensore. Poiché potrei importare nuovamente i dati, ho scritto questo JSL per eseguire la conversione. (In realtà la maggior parte del codice serve a produrre le immagini, note alla fine.)
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>
Cerca la funzione aperta per "gpsLog3.txt". Ha lo script che ho copiato da una tabella di dati con cui l'anteprima di importazione mi ha aiutato. Le righe successive eliminano alcune righe con dati non validi. C'erano solo 6 cattivi; Non sono sicuro del motivo per cui il GPS sul canale 2 ha riportato 0,0.
Le righe successive creano lat9,lon9 come media di lat1,2,3 e lon1,2,3. Un messaggio <
Il passaggio successivo crea dei sottoinsiemi con solo le colonne da concatenare, li rinomina, aggiunge la variabile id. Quindi le tabelle vengono concatenate, le tabelle non necessarie vengono chiuse.
La tabella di riepilogo che viene generata successivamente viene utilizzata per impostare le linee di riferimento ei limiti degli assi nel GraphBuilder che segue. Poi ci sono alcuni loop per guidare una sequenza di animazione nel generatore di grafici (e la strana funzione all'inizio per scattare foto).
- Ho preso in prestito del codice github per gestire alcuni dei problemi del GPS NMEA, grazie Knio!
- Se provi a farlo, probabilmente avrai bisogno anche di "sudo adduser $USER dialout", cercalo.
Explaining the density ellipse in the videoSpiegazione dell'ellisse di densità nel video
IL Navigazione GPS video.