Add serial GPS support (possibly buggy)

bearings
Mark Jessop 2018-08-28 22:48:29 +09:30
rodzic af84d5442c
commit 3686e84581
4 zmienionych plików z 47 dodań i 7 usunięć

Wyświetl plik

@ -56,6 +56,10 @@ def parse_config_file(filename):
chase_config['car_gpsd_host'] = config.get('gpsd','gpsd_host') chase_config['car_gpsd_host'] = config.get('gpsd','gpsd_host')
chase_config['car_gpsd_port'] = config.getint('gpsd','gpsd_port') chase_config['car_gpsd_port'] = config.getint('gpsd','gpsd_port')
# Serial GPS Settings
chase_config['car_serial_port'] = config.get('gps_serial', 'gps_port')
chase_config['car_serial_baud'] = config.getint('gps_serial', 'gps_baud')
# Predictor # Predictor
chase_config['pred_enabled'] = config.getboolean('predictor', 'predictor_enabled') chase_config['pred_enabled'] = config.getboolean('predictor', 'predictor_enabled')
chase_config['pred_burst'] = config.getfloat('predictor', 'default_burst') chase_config['pred_burst'] = config.getfloat('predictor', 'default_burst')

Wyświetl plik

@ -21,12 +21,14 @@ class SerialGPS(object):
serial_port = '/dev/ttyUSB0', serial_port = '/dev/ttyUSB0',
serial_baud = 9600, serial_baud = 9600,
timeout = 5, timeout = 5,
callback = None): callback = None,
uberdebug = False):
''' '''
Initialise a SerialGPS object. Initialise a SerialGPS object.
This class assumes the serial-connected GPS outputs GPRMC and GPGGA NMEA strings This class assumes the serial-connected GPS outputs GPRMC and GPGGA NMEA strings
using 8N1 RS232 framing. using 8N1 RS232 framing. It also assumes the GPGGA string is send after GPRMC. If this
is not the case, position data may be up to 1 second out.
Args: Args:
serial_port (str): Serial port (i.e. '/dev/ttyUSB0', or 'COM1') to receive data from. serial_port (str): Serial port (i.e. '/dev/ttyUSB0', or 'COM1') to receive data from.
@ -48,9 +50,11 @@ class SerialGPS(object):
self.serial_baud = serial_baud self.serial_baud = serial_baud
self.timeout = timeout self.timeout = timeout
self.callback = callback self.callback = callback
self.uberdebug = uberdebug
# Current GPS state, in a format which matches the Horus UDP # Current GPS state, in a format which matches the Horus UDP
# 'Chase Car Position' message. # 'Chase Car Position' message.
# Note that these packets do not contain a timestamp.
self.gps_state = { self.gps_state = {
'type': 'GPS', 'type': 'GPS',
'latitude': 0.0, 'latitude': 0.0,
@ -103,7 +107,7 @@ class SerialGPS(object):
while self.ser == None and self.serial_thread_running: while self.ser == None and self.serial_thread_running:
try: try:
self.ser = serial.Serial(port=self.serial_port,baudrate=self.serial_baud,timeout=self.timeout) self.ser = serial.Serial(port=self.serial_port,baudrate=self.serial_baud,timeout=self.timeout)
logging.info("SerialGPS - Connected to serial port.") logging.info("SerialGPS - Connected to serial port %s" % self.serial_port)
except Exception as e: except Exception as e:
# Continue re-trying until we can connect to the serial port. # Continue re-trying until we can connect to the serial port.
# This should let the user connect the gps *after* this object if instantiated if required. # This should let the user connect the gps *after* this object if instantiated if required.
@ -126,6 +130,7 @@ class SerialGPS(object):
try: try:
self.parse_nmea(data.decode('ascii')) self.parse_nmea(data.decode('ascii'))
except: except:
traceback.print_exc()
pass pass
# Clean up before exiting thread. # Clean up before exiting thread.
@ -157,6 +162,9 @@ class SerialGPS(object):
If we have received a GPGGA string containing a position valid flag, If we have received a GPGGA string containing a position valid flag,
send the data on to the callback function. send the data on to the callback function.
''' '''
if self.uberdebug:
print(data.strip())
if "$GPRMC" in data: if "$GPRMC" in data:
logging.debug("SerialGPS - Got GPRMC.") logging.debug("SerialGPS - Got GPRMC.")
gprmc = data.split(",") gprmc = data.split(",")
@ -227,6 +235,17 @@ class SerialGPS(object):
logging.error("SerialGPS - Error Passing data to callback - %s" % str(e)) logging.error("SerialGPS - Error Passing data to callback - %s" % str(e))
class GPSDGPS(object):
''' Read GPS data from a GPSD server '''
def __init__(self,
hostname = '127.0.0.1',
port = 2947,
callback = None):
''' Init '''
pass
if __name__ == '__main__': if __name__ == '__main__':
import sys, time import sys, time
logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', level=logging.DEBUG) logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', level=logging.DEBUG)
@ -236,8 +255,8 @@ if __name__ == '__main__':
def print_data(data): def print_data(data):
print(data) print(data)
_gps = SerialGPS(serial_port=_port, serial_baud=_baud, callback=print_data) _gps = SerialGPS(serial_port=_port, serial_baud=_baud, callback=print_data, uberdebug=True)
time.sleep(20) time.sleep(100)
_gps.close() _gps.close()

Wyświetl plik

@ -28,6 +28,7 @@ telemetry_source_port = 8942
# Car Position Source # Car Position Source
# none - No Chase-Car GPS # none - No Chase-Car GPS
# horus_udp - Read Horus UDP Broadcast 'Car GPS' messages # horus_udp - Read Horus UDP Broadcast 'Car GPS' messages
# serial - Read GPS positions from a serial-connected GPS receiver.
# gpsd - Poll GPSD for positions (TO BE IMPLEMENTED) # gpsd - Poll GPSD for positions (TO BE IMPLEMENTED)
car_source_type = horus_udp car_source_type = horus_udp
# Car position source port (UDP) - only used if horus_udp is selected # Car position source port (UDP) - only used if horus_udp is selected
@ -46,11 +47,18 @@ car_source_port = 55672
[gpsd] [gpsd]
# GPSD Host/Port - Only used if selected in the telemetry profile # GPSD Host/Port - Only used if selected in a telemetry profile above.
# TO BE IMPLEMENTED # TO BE IMPLEMENTED
gpsd_host = localhost gpsd_host = localhost
gpsd_port = 2947 gpsd_port = 2947
[gps_serial]
# Serial GPS Settings - Only used if selected in a telemetry profile above.
# GPS serial device (i.e. /dev/ttyUSB0, COM1, etc...)
gps_port = /dev/ttyUSB0
# GPS baud rate
gps_baud = 9600
# Map Defaults # Map Defaults
[map] [map]

Wyświetl plik

@ -20,6 +20,7 @@ from dateutil.parser import parse
from chasemapper.config import * from chasemapper.config import *
from chasemapper.earthmaths import * from chasemapper.earthmaths import *
from chasemapper.geometry import * from chasemapper.geometry import *
from chasemapper.gps import SerialGPS, GPSDGPS
from chasemapper.atmosphere import time_to_landing from chasemapper.atmosphere import time_to_landing
from chasemapper.listeners import OziListener, UDPListener from chasemapper.listeners import OziListener, UDPListener
from chasemapper.predictor import predictor_spawn_download, model_download_running from chasemapper.predictor import predictor_spawn_download, model_download_running
@ -588,7 +589,7 @@ def start_listeners(profile):
try: try:
_thread.close() _thread.close()
except Exception as e: except Exception as e:
logging.error("Error closing thread.") logging.error("Error closing thread - %s" % str(e))
# Reset the listeners array. # Reset the listeners array.
data_listeners = [] data_listeners = []
@ -635,6 +636,14 @@ def start_listeners(profile):
# GPSD Car Position Source - TODO # GPSD Car Position Source - TODO
logging.info("Starting GPSD Car Position Listener.") logging.info("Starting GPSD Car Position Listener.")
elif profile['car_source_type'] == "serial":
# Serial GPS Source.
logging.info("Starting Serial GPS Listener.")
_serial_gps = SerialGPS(serial_port=chasemapper_config['car_serial_port'],
serial_baud=chasemapper_config['car_serial_baud'],
callback=udp_listener_car_callback)
data_listeners.append(_serial_gps)
else: else:
# No Car position. # No Car position.
logging.info("No car position data source.") logging.info("No car position data source.")