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:

geojson_filename = "data/finland_2021.geojson"
geojson_sf = sf::st_read(geojson_filename)
## 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
latlon_crs = 4326

# Use a convenience function that loads in the geojson file
# and then generates a spatial features dataframe with a UTM projection
stage_route_utm = get_route(geojson_sf, 7)
## 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
stage_length_m = st_length(stage_route_utm)

stage_length = drop_units(stage_length_m)

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
buffer_width = 50
buffered_route = get_buffered_route(stage_route_utm, buffer_width,
                                    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
path = "../../wrcplus/notebooks/2021_secto_Rally_Finland"

TO DO - set the origin as the dummy origin

evans_min_telem = get_min_telem("Evans", "SS7", path)
evans_min_telem_utm = evans_min_telem %>%
                        st_transform(crs = st_crs(utm_proj4_string))

# Get the buffer filtered data
route_telem_evans = get_route_telem(stage_route_utm,
                                    evans_min_telem_utm, crs=original_crs)
                        
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)

tmp_route <- evans_min_telem %>% st_coordinates() 

leaflet(tmp_route) %>% 
  addProviderTiles("OpenTopoMap", group = "OSM") %>% 
  addPolylines(color = "purple", weight = 5)

Let’s get some data for some other drivers:

fourmaux_min_telem = get_min_telem("Fourmaux", "SS7", path)

fourmaux_min_telem_utm = fourmaux_min_telem %>%
                            st_transform(crs = st_crs(utm_proj4_string))

route_telem_fourmaux = get_route_telem(stage_route_utm,
                                       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>
breen_min_telem = get_min_telem("Breen", "SS7", path)

breen_min_telem_utm = breen_min_telem %>%
                            st_transform(crs = st_crs(utm_proj4_string))

route_telem_breen = get_route_telem(stage_route_utm,
                                    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:

route_telem_evans_utm = to_utm(route_telem_evans)
route_telem_evans_utm = route_telem_evans_utm %>% 
                          get_telem_dists(stage_route_utm)
#route_telem_evans_utm


route_telem_fourmaux_utm = to_utm(route_telem_fourmaux)
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:

fourmaux_time_estimator = approxfun(c(0, route_telem_fourmaux_utm$dist),
                           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
evans_time_estimator = approxfun(c(0, route_telem_evans_utm$dist),
                           c(0, route_telem_evans_utm$roundeddelta_s))

7.5 Creating a Common False Time Origin

TO DO

7.6 Visual Driver Comparison

Let’s see if a visual comparison reveals anything:

# Sample every 500m
vals = seq(to=max(c(route_telem_fourmaux_utm$dist,
                    route_telem_evans_utm$dist)), by=500)

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')