Wednesday, August 11th, 2010...07:17
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

4 Comments
June 17th, 2011 at 19:32
Thanks for the post. I have a small change to the code:
— a/gpxlib.py
+++ b/gpxlib.py
@@ -49,6 +49,8 @@ class Geopoint(object):
# well as taking into account elevation change via the Pythagorean Theorem
# http://en.wikipedia.org/wiki/Pythagorean_theorem
def distance(self, point):
+ if self.latitude == point.latitude and self.longitude == point.longitude:
+ return 0
averageDistance = (self.haversineDistance(point) +
self.sphericalLawOfCosinesDistance(point)) / 2
return averageDistance
If you stand still (to take a photo for example) the lat/lng might be the same from point to point which causes the distance calculation fails.
June 23rd, 2011 at 17:16
Hey Brian, thanx for taking the time to look through the code. I don’t think the special case is necessary since both the haversineDistance and sphericalLawOfCosinesDistance functions return 0.0 when both points have the same latitude/longitude, therefore averageDistance is 0.0. If you have a gpx file where you see different behavior, please post a snippet of XML and I can look into it.
December 8th, 2011 at 04:13
hi,
I’m not a pro of python, but while searching in the web about drawing gpx profile elevation i found this post… and i like it and just get a python book to start!
My question is do u think that there is way to interact this code with any website using google map to plot elevation of gpx file ? Or i have to code this in php or even js.
regards
fD
December 22nd, 2011 at 14:57
Hey fD,
I think there is probably a way to use this code on the server, but instead of generating the Google Chart API URL, generate some JSON which can then be used via a bit of JavaScript to interact with Google Maps.
Leave a Reply