Jörgs Linux Pages: GPS Software

GPS software programming

"There are no road signs to help navigate. And, in fact, no one has yet determined which side of the road we're supposed to be on."
- Steve Case

Using Garmin MapSource under Linux

This is a short "How-To" on using Garmin MapSource inside a Linux system, including use of the USB connection to the GPS receiver. Essentially, it makes use of a virtual system based on VirtualBox that is running Microsoft Windows XP as "guest" on the Linux "host". Please note that this description is rather specific to Fedora Linux; I first wrote it under Fedora 8 and adapted it to Fedora 11 and Fedora 14 later on. Most of it will also apply to other Linux systems, in particular RHEl and its clones.

Introduction

The standard software for Garmin GPS units is Garmin MapSource. It is used to plan routes, to upload data (maps, routes, waypoints etc.) to the GPS receiver and to retrieve track, waypoint and route information from the GPSr.

Garmin MapSource is one of the few applications that still have no equivalent in the Linux world. Although a dual-boot system is easy to set up, I see no point in rebooting the computer just for a single application.

One solution that is now truly mature is "virtualisation". Essentially, this allows to run one OS, such as Microsoft Windows, as "guest" inside another OS, the "host" - in my case Linux.

The product that I am using with success is VirtualBox, a commercial and proprietary (with a limited GPL version) x86 virtualizer. Albeit an open-source version is available, I had to go for the proprietary release since this was - at that time - the only one that provides USB controller emulation.

VirtualBox Installation

Installation is straightforward. In a nutshell, you download the "VirtualBox for Linux Hosts" executable for your distribution from the manufacturer's website and install it using yum.

A common prerequisite is the Dynamic Kernel Module Support, DKMS:

yum install dkms

This will resolve dependencies and load other packages such as kernel-devel, kernel-headers etc.

If you want to use repositories, you will probably proceed along the following lines:

wget -P /etc/yum.repos.d http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo
yum install VirtualBox-4.3

... and that's it. Updates are then handled through yum update.

If you prefer a manual installation:

wget http://download.virtualbox.org/virtualbox/4.1.30/VirtualBox-4.1-4.1.30_91550_fedora14-1.i686.rpm
yum --nogpgcheck localinstall VirtualBox-4.1-4.1.30_91550_fedora14-1.i686.rpm

... here, updates need to be downloaded and installed manually, using the same commands.

All that remains is to add the user that is running VirtualBox in the group vboxusers, either through your User Admin tool or an the command line:

usermod -a -G vboxusers username

After that, you can launch VirtualBox and set up a virtual system, then install the guest operating system - simply use the Wizard and/or refer to the manual. In my case, the guest is Microsoft Windows XP.

When the install is complete, do not forget to install the "VirtualBox Guest Additions". Among others, they provide a video driver that allows re-sizing the Windows window ;-) to any size and at any time.

To exchange data between this Microsoft Windows guest and the Linux host, I use a shared drive (please refer to the manual). For reasons of security and privacy, I do not allow any Internet connection for the Windows guest.

Moving a Virtual Machine

Moving a virtual Machine is straightforward and is described on the VirtualBox website.

However, one thing you may want to keep in mind is that, in spite of all virtualisation, Microsoft Windows does not transfer easily from one hardware to another: Windows seems to "memorize" on which hard disk controller it was installed; if the controller changes, the boot will likely fail and you get the infamous BSOD.

The preventive maintenance is to perform a few modifications to the Windows registry, essentially relaxing the IDE checks, before moving the system to another hardware. This can be done e.g. with the little MergeIDE utility developed by c't, available through the VirtualBox website. The same webpage contains instructions for moving a physical Windows installation into a virtual environment.

MapSource Installation and USB setup

At this time, you can install Garmin Mapsource. The only problem that remains is the USB connection to the GPSr, and it took me one evening to resolve this.

The key problem was that the current user (running VirtualBox) needs access to the USB filesystem, which is by default not the case in most distributions. A clear symptom was that the USB devices are listed but "greyed out" in the VirtualBox menu.

As usbfs is a virtual filesystem, its permissions can only be changed at boot time. How this is done in depends on the particular distribution - the VirtualBox manual says it nicely: "The various distributions are very creative from which script the usbfs filesystem is mounted. Sometimes the command is hidden in unexpected places."

For Fedora 11, it is sufficient to umount /proc/bus/usb before launching VirtualBox. See this bug report for an explanation.

For Fedora 8, usbfs is mounted via /etc/rc.sysinit. The two commented lines below show the original entries; what is added is the mount option -o devgid=500,devmode=664, where "500" is the numerical group id for the group vboxusers (see /etc/group).

if [ ! -d /proc/bus/usb ]; then
    modprobe usbcore >/dev/null 2>&1 && mount -n -t usbfs -o devgid=500,devmode=664 /proc/bus/usb /proc/bus/usb
    # modprobe usbcore >/dev/null 2>&1 && mount -n -t usbfs /proc/bus/usb /proc/bus/usb
else
    mount -n -t usbfs -o devgid=500,devmode=664 /proc/bus/usb /proc/bus/usb
    # mount -n -t usbfs /proc/bus/usb /proc/bus/usb
fi

Note: For Fedora 8, it is useless to add a mount command for usbfs in /etc/fstab, and it is not necessary to blacklist garmin_gps in /etc/modprobe.conf either. - For Ubuntu Linux, the approach is slightly different; see this thread.

With that, the USB devices should be available to Windows XP and upon connecting the Garmin GPSr the Hardware Wizard should guide you through the process of installing the Garmin USB drivers. If you run into problems in this process, please verify the following settings:

The image below shows the Fedora 8 Desktop, running Microsoft Windows XP in a window, and this in turn is running Garmin Mapsource in a window ;-) Note that the "Find Device" dialog is active; my GPSmap 60CS was detected on the USB port.

VirtualBox Settings VirtualBox USB Settings VirtualBox running WinXP and MapSource

USB Reset

There was still one additional problem: Albeit Windows XP recognises the connection of the GPSr, MapSource would not find the device. The solution is to reset (disable and re-enable) the proprietary Garmin USB drivers inside Microsoft Windows. Probably the most elegant solution was posted in the VirtualBox forums; in short:

  1. From the Microsoft support website, download the DevCon command-line utility.
  2. Unpack (run) the file and move the 32-bit executable devcon.exe into an appropriate system folder, e.g. c:\windows.
  3. Every time MapSource does not find your GPSr, run devcon restart @usb\vid_091e* (e.g. as a batch file). This command restarts all USB drivers that are made by Garmin ("091e" is the manufacturer code).

Miscellaneous

Extracting coordinates and altitude information from Garmin tracks

If you export track information from Garmin GDB files as text files, the resulting files are tab-delimited, with the coordinates written in lat/long pairs. The following one-liner extracts coordinates and altitude of a track, leaving a file that can be plotted directly e.g. with gnuplot:

cat /path/to/logfile.txt | grep "^Trackpoint" \
    | awk -F '\t' '{print $2, $4}' 
    | tr NSWE +--+ > /path/to/out.dat

To get the axis right, you need to swap the first and second column in gnuplot:

set size ratio 1
splot 'file' using 2:1:3 w lin title ''
unset xtics
unset ytics

Extracting profiles from GPX tracks

Sometimes I like to generate an altitude profile from a GPS track in gpx format. gpsdings is a java command line tool for the manipulation and analysis of track and waypoint data. Among others, it comprises a GPS track analyzer.

To generate a plot of elevation over distance from the file 20080622.gpx:

java -jar gpsdings.jar trackanalyzer --plot "DistanceTravelled|Elevation|20080622.altitude.svg|Jura, 20080622" 20080622.gpx

To generate a kml file for use with Google Earth from the file 20080622.gpx:

java -jar gpsdings.jar trackanalyzer --kml "Elevation|20080622.kml|Jura, 20080622" 20080622.gpx

Or, alternatively (tracks will be coded by their names):

java -jar gpsdings.jar gpxkml -z 20080622.gpx

Modifying GPX track data

The gpx files that are exported by Garmin's MapSource are not exactly like I want them to be. Using GPSBabel, the following one-liner extracts and merges all the tracks (-x track,merge), adjusts time so that the data points show the "real" time (-x move=+2h), drops any routes (-x nuketypes,routes), plus invokes some more clean-up:

gpsbabel -t -i gpx -f /path/to/infile.gpx \
         -x track,merge,title="Title of Track",move=+2h -x nuketypes,routes \
         -o gpx -c latin1 -F path/to/outfile.gpx

I have put this into a shell script: bullet click here to download the gpxclean.sh script.

Reduce GPX tracks

Sometimes I need to reduce the number of points in a gpx file, but preserve the overall shape of the track. I found this useful e.g. to create overview maps from large gpx files. The following one-liner will reduce all points within a radius of 1 km. Applied to a file with more than 40'000 trackpoints (4.5 MB), the resulting track was reduced to about 400 points (45 kB) but still represented the original track shape very well:

gpsbabel -r -i gpx -f in.gpx -x simplify,error=1k -o gpx -F out.gpx

If, in addition, you want to pack all tracks into one, use something like this:

gpsbabel -r -i gpx -f in.gpx -x simplify,error=1k -x track,pack -o gpx -F out.gpx

Converting GPX tracks into a transparent overlay map

A memory-saving technique to carry your favourite tracks with you is to convert them into a transparent overlay map. This can be achieved by manual import of the tracks into an empty map, then compiling manually ... but since the process as such does not really require manual interaction, I wrote a Perl script for this purpose.

The script is called gpx2ovl.pl ("gpx to overlay") and takes exactly one gpx file as argument. By default, it will extract all tracks and convert each of them into a polyline of type "0x0003". The display of these lines is customised using a TYP file (which is generated on-the-fly). The result is a complete set of files that can be used directly with MapSource.

bullet Click here to download the gpx2ovl.pl script. Please note that a number of variables (such as map names, etc) are hardcoded at the beginning of the script; you may want to change them to suit your needs.

Converting GPX points of interest into a transparent overlay map

Similar to the above, I wrote a script that converts arbitrary "points of interest" into a transparent overlay map. Again, this is a Perl script that does not require manual interaction. The script is somewhat more sophisticated than the previous one, since it will automatically cut large areas into suitable tiles.

The script is called csv2ms.pl ("csv to MapSource") and takes exactly one csv file as argument. It will parse all coordinate pairs in the file and convert each of them into a [RGN10]-symbol of type "0x1610", which will show up as a red dot on most Garmin GPSr. The result is a complete set of files that can be used directly with MapSource.

bullet Click here to download the csv2ms.pl script. Please note that a number of variables (such as map names, etc) are hardcoded at the beginning of the script; you may want to change them to suit your needs. - The script was updated 2008-11-30; the maps now work also with the "infamous" MapSource version 6.14.x.

Converting from and to GPX format

For most GPS data conversions, I use GPSBabel. However, here are a few cases that can be done easily on the command line.

The following one-liner converts GPX waypoints into plain text:

cat file.gpx | grep "<wpt" | sed 's/[^0-9.]/ /g'| awk '{print $2,$1}'

To convert a comma-delimited list of waypoints to GPX format, I wrote a script called csv2pgx.pl. Please note that this is extremely basic; in particular the resulting GPX file is not complete: it merely consists of waypoints in GPX format, but without the formal XML header. I use this script mosty to convert geographic locations that I then include into (other) GPX files.

bulletClick here to download the csv2gpx.pl script.

Links

On this site

Map Authoring

Most of this is specific to the maps used by Garmin GPS receivers.