Using python with a GPS receiver on a Raspberry Pi

Here are three examples of how to  use python to get GPS data from a GPS receiver attached to a Raspberry Pi.

  1. Using GPSD client libraries
  2. Manually parsing NMEA sentences
  3. Using  pynmea2 to parse NMEA sentences

GPSD client libraries

The gpsd client libraries are based on JSON. The JSON objects have a "class" attribute (E.g. TPV,  SKY, DEVICE.etc...)  which can be used to filter on different information.

This guide shows how to get gpsd up an running on a Raspberry Pi.

The example python  script below filters on the TPV class, which is the Time Position Velocity report and then prints out the relevant information.

#! /usr/bin/python

from gps import *
import time
   
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE) 
print 'latitude\tlongitude\ttime utc\t\t\taltitude\tepv\tept\tspeed\tclimb' # '\t' = TAB to try and output the data in columns.
  
try:


	while True:
		report = gpsd.next() #
		if report['class'] == 'TPV':
			
			print  getattr(report,'lat',0.0),"\t",
			print  getattr(report,'lon',0.0),"\t",
			print getattr(report,'time',''),"\t",
			print  getattr(report,'alt','nan'),"\t\t",
			print  getattr(report,'epv','nan'),"\t",
			print  getattr(report,'ept','nan'),"\t",
			print  getattr(report,'speed','nan'),"\t",
			print getattr(report,'climb','nan'),"\t"

		time.sleep(1) 

except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
	print "Done.\nExiting."

 

 

This python script filters on the SKY class and prints out satellite information.




#! /usr/bin/python

from gps import *
import time
import os
   
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE) 
  
try:
	while True:
		
		report = gpsd.next() #
		if report['class'] == 'SKY':
			os.system('clear')
			print ' Satellites (total of', len(gpsd.satellites) , ' in view)'
			for i in gpsd.satellites:
				print 't', i

		
			print '\n\n'
			print 'PRN = PRN ID of the satellite. 1-63 are GNSS satellites, 64-96 are GLONASS satellites, 100-164 are SBAS satellites'
			print 'E = Elevation in degrees'
			print 'As = Azimuth, degrees from true north'
			print 'ss = Signal stength in dB'
			print 'used = Used in current solution?'

		time.sleep(1) 


except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
	print "Done.\nExiting."


BerryGPS Raspberry Pi GPS

Manually parsing NMEA sentences

The python script below shows how to access GPS data by connecting directly to the serial interface.
It filters on $GPRMC NMEA sentences and then splits the well know attributes into different variables.



import serial

port = "/dev/serial0"

def parseGPS(data):
#    print "raw:", data #prints raw data
    if data[0:6] == "$GPRMC":
        sdata = data.split(",")
        if sdata[2] == 'V':
            print "no satellite data available"
            return
        print "---Parsing GPRMC---",
        time = sdata[1][0:2] + ":" + sdata[1][2:4] + ":" + sdata[1][4:6]
        lat = decode(sdata[3]) #latitude
        dirLat = sdata[4]      #latitude direction N/S
        lon = decode(sdata[5]) #longitute
        dirLon = sdata[6]      #longitude direction E/W
        speed = sdata[7]       #Speed in knots
        trCourse = sdata[8]    #True course
        date = sdata[9][0:2] + "/" + sdata[9][2:4] + "/" + sdata[9][4:6]#date

        print "time : %s, latitude : %s(%s), longitude : %s(%s), speed : %s, True Course : %s, Date : %s" %  (time,lat,dirLat,lon,dirLon,speed,trCourse,date)

def decode(coord):
    #Converts DDDMM.MMMMM > DD deg MM.MMMMM min
    x = coord.split(".")
    head = x[0]
    tail = x[1]
    deg = head[0:-2]
    min = head[-2:]
    return deg + " deg " + min + "." + tail + " min"


print "Receiving GPS data"
ser = serial.Serial(port, baudrate = 9600, timeout = 0.5)
while True:
   data = ser.readline()
   parseGPS(data)


 

Using  pynmea2 to parse NMEA sentences

The python script below shows how to access GPS data by connecting directly to the serial interface.
It filters on $GPGGA NMEA sentences and then uses pynmea2 to parse the data.

Pynmea2 can be installed with;

pi@raspberrypi ~ $ pip install pynmea2

import serial
import pynmea2

port = "/dev/serial0"

def parseGPS(str):
    if str.find('GGA') > 0:
        msg = pynmea2.parse(str)
        print "Timestamp: %s -- Lat: %s %s -- Lon: %s %s -- Altitude: %s %s -- Satellites: %s" % (msg.timestamp,msg.lat,msg.lat_dir,msg.lon,msg.lon_dir,msg.altitude,msg.altitude_units,msg.num_sats)


serialPort = serial.Serial(port, baudrate = 9600, timeout = 0.5)
while True:
    str = serialPort.readline()
    parseGPS(str)

4 thoughts on “Using python with a GPS receiver on a Raspberry Pi”

  1. What instance would you use NMEA over GPSD?
    This is the first time I've looked into using pi for gps so keep it simple please 🙂

  2. Thank you very much you have helped me immensely putting a link to the documentation. I was using SKY for the longest time and wondering why I wasn't able to get all of the data I wanted.

  3. Regarding the question on using gpsd versus nmea. The gpsd client is a full featured gps interface that enables high level programming interface for gps data for lots of conceiveable applications but the price for that is the application programmer does not have visibility into the actual performance of the gps interface and the data. The gps function involves satellites that may or may not be in view and a fairly weak signal that is not received reliably (like not indoors- not unless the signal can leak into the building .) The gpsd software library may not converge for many minutes to compute a gps location so if you application uses a gps computed location of the receiver the programmer must deal with variable delays. With the nmea the software interface to the receiver just uses the serial port and gives access to the low level data which is text based characters, The data is easily parsed and so the programmer can can just check the message streams for a message type that has information his/her application needs. NMEA messages are computed by the gps receiver every second. If the receiver can't figure out a location solution a message like the $GGA message will have something like "-/-" in a lat/long field. The application program can then keep reading messages until lat/long shows numbers or report a status of a problem. Much simpler to program but certainly not full featured. The trade-off is for the programmer to decide how to use the gps receiver interface and then make the function robust.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.