Distance Accuracy of GPS Tracks, High Sierra Trail

How accurate are distance measurements using hiker GPS tracking? The GPS track is a popular way to obtain the distance of a planned hike. GPS tracks are often available when trusted sources are not. However, GPS tracks are subject to errors from undersampling or satellite noise.

This is an investigation of distance measurements from GPS tracks as compared with reference distances published at the Sequoia Kings (SEKI) Canyon National Park website, (“High Sierra Trail” 2018). The mileages from SEKI are not necessarilty error free but derive from the best external and authoritative source for this trail. Trail distances from the government land management agencies most likely come from surveys using the calibrated measuring wheel, still the best known instrument for trail distance measurement (“How Far Is It? The Truth Behind Trail Measurements” 2019; Daniels 1995).

In this analysis we take a random sample of three GPS tracks for each trail segment listed at the High Sierra Trail website. We measure the distance of each GPS track using software (“GpsPrune” 2018). The statistical analysis will check for an overall bias relative to the government data and for variability between GPS track measurements.

This research found that GPS tracks are remarkably consistent when sampled from the same trail segment. However, the average distance of multiple GPS tracks taken from the same trail segment usually differs from the government data. Sometimes, the difference between the average measured and reference distance can be over a mile.

GPS Track Distance Data

The High Sierra Trail site lists 16 segments which total 72.2 miles end to end, (“High Sierra Trail” 2018). A footnote about the Moraine Lake excursion allows us to add another segment for a total of 17 trail segments that have a reference distance. Distances are listed in miles to the nearest tenth of a mile and kilometers to the nearest tenth of a kilometer. Since the data in kilometers has a lower relative roundoff error than the data in miles, we use the kilometer-units data, converting it to miles and rounding it to the nearest 100th of a mile. Reference mileages derived this way has a roundoff error of about \(\pm 0.06\) miles.

For each segment, we randomly sample three GPS tracks from gaiagps.com (“Explore the Map” 2019), for a total of 51 GPS track distance measurements. We “pruned” each track, removing obvious knots when the GPS device was at rest, or when the hiker took an excursion.

The hst_data data frame contains 51 observations on seven variables. It is the original track distance measurement and reference distances stored in a .csv file.

The lhst_data contains 51 observations on ten variables, seven of which are from hst_data, plus additional variables needed for analysis in this document. A listing appears at the end.

The following R-code chunk reads in and prepares the data sets. It loads raw data from a .csv file. It adds distance measurement error for the study of absolute errors. It converts the trail_segment designator to a factor. It adds the log of distance measurements for a study of relative errors.

hst_data <- read_csv('data_hst.csv', col_types = cols(
  trail_segment = col_character(),
  start = col_character(),
  end = col_character(),
  dist_meas_mi = col_double(),
  dist_gov_mi = col_double()
)
)

lhst_data <- hst_data %>%
  mutate(dist_error=dist_meas_mi-dist_gov_mi, ldist_meas_mi=log(dist_meas_mi), 
         ldist_gov_mi=log(dist_gov_mi),
         trail_segment=as_factor(trail_segment))

Dictionary of variables in data_hst and ldata_hst data frames

trail_segment - short name for this segment and used for trail segment factor.

start - name of start of trail segment.

end - name of end of trail segment.

dist_meas_mi - GPS track length in miles.

dist_gov_mi - reference distance from High Sierra Trail website.

npoints - number of track points in the GPS track.

gain_loss - sum of cumulative gain and cumulative loss for the track.

dist_error - dist_meas_mi - dist_gov_mi.

ldist_meas_mi - \(\log(dist\_meas\_mi)\).

ldist_gov_mi - \(\log(dist\_gov\_mi)\).

Trail segments are referenced by their short names, HST_xx, where xx is the order that they appear from west to east. The following table identifies the short names with their start and end points.

Absolute error with trail segment effect

We subtract the measured distance from the reference distance, resulting in a distance error for each observation.

\[ dist\_error = dist\_meas\_mi - dist\_gov\_mi\] Distance errors can be reflected in an overall bias, measurement-to-measurement errors for the same trail segment and errors varying between trail segments. An overall bias would imply that all GPS track measurements have an additive uniform error. A measurement-to-measurement error occurs due to GPS satellite noise, sampling rate and time-varying factors in the GPS system. Finally, it is possible that some trail segments could have average measurement errors different from others. The most obvious reason for this is an error in the reference distance, since the same reference distance is used to calculate the measurement errors for all of the the measurements on that segment. The discussion section below addresses someother reasons for between-trail segments variation in distance error.

The next chunk plots the measured distances as box plots, one set for each segment. It overlays the plot with the reference distance for each segment.

ggplot(lhst_data, aes(x=trail_segment)) +
  geom_boxplot(aes(y=dist_meas_mi)) +
  geom_point(aes(y=dist_gov_mi), color="blue") + 
  theme(axis.text.x = element_text(angle=45)) +
  xlab("Trail Segment") +
  ylab("Distance (miles)") +
  ylim(0,15)

This graphic illustrates the types of errors that occur in distance measurement. The blue dots are the reference distances and each box plot is for three GPS measurements. The spread of the box plots indicate the reliability of the GPS track measurements, the tendency for repeat measurements on the same trail segment to agree. The measurements usually agree with each other to within a fraction of a mile. The measurements follow the reference distance, and often (e.g. HST_2, HST_7, HST_11, HST_12, HST_14, HST_15, HST_17), they agree quite well with the reference distance. However, for more than half of the trail segments, the mean differs from the reference distance by more than the range of the measurements (e.g. HST_1, HST_4, HST_5, HST_6, HST_8, HST_9, HST_10, HST_13, HST_16). This points to a trail segment effect, a systematic error that repeats with every measurement made on the same trail segment.

To test for a trail segment effect on distance measurement error, we can use the model:

\[ dist\_error = \beta_0 + \gamma_{i}*dtrail\_segment_{i} + \epsilon. \] \(\beta_0\) is the overall measurement error for “HST_01”. \(\gamma_{i}\) is the effect of the \(i\)th segment relative to the first one for the remaining 16 trail segments. \(\epsilon\) is the independent measurement error for each GPS measurement. If all \(\gamma_{i}\) are zero, then the measurement errors do not depend on the particular segment, and \(\beta_0\) is an overall measurement bias.

The next chunk performs a one-way analysis of variance (AVOVA) test for the group of coefficients \(\{\gamma_i\}\).

lm_dist_error <- lm(dist_error ~ trail_segment, data=lhst_data)
aov_dist_error <- aov(lm_dist_error)
summary(aov_dist_error)
##               Df Sum Sq Mean Sq F value   Pr(>F)    
## trail_segment 16 24.921  1.5575   24.59 4.09e-14 ***
## Residuals     34  2.153  0.0633                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
waldtest(lm_dist_error, dist_error ~ 1, vcov=vcovHC)

The Wald test repeats the one-way ANOVA, but without assuming homoskedasticity.

The Wald test confirms that the individual trail segment is a factor in GPS measurement error ( $ p = 5.2 10^{-16}$ ). We discussed above how this could be from errors in the reference data or because of trail segment attributes that affect GPS measurements. We cannot address the hypothesis of errors in reference data, since there is no third source of distance data with which to compare. Later, we will investigate if trail segment length and other trail segment attributes that might explain some of the trail segment effect.

For the current model, we can break down the total distance error in this experiment into 1) overall measurement bias, 2) between trail segments variation and 3) within trail segments variation.

## [1] "Overall measurement bias (mi):"
## [1] 0.1521569
## [1] "Between trail segments standard deviation (mi):"
## [1] 1.248012
## [1] "Within trail segment standard deviation (mi):"
## [1] 0.2516611
## [1] "Total measurement error standard deviation (mi):"
## [1] 1.273133

The overall measurement bias is 0.15 miles. The measurement error varies between segments with a standard deviation of 1.25 miles. Within trail segments, it only varies with standard deviation 0.25 miles. Therefore, the main source of measurement error is between segments.

Analysis of between trail segments error

It is clear that the trail segment factor is the largest source of variation. We will graph mean distance error when averaged within segments to get a look at its distribution.

The hst_byseg data frame contains 17 observations of mean measured distance, mean distance error and reference distance.

Make a stem and leaf plot of mean distance error.

# calculate data frame hst_byseg
hst_byseg <- lhst_data %>%
  group_by(trail_segment) %>%
  summarize(dist_meas_mi=mean(dist_meas_mi), dist_error=mean(dist_error), dist_gov_mi=mean(dist_gov_mi))
print("Stem and leaf plot of distance error (miles)")
## [1] "Stem and leaf plot of distance error (miles)"
stem(hst_byseg$dist_error, scale=2)
## 
##   The decimal point is at the |
## 
##   -0 | 8766
##   -0 | 330
##    0 | 11223
##    0 | 579
##    1 | 2
##    1 | 9
shapiro.test(hst_byseg$dist_error)
## 
##  Shapiro-Wilk normality test
## 
## data:  hst_byseg$dist_error
## W = 0.9471, p-value = 0.4123

Eight of the 17 segments have an absolute error less than \(\pm0.3\), which is comparable to the within-segment variation of GPS measurements. The nine others are outside that interval. Two of them are more than one mile. The distribution superficially appears bimodal with a heavy upper tail. However, it passes the Shapiro-Wilk test, with p = 0.41. The sample is too small to detect any non-normality.

One possible explanation of trail segment effect on distance error is that the GPS errors depend on the true length of the segment. The longer the segment, the more track points are in each GPS track, and each additional track point incurs an additional error. A plot of mean error versus reference distance suggests a weak relationship. The residuals are low in the 0-4 mile range and high in the range 5-7.5 range. However, the two longest segments run counter to the hypothesis that longer trail segments have larger errors.

ggplot(hst_byseg, aes(x=dist_gov_mi, y=dist_meas_mi)) +
  geom_point(color="blue") + 
  geom_line(aes(x=line_x, y=line_y), data=data.frame(line_x = c(0, 15), line_y = c(0, 15))) +
  xlim(0, 15) +
  xlab("Reference Distance (mi)") +
  ylim(0, 15) +
  ylab("Mean Measured Distance (mi)")

To test the hypothesis, we cannot directly regress the measurement error on reference distance, because the latter was used to compute the former. The two variables are already associated with a slope of -1. However, if measurement error is proportional to trail segment length, then the relative error is nearly constant.

\[ \log(\frac{dist\_meas\_mi}{dist\_gov\_mi}) = \beta_0 + \epsilon\] which, with \(\beta_1=1\), is equivalent to \[ \log(dist\_meas\_mi) = \beta_0 + \beta_1\log(dist\_gov\_mi) +\epsilon.\] However, if we allow \(\beta_1\ne1\), it will admit the larger family of power law relationships between \(dist\_meas\_mi\) and \(dist\_gov\_mi\). If \(\beta_1 = 1\), then the exponent of the power law is one, which is a simple proportional relationship, or a constant relative error.

Suppose we have estimated the prediction equation \[ \widehat{\log(dist\_meas\_mi)} = \hat{\beta}_0 + \hat{\beta}_1\log(dist\_gov\_mi),\] then subtracting \(\log(dist\_gov\_mi)\),

\[ \widehat{\log(\frac{dist\_meas\_mi}{dist\_gov\_mi})} = \hat{\beta}_0 + (\hat{\beta}_1 -1)\log(dist\_gov\_mi),\] which implies a power law relationship between relative error and reference distance. The hypothesis \(H_0: \beta_1=1\) can be used to test for a relationship between relative error and reference distance.

# estimate the log(dist_meas_mi) versus log(dist_gov_mi) equation
lhst_byseg <- hst_byseg %>%
  mutate(ldist_meas_mi=log(dist_meas_mi), ldist_gov_mi=log(dist_gov_mi))
lm_relerror <- lm(ldist_meas_mi ~ ldist_gov_mi, data=lhst_byseg)
sumlm_relerror <- summary(lm_relerror)
sumlm_relerror
## 
## Call:
## lm(formula = ldist_meas_mi ~ ldist_gov_mi, data = lhst_byseg)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.26865 -0.11926  0.02469  0.08335  0.27843 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -0.06677    0.12742  -0.524    0.608    
## ldist_gov_mi  1.04947    0.08170  12.846  1.7e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.1659 on 15 degrees of freedom
## Multiple R-squared:  0.9167, Adjusted R-squared:  0.9111 
## F-statistic:   165 on 1 and 15 DF,  p-value: 1.695e-09
# test statistic and p-value for H0: beta1 = 1
# These are printed out next chunk.
tbeta1 <- (sumlm_relerror$coefficients[2,1] - 1)/sumlm_relerror$coefficients[2,2]
pbeta1 <- 2*pt(-abs(tbeta1), sumlm_relerror$df[2])
## [1] "Test for beta_1 <> 1:"
## [1] "T statistic:"
## [1] 0.6054617
## [1] "p-value:"
## [1] 0.5539234

The slope coefficient for \(ldist\_gov\_mi\) is not significanly different from 1 ( \(p = 0.55\) ). There is insufficient evidence to deny a constant relative error for different reference distances.

Relative error, between trail segments

Now we will verify that the previous findings for absolute error carry over to relative error. Relative error, on a log scale, is \[ \log(relerror) = \log(\frac{dist\_meas\_mi}{dist\_gov\_mi})\]

\[ = \log(dist\_meas\_mi) - \log(dist\_gov\_mi)\] Mainly, we will verify that relative error also depends on trail segment after rescaling to account for trail segment length. Then we will break down the components of relative error.

First, add the lrelerror ( \(\log(relerror)\) ) field to the data frame.

lhst_data <- lhst_data %>%
  mutate(lrelerror=log(dist_meas_mi)-log(dist_gov_mi))

At box pot of relative error follows.

ggplot(lhst_data, aes(x=trail_segment)) +
  geom_boxplot(aes(y=lrelerror)) +
  theme(axis.text.x = element_text(angle=45)) +
  xlab("Trail Segment") +
  ylab("Log relative error") +
  ylim(-.4,.4) +
  ggtitle("Relative error versus trail segment")

Graphically, relative errors vary mostly by trail segment. They are centered at zero and vary by \(\pm 35\%\). They are heteroskedastic, their spreads also varying by trail segment.

The linear model for relative error is the same as with dist_error, except using lrelerror as the response variable.

\[ \log(relerror) = \beta_0 + \gamma_{i}*dtrail\_segment_{i} + \epsilon. \]

This chunk tests the trail segments effect as a group on the lrelerror variable. It uses the heteroskedasticity-robust covariance estimator.

lm_lrelerror <- lm(lrelerror ~ trail_segment, data=lhst_data)
waldtest(lm_lrelerror, lrelerror ~ 1, vcov=vcovHC)

These tests confirm what we can see in the box plots above, that lrelerror varies with trail segment ( \(p=2.2 \times 10^{-16}\) ).

Just as we did for absolute error, we break down the relative error into its bias, trail segment and measurement error components. Because \(\log(\frac{dist\_meas\_mi}{dist\_gov\_mi})\) is not quite the relative error, \(\frac{dist\_meas\_mi}{dist\_gov\_mi}-1\), we apply formulas for \(E(\frac{dist\_meas\_mi}{dist\_gov\_mi}-1)^2\), assuming that the measurement error and random effect from the trail segment are both normal (Ahrens 2020).

# get parameters from the coefficients for log(relative error).
ct <- coeftest(lm_lrelerror)
mu <- mean(ct[,1])
tausqr <- var(ct[,1])
sigsqr <- sum(lm_lrelerror$residuals^2)/lm_lrelerror$df.residual
# overall measurement bias
mu_relerror <- (exp(mu + (tausqr + sigsqr)/2) - 1)*100
# between trail segments standard deviation
sigma_between <- exp(mu + (tausqr + sigsqr)/2)*sqrt(exp(tausqr)-1)*100
# within trail segments standard deviation
sigma_within <- exp(mu + tausqr + sigsqr/2)*sqrt(exp(sigsqr)-1)*100
# total standard deviation
sigma_total <- exp(mu + (tausqr + sigsqr)/2)*sqrt(exp(tausqr+sigsqr)-1)*100
## [1] "Overall measurement bias (%):"
## [1] -4.842595
## [1] "Between trail segments standard deviation (%):"
## [1] 15.73783
## [1] "Within trail segment standard deviation (%):"
## [1] 6.202284
## [1] "Total measurement error standard deviation (%):"
## [1] 16.9159

For relative errors, between trail segment variation is still dominant at about 16% of trail length. GPS distance measurements, for the same trail segment, agree with each other to within about 6% of trail length. The relative error bias is about -5%.

Discussion

Since the largest source of distance measurement error is apparently from the track segment, it is worthwhile to discuss some of the ways this can occur. This discussion is speculative. It is beyond scope to try to test any of these hypotheses.

The most obvious reason for an error that varies between track segments is errors in the reference data, since this value is used to compute all of the distance errors for the same trail segment. Although we rank the government data for the High Sierra Trail as best available, we are not claiming that the data is 100% error free. Some of the ways that the reference distances might be in error are:

Anecdotally, on my High Sierra Trail trip in September 2019, we all three agreed that the “official mileage” for HST_08 and HST_10 had to be too low. These sections took longer than planned, and we sensed that there must be some missing miles. The average GPS error for HST_08 was 1.87 miles and for HST_10, it was 0.9 miles.

There are reasons less obvious than reference data errors that could explain distance errors that vary between track segments. One is that one or more attributes of a trail segment could have a common effect on all GPS distance measurements for that segment. The true length of the trail segment is one explanation. The longer the segment, the more track points are in each GPS track. Each additional track point contributes to distance error through its own position measurement errors. We found evidence of a trail segment length effect and mitigated it by analysing relative distance errors. Yet, we found that relative errors also have a significant component that varies between trail segments.

We could speculate that another such trail attribute, such as its shape could have a common effect on GPS distance measurement. If a trail segment has a higher than average number of switchbacks, this could result in a common under-measurement of distance, since a GPS track, being a polygonal path that approximates the trail, cannot be counted on to always place a track point at every sharp turn of the trail.

To settle the source of these errors, we might design an experiment that includes new calibrated wheel measurements. We could try assessing GPS distance accuracy against straight-line courses on highways or bicycle courses, although the results may not carry over to hiking trails.

This data does not persuade me to abandon the use of GPS tracks for trip planning. Except for a few cases, we found that they differed from the reference distance by less than a mile. For half the cases, they differed by less then 0.3 miles. These errors do not figure largely in the art of trip planning. GPS tracks are available when certified distances are not available. They are transparent in the sense that one has the polygonal path that is the source of the distance measurement. In short, I have never had regrets about using GPS tracks as part of a system for predicting trail travel time.

Listing of the lhst_data data frame.

lhst_data

References

Ahrens, F. 2020. “Nested Error Budget for a Lognormal Response.”

Daniels, Walt. 1995. “To Measure a Trail.” Available at https://www.nynjtc.org/content/measure-trail (2019/12/25).

“Explore the Map.” 2019. Available at https://www.gaiagps.com/map/?loc=10.4/-118.4652/36.5599&layer=CalTopo (2019/12/25); Gaia GPS.

“GpsPrune.” 2018. Available at http://activityworkshop.net/software/gpsprune/ (2019/11/10); Activity Workshop.

“High Sierra Trail.” 2018. Available at https://www.nps.gov/seki/planyourvisit/high-sierra-trail.htm (2019/12/25); National Park Service.

“How Far Is It? The Truth Behind Trail Measurements.” 2019. Available at https://www.wta.org/news/magazine/features/how-far-is-it-the-truth-behind-trail-measurements (2019/12/25); Washington Trails Association.