2 Loading the Live Telemetry Route Data
The examples provided utilise data that has already been downloaded.
2.1 Spatial Utilities
The GPS data is provided as a set of latitude and longitude co-ordinates. For various forms of analysis, such as calculating and comparing distance in meters, we need to map from the latitude/longitude co-ordinate system to a projection such as UTM (Universal transverse Mercator).
The following function identifies the correct UTM region for managing the conversion.
library(sf)
<- function(lonlat) {
lonlat2UTM_hemisphere ifelse(lonlat[1] > 0, "north", "south")
}
= function(lonlat) {
lonlat2UTMzone = (floor((lonlat[1] + 180) / 6) %% 60) + 1
utm if(lonlat[2] > 0) {
+ 32600
utm else{
} + 32700
utm
} }
Create a simple latitude/longitude CRS (co-ordinate reference system) string to specify the CRS for use with simple lat/long data:
= 4326 latlon_crs
We can also set the timezone. This might be done explicitly, or from a location co-ordinate using the R lutz
package.
= "Europe/Helsinki" timezone
2.2 Loading in the Telemetry Route Data
The data is available in the form of a simple CSV data file.
The data is presented in a reverse chronological order, but it is more natural for us to present it in chronological (increasing time) order.
= read.csv(file.path(path, "df_telemetrydata_SS7_Evans.csv") ) %>%
telem_df_min map_df(rev)
kable(head(telem_df_min), format = "html") %>%
kable_styling() %>%
::scroll_box(width = "100%") kableExtra
X | accx | accy | altitude | brk | driverid | gear | heading | kms | lat | lon | name | rpm | speed | status | throttle | track | utx | X_rally_stageid | X_carentryid | X_telemetryID | X_name |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1870 | 0 | 0 | 0 | 0 | NA | 0 | 144 | 0.6 | 61.83077 | 25.12109 | 33 | 0 | 166 | Competing | 0 | NA | 1.633164e+12 | bcc5537d-d28a-40af-ba86-95dad7fb9cd1 | b185c5df-8115-40cf-bd81-566f016f6bf5 | /a3f5f3f5-3fb0-42ab-af90-24d91c0493d0/ss07eva_telemetry_js/js | Evans |
1869 | 0 | 0 | 0 | 0 | NA | 0 | 150 | 0.7 | 61.82966 | 25.12240 | 33 | 0 | 140 | Competing | 0 | NA | 1.633164e+12 | bcc5537d-d28a-40af-ba86-95dad7fb9cd1 | b185c5df-8115-40cf-bd81-566f016f6bf5 | /a3f5f3f5-3fb0-42ab-af90-24d91c0493d0/ss07eva_telemetry_js/js | Evans |
1868 | 0 | 0 | 0 | 0 | NA | 0 | 172 | 0.8 | 61.82912 | 25.12291 | 33 | 0 | 60 | Competing | 0 | NA | 1.633164e+12 | bcc5537d-d28a-40af-ba86-95dad7fb9cd1 | b185c5df-8115-40cf-bd81-566f016f6bf5 | /a3f5f3f5-3fb0-42ab-af90-24d91c0493d0/ss07eva_telemetry_js/js | Evans |
1867 | 0 | 0 | 0 | 0 | NA | 0 | 220 | 0.9 | 61.82856 | 25.12200 | 33 | 0 | 107 | Competing | 0 | NA | 1.633164e+12 | bcc5537d-d28a-40af-ba86-95dad7fb9cd1 | b185c5df-8115-40cf-bd81-566f016f6bf5 | /a3f5f3f5-3fb0-42ab-af90-24d91c0493d0/ss07eva_telemetry_js/js | Evans |
1866 | 0 | 0 | 0 | 0 | NA | 0 | 210 | 1.0 | 61.82766 | 25.12067 | 33 | 0 | 149 | Competing | 0 | NA | 1.633164e+12 | bcc5537d-d28a-40af-ba86-95dad7fb9cd1 | b185c5df-8115-40cf-bd81-566f016f6bf5 | /a3f5f3f5-3fb0-42ab-af90-24d91c0493d0/ss07eva_telemetry_js/js | Evans |
1865 | 0 | 0 | 0 | 0 | NA | 0 | 208 | 1.1 | 61.82662 | 25.11919 | 33 | 0 | 159 | Competing | 0 | NA | 1.633164e+12 | bcc5537d-d28a-40af-ba86-95dad7fb9cd1 | b185c5df-8115-40cf-bd81-566f016f6bf5 | /a3f5f3f5-3fb0-42ab-af90-24d91c0493d0/ss07eva_telemetry_js/js | Evans |
We note quite a few null columns in there, so let’s clean those out of the dataframe too:
= telem_df_min %>%
telem_df_min select(-c(accx, accy, altitude, brk, driverid,
%>%
gear, rpm, throttle, track)) select(-c(X_rally_stageid, X_carentryid, X_telemetryID))
kable(head(telem_df_min), format = "html") %>%
kable_styling() %>%
::scroll_box(width = "100%") kableExtra
X | heading | kms | lat | lon | name | speed | status | utx | X_name |
---|---|---|---|---|---|---|---|---|---|
1870 | 144 | 0.6 | 61.83077 | 25.12109 | 33 | 166 | Competing | 1.633164e+12 | Evans |
1869 | 150 | 0.7 | 61.82966 | 25.12240 | 33 | 140 | Competing | 1.633164e+12 | Evans |
1868 | 172 | 0.8 | 61.82912 | 25.12291 | 33 | 60 | Competing | 1.633164e+12 | Evans |
1867 | 220 | 0.9 | 61.82856 | 25.12200 | 33 | 107 | Competing | 1.633164e+12 | Evans |
1866 | 210 | 1.0 | 61.82766 | 25.12067 | 33 | 149 | Competing | 1.633164e+12 | Evans |
1865 | 208 | 1.1 | 61.82662 | 25.11919 | 33 | 159 | Competing | 1.633164e+12 | Evans |
2.3 Preparing the Telemetry Route Data
We can perform a small amount of cleaning on the data to remove any rows where there are missing latitude or longitude values before before generating a spatial features data object with a column containing the geometry information with the lat/long co-ordinate reference system (CRS) specified.
To better manage the timing components, we can cast the universal time stamp (in milliseconds) to a datetime stamp, ensuring we also set the correct time zone along the way. A delta_s
columns is also used to capture the time difference (in seconds) between sample points.
X | heading | kms | name | speed | status | utx | X_name | geometry | delta_s | utc |
---|---|---|---|---|---|---|---|---|---|---|
1870 | 144 | 0.6 | 33 | 166 | Competing | 1.633164e+12 | Evans | POINT (25.12109 61.83077) | 0.0 | 2021-10-02 11:37:23 |
1869 | 150 | 0.7 | 33 | 140 | Competing | 1.633164e+12 | Evans | POINT (25.1224 61.82966) | 3.2 | 2021-10-02 11:37:26 |
1868 | 172 | 0.8 | 33 | 60 | Competing | 1.633164e+12 | Evans | POINT (25.12291 61.82912) | 6.4 | 2021-10-02 11:37:30 |
1867 | 220 | 0.9 | 33 | 107 | Competing | 1.633164e+12 | Evans | POINT (25.122 61.82856) | 9.6 | 2021-10-02 11:37:33 |
1866 | 210 | 1.0 | 33 | 149 | Competing | 1.633164e+12 | Evans | POINT (25.12067 61.82766) | 12.8 | 2021-10-02 11:37:36 |
1865 | 208 | 1.1 | 33 | 159 | Competing | 1.633164e+12 | Evans | POINT (25.11919 61.82662) | 16.0 | 2021-10-02 11:37:39 |
For convenience, let’s also generate a UTM projection of this spatial features dataframe:
# Generate a UTM projection of the route telemetry
= telem_df_min %>%
telem_df_min_utm st_transform(crs = st_crs(utm_proj4_string))
2.4 Visual Preview of the Telemetry Route Data
We can preview the route on an interactive map using the leaflet
package, casting the route data to a set of paired co-ordinates:
library(leaflet)
## Warning: package 'leaflet' was built under R version 4.0.5
<- telem_df_min %>% st_coordinates()
tmp_route
leaflet(tmp_route) %>%
addProviderTiles("OpenTopoMap", group = "OSM") %>%
addPolylines(color = "red", weight = 5)
The “live” telemetry includes the road section data. To access the data for just the stage we need to filter it somehow. There are two ways we might do this:
- based on time: if we know the stage start time for the driver, and their stage time, we can filter the data based on timestamps;
- based on location: if we have route data for the stage, we can create a buffered area around the stage route, and then filter telemetry data based on points that lay inside that buffered area.