GPX tracks: a quick intro
|What is a GPX file ?|
|GPX stands for GPS Exchange Format; it's a very popular file format used in order to exchange GPS data across different devices.|
GPX is an open format and is almost always supported: it's based on a formally defined XML schema
Many real word implementations are only loosely conformant to the standard schema and further non-standard tags have been introduced by several vendors.
A GPX file is expected to internally store at least one of the following contents:
- Tracks: a Track is an ordered list of points describing a path.
A Track must contain at least one Track Segment holding a list of Track Points which are logically connected in order.
A Track can contain more Segments, and more Tracks can be stored into the same GPX file.
- WayPoints: a WayPoint consists of the WGS 84 (GPS) coordinates of a point and possibly other descriptive information.
The same GPX file can contain a collection of many WayPoints with no sequential relationship.
- Routes: a Route is an ordered list of routepoints (waypoints representing a series of significant turn or stage points) leading to a destination.
SpatiaLite only supports GPX Tracks and will always silently ignore any other content.
Anatomy of a GPX file containing a GPS Track
If you are interested into GPS Tracks you'll very probably have lots of GPX files of your own that you can use as test samples.
The following examples use this GPX sample
<gpx version="1.0" xmlns="http://www.topografix.com/GPX/1/0">
<trkpt lat="55.753572" lon="37.808250">
<trkpt lat="55.753622" lon="37.808255">
<trkpt lat="55.753593" lon="37.808158">
<trkpt lat="55.758177" lon="37.677802">
- the whole GPX file is enclosed within <gpx> and </gpx> tags.
- each Track is delimited by a matching pair of <trk> and </trk> tags.
- each Track Segment is delimited by a matching pair of <trkseg> and </trkseg> tags.
- each Track Point is enclosed within <trkpt> and </trkpt> tags.
- the lat and lon mandatory attributes are intended to declare the WGS 84 latitude and longitude of the point.
- the elevation of the point (measured in meters) can be optionally declared within a pair of <ele> and </ele> tags.
- the date and time of the corresponding GPS measure can be optionally declared within a pair of <time> and </time> tags.
Dates and times are not local time, but instead are Coordinated Universal Time (UTC) using ISO 8601 format.
Importing GPX tracks into a SpatiaLite GeoTable
CREATE TABLE raw_gpx (
id_gpx INTEGER PRIMARY KEY AUTOINCREMENT,
gpx BLOB NOT NULL);
INSERT INTO raw_gpx VALUES (NULL, XB_Create(XB_LoadXML('Gpx-full-sample.gpx')));
SELECT id_gpx, XB_IsGPX(gpx)
Since GPX files are XML files, you must use the standard SQL functions supporting generic XML.
XB_IsGPX() is a new SQL function introduced by SpatiaLite 4.4.0; it will test the actual XML input and will return 1 if it really is of the GPX type, 0 if not, and -1 when the passed argument is not a valid XML document.
CREATE TABLE gpx_tracks (
id_trk INTEGER PRIMARY KEY AUTOINCREMENT);
SELECT AddGeometryColumn('gpx_tracks', 'geom', 4326, 'MULTILINESTRING', 'XYZM');
INSERT INTO gpx_tracks
SELECT NULL, XB_MLineFromGPX(gpx)
Now we'll create another table including a Geometry column declared of the MULTILINESTRING type and having XYZM dimensions. The SRID for this Geometry must be 4326 (alias WGS 84), which is always used with GPS data.
With this, we can invoke the new XB_MLineFromGPX() SQL function which will parse the GPX input, possibly creating a MultiLinestring corresponding to all of the Track-Segments defined in the GPX-File.
- XB_MLineFromGPX() will return NULL if either the passed argument is not a valid BLOB, or it's a valid BLOB but not of the GPX type.
- XB_MLineFromGPX() will return a NULL value, if it does not contains any Tracks.
- when successful, the returned Geometry will always be a MultiLinestring, and a distinct Linestring will be created inside for every Track Segment found within the GPX-File.
Each TrackPoint will correspond to a Vertex of the corresponding Linestring
- the X and Y coordinates of the Vertex will be set accordingly to the declared lon and lat.
- if an ele tag was declared the Z coordinate will be set to the corresponding value.
Otherwise the Z coordinate will be set to 0.0 (default value).
- if a time tag was declared, the ISO 8601 timestamp will be transformed into a julian day number, and the M coordinate will be set to the corresponding value.
Otherwise the M coordinate will be set to 1721059.5, this corresponding to 0000-01-01T00:00:00Z (default value).
Checking the imported TrackPoints
SELECT 'Point #1' AS point, ST_X(a.pt) AS lon, ST_Y(a.pt) AS lat, ST_Z(a.pt) AS ele, DateTime(ST_M(a.pt)) AS time
FROM (SELECT ST_StartPoint(geom) AS pt FROM gpx_tracks) AS a
SELECT 'Point #2' AS point, ST_X(a.pt) AS lon, ST_Y(a.pt) AS lat, ST_Z(a.pt) AS ele, DateTime(ST_M(a.pt)) AS time
FROM (SELECT ST_PointN(geom, 2) AS pt FROM gpx_tracks) AS a
SELECT 'Point #3' AS point, ST_X(a.pt) AS lon, ST_Y(a.pt) AS lat, ST_Z(a.pt) AS ele, DateTime(ST_M(a.pt)) AS time
FROM (SELECT ST_PointN(geom, 3) AS pt FROM gpx_tracks) AS a
SELECT 'Point #N' AS point, ST_X(a.pt) AS lon, ST_Y(a.pt) AS lat, ST_Z(a.pt) AS ele, DateTime(ST_M(a.pt)) AS time
FROM (SELECT ST_EndPoint(geom) AS pt FROM gpx_tracks) AS a;
|Point #1||37.808250||55.753572||135.000000||2009-05-19 04:00:30|
|Point #2||37.808255||55.753622||135.000000||2009-05-19 04:00:31|
|Point #3||37.808158||55.753593||135.000000||2009-05-19 04:00:32|
|Point #N||37.677802||55.758177||152.000000||2009-05-19 04:46:27|
As you can easily see, the MultiLinestring XYZM returned by XB_MLineFromGPX() faithfully preserves both the spatial coordinates and the timestamps originally registered by the GPS sensor.