Getting GPSd to work with Python and Threading

Publié le par duteil

I bought a few Raspberry Pis with great ambition of doing something awesome with them. Beyond showing my co-workers how cool I was for having them, the Raspberry Pis  pretty much just sat on my desk collecting dust. A month or two after getting them I realized that the Pis would fit nicely into our RallyRecorder project as a GPS tracker/recorder. Previously we had this running on a netbook with a USB GPS receiver using GPSd, a combination of command-line PHP and shell scripts, and MySQL. With the reduced specs on the Raspberry Pi (700 MHz, 256 MB RAM), I wanted to go with something with a little less overhead. Wisely or not, I chose Python and SQLite. Not having worked with either of the before, it should also provide a nice challenge.

After I started looking around the web for info about getting GPSd working with Python, I quickly found that any information was out of date, out of version, or just didn’t compile. It didn’t help that I started learning Python last night. Hey, go big or go home, right?

First we’ll quickly go through how to get all of the software prereqs. This is written for the Raspberry Pi but should work on most Linux distros too. 

Required Hardware

  • Raspberry Pi with Debian Wheezy installed (or something running Linux)
  • GPSd compatible GPS Receiver (I used this one)

Getting the Software

If you have a USB GPS receiver, don’t plug it in yet.

From the command-line, enter the following command to install Python, GPSd, and the Python modules to bring them together.

1
sudo apt-get install python gpsd gpsd-clients

If you have a USB receiver, you can plug it in now. For Bluetooth and serial receivers, you’re on your own for this step. Plugging in the USB receiver should start GPSd automatically. To make sure that GPSd is playing nice, you can open cgps to see what data it is receiving.

1
cgps

After your GPS receiver has a satellite fix, it should look something like this:

Reading GPS data with Python

Now that GPSd is communicating successfully with your receiver and you have the right software installed, we can read in the GPS data through Python. The code below uses threading to get every GPS update (otherwise the buffer fills up) and when requested (lines 31-54) fetches the most recent set of data. You can replace lines 31-54 with whatever you want to do with the data. I plan on storing unique points in a SQLite database (maybe in a follow-up post).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#! /usr/bin/python
# Written by Dan Mandle http://dan.mandle.me September 2012
# License: GPL 2.0
 
import os
from gps import *
from time import *
import time
import threading
 
gpsd = None #seting the global variable
 
os.system('clear') #clear the terminal (optional)
 
class GpsPoller(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    global gpsd #bring it in scope
    gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
    self.current_value = None
    self.running = True #setting the thread running to true
 
  def run(self):
    global gpsd
    while gpsp.running:
      gpsd.next() #this will continue to loop and grab EACH set of gpsd info to clear the buffer
 
if __name__ == '__main__':
  gpsp = GpsPoller() # create the thread
  try:
    gpsp.start() # start it up
    while True:
      #It may take a second or two to get good data
      #print gpsd.fix.latitude,', ',gpsd.fix.longitude,'  Time: ',gpsd.utc
 
      os.system('clear')
 
      print
      print ' GPS reading'
      print '----------------------------------------'
      print 'latitude    ' , gpsd.fix.latitude
      print 'longitude   ' , gpsd.fix.longitude
      print 'time utc    ' , gpsd.utc,' + ', gpsd.fix.time
      print 'altitude (m)' , gpsd.fix.altitude
      print 'eps         ' , gpsd.fix.eps
      print 'epx         ' , gpsd.fix.epx
      print 'epv         ' , gpsd.fix.epv
      print 'ept         ' , gpsd.fix.ept
      print 'speed (m/s) ' , gpsd.fix.speed
      print 'climb       ' , gpsd.fix.climb
      print 'track       ' , gpsd.fix.track
      print 'mode        ' , gpsd.fix.mode
      print
      print 'sats        ' , gpsd.satellites
 
      time.sleep(5) #set to whatever
 
  except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
    print "\nKilling Thread..."
    gpsp.running = False
    gpsp.join() # wait for the thread to finish what it's doing
  print "Done.\nExiting."

To use this code, copy/paste all of it in to a text editor of you choosing and save it as gpsdData.py. You can then run it with the following command:

1
python gpsdData.py

I am by no means an expert in well… anything. But this does work with GPSd 3.6, Python 2.7.3, and Debian Wheezy. I am all ears with ways to make this better and more efficient. Please let me know in the comments.

Some resources that helped me put this all together:

Publié dans technologie

Commenter cet article