PHP GPX Ingest

GPS eXchange format files (GPX's) allow you to record data from your Global positioning system for processing/import into other systems.

The PHP GPX-Ingest class allows you to import basic GPX files and converts them into an object for easy data retrieval. In the process of doing so, it also generates basic statistics such as average speed, number of track points and journey length.

The resulting object can be exported as a JSON string for easy storage and re-import back into the class at a later date (perhaps to extract more information).

This documentation details how to include and use the class in your project.

PHP GPX-Ingest is licensed under the GNU GPL V2 License.

 


Contents

  1. Introduction
    1. Getting PHP GPX Ingest
    2. Requirements
    3. Including the Library
    4. Ingesting a GPX File
    5. Ingesting a GPX String
    6. Extracting the JSON Object
    7. Importing a JSON String/File
  2. Extracting Data - ID's
    1. Getting Track IDs
    2. Getting Track Names
    3. Get Track Segments
    4. Get Trackpoint Names
  3. Extracting Data - Stats
    1. Extracting the stats objects
    2. Extracting specific statistics
  4. Extracting Data - Objects
    1. Extracting the Journey Object
    2. Extracting a Track Object
    3. Extracting a Segment Object
    4. Extracting a Trackpoint Object
  5. Waypoints
    1. getWayPointCount
    2. getWayPoints
    3. getWayPoint
  6. Routes
    1. getRoutesObject
    2. getRouteIDs
    3. getRouteNames
    4. getRoute
    5. getRoutePointNames
    6. getRoutePoint
    7. getRouteCount
    8. getRouteStats
  7. Utility Functions
    1. getGPXTime
    2. getGPXTimeZone
    3. reset
  8. Object Heirachy
    1. Journey Object
    2. Track Object
    3. Segment Object
    4. Trackpoint Object
  9. Experimental Features
  10. GPX Extensions

 

 


Introduction

Getting PHP GPX Ingest

You can download PHP GPX-Ingest from GitHub here.

Requirements

The class has no special requirements other than SimpleXML, you must be using PHP 5.3 or greater but no non-core libraries are used.

 

Including the Library

Just make sure the class has been loaded before you try to use it!

<?php
require_once('GPXIngest.class.php');
?>

 

Ingesting a GPX file

To ingest a file, we simply call loadFile and then ingest.

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadFile('myfile.gpx');
$gpx->ingest();
?>

 

Ingesting a GPX String

The GPX data may not be stored on the filesystem, for example you may have stored it in a MySQL database, in this case we simply pass the data to loadString

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadString($mygpxstring);
$gpx->ingest();
?>

 

Extracting the JSON object

To extract the JSON object for later use, we call getJSON

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadFile('somefile.gpx');
$gpx->ingest();
$json = $gpx->getJSON();
?>

 

Importing a JSON String/File

If we wanted to import that JSON string at a later date we'd call loadJSON or loadJSONFile. These work on almost exactly the same basis as above, but with one key difference - there's no need to run ingest.

It's more efficient to import JSON than to re-import from the source GPX as the JSON import doesn't require each individual trackpoint to be processed - that data is already available within the object.

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
?>

 

 


Extracting Data - ID's

So far we've loaded the GPX and exported/imported JSON. But what if we actually want to extract data from the object? Data can be extracted directly from the object, or using functions within the class. The object is stored within a class variable called journey, but for the purposes of this documentation we'll limit ourselves to using the methods provided by GPXIngest, for most calls we'll need to know the ID of the track/segment we want to examine

 

Getting the Track ID's

If we want information on a specific track, we'll need to provide it's ID, to get a list of the tracks within the object we call getTrackIDs;

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getTrackIDs());
?>

Output:

Array
(
[0] => journey0
)

 

Get Track Names

Whilst knowing the track ID's is useful if you plan on blindly cycling through each, it might be more useful to know the names that were specified in the source GPX as well

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getTrackNames());
?>

Output:

Array
(
[0] => Array
(
[id] => journey0
[name] => SpeedView
)
)

 

Get Track Segments

To get the segments of a track, we need to call getTrackSegmentNames and specify the track ID

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getTrackSegmentNames('journey0'));
?>

Output:

Array
(
[0] => seg0
)

 

Get Trackpoint Names

You may wish to a specific trackpoint within a segment, in which case you'll need to call getTrackPointNames

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getTrackPointNames('journey0','seg0'));
?>

 

 


Extracting Data - Stats

When the source GPX was ingested, a variety of stats were generated for each track and segment. Overall stats were also generated for the entire object. At the time of writing these include

  • Number of trackpoints
  • Recorded Journey duration
  • Journey Start time
  • Journey end time
  • Time spent moving
  • Time spent stationary
  • Average speed
  • Modal Speed
  • Min speed
  • Max speed
  • Acceleration/Deceleration Statistics
  • Unit of Measure (for speeds)
  • Min Elevation
  • Max Elevation
  • Latitude/Longitude bounds
  • Distance Travelled (See Experimental features below)

In reality, Min Speed is largely useless as it will almost always be 0, however it is provided nonetheless.

There are two methods of obtaining stats, you can either retrieve the stats object in full, or request specific data.

 

Extracting the stats objects

There are three types of track objects - Total, track and segment. Each contains stats for it's particular point in the heirachy - a segment stats object will only contain stats for trackpoints within that segment whilst the Total stats object contains stats based on every trackpoint in the Journey object.

We have two functions - getJourneyStats and getStats. The former provides the Total stats object whilst the former will provide either a track stats object or a segment stats object if a segment ID was provided;

 

Total Stats

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getJourneyStats());
?>

Output:

stdClass Object
(
    [trackpoints] => 778
    [recordedDuration] => 7556
    [segments] => 16
    [tracks] => 16
    [maxacceleration] => 0
    [maxdeceleration] => 0
    [minacceleration] => 0
    [mindeceleration] => 0
    [avgacceleration] => 0
    [avgdeceleration] => 0
    [speedUoM] => Array
        (
        )

    [timeMoving] => 0
    [timeStationary] => 0
    [timeAccelerating] => 0
    [timeDecelerating] => 0
    [distanceTravelled] => 0
    [bounds] => stdClass Object
        (
            [Lat] => stdClass Object
                (
                    [min] => 56.114105
                    [max] => 56.179494
                )

            [Lon] => stdClass Object
                (
                    [min] => 43.346461
                    [max] => 43.522420
                )

        )

    [start] => 1368860043
    [end] => 1368888867
)

 

Track Stats

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getStats('journey0'));
?>

Output:

stdClass Object
(
    [journeyDuration] => 1562
    [maxacceleration] => 0
    [maxdeceleration] => 0
    [minacceleration] => 0
    [mindeceleration] => 0
    [avgacceleration] => 0
    [avgdeceleration] => 0
    [speedUoM] => Array
        (
        )

    [timeMoving] => 0
    [timeStationary] => 0
    [timeAccelerating] => 0
    [timeDecelerating] => 0
    [distanceTravelled] => 0
    [bounds] => stdClass Object
        (
            [Lat] => stdClass Object
                (
                    [min] => 56.114105
                    [max] => 56.119712
                )

            [Lon] => stdClass Object
                (
                    [min] => 43.503630
                    [max] => 43.522420
                )

        )

    [start] => 1368860043
    [end] => 1368861605
    [recordedDuration] => 1562
    [elevation] => stdClass Object
        (
            [max] => 129.22
            [min] => 60.83
            [avgChange] => 0.38
        )

)

 

Segment Stats

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getStats('journey0','seg0'));
?>

Output:

stdClass Object
(
    [distanceTravelled] => 0
    [bounds] => stdClass Object
        (
            [Lat] => stdClass Object
                (
                    [min] => 56.114105
                    [max] => 56.119712
                )

            [Lon] => stdClass Object
                (
                    [min] => 43.503630
                    [max] => 43.522420
                )

        )

    [start] => 1368860043
    [end] => 1368861605
    [journeyDuration] => 1562
    [elevation] => stdClass Object
        (
            [max] => 129.22
            [min] => 60.83
            [avgChange] => 0.38
        )

    [timeMoving] => 0
    [timeStationary] => 0
    [timeAccelerating] => 0
    [timeDecelerating] => 0
)

Note: Support for max, min and modal speed will be added to Segment stats very soon

 

Extracting specific Statistics

There may be occasions when you simply require a specific statistic, in order to obtain these you can use the methods below

Function Description Arguments Returns
getJourneyStats Return the Total Stats Object   Object
getStats Return either a Track or a Segment Stats Object TrackID - Mandatory
SegmentID - Optional
Object
getTrackPointCount Return the number of trackpoints within a segment TrackID - Mandatory
SegmentID - Mandatory
INT
getTotalAvgSpeed Return the average speed from the Total Stats Object   DECIMAL
getJourneyStart Return a UNIX timestamp denoting the first recorded trackpoint in the journey   INT
getJourneyEnd Return a UNIX timestamp denoting the last recorded trackpoint in the journey   INT
getAvgSpeed Return either a Track or a Segment Stats Object TrackID - Mandatory
SegmentID - Optional
DECIMAL

 

Additional statistical functions will be provided in later releases

 

 


Extracting Data - Objects

You can directly extract each type of object in order to gain the data within. The four types are

  • Journey - The entire content
  • Track - A specific track recorded within the Journey object
  • Segment - A specific segment recorded within a specific track
  • Trackpoint - A specific GPS datapoint within a specific segment

Extracting the Journey Object

You may want to extract the journy object for use elsewhere, you could of course extract the JSON encoded version using getJSON, but for efficiency you can also request the full object directly

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
$journey = $gpx->getObject();
?>

 

Extracting a Track Object

To extract a specific track we use getTrack and specify the relevant track ID;

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
$track = $gpx->getTrack('journey0');
?>

 

Extracting a Segment Object

To extract a specific segment we use getSegment and specify both the relevant track ID and the segment ID;

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
$segment = $gpx->getSegment('journey0','seg0');
?>

 

Extracting a Trackpoint Object

We extract individual trackpoints using getTrackPoint, specifying the parent track and segment ID's as well as the trackpoint ID

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r( $gpx->getTrackPoint('journey0','seg0','trackpt0') );
?>

Output:

stdClass Object
(
[lat] => 54.129725
[lon] => 3.415779
[time] => 1377581448
[speed] => 0 mph
[ele] => 62
)

Note: Earlier versions of GPXIngest used "elevation", as of GPXIN-34 that attribute is now deprecated and you should use "ele" instead.

 

 


Waypoints

As of GPXIN-24, the class includes support for ingesting Waypoint information. A number of simple methods have been provided to allow for extraction of waypoint information

getWayPointCount

No arguments required, simply returns an integer indicating how many waypoints are represented within the object

getWayPoints

No arguments requred, returns an array populated with waypoint objects. Array keys are numerical

getWayPoint((int)$id)

Expects an array key to identify the desired waypoint, and returns a waypoint object of the following structure

stdClass Object
(
    [name] => Position 1
    [description] => 
    [comment] => 
    [position] => stdClass Object
        (
            [lat] => 54.9328621088893
            [lon] => 9.860624216140083
            [ele] => 0.0
            [geoidheight] => 
        )

    [meta] => stdClass Object
        (
            [time] => 
            [magvar] => 
            [source] => 
            [link] => 
            [symbol] => 
            [type] => 
            [GPS] => stdClass Object
                (
                    [fix] => 
                    [sat] => 
                    [hdop] => 
                    [vdop] => 
                    [pdop] => 
                    [ageofdgpsdata] => 
                    [dgpsid] => 
                )

        )

)

All properties defined within the specification will always be present. However, if they were not present within the source GPX file their values will be null


Routes

The GPX specification also allows for a Route type. The distinction between a route and a track is that the route is (theoretically) the route that was originally planned, where a track is the path that was actually followed. As of GPXIN-27 basic route support has been implemented

getRoutesObject

Returns the routes object with all routes nested under it

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRoutesObject());
?>

getRouteIDs

Returns an array containing all valid route ids

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRouteIDs());
?>
Output
Array
(
    [0] => route0
)

getRouteNames

Returns an array with each entry containing the internal ID and the name (if set) of a route that has been ingested

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRouteNames());
?>
Output
Array
(
    [0] => Array
        (
            [id] => route0
            [name] => Patrick's Route
        )

)

getRoute

Retrieves a route based on the internal ID (so taking from the example above, we may pass in route0). Routepoints can be found under the property points and have the same base structure as waypoints

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRoute('route0'));
?>
Output
stdClass Object
(
    [name] => Patrick's Route
    [meta] => stdClass Object
        (
            [comment] => 
            [description] => 
            [src] => 
            [link] => 
            [number] => 
            [type] => 
        )

    [points] => stdClass Object
        (
            [rtpoint0] => stdClass Object
                (
                    [name] => Position 1
                    [description] => 
                    [comment] => 
                    [position] => stdClass Object
                        (
                            [lat] => 54.9328621088893
                            [lon] => 9.860624216140083
                            [ele] => 0.0
                            [geoidheight] => 
                        )

                    [meta] => stdClass Object
                        (
                            [time] => 
                            [magvar] => 
                            [source] => 
                            [link] => 
                            [symbol] => 
                            [type] => 
                            [GPS] => stdClass Object
                                (
                                    [fix] => 
                                    [sat] => 
                                    [hdop] => 
                                    [vdop] => 
                                    [pdop] => 
                                    [ageofdgpsdata] => 
                                    [dgpsid] => 
                                )

                        )

                )
        )

)

getRoutePointNames

Returns an array containing a list of all valid routepoint names/ids for the given route

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRoutePointNames('route0'));
?>
Output
Array
(
    [0] => rtpoint0
    [1] => rtpoint1
    [2] => rtpoint2
    [3] => rtpoint3
    [4] => rtpoint4
    [5] => rtpoint5
    [6] => rtpoint6
    [7] => rtpoint7
)

getRoutePoint

Retrieves a specific route point. Requires route and routepoint id

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRoutePoint('route0','rtpoint0'));
?>
Output
stdClass Object
(
    [name] => 
    [description] => 
    [comment] => 
    [position] => stdClass Object
        (
            [lat] => 39.6856861
            [lon] => -105.5073323
            [ele] => 1
            [geoidheight] => 
            [elechange] => 
        )

    [meta] => stdClass Object
        (
            [time] => 
            [magvar] => 
            [source] => 
            [link] => 
            [symbol] => 
            [type] => 
            [GPS] => stdClass Object
                (
                    [fix] => 
                    [sat] => 
                    [hdop] => 
                    [vdop] => 
                    [pdop] => 
                    [ageofdgpsdata] => 
                    [dgpsid] => 
                )

        )

)

getRouteCount

Returns an integer identifying how many routes were ingested from the source GPX file

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
echo $gpx->getRouteCount();
?>

getRouteStats

Statistics for routes are embedded within the main Stats Object under attribute routestats, however as of GPXIN-33 they can be retrieved directly with getRouteStats()

<?php
$gpx = new GPXIngest\GPXIngest();
$gpx->loadJSON($myJSONstring);
print_r($gpx->getRouteStats());
?>
Output
stdClass Object
(
    [bounds] => stdClass Object
        (
            [Lat] => stdClass Object
                (
                    [min] => 39.6856861
                    [max] => 39.68865
                )

            [Lon] => stdClass Object
                (
                    [min] => -105.5073323
                    [max] => -105.50693
                )

        )

    [elevation] => stdClass Object
        (
            [min] => -15
            [max] => 60
            [avgChange] => -2.29
            [maxChange] => 50
            [minChange] => -40
        )

)

The statistics available for route points are much more limited than with tracks, as a route will not normally contain quite as much data.


Utility Functions

There are a number of utility functions within the class, providing information that may be required for further processing of the data.

 

getGPXTime

This utility function returns the time (as a UNIX timestamp) that the GPX file was generated (based on the value stored in the GPX at import)

 

getGPXTimeZone

This utility function details the timezone that was in use when the source GPX file was first ingested. This may be of use when converting dates following the import of a JSON file from another source - being GPS all times should be UTC/Zulu, however it's always wise to check that this is the case.

This function returns a string which can be directly input into date_default_set()

 

reset

This utility function resets all internal counters and stats. If importing multiple files (e.g. in a while loop) calling reset means you don't need to deconstruct and then reconstruct the class between each source file.

<?php
$gpx = new GPXIngest\GPXIngest();

foreach($files as $file){
$gpx->reset();
$gpx->loadFile($file);
$gpx->ingest();
// Do whatever we need to
}
?>

 

 


Object Heirachy

There are essentially four object types generated by an import, these follow the same internal logic as a GPX file

    • Journey - Roughly equivalent to the GPX file itself
    • Track - One generated for each track within the GPX file (>trk<)
    • Segment - One generated for each segment within a track (>trkseg<)
    • Trackpoint - One generated for each trackpoint within a segment (>trkpt<)

Each level of object is nested within it's parent so for a basic GPX file we might have

 

GPX

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

<gpx xmlns="http://www.topografix.com/GPX/1/1"
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
  <metadata>     <link href="http://www.garmin.com">
      <text>Garmin International</text>
    </link>
    <time>2009-10-17T22:58:43Z</time>
  </metadata>
  <trk>
    <name>Example GPX Document</name>
    <trkseg>
      <trkpt lat="47.644548" lon="-122.326897">
        <ele>4.46</ele>
        <time>2009-10-17T18:37:26Z</time>
      </trkpt>
      <trkpt lat="47.644548" lon="-122.326897">
        <ele>4.94</ele>
        <time>2009-10-17T18:37:31Z</time>
      </trkpt>
      <trkpt lat="47.644548" lon="-122.326897">
        <ele>6.87</ele>
        <time>2009-10-17T18:37:34Z</time>
      </trkpt>
    </trkseg>
  </trk>
</gpx>

Object Heirachy:

- Journey Object
-- Track
--- Segment
---- Trackpoint
---- Trackpoint
---- Trackpoint

Each object type also contains some enhanced information generated when the GPX source file was first imported, these are detailed below.

 

Journey Object

The journey object is roughly equivalent to the GPX file in it's entirety, but with additional data (such as statistics) added.

- created
-- creator
-- version
-- format
-- time
- timezone
- stats (Journey Stats Object)
- journeys
-- Track object
-- Track object
- related
-- Waypoints
-- Routes

 The number of track objects will obviously depend on the number of tracks within the source GPX file. In our example above, there would be only one.

 

Track Object

The track object is roughly equivalent to it's counterpart within the source GPX file and may contain one or more segments (reasons for a new segment being started vary, but may include a loss of GPS signal).

- name
- stats (Track Stats Object)
- segments
-- segment object

 

Segment Object

The segment object will contain, amongst other things multiple trackpoints and is roughly equivalent to the <trkseg> section(s) of a GPX file

- stats (Segment stats object)
- points (Trackpoint object(s))

 

Trackpoint Object

The trackpoint object stores almost exactly the same data as the <trkpt> section within a GPX file, although the format may be slightly different

- lat
- lon
- time
- speed
- ele
- travelled


Experimental Features

Certain features are disabled by default, either because they are in an early stage of development (i.e. experimental) or are considered to be computationally expensive. The ability to use experimental features was implemented in GPXIN-17

In order to use an experimental feature, you need to enable the functionality prior to ingest - each experimental feature has a unique identifier to be used. There are three methods relating to experimental features

  • enableExperimental($type)
  • disableExperimental($type)
  • listExperimental()

The method listExperimental() returns an array containing all feature identifiers (as the key) and whether or not that functionality is enabled as the value (boolean). For ease of troubleshooting, the output of this function is also embedded into the metadata if a JSON string is retrieved with getJSON()

Distance Calculations

Key: calcDistance

Note: as of GPXIN-23 this feature is no longer experimental and is enabled by default.

When enabled, the library will calculate the distance between each trackpoint, and write to a property called travelled. A property within each statistics object - distanceTravelled is also updated

The Unit of Measure for these properties is feet

As of GPXIN-13, The Time Moving statistic will also be updated based on this calculation


GPX Extensions

Various devices use schemas in order to extend the basic GPX spec. GPXIngest has limited support for these (implemented in GPXIN-20). Extension data is embedded into the resulting GPXIngest object, and observes the namespaces defined in the source GPX file.

In order to get a list of the namespaces used, we'd do

$gpx->getGPXNameSpaces();
Output:
Array
(
    [] => http://www.topografix.com/GPX/1/0
    [xsi] => http://www.w3.org/2001/XMLSchema-instance
)

Extension data is embedded into the trackpoint in which it occurs

[trackpt0] => stdClass Object
(
    [extensions] => stdClass Object
        (
            [nmea] => Array
                (
                    [course] => 11.6
                    [speed] => 1.7
                )

        )

    [lat] => 11.543009877
    [lon] => -85.697211027
    [ele] => 55.0
    [elevationChange] => 0
    [time] => 1437825722
)

In the future it will be possible to tell GPXIngest to use an extension element for a specific purpose (such as the speed).