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
print 'latitude\tlongitude\ttime utc\t\t\taltitude\tepv\tept\tspeed\tclimb' # '\t' = TAB to try and output the data in columns.

	while True:
		report = #
		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"
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
	while True:
		report = #
		if report['class'] == 'SKY':
			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?'

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

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"
        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()


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_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()

14 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.

  4. Is there a way to specify which serial port the gps library gathers data from? I’m using the USB to USB connector between the GPS/GSM and rPi so my NMEA sentences are piped to ttyACM3, not serial0

    1. The first and second pieces of code use GPSD, which means you would need to update the GPSD config file;
      sudo nano /etc/default/gpsd
      And for the 3rd example, you can change the port on line 3

  5. Is there any example Python code showing how to read the GPS using the i2c interface on a Raspberry Pi ?

  6. Hi

    I have a G-STAR IV GPS receiver, and I want to get the $GPZDA to get the time and i want to get the : Hoarse, Minutes, Seconds, and Milliseconds from the GPS from the Raspberry Pi code.

    How can I write a code that can give me the GPS time including the Milliseconds ?

    thank you

  7. Thanks for this useful information. I am trying to parse using your $GPRMC example, however my raw data looks like this:
    Consequently it never finds anything to parse.
    Any idea why I have the extra characters at each end of the GPRMC sentence? I am using a GPS on a usb serial port on a RaspberryPi.

  8. It looks like there is something else wrong – the extra characters “b” and “\r\n” are not part of the data and are not causing a problem. The problem is that the “if data[0:6] ==”$GPRMC”: statement never comes true even if data[0:6] is $GPRMC. I’ve not used python before so maybe I’m missing the obvious…

  9. OK, so i eventually worked out that the b means the data is binary. However the code is written for string. Easily fixed by changing
    str = serialPort.readline()
    str = serialPort.readline().decode()

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.