Los topógrafos utilizan sistemas GPS diferenciales para obtener ubicaciones precisas. Un GPS estacionario y un vagabundo trabajar juntos para cancelar algunos errores.Pensé que podría construir un GPS diferencial para pobres con dos GPS económicos recopilando los datos de ambos y restando los vectores de movimiento del dispositivo estacionario del rover. Pero esto no funciona con los GPS de consumo. Si yo d lee primero , podría haber ido directamente a...
Promediar varias salidas de GPS de dispositivos adyacentes produce una mejor respuesta que un solo dispositivo.Terminé con tres en el alféizar de una ventana, alimentando una máquina Linux a través de puertos USB.
USB GPSs in a windowGPS USB en una ventana
Cometí otro error cuando escribí el código de Python que lee los dispositivos, cerca del final:
### 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()
El código se repite para siempre, leyendo cada uno de los tres dispositivos, buscando el GPRMC mensaje que tiene los datos interesantes e imprimir un mensaje formateado en el archivo de salida. En retrospectiva, esa declaración de impresión simple debería haber formateado los datos para que tuvieran la forma que eventualmente quería. Lo que tengo es un archivo como
2017-06-29T13:59:59, 35.111,-78.222,35.112,-78.223,35.113,-78.224
donde 35 y -78 son latitud y longitud, aproximadamente. Pero lo que voy a querer está bastante reorganizado:
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
donde el final 1,2,3 identifica el sensor. Como podría volver a importar los datos, escribí este JSL para hacer la conversión. (En realidad, la mayor parte del código es para producir las imágenes, notas al final).
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>
Busque la función abierta para "gpsLog3.txt". Tiene el script que copié de una tabla de datos con la que me ayudó la vista previa de importación. Las siguientes líneas eliminan algunas filas con datos no válidos. Solo hubo 6 malos; No estoy seguro de por qué el GPS en el canal 2 informó 0,0.
Las siguientes líneas crean lat9,lon9 como el promedio de lat1,2,3 y lon1,2,3. Un mensaje <
El siguiente paso crea subconjuntos con solo las columnas que se concatenarán, les cambia el nombre y agrega la variable id. Luego, las tablas se concatenan, las tablas innecesarias se cierran.
La tabla de resumen que se genera a continuación se usa para establecer líneas de referencia y límites de eje en el GraphBuilder que sigue. Luego, hay algunos bucles para impulsar una secuencia de animación en el generador de gráficos (y la extraña función al principio para tomar fotografías).
- Tomé prestado un código de github para manejar algunos de los problemas de NMEA GPS, ¡gracias, Knio!
- Si intenta hacer esto, probablemente también necesitará "sudo adduser $ USER dialout", búsquelo.
Explaining the density ellipse in the videoExplicando la elipse de densidad en el video
El Deambular por GPS video.