I document my adventures and problems so that I remember my mistakes, and perhaps you may learn something.
I'm not a programmer, nor a computer expert.
I'm just a tinkering guy in Milwaukee with a store and three kids to keep me busy.
Thursday, March 29, 2012
TomTom Home on Linux
Experiment 1: Can the laptop's gpsd read the device as a dumb GPS?
Well, no. GPSD can't locate the device at all. I suspect that's because the TomTom One isn't GPS dongle, it's a full system on it's own. And it doesn't know to pass-through the raw GPS data to simulate a dongle.
Experiment 2: Can TomTome Home 2.8 (for controlling the device, uploading new maps, etc) be installed on Ubuntu 11.10?
No. The available TTH 2.8 clients are for Win and OSX only.
Experiment 3: Can TTH 2.8 be installed on Ubuntu 11.10 using Wine?
Sadly, no. The install itself went poorly. On several attempts, only one was successful. Due to two bugs (some custom jiggery in the TTH does in the Windows Registry, and a bug with Wine support for USB) the device cannot be recognized, loaded, or interacted with.
Experiment 4: Can TTH 2.8 be installed on Ubuntu 11.10 using a Virtual Machine?
Yes. I use a Virtualbox XP VM. TTH 2.8 installed perfectly first time. The device, like all USB devices in VB, must be manually added in the VB 'Device" menu. After that, control of the device was perfect.
Sunday, November 27, 2011
GPS dongle, gpsd, and Ubuntu 11.10
Install the hardware: Plug it in, of course.
- Check the kernel message log to discover the GPS dongle location in the filesystem:
$ dmesg | grep tty [1769190.919411] usb 2-1: pl2303 converter now attached to ttyUSB0
- Test for signal with the following command:
$ cat /dev/ttyUSB0 5�y�220,N,08754.5061,W,000.0,316.5,271111,,,A*71 $GPVTG,316.5,T,,M,000.0,N,000.0,K,A*0C $GPGGA,173905.000,4259.7220,N,08754.5060,W,1,08,1.0,190.0,M,-33.8,M,,0000*63 $GPGSA,A,3,12,04,10,23,02,05,17,25,,,,,1.7,1.0,1.4*31 $GPRMC,173905.000,A,4259.7220,N,08754.5060,W,000.0,316.5,271111,,,A*71
Use CTRL+C to end the signal check.
If you get a bunch of zero-data, then try moving closer to a window, since GPS signals are line-of-sight. Or try a USB hub or extension cable, to reduce interference from your computer.
Install the gps daemon so you can use gps data.
sudo apt-get install gpsd gpsd-clients
- Normally, udev will start gpsd automatically when a USB GPS device is inserted. If it fails to start after 5-10 seconds, you can start it manually:
gpsd /dev/ttyUSB0 #You must tell gpsd where to look for the dongle
- Test the GPS and gpsd output using the gpsmon and cgps terminal programs, or the xgps program (all included in the gpsd-clients package)
- Capture data for recycling (optional - handy for development). gpsfake will simulate gpsd output
$cat /dev/ttyUSB0 > path/to/datalog # Create data file. Use CTRL+C to end the capture. $gpsfake path/to/datalog # Run gpsd simulator (not a daemon - it will occupy the terminal)
Command-line tools to get GPS data
- Use the gpspipe command to get gpsd data:
$ gpspipe -w -n 5 netlib_connectsock() returns socket on fd 3 {"class":"VERSION","release":"2.95","rev":"2011-07-27T11:20:24","proto_major":3,"proto_minor":3} {"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyUSB0"}]} {"class":"WATCH","enable":true,"json":true,"nmea":false,"raw":0,"scaled":false,"timing":false} {"class":"TPV","tag":"RMC","device":"/dev/ttyUSB0","time":1322418390.001,"ept":0.005,"lat":42.995410000,"lon":-87.908430000,"alt":195.400,"epx":11.739,"epy":17.294,"epv":36.800,"track":342.2000,"speed":0.000,"climb":0.000,"eps":34.59,"mode":3} {"class":"SKY","tag":"GSV","device":"/dev/ttyUSB0","xdop":0.66,"ydop":1.15,"vdop":1.46,"tdop":1.01,"hdop":1.32,"gdop":2.22,"pdop":1.97,"satellites":[{"PRN":2,"el":77,"az":360,"ss":26,"used":true},{"PRN":10,"el":58,"az":72,"ss":32,"used":true},{"PRN":12,"el":51,"az":247,"ss":34,"used":true},{"PRN":5,"el":45,"az":192,"ss":21,"used":true},{"PRN":4,"el":40,"az":65,"ss":20,"used":true},{"PRN":25,"el":39,"az":292,"ss":21,"used":true},{"PRN":13,"el":15,"az":60,"ss":18,"used":true},{"PRN":24,"el":14,"az":258,"ss":0,"used":false},{"PRN":29,"el":12,"az":304,"ss":23,"used":false},{"PRN":17,"el":8,"az":121,"ss":17,"used":true},{"PRN":23,"el":7,"az":35,"ss":10,"used":false},{"PRN":31,"el":0,"az":334,"ss":0,"used":false}]}
- Let's refine the command a bit, limit to the first "TPV" (time, position, velocity) sentence:
$ gpspipe -w -n 5 | grep -m 1 TPV netlib_connectsock() returns socket on fd 3 {"class":"TPV","tag":"RMC","device":"/dev/ttyUSB0","time":1322418481.001,"ept":0.005,"lat":42.995406667,"lon":-87.908428333,"alt":195.300,"epx":10.003,"epy":17.383,"epv":36.800,"track":342.2000,"speed":0.000,"climb":0.000,"eps":34.77,"mode":3}
- We can use basic shell commands to extract single variables from this sentence:
tpv=$(gpspipe -w -n 5 | grep -m 1 TPV | cut -d, -f4,6-8,13) seconds=$(echo $tpv | cut -d, -f1 | cut -d: -f2) latitude=$(echo $tpv | cut -d, -f2 | cut -d: -f2) longitude=$(echo $tpv | cut -d, -f3 | cut -d: -f2) altitude=$(echo $tpv | cut -d, -f4 | cut -d: -f2) speed=$(echo $tpv | cut -d, -f5 | cut -d: -f2)
- For fun, let's compare GPS time with system time using shell commands:
date -u +%s # System utc time in seconds gpspipe -w -n 5 | grep -m 1 TPV | cut -d, -f4 | cut -d: -f2 # GPS utc time in seconds # Let's compare them side-by side $ echo System: $(date -u +%s) , GPS: $(gpspipe -w -n 5 | grep -m 1 TPV | cut -d, -f4 | cut -d: -f2) netlib_connectsock() returns socket on fd 3 System: 1322419689 , GPS: 1322419689.000 # Our sytem time is within one second of GPS time. That's good!
- For fun, let's use shell script to post the GPS location to Google Maps:
The format is simple enough: http://maps.google.com/?ll=40.480381,-92.373047&z=16 will return a valid map. So that's three variables: Latitude, longitude, and zoom Level.
tpv=$(gpspipe -w -n 5 | grep -m 1 TPV | cut -d, -f4,6-8,13) latitude=$(echo $tpv | cut -d, -f2 | cut -d: -f2) longitude=$(echo $tpv | cut -d, -f3 | cut -d: -f2) zoom=20 map_url="http://maps.google.com/?ll=${latitude},${longitude}&z=${zoom}" firefox $map_url
Python tools to get GPS data
- Python bindings to gpsd are provided by the python-gps package.
sudo apt-get install python-gps
- The python tools have changed a *lot* in two years. The old methods don't work anymore. No Python 3 version is available yet. There's a decent example here, but I couldn't get it to work.
Conversion between Lat/Lon and MGRS/UTM and other systems: gpsd doesn't do this, though apparently the geographiclib-tools package does. And so does this website.
Tuesday, February 24, 2009
You Are Here on a Google Map
The following python 2.x script shows your current (GPS-enabled) location on a Google Map. A useful learning experience:
#!/usr/bin/env python """This is a python 2.5 script that plot's a GPS receiver's location on the Google Maps website. In order to work, you need a network connection, an attached GPS receiver, and the GPS daemon (gpsd). """ import os #import subprocess and SU import gps import dbus import sys def test( ): """ Step 1: Test for the existence of a running gpsd, test for the existence of an open network connection, and test for a firefox process. If any fail, give an error message, don't try to recover. FUTURE: Could also use DBus to test for firefox and gpsd.""" process_list = os.popen('ps -e') # os.popen is deprecated in favort of subprocess.Popen #process_list = SU.Popen(['ps','e'], stdout=SU.PIPE).stdout.read() gpsd_existence_flag = 0 firefox_existence_flag = 0 for line in process_list.readlines(): if line.count('gpsd') > 0: gpsd_existence_flag = 1 if line.count('firefox') > 0: firefox_existence_flag = 1 if not gpsd_existence_flag: print ("gpsd is not running. Use 'gpsd -b /dev/ttyUSB0' to start it, and then try again.") sys.exit() else: print ('Checking...found gpsd') if not firefox_existence_flag: print ("firefox is not running. Please start it and try again.") sys.exit() else: print ('Checking...found firefox') bus = dbus.SystemBus() nm_item = ('org.freedesktop.NetworkManager') # This string gets used a lot nm_path = ('/org/freedesktop/NetworkManager') nm_device = ('org.freedesktop.NetworkManager.Device') list_of_interface_paths = dbus.Interface(bus.get_object(nm_item, nm_path), nm_device).getDevices() found_network_flag = 0 for interface_path in list_of_interface_paths: one_interface = dbus.Interface(bus.get_object(nm_item, interface_path), nm_device) if one_interface.getLinkActive(): # True if there is an active network on this interface if one_interface.getType() == 2: # 0 unknown, 1 wired, 2 wireless print('Checking...found the wireless network') found_network_flag = 1 elif one_interface.getType() == 1: print('Checking...found the wired network') found_network_flag = 1 if found_network_flag: return else: print ("cannot find a network connection. Please connect and try again.") sys.exit() def get_position_fix( ): """Step 2: Get a position fix from gpsd.""" session = gps.gps('localhost','2947') # Open a connection to gpsd session.query('p') # Get the location fix lat = session.fix.latitude lon = session.fix.longitude print ('Location is ' + str(lat) + ' latitude and ' + str(lon) + ' longitude.') return (lat, lon) def show_map(lat_lon_tuple): """Step 3: Submit the position fix to Google Maps. Note that the parentheses '()' in the URL must be escaped '\' to work. Sample URL format: http://maps.google.com/maps?q=37.771008,+-122.41175+(You+can+insert+your+text+here)&iwloc=A&hl=en""" url_string = ('http://maps.google.com/maps?q=' + str(lat_lon_tuple[0]) + ',+' + str(lat_lon_tuple[1]) + '+\(You+Are+Here\)&iwloc=A&hl=en') os.popen('firefox ' + url_string) return # Run this script as a standalone program if __name__ == "__main__" : test() location = get_position_fix() show_map(location)
Monday, February 23, 2009
GPS and Xubuntu 8.04
I'm experimenting with USB GPS receiver (dongle). It's a Canmore GT-730F that I received in January 2009. Here's what I've learned so far.
Manually getting data using the command line (source):
- Check
dmesg
, the kernel log, to find out where the device has been mounted. In my case, it mounts reliably to /dev/ttyUSB0. If it doesn't mount, try the commandsudo modprobe pl2303
to load the correct USB driver. - Set the data output rate to 4800 baud using the
stty
command:stty 4800 > /dev/ttyUSB0
- Read the data stream using the
cat
command:cat /dev/ttyUSB0
- You should see a set of data scroll down the screen. Use CTRL+C to end the test.
The Linux GPS Daemon (gpsd) is the central clearinghouse for receiving GPS data from the receiver, buffering it, and forwarding it to the applications that want it. gpsd has features to broadcast to dbus (system bus), update ntpd, and respond to a multitude of specific queries from clients. References: Project home page, gpsd man page, and a great example program
$sudo apt-get install gpsd gpsd-clients # Installs the daemon (gpsd) and test set (gpsd-clients) packages $gpsd -b /dev/ttyUSB0 # Start gpsd, telling it where to find the receiver $cgps # Current satellite data - great way to test that the receiver and gpsd are working
gpsfake is a gpsd simulator. It tricks gpsd into reading from a logfile instead of a real GPS device. Very handy for testing without actually using a GPS dongle. It is included with the gpsd package, and has a man page for additional reference. To make a logfile, and then to use gpsfake:
$cat /dev/ttyUSB0 > path/to/testlog # Create the log file. Use CTRL+C to end the capture. $gpsfake path/to/testlog # Run gpsd simulator (not a daemon - it will occupy the terminal)
Python interface to gpsd (python-gps) is a programming tool to build your own gps-aware application.
>>>import gps # Load the module >>>session = gps.gps('localhost','2947') # Open a connection to gpsd >>>session.query('o') # See man gpsd(8) for the list of commands >>>print session.fix.latitude # Query responses are attributes of the session >>>dir(session) # To see the possible responses >>>del session # Close the connection to gpsd
In this case, it seems that I need a periodic session.query('p')
, which just gives lat/lon and timestamp.
Time might be an issue, since the system and the GPS may think the time is different. To see if it's an issue, compare them using the python script below. In my tests, they vary from 0.08 to 1.3 seconds apart, not enough to worry about. GPS timestamps use GMT, not localtime.
#!/usr/bin/env python import calendar, time, gps system_time = calendar.timegm(time.gmtime()) # System time (in seconds) session = gps.gps('localhost','2947') # Open a connection to gpsd session.query('p') # See man gpsd(8) for the list of commands gps_time = session.timings.c_recv_time # GPS time (in seconds) print ('The time difference is ' + str(system_time - gps_time) + ' seconds.')
MGRS (military map coordinates) conversion to/from latitude and longitude is not currently available in Ubuntu...that I can find. The dongle documentation doesn't mention MGRS at all. An online converter is available. The proj package looks promising, but I haven't figured it out yet. Perhaps Lat/Lon -> UTM -> MGRS?
DBus access appears to be undocumented...but there are tantalizing hints on Google that examples are out there. I can listen to dBus using cgps
to make traffic, then dbus-monitor --system
to see it.
The best storage format for tracklogs, routes, and waypoints seems to be GPX format, since it's easy to understand and cgpxlogger
, included with gpsd, will create an XML track in GPX 1.1 format. Google's KML is more powerful, but also much more complex. GPSbabel universal data translator is a command-line application that translates one file type to another, and does convert GPX <-> KML.
$cgpxlogger -i 30 > path/to/logfile # Save data every 30 seconds to an XML file $gpsbabel -i gpx -f path/to/gpx_file -x duplicate -o kml -F path/to/kml_file $#gpsbabel [options] -i INTYPE -f INFILE -x FILTER -o OUTTYPE -F OUTFILE
GPSdrive navigation system looks cool, but I couldn't get maps to load, so it's utility was limited. However, it seems that online plotting of tracklogs, routes, and waypoints is possible on Google Maps (and Yahoo Maps, and others). One example is the cool GPS Visualizer.
Gypsy is an alternative daemon, but not currently in Debian or Ubuntu, so I haven't tried it. Last release 0.6 in March 2008.
GPSman device manager is an app I know nothing about. I couldn't get it to work, so I removed it. The dongle seems small enough and simple enough that it may not need to be 'managed' at all.