7 Comparing Drivers’ Live (Sparse) Telemetry
In this chapter, we will start to explore the extent we can compare the live telemetry data traces of different drivers. Note that te data may be quite sparse at times, which might limit what we are able to do.
Where large gaps exist between data samples, we are more likely to require a sensible time model more the stage to try to minimise errors in using a simple, linear interpolator to generate missing data.
7.1 Load Route Data
Get the route in a UTM form:
= "data/finland_2021.geojson"
geojson_filename = sf::st_read(geojson_filename) geojson_sf
## Reading layer `finland_2021' from data source
## `/Users/tonyhirst/Documents/GitHub/visualising-wrc-telemetry-data/src/data/finland_2021.geojson'
## using driver `GeoJSON'
## Simple feature collection with 13 features and 2 fields
## Geometry type: GEOMETRY
## Dimension: XYZ
## Bounding box: xmin: 24.86575 ymin: 61.52393 xmax: 26.20794 ymax: 62.39946
## z_range: zmin: 0 zmax: 148.839
## Geodetic CRS: WGS 84
= 4326
latlon_crs
# Use a convenience function that loads in the geojson file
# and then generates a spatial features dataframe with a UTM projection
= get_route(geojson_sf, 7) stage_route_utm
## Reading layer `finland_2021' from data source
## `/Users/tonyhirst/Documents/GitHub/visualising-wrc-telemetry-data/src/data/finland_2021.geojson'
## using driver `GeoJSON'
## Simple feature collection with 13 features and 2 fields
## Geometry type: GEOMETRY
## Dimension: XYZ
## Bounding box: xmin: 24.86575 ymin: 61.52393 xmax: 26.20794 ymax: 62.39946
## z_range: zmin: 0 zmax: 148.839
## Geodetic CRS: WGS 84
stage_route_utm
## Simple feature collection with 1 feature and 2 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: 400114.7 ymin: 6847317 xmax: 403275.1 ymax: 6857089
## CRS: +proj=utm +zone=35 +datum=WGS84 +units=m +no_defs
## name styleUrl geometry
## 7 SS7/11 KakaristoHassi #msn_ylw-pushpin60 LINESTRING (400679.3 685708...
We can obtain the stage length in meters from the route:
# Get the stage length.. this includes the units
= st_length(stage_route_utm)
stage_length_m
= drop_units(stage_length_m)
stage_length
stage_length
## [1] 18163.4
7.1.1 Generate Buffered Route
We can also take this opportunity to create a buffered route for filtering the telemetry data:
#Use a convenience function to get buffered route
= 50
buffer_width = get_buffered_route(stage_route_utm, buffer_width,
buffered_route crs=original_crs, utm=FALSE)
leaflet(buffered_route) %>%
addProviderTiles("OpenTopoMap", group = "OSM") %>%
addPolylines(color = "red", weight = 2)
7.2 Load Driver Data
Load in data for a handful of drivers:
# Path to the telem data
= "../../wrcplus/notebooks/2021_secto_Rally_Finland" path
TO DO - set the origin as the dummy origin
= get_min_telem("Evans", "SS7", path)
evans_min_telem = evans_min_telem %>%
evans_min_telem_utm st_transform(crs = st_crs(utm_proj4_string))
# Get the buffer filtered data
= get_route_telem(stage_route_utm,
route_telem_evans crs=original_crs)
evans_min_telem_utm,
evans_min_telem_utm
## Simple feature collection with 1871 features and 10 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 386781.7 ymin: 6821405 xmax: 435552.1 ymax: 6901464
## CRS: +proj=utm +zone=35 +datum=WGS84 +units=m +no_defs
## # A tibble: 1,871 × 11
## X heading kms name speed status utx X_name
## * <int> <int> <dbl> <int> <int> <chr> <dbl> <chr>
## 1 1870 144 0.6 33 166 Competing 1633163843600 Evans
## 2 1869 150 0.7 33 140 Competing 1633163846800 Evans
## 3 1868 172 0.8 33 60 Competing 1633163850000 Evans
## 4 1867 220 0.9 33 107 Competing 1633163853200 Evans
## 5 1866 210 1 33 149 Competing 1633163856400 Evans
## 6 1865 208 1.1 33 159 Competing 1633163859600 Evans
## 7 1864 194 1.3 33 149 Competing 1633163862800 Evans
## 8 1863 220 1.5 33 92 Competing 1633163869200 Evans
## 9 1862 176 1.6 33 117 Competing 1633163872400 Evans
## 10 1861 172 1.7 33 113 Competing 1633163875600 Evans
## # … with 1,861 more rows, and 3 more variables: geometry <POINT [m]>,
## # delta_s <dbl>, utc <dttm>
We can always preview the data just to check that it is sensible:
library(leaflet)
<- evans_min_telem %>% st_coordinates()
tmp_route
leaflet(tmp_route) %>%
addProviderTiles("OpenTopoMap", group = "OSM") %>%
addPolylines(color = "purple", weight = 5)
Let’s get some data for some other drivers:
= get_min_telem("Fourmaux", "SS7", path)
fourmaux_min_telem
= fourmaux_min_telem %>%
fourmaux_min_telem_utm st_transform(crs = st_crs(utm_proj4_string))
= get_route_telem(stage_route_utm,
route_telem_fourmaux
fourmaux_min_telem_utm,crs=original_crs)
fourmaux_min_telem_utm
## Simple feature collection with 2971 features and 10 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 386804.1 ymin: 6821404 xmax: 435545.6 ymax: 6901462
## CRS: +proj=utm +zone=35 +datum=WGS84 +units=m +no_defs
## # A tibble: 2,971 × 11
## X heading kms name speed status utx X_name
## * <int> <int> <dbl> <int> <int> <chr> <dbl> <chr>
## 1 2970 328 28.1 16 62 Competing 1633163843700 Fourmaux
## 2 2969 328 28.2 16 61 Competing 1633163850100 Fourmaux
## 3 2968 328 28.3 16 55 Competing 1633163856500 Fourmaux
## 4 2967 310 29.4 16 75 Competing 1633163912000 Fourmaux
## 5 2966 240 29.5 16 79 Competing 1633163918400 Fourmaux
## 6 2965 232 29.6 16 80 Competing 1633163920500 Fourmaux
## 7 2964 296 29.7 16 78 Competing 1633163926900 Fourmaux
## 8 2963 280 29.8 16 83 Competing 1633163933300 Fourmaux
## 9 2962 312 30 16 70 Competing 1633163939700 Fourmaux
## 10 2961 284 30.1 16 81 Competing 1633163946100 Fourmaux
## # … with 2,961 more rows, and 3 more variables: geometry <POINT [m]>,
## # delta_s <dbl>, utc <dttm>
= get_min_telem("Breen", "SS7", path)
breen_min_telem
= breen_min_telem %>%
breen_min_telem_utm st_transform(crs = st_crs(utm_proj4_string))
= get_route_telem(stage_route_utm,
route_telem_breen
breen_min_telem_utm,crs=original_crs)
route_telem_breen
## Simple feature collection with 84 features and 10 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 25.10563 ymin: 61.7465 xmax: 25.15306 ymax: 61.83367
## Geodetic CRS: WGS 84
## # A tibble: 84 × 11
## X heading kms name speed status utx X_name
## * <int> <int> <dbl> <int> <int> <chr> <dbl> <chr>
## 1 2102 98 0.1 42 120 Competing 1633164186300 Breen
## 2 2101 102 0.2 42 77 Competing 1633164189500 Breen
## 3 2100 126 0.2 42 44 Competing 1633164192700 Breen
## 4 2099 136 0.3 42 101 Competing 1633164195900 Breen
## 5 2098 132 0.4 42 142 Competing 1633164199100 Breen
## 6 2097 138 0.5 42 167 Competing 1633164202300 Breen
## 7 2096 150 0.7 42 159 Competing 1633164205500 Breen
## 8 2095 154 0.8 42 73 Competing 1633164208700 Breen
## 9 2094 222 0.8 42 94 Competing 1633164211900 Breen
## 10 2093 212 1 42 139 Competing 1633164215100 Breen
## # … with 74 more rows, and 3 more variables: geometry <POINT [°]>,
## # delta_s <dbl>, utc <dttm>
And preview the telemetry sample points for all the drivers we have gathered telemetry data for:
leaflet( ) %>%
addProviderTiles("OpenTopoMap", group = "OSM") %>%
addCircleMarkers(data=route_telem_evans, radius=1, color="blue") %>%
addCircleMarkers(data=route_telem_breen, radius=1,color="red") %>%
addCircleMarkers(data=route_telem_fourmaux, radius=1, color="black")
7.3 Get Annotated Route Telemetry
The route telemetry annotation includes the distance along the stage route for each telemetry sample:
= to_utm(route_telem_evans)
route_telem_evans_utm = route_telem_evans_utm %>%
route_telem_evans_utm get_telem_dists(stage_route_utm)
#route_telem_evans_utm
= to_utm(route_telem_fourmaux)
route_telem_fourmaux_utm = route_telem_fourmaux_utm %>%
route_telem_fourmaux_utm get_telem_dists(stage_route_utm)
route_telem_fourmaux_utm
## Simple feature collection with 57 features and 13 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 400112.8 ymin: 6848161 xmax: 403238.1 ymax: 6857092
## CRS: +proj=utm +zone=35 +datum=WGS84 +units=m +no_defs
## # A tibble: 57 × 14
## X heading kms name speed status utx X_name
## * <int> <int> <dbl> <int> <int> <chr> <dbl> <chr>
## 1 217 100 0 16 106 Competing 1633187766200 Fourmaux
## 2 216 112 0.1 16 90 Competing 1633187769400 Fourmaux
## 3 215 144 0.3 16 85 Competing 1633187775800 Fourmaux
## 4 214 132 0.4 16 134 Competing 1633187779000 Fourmaux
## 5 213 136 0.5 16 160 Competing 1633187782200 Fourmaux
## 6 212 148 0.8 16 83 Competing 1633187788600 Fourmaux
## 7 211 212 1 16 153 Competing 1633187798200 Fourmaux
## 8 210 206 1.3 16 130 Competing 1633187804600 Fourmaux
## 9 209 244 1.4 16 141 Competing 1633187807800 Fourmaux
## 10 208 204 1.5 16 86 Competing 1633187811000 Fourmaux
## # … with 47 more rows, and 6 more variables: geometry <POINT [m]>,
## # delta_s <dbl>, utc <dttm>, dist <dbl>, roundeddelta_t <drtn>,
## # roundeddelta_s <dbl>
7.4 Create Driver Estimators
From the annotated data can generate some naive estimators for stage time along route based on distance along route:
= approxfun(c(0, route_telem_fourmaux_utm$dist),
fourmaux_time_estimator c(0, route_telem_fourmaux_utm$roundeddelta_s))
## Warning in regularize.values(x, y, ties, missing(ties), na.rm = na.rm):
## collapsing to unique 'x' values
= approxfun(c(0, route_telem_evans_utm$dist),
evans_time_estimator c(0, route_telem_evans_utm$roundeddelta_s))
7.6 Visual Driver Comparison
Let’s see if a visual comparison reveals anything:
# Sample every 500m
= seq(to=max(c(route_telem_fourmaux_utm$dist,
vals $dist)), by=500)
route_telem_evans_utm
ggplot() +
# Predicted line in pink
geom_line(aes(x=vals, y=evans_time_estimator(vals)), size=1, colour='blue') +
geom_point(data=route_telem_evans_utm,
aes(x=dist, y=roundeddelta_s), size=1, colour='red') +
# Sampled times in black
geom_line(aes(x=vals, y=fourmaux_time_estimator(vals)),
color='red', size=1) +
geom_point(data=route_telem_fourmaux_utm,
aes(x=dist, y=roundeddelta_s), size=1, colour='blue')