# How to calculate 'off track' error from GPS data?

I'd like to analyse navigational accuracy, comparing planned transects with the actual track flown from GPS data.

For example, the planned transects below (green) don't match perfectly with the actual flown (blue) - for the areas adjacent to the transects, what is the average error (distance), IGNORING the bits beyond the ends of each transect?

The planned transects are lines, typically only with start and end nodes. The tracks are from GPX files and may be made of many, many nodes - but may only have a few nodes recorded when the aircraft is flying particularly straight.

I'd like to use QGIS. One thought was to use the v.to.points tool from GRASS in the Processing toolbox to split each transect into points of, say, 50m spacing, and determine the nearest distance to the track for each point (then average them).

Is there, perhaps, a better way of calculating average distance than splitting the lines into individual points?

• The solution might depend on exactly what you are trying to use the data for. In the answers, Hausdorff distance is going to give you a "worst ever" measure. So given two sets of data, one set of data which is consistently off will have lower Hausdorff distance than the other set of data that is exactly on, except for one big excursion. That is particularly dangerous with raw GPS measurements where a multipath situation gets you a couple of very short term "spikes" in pseudorange error. You also need to precisely define what you mean by "no adjacent green" - visually OK, but bad mathematically Feb 27, 2015 at 23:57
• Right- see my comment to @Jesse below, the Hausdorff solution may work with enough segments (i.e. samples), but will always give a 'max' rather than 'mean' answer. I'll edit the question to answer more of the 'no adjacent' issue, which is poorly defined. Feb 28, 2015 at 5:46

From the above example, I suggest that you

1. Create points along the green lines at a regular interval
2. Get the perpendicular distance from those points to the blue line and, finally,
3. Compute the average error based on those distances.

Note that you could reject points that are too far (above a given tolerance for GPS worst precision) due to the absence of blue line in front of a green line (this does not happen on your drawing, but it could be an issue).

For the first and the second step, there are two excellent answers (both by gene) here for step 1 and here for step 2. The last step shouldn't be a problem for you (using postgis, or group stats plugin, or python...).

Alternatively, you can draw the perpendicular line for each end point of the green line. Then you build an area from you set of lines (e.g. with GRASS), then you divide your area by the length of the green lines => this gives you the average absolute error.

• Good point on the possible lack of a matching ('in front') line. Will try this out - though my Python skills may not be up to step 2 ... Feb 23, 2015 at 16:28
• Keep in mind that not only does the offset make a difference, but the transect bearing can (for example) rotate the observation frame in yaw. Production errors associated with poor overlap of photogrammetric images can be related to these framing issues. So, consider evaluating the absolute error of the transect bearing (relative to the planned route) at regular sample intervals as well. Feb 26, 2015 at 0:16
• Good remark. In the case of a GPS track, however, the track orientation should not be biased as far as I know. Of course, if the planned transects do not use the same bearing method as the field transect (e.g. compass vs map), there could be a bias also from projection issues). You can detect bias using a regression between the coordinates of the points on the planned track and the coordinates of the corresponding GPS points (testing the hypothesis that the slope of the regression = 0) Feb 26, 2015 at 10:41
• @JasonInVegas, good point - the final version of this validation script/analysis is going to need to include bearing to examine the distance perpendicular to the transect. Feb 27, 2015 at 10:52
• This solution definitely will give the best answer; perpendicular distance samples are what I'm after. Thanks! Implementing it the next challenge (will update the question with the final solution). Mar 1, 2015 at 12:58

I think Hausdorff distance may be what your looking for. It's basically a measure of how similar two geometries are.

General steps to apply it to this problem:

1. Find the closest point on the track to beginning and end of each planned segment.
2. divide the track into segments between these sets of points.
3. Calculate the Hausdorff distance between the planned segment and the closest segment.

Your question said qgis, but the bounty says any FOSS solution, so im going for PostGIS:

``````SELECT ST_HausdorffDistance(
(SELECT geometry FROM segments WHERE fid=1),
ST_Line_Substring(geometry,
ST_Line_Locate_Point(geometry, (select st_pointn(geometry, 1) from segments)),
ST_Line_Locate_Point(geometry, (select st_pointn(geometry, ST_NPoints(geometry)) from segments))
)
)
FROM tracks WHERE ogc_fid=1
``````
• Interesting - but wow does that Wikipedia entry need a 'human-readable' edit! Will the `ST_HausdorffDistance()` function return a value in a particular unit (like metres), or does it give a non-dimensioned number? Feb 23, 2015 at 16:21
• If your geometries are stored in degrees, it's not a very useful number. If they stored in UTM, or you ST_Transform them to UTM as part of the query, the it seems more useful. Feb 23, 2015 at 16:46
• Am playing with this in spatialite, which has `ST_HausdorffDistance()` as well - seems that it gives a reading which is the maximum distance between geometries, which will be OK if I use enough segments. Feb 27, 2015 at 17:11

The following workflow is for QGIS and will give you the mean distance from the route for each transect in metres. I'm assuming the data will be using a projection in metres.

Buffer your transects and route, for example, by 1m with `Vector > Geoprocessing Tools > Buffer(s)`. You now have two polygon layers - the transects and the route. Give the route polygon a value of 1 in its attribute table. Now covert the route polygon to a raster with `Raster > Conversion > Rasterize`. Choose the route polygon as the `input file`, and the `attribute field` to the whatever you gave the value of 1. Set the `raster resolution in map units per pixel` to 1 metre and create your raster.

Now run `Raster > Analysis > Proximity (Raster Distance)` on this new 'route' raster layer. Choose it as the `input file`, set `Values` to 1 and `Dist Units` to GEO. This second raster layer gives the distance value from your route polygon and allows us to use the `Raster > Zonal Statistics` plugin, available from the plugin manager. Run the plugin with the `Raster layer` set to our 'distance' raster and the `Polygon layer` to the transects polygon. You will now have mean distances for each transect to the route listed in the attribute table.