Calculating speed of GPS dataset and distance between points

I have the GPS tracks of a skier's morning activity where they have hiked up the mountain for the most part, and then skied down from the top afterwards. I am attempting to differentiate sections of the GPS track using a speed threshold. This threshold is to determine which sections of the GPS track consists of skiing and of walking. I want to be able to identify this so that I can calculate the skiing distance separately from the walking distance.

I have loaded the gpx file into R and managed to plot a simple line-route of the skiing activity. When I load the same file into Google Earth Pro, the elevation model tells me the speed at which the skier is travelling at in kmph. Therefore, I assume the speed is already included in the gpx dataset, though this is not present when I load the same gpx dataset into R. How do I calculate the speed at each data point of my GPS track and create a column for this data?

Once I have calculated the speed of each of these points, I then want to select all the data points which have a speed above a certain threshold. Of the selected points, I want to calculate the total distance travelled above the threshold speed. For example, the average speed of a skier is 10-20mph. Therefore, I would select all of the data points which have a speed above 10mph and then calculate the distance between each of these points. How can I do this?

Interesting project! This might get you started Loading and analyzing GPS tracks with R • geocompkg | metapackage for the book Gecomputation with R.
If you want more targeted help, please provide a reproducible example.


Think of speed as distance over time. Time you should have in your dataset, and distance from previous point is not a complicated calculation (you will find it in the resource linked by @etiennebr; the example uses Haversine distance from {geosphere}, but simple sf::st_distance will do).

The distance between points can be then used to calculate the total distance above speed threshold.

1 Like

Thank you! I have been following this guide so far and its been really helpful. However, my issue is: where the speed is calculated as a separate column titled 's', the units are in m/s. Though this is useful, it seems that the conversion to this unit is incorrect, as it has mistaken the distances between the points to be in imperial yards instead of metric meters. I believe it is this section of code which must be edited to have the correct conversion ratio. Please see below:

points2line_trajectory = function(p) {
  c = st_coordinates(p)
  i = seq(nrow(p) - 2)
  l = purrr::map(i, ~ sf::st_linestring(c[.x:(.x + 1), ]))
  s = purrr::map_dbl(i, function(x) {
    geosphere::distHaversine(c[x, ], c[(x + 1), ]) /
      as.numeric(p$time[x + 1] - p$time[x])
  lfc = sf::st_sfc(l)
  a = seq(length(lfc)) + 1 # sequence to subset
  p_data = cbind(sf::st_set_geometry(p[a, ], NULL), s)
  sf::st_sf(p_data, geometry = lfc)

l = points2line_trajectory(p)

@jlacko mentioned about changing




However, when I run this section of code with the replacement recommended, this error occurs:

> l = points2line_trajectory(p)
Error in UseMethod("st_geometry") : 
  no applicable method for 'st_geometry' applied to an object of class "c('double', 'numeric')"
In addition: Warning messages:
1: In if ( NA_crs_ else if (inherits(x, "crs")) x else if (is.character(x)) { :
  the condition has length > 1 and only the first element will be used
2: In CPL_crs_from_input(x) :
  GDAL Error 1: PROJ: proj_create_from_database: crs not found
3: In if ( NA_crs_ else if (inherits(x, "crs")) x else if (is.character(x)) { :
  the condition has length > 1 and only the first element will be used
4: In CPL_crs_from_input(x) :
 Error in UseMethod("st_geometry") : 
  no applicable method for 'st_geometry' applied to an object of class "c('double', 'numeric')" 

How can I resolve this?

Once the conversion is correct, as I stated in my original query, I then want to select the GPS co-ordinates that have speeds above the set threshold and calculate the distance covered between these. Do you know how I would be able to do that?

I don't have a great deal of experience in RStudio so please excuse any silly questions/queries I might have asked. Thank you in advance - I really appreciate any help you can provide as this is something I'm really struggling with. I just wish there was a counselling/calling service for help with RStudio as I worry I don't explain my issues very clearly in text.

Thank you for your input - I have referred to your comment in my reply to @etiennebr . Please check this out as an error has occurred after making the replacement you suggested! :slight_smile:

@jlacko Just to let you know, my response has been temporarily hidden by the automated spam filter, Akismet. Hopefully it will be reviewed soon and accepted, providing more information regarding my query. I just want to say a massive thank you for helping me with this - its been a real struggle and I appreciate any advice you could provide me with.