Please be aware of all shipping deadlines before placing your order - we cannot guarantee orders will arrive before Christmas!

Ultimate GPS Daemon
Moderators: adafruit_support_bill, adafruit

Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/

Ultimate GPS Daemon

by downeym on Mon Mar 18, 2013 5:03 pm

I am trying to fully understand the sample code released by Adafruit for the ultimate gps and I have some questions about the code used in the example.

I have modified the example code in the tutorial and have written the following function to get data from the GPSd daemon and return it in a useful format, including offsetting the time to local instead of GMT:

Code: Select all | TOGGLE FULL SIZE
#!/usr/bin/python

import gps
from string import find
from datetime import datetime, timedelta

# ===========================================================================
def get_gps(time_offset):
    session = gps.gps("localhost", "2947") #start a new session with the GPS daemon
    session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
    report_received = 0
    while report_received == 0:
        report = session.next() # wait for the next status message from the GPS receiver
        if report['class'] == 'TPV': # Wait for a 'TPV' report and display the current time
            if hasattr(report, 'time'):
                report_received = 1
                s = report.time
                s = s[:find(s, "T")] + " " + s[find(s, "T")+1:]
                s = s[:find(s, ".")] 
                dt = datetime.strptime(s, '%Y-%m-%d %H:%M:%S')
                dt = dt + timedelta(hours=time_offset) # apply an offset for the local time zone
                gps_time = dt.strftime('%Y-%m-%d %H:%M:%S') #convert time string into a useful format
                mode = report.mode # get status from the GPS receiver. either no lock, 2d or 3d
                if mode == 1:
                    mode_string = "NO"
                if mode == 2:
                    mode_string = "2D"
                if mode == 3:
                    mode_string = "3D"
                lat = report.lat
                longatude = report.lon
                speed = 2.236936*report.speed # convert meters per second to mph
                alt = report.alt
    return gps_time, lat, longatude, speed, alt, mode_string;  #return data back from the receiver.
   
gps_data = get_gps(-4)
print gps_data
gps_data = get_gps(-4)
print gps_data
gps_data = get_gps(-4)
print gps_data




when I run this, I get the following output

Code: Select all | TOGGLE FULL SIZE
('2013-03-18 16:48:03', 33.xxxxxxx, -84.xxxxxxxx, 0.219219728, 295.6, '3D')
('2013-03-18 16:48:04', 33.xxxxxxx, -84.xxxxxxxx, 0.14987471200000002, 295.6, '3D')
('2013-03-18 16:48:05', 33.xxxxxxx, -84.xxxxxxxx, 0.091714376, 295.6, '3D') 

I have 3 issues with this code I hope someone can help me with.

1. Currently the GPS module and daemon seem to default to a 1hz operation (which is why there is 1 second between each time sample). The way the function is written, I am waiting for an updated packet to be sent after I enter the function. Shouldn't the daemon be handling this function? Why cant I just ask the daemon what the last packet was instead of waiting for a whole new message from the GPS receiver?

2. I found some documentation online that shows that the GPSd daemon can accept input from the client connecting to it. Since the GPS receiver is capable to operating at 10Hz, cant I send a packet to the Daemon so it can send the configuration string to the GPS receiver to configure the receiver to operate at 10Hz instead of 1Hz?

3. I have noticed that sometimes the GPS receiver deosnt send an update packet for some reason. Unfortunately, the session.next() function call will wait for the next session, no matter what. There apparently is no timeout and no way to set one as far as I can tell. Does anyone know how to configure this so that it will drop out of this function in case the GPS receiver gets hung for some reason?

I need this function to be sped up because it is limiting the overall speed of my application.

I appreciate any insight anyone can give as to how this is actually working.

Thanks
downeym
 
Posts: 7
Joined: Tue Aug 28, 2012 2:18 am

Re: Ultimate GPS Daemon

by downeym on Tue Mar 19, 2013 2:55 pm

I figured out how to reconfigure the module for 10Hz operation, but only outside of the daemon itself.. if you run this sequence of commands from a command line, it will set the module for faster operation.

It would be nice to do this through python though so you were able to contain this completely within the code and not be dependent on someone running this before the code is executed.

unless the battery is mounted on the module, I think the GPS will revert to 4800bps and 1Hz when power is lost again.

Code: Select all | TOGGLE FULL SIZE
sudo killall gpsd
printf '$PMTK251,115200*1F\r\n'>/dev/ttyUSB0
stty speed 115200 </dev/ttyUSB0
printf '$PMTK220,100*2F\r\n'>/dev/ttyUSB0
sudo gpsd /dev/ttyUSB0 -F /var/run/gpsd.sock
downeym
 
Posts: 7
Joined: Tue Aug 28, 2012 2:18 am

Re: Ultimate GPS Daemon

by downeym on Tue Mar 19, 2013 5:12 pm

I see why #3 is failing. It is not that the daemon is not sending an update packet. it is that it is not sending time as part of the TPV packet, so my function has nothing to trigger off of. It is sending mode though... In this case we can send the local system time and zeros for the rest of the data

Code: Select all | TOGGLE FULL SIZE
def get_gps(time_offset):
    session = gps.gps("localhost", "2947") #start a new session with the GPS daemon
    session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
    report_received = 0
    while report_received == 0:
        report = session.next() # wait for the next status message from the GPS receiver
        #print report
        if report['class'] == 'TPV': # Wait for a 'TPV' report and display the current time
            if hasattr(report, 'time'):
                report_received = 1
                s = report.time
                s = s[:find(s, "T")] + " " + s[find(s, "T")+1:]
                s = s[:find(s, ".")] 
                dt = datetime.strptime(s, '%Y-%m-%d %H:%M:%S')
                dt = dt + timedelta(hours=time_offset) # apply an offset for the local time zone
                gps_time = dt.strftime('%Y-%m-%d %H:%M:%S') #convert time string
                mode = report.mode # get status from the GPS receiver. either no lock, 2d, or 3d
                if mode == 1:
                    mode_string = "NO"
                if mode == 2:
                    mode_string = "2D"
                if mode == 3:
                    mode_string = "3D"
                lat = report.lat
                longatude = report.lon
                speed = 2.236936*report.speed # convert meters per second to mph
                alt = report.alt
            else:
                if hasattr(report, 'mode'):
                    report_received = 1
                    lat = 0
                    longatude = 0
                    speed = 0
                    alt = 0
                    mode = report.mode # get status from the GPS receiver
                    if mode == 1:
                        mode_string = "NO"
                    if mode == 2:
                        mode_string = "2D"
                    if mode == 3:
                        mode_string = "3D"
                    gps_time = strftime('%Y-%m-%d %H:%M:%S', localtime())
    return gps_time, lat, longatude, speed, alt, mode_string;  #return data back from the receiver.
downeym
 
Posts: 7
Joined: Tue Aug 28, 2012 2:18 am