## GPX Elevation Profile Plotting With The Google Chart API

Last month I went on a few training hikes for an upcoming backpacking trip, and on the final two, I took along my GPS. Google Earth provides a wealth of options for visualizing GPS data, but I wanted to get a better understanding of what was going on under the hood. So I exported my tracks and waypoints as .gpx files and threw together a Python script which calculates a few data points as well as outputs a Google Chart URL with the elevation profile.

The first step was to understand the structure of a .gpx file. My Garmin eTrex Legend HCx only populates a subset of the fields in the schema, the important ones being waypoints <wpt>, tracks <trk>, track segments <trkseg> and track points <trkpt>. A track is comprised of a series of track segments, which in turn are made up of a series of track points. Track points have latitude, longitude and elevation information. Waypoints are similar to track points with the addition of name, type, label, but do not belong to a given track.

I created a class called Geopoint to represent the data contained in a track point. Since the GPS does not record track points at fixed intervals, the next step was to figure out how to calculate the distance between two track points. It’s been quite some time since I had to calculate the length of an arc on an approximate sphere, so it was time to consult the wondernet. It turns out there are a number of ways to calculate the distance between two latitude and longitude coordinates with varying degrees of accuracy. The two that I could understand relatively quickly were the Haversine formula and the Spherical law of cosines, both of which operate with radians and the mean radius of the Earth. Once I had both of those coded, I used the average as the distance between points.

In addition, I also added a field to the Geopoint class to hold a Waypoint (subclass of Geopoint which has a label) and looped through all the Waypoints (trail intersections in my case), associating them with the closest Geopoint allowing me to annotate the elevation profile with them.

The rest of the challenge lay in converting the elevation and distance data such that it can be scaled and displayed properly via the Google Chart API. The API is URL based and has a few limitations such as a max size and URL length. I also added a switch to output units in imperial or metric. The code can be found here: gpx.tar.gz. The archive includes the two .gpx files from my training hikes. You can see the output by running the script like so:

./gpxstats.py -i 2010-07-17_redwood_hike.gpx 2010-07-18_tilden_hike.gpx

That will print the data in feet/miles as well as the URL to the elevation profile in Google Charts.

Track: 17-JUL-10
total distance: 12.23mi
ascent: 3576.5ft
descent: 3571.8ft
minimum elevation: 486.2ft
maximum elevation: 1662.6ft
URL length: 1728

Track: TildenSoLoop
total distance: 10.13mi
ascent: 3060.9ft
descent: 3056.8ft
minimum elevation: 588.7ft
maximum elevation: 1703.6ft
URL length: 1653