GPX file is a GPS data that stored in XML format. There are some types of data that stored in GPS namely waypoint, route and track. Track is a type of data which is recorded regularly by GPS in an interval. Therefore, with GPS tracker data we can visualize a trip that we did, which road we passed by, the length of track, time taken, etc. There are some tools or apps that available to view or visualize a GPS track file such as ArcGIS, QGIS, Google Earth and also some online GPX viewer app also available to visualize a GPS tracker data. Just do online searching and you will find many of them.





In this tutorial, I will discuss how to create a GPX track file viewer in Python. I'm using Jupyter Notebook with Python 3. So if you want to run the code make sure you have Jupyter Notebook installed in your machine. We will visualize the track itself, speed and elevation profile along the track. Moreover the visualization will be dynamic in an animation that plot each GPS tracking point as in the figure below.

To create the GPX file viewer we need some modules like matplotlib, time, IPython, xml dom and math. Import all the required modules as in the code below.

import matplotlib.pyplot as plt import time from IPython import display from xml.dom import minidom import math

Then open a GPX file and parse the data using minidom. Here we are taking some important elements: 'trkpt', 'ele' and 'time' for track point, elevation and time.

#READ GPX FILE data = open ( 'F:/ride.gpx' ) xmldoc = minidom . parse(data) track = xmldoc . getElementsByTagName( 'trkpt' ) elevation = xmldoc . getElementsByTagName( 'ele' ) datetime = xmldoc . getElementsByTagName( 'time' ) n_track = len (track)

After getting those elements, we need to get the value from each elements. Then we need to parse the elements to get latitude, longitude, elevation and time. At the end, the time is converted to second. It will be used later in speed calculation.

#PARSING GPX ELEMENT lon_list = [] lat_list = [] h_list = [] time_list = [] for s in range (n_track): lon,lat = track[s] . attributes[ 'lon' ] . value,track[s] . attributes[ 'lat' ] . value elev = elevation[s] . firstChild . nodeValue lon_list . append( float (lon)) lat_list . append( float (lat)) h_list . append( float (elev)) # PARSING TIME ELEMENT dt = datetime[s] . firstChild . nodeValue time_split = dt . split( 'T' ) hms_split = time_split[ 1 ] . split( ':' ) time_hour = int (hms_split[ 0 ]) time_minute = int (hms_split[ 1 ]) time_second = int (hms_split[ 2 ] . split( 'Z' )[ 0 ]) total_second = time_hour *3600+ time_minute *60+ time_second time_list . append(total_second)

Now we have all parameters that are needed to create the GPX file viewer. To do further calculation like distance and speed, we create some functions namely geo2cart, distance and speed. geo2cart is a function to convert Geodetic coordinate into Cartesian coordinate with WGS-84 ellipsoid reference datum. We need the Cartesian coordinate because it will be used to calculate a distance in meter between two GPS tracking points. After getting the distance, then the speed in m/s can be calculated by divided with time difference.

#GEODETIC TO CARTERSIAN FUNCTION def geo2cart (lon,lat,h): a =6378137 #WGS 84 Major axis b =6356752.3142 #WGS 84 Minor axis e2 =1- (b **2/ a **2 ) N = float (a / math . sqrt( 1- e2 * (math . sin(math . radians( abs (lat))) **2 ))) X = (N + h) * math . cos(math . radians(lat)) * math . cos(math . radians(lon)) Y = (N + h) * math . cos(math . radians(lat)) * math . sin(math . radians(lon)) return X,Y #DISTANCE FUNCTION def distance (x1,y1,x2,y2): d = math . sqrt((x1 - x2) **2+ (y1 - y2) **2 ) return d #SPEED FUNCTION def speed (x0,y0,x1,y1,t0,t1): d = math . sqrt((x0 - x1) **2+ (y0 - y1) **2 ) delta_t = t1 - t0 s = float (d / delta_t) return s

#POPULATE DISTANCE AND SPEED LIST d_list = [ 0.0 ] speed_list = [ 0.0 ] l =0 for k in range (n_track -1 ): if k < (n_track -1 ): l = k +1 else : l = k XY0 = geo2cart(lon_list[k],lat_list[k],h_list[k]) XY1 = geo2cart(lon_list[l],lat_list[l],h_list[l]) #DISTANCE d = distance(XY0[ 0 ],XY0[ 1 ],XY1[ 0 ],XY1[ 1 ]) sum_d = d + d_list[ -1 ] d_list . append(sum_d) #SPEED s = speed(XY0[ 0 ],XY0[ 1 ],XY1[ 0 ],XY1[ 1 ],time_list[k],time_list[l]) speed_list . append(s)

#PLOT TRACK f,(track,speed,elevation) = plt . subplots( 3 , 1 ) f . set_figheight( 8 ) f . set_figwidth( 5 ) plt . subplots_adjust(hspace =0.5 ) track . plot(lon_list,lat_list, 'k' ) track . set_ylabel( "Latitude" ) track . set_xlabel( "Longitude" ) track . set_title( "Track Plot" ) #PLOT SPEED speed . bar(d_list,speed_list, 30 ,color = 'w' ,edgecolor = 'w' ) speed . set_title( "Speed" ) speed . set_xlabel( "Distance(m)" ) speed . set_ylabel( "Speed(m/s)" ) #PLOT ELEVATION PROFILE base_reg =0 elevation . plot(d_list,h_list) elevation . fill_between(d_list,h_list,base_reg,alpha =0.1 ) elevation . set_title( "Elevation Profile" ) elevation . set_xlabel( "Distance(m)" ) elevation . set_ylabel( "GPS Elevation(m)" ) elevation . grid()

#ANIMATION/DYNAMIC PLOT for i in range (n_track): track . plot(lon_list[i],lat_list[i], 'yo' ) speed . bar(d_list[i],speed_list[i], 30 ,color = 'g' ,edgecolor = 'g' ) elevation . plot(d_list[i],h_list[i], 'ro' ) display . display(plt . gcf()) display . clear_output(wait = True ) time . sleep( 1 ) plt . show()

That's all the tutorial how to create a GPX file viewer to visualize track, speed and elevation profile with Python in Jupyter Notebook. You can try to run the code by downloading the GPX file viewer Jupyter Notebook and a GPX file sample that used in this tutorial. Finally use your own GPX track file and try to visualize it with the code.

Next step, using the function we do calculation of distance and speed. The result are stored in distance and speed list.Now we can visualize the GPX file track data with three plots: Track, speed and elevation profile.Lastly in a loop, dynamic plot is created in one second interval by plotting each tracking points over the track and elevation profile. The speed change is visualized in a bar chart.

 Geoanalytics Python Tutorial