GPS Mouse in Python

Some months ago I aquired a cheap gps mouse (Royaltek RGM-2000, really cheap, 2 € + shipping) at ebay. My plans to use it in combination with an microcontroller and a display haven’t worked out, it is a lot of work and the garmin units do that job fine.
However, playing around with it in python lead to better results. Getting the data to google earth works nicely, and at least qlandkarte can read the generated gpx tracks.

Usage

  • Start the Program, add a parameter for the port your nmea device is attached to (/dev/ttyUSB0 is the default
  • Start google earth or something, load the generated kml file (/tmp/posdate by default)
  • Exit the program by pressing ctrl-c, track data will be written to /tmp/track-some time.gpx

Guess I should code something with extra geek value now.
It might be comfortable to have google earth automatically reload the file, so instead open sth. like

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<NetworkLink>
	<name>GPS</name>
	<flyToView>1</flyToView>
	<Url>
		<href>/tmp/posdata.kml</href>
		<refreshMode>onInterval</refreshMode>
		<refreshInterval>10</refreshInterval>
	</Url>
</NetworkLink>
</kml>
#!/usr/bin/python
"""
Script to read nmea data from a GPS mouse
Copyright (C) 2008  Andreas Goelzer
 
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
This program reads data from a nmea device (uses the GGA sentence),
and creates a google kml file with the current position and the path
leading there. Additionally, a gpx file is generated containing the
track data with time information.
"""

from serial import Serial;
from time import strftime, gmtime;
from optparse import OptionParser;


hist = "";
gpx = "";

kmlmask="""<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
	<Placemark>
		<name>Your Position</name>
		<Point>
			<coordinates>%s</coordinates>
		</Point>
	</Placemark>
	<Placemark>
		<name>Previous positions</name>
		<description>Path that lead you here</description>
		<LineString>
			<coordinates>%s</coordinates>
		</LineString>
	</Placemark>
</Document>
</kml>"""
#			<altitudeMode>absolute</altitudeMode>

gpxmask = """<?xml version="1.0" encoding="UTF-8" standalone="no" ?><gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Colorado 300" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtension/v1/TrackPointExtensionv1.xsd">
<trk><name>%s</name><trkseg>%s</trkseg></trk></gpx>"""

def gpstime():
	return strftime("%Y-%m-%dT%H:%M:%SZ",gmtime());

def readlatlon(value,inverse):
	lat = float(value);
	lat2 = int(lat) / 100;
	lat = lat2 + (lat - 100 * lat2)/ 60; 
	if inverse:
		lat = -lat;
	return lat;

def calcchecksum(checkstr):
	cs = ord(checkstr[0]);
	for i in range(1,len(checkstr)):
		cs ^= ord(checkstr[i])
	return cs;


class sentencevalidator:
	"Check checksum and other stuff and split to fields"
	def __init__(self,line):
		if(line[0] == '$' and line[-5] == '*' and calcchecksum(line[1:-5]) ==  int(line[-4:-2],16)):
			self.valid = True;
			self.sentence = line[3:6];
			self.data = line[7:-5].split(',');
		else :
			self.valid = False;

parser = OptionParser(version="%prog 0.1");
parser.add_option("-s", "--serial", dest="serial",
                  help="serial terminal of the gps unit", default='/dev/ttyUSB0', metavar="FILE");
parser.add_option("-g", "--gpxfile", dest="gpxfile",
                  help="GPX output file", default="/tmp/track" + gpstime() + ".gpx", metavar="FILE");
parser.add_option("-k", "--kmlfile", dest="kmlfile",
                  help="KML output file", default="/tmp/posdata.kml", metavar="FILE");
parser.add_option("-v", "--verbose",
                  action="store_true", dest="verbose", default=False,
                  help="print debug messages");
 
(options, args) = parser.parse_args();

gps = Serial(options.serial, 4800, timeout=1);


#on sirf chips, activate all sentences
for i in range(1,5):
	cmd = "PSRF103,0%d,00,05,01" % i;
	realcmd="$%s*%x\r\n" % (cmd,calcchecksum(cmd));
	print realcmd;
	gps.write(realcmd)

try:
	while 1:
		line = gps.readline()
		if(options.verbose): print line,
		s = sentencevalidator(line);
		if(s.valid and s.sentence == "GGA" and int(s.data[5]) != 0):
			lat = readlatlon(s.data[1],s.data[2]=='S');
			lon = readlatlon(s.data[3],s.data[4]=='W');
			alt = float(s.data[8]);
				
			gpx += "\n" + '<trkpt lat="%f" lon="%f"><ele>%f</ele><time>%s</time></trkpt>' % (lon,lat,alt,gpstime())
			
			position =  "%f, %f, %f" % (lon,lat,alt);
			print position
			hist += "\n" + position;
			f=open("/tmp/posdata.kml",'w');
			f.write(kmlmask % (position,hist));
			f.close();

except:
	0

f=open(options.gpxfile,'w');
f.write(gpxmask % (gpstime(),gpx));
f.close();

gps.close()

filetype readgps.py (4.46 kiB, 2008-11-08)

This entry was posted in Computers and tagged , . Bookmark the permalink.

2 Responses to GPS Mouse in Python

  1. Lora Ireland says:

    This is great! Thanks for this post. I am a newbie at python and this got me straight.

  2. Thaks sharing it… it will help..

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>