traviz is a package to meaningfully analyze and visualize trajectories in multiple ways. To showcase some of the features of traviz, we’ll use enviroCar trajectory data in Muenster, Germany. To collect enviroCar data, the envirocar-py package was used. Keep in mind traviz is not limited to vehicular trajectory data only and can work with all types of trajectory data.

library(traviz)
#> Loading required package: sf
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
#> Loading required package: trajectories
#> Loading required package: tidyverse
#> ── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
#> ✓ ggplot2 3.3.2     ✓ purrr   0.3.4
#> ✓ tibble  3.0.1     ✓ dplyr   1.0.0
#> ✓ tidyr   1.1.0     ✓ stringr 1.4.0
#> ✓ readr   1.3.1     ✓ forcats 0.5.0
#> ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
#> x dplyr::filter() masks stats::filter()
#> x dplyr::lag()    masks stats::lag()
#> Loading required package: sp
#> Loading required package: spacetime
#> Loading required package: Rcpp
library(rgl)
knitr::knit_hooks$set(webgl = hook_webgl)

traviz approaches to trajectories: point analysis or overall line analysis

traviz offers two approaches to dealing with trajectory data. The trajectory can either be analyzed as a whole geometry with the complete line or the trajectory can be analyzed point by point. The point by point approach will be showcased in this vignette.

Dataset: enviroCar sampled data

To explore the basics of working with trajectory data in traviz, we’ll use the enviroCar data included in the package. This is included as ‘ec.trj’. The dataset consists of:

ec <- read.csv("/home/john/Desktop/traviz/data/tracks.csv",header = TRUE, check.names = TRUE)
ec[1,]
#>                         id                time
#> 1 5eb7582c65b80c5d6be6b013 2020-05-09T23:45:27
#>                                     geometry Calculated.MAF.value
#> 1 POINT (7.619238953523779 51.9746148909074)             10.74542
#>   Calculated.MAF.unit Intake.Pressure.value Intake.Pressure.unit CO2.value
#> 1                 g/s                    53                  kPa    8.3008
#>   CO2.unit Intake.Temperature.value Intake.Temperature.unit GPS.VDOP.value
#> 1     kg/h                       27                       c            0.8
#>   GPS.VDOP.unit GPS.Accuracy.value GPS.Accuracy.unit Consumption.value
#> 1     precision                  2                 %          3.532256
#>   Consumption.unit GPS.Bearing.value GPS.Bearing.unit GPS.Speed.value
#> 1              l/h          265.7585              deg        52.06206
#>   GPS.Speed.unit Engine.Load.value Engine.Load.unit Speed.value Speed.unit
#> 1           km/h          45.88235                %          52       km/h
#>   GPS.HDOP.value GPS.HDOP.unit Throttle.Position.value Throttle.Position.unit
#> 1      0.5177532     precision                      17                      %
#>   Rpm.value Rpm.unit GPS.PDOP.value GPS.PDOP.unit GPS.Altitude.value
#> 1  1371.601    u/min      0.9177532     precision                101
#>   GPS.Altitude.unit                 track.id track.length          track.begin
#> 1                 m 5eb7582c65b80c5d6be6b011     169.3725 2020-05-09T23:45:27Z
#>              track.end sensor.type sensor.engineDisplacement sensor.model
#> 1 2020-05-10T01:22:21Z         car                      1798      Caliber
#>                  sensor.id sensor.fuelType sensor.constructionYear
#> 1 58395f40e4b0a979d45bd61b        gasoline                    2007
#>   sensor.manufacturer track.appVersion track.touVersion
#> 1               Dodge                                  
#>   O2.Lambda.Voltage.ER.value O2.Lambda.Voltage.ER.unit MAF.value MAF.unit
#> 1                         NA                                  NA         
#>   O2.Lambda.Voltage.value O2.Lambda.Voltage.unit
#> 1                      NA

enviroCar trajectory data contains geographic data with geometry points in sf format, a unique identifier for each track, time stamps, and data measurements at those timestamps.

ec$time <- gsub("T", " ", ec$time)
ec$time = as.POSIXct(ec$time)
trajectories = geodata_to_sf(ec, identifier = "track.id")

Getting the enviroCar data ready for input

Approach two: Overall line analysis

To handle trajectory data, a model similar to trajectories was followed, extending aspects the data structure to support sf. The class is called sfTrack and it stores a single trajectory and contains the timestamps, data, and geometry of thetrajectory. sfTrack is a S4 class and contains the following slots:

  • id: unique id value for track
  • data: dataframe of track data
  • time: POSIXct format timestamps
  • geometry: point geometry of track in sfc format
  • line: LINESTRING trajectory of track

Similar to the Tracks class in trajectories, multiple sfTrack objects are stored under sfTracks which is a list of sfTrack objects.

Creating a sfTrack object

To create a sfTrack, use the constructor with two parameters: * df: the data frame of trajectories * identifier: the unique identifier for each track. In the case of enviroCar data, it is track.id

track = sfTrack(df = trajectories[1,], identifier = "track.id")
track
#> An object of class sfTrack 
#> 1154points 
#> bbox: 
#>      xmin      ymin      xmax      ymax 
#>  7.561992 51.973755  8.799215 53.076326 
#> Time period: [2020-05-09 23:45:27, 2020-05-10 01:22:21]

Creating a sfTracks object

To create a sfTracks object, combine multiple sfTrack in a list.

track1 = sfTrack(df = trajectories[63,], identifier = "track.id")
track2 = sfTrack(df = trajectories[64,], identifier = "track.id")
track3 = sfTrack(df = trajectories[65,], identifier = "track.id")
tracks = sfTracks(c(track1, track2, track3))
tracks
#> An object of class sfTracks 
#> 3 sftracks

sfTrack and sfTracks methods

We will now showcase the methods of sfTrack and sfTracks.

Coercion to data frame

track1_df = as(track1, 'data.frame')
tracks_df = as(tracks, 'data.frame')

track1_df[1,]
#>                         id                time Calculated.MAF.value
#> 1 5ddcdd4a44ea85025cfdf87a 2019-11-25 16:13:34             3.607641
#>   Calculated.MAF.unit Intake.Pressure.value Intake.Pressure.unit CO2.value
#> 1                 g/s                    31                  kPa  2.786892
#>   CO2.unit Intake.Temperature.value Intake.Temperature.unit GPS.VDOP.value
#> 1     kg/h                        9                       c            0.9
#>   GPS.VDOP.unit GPS.Accuracy.value GPS.Accuracy.unit Consumption.value
#> 1     precision                  4                 %          1.185911
#>   Consumption.unit GPS.Bearing.value GPS.Bearing.unit GPS.Speed.value
#> 1              l/h          326.0112              deg        9.569653
#>   GPS.Speed.unit Engine.Load.value Engine.Load.unit Speed.value Speed.unit
#> 1           km/h          31.76471                %     7.55481       km/h
#>   GPS.HDOP.value GPS.HDOP.unit Throttle.Position.value Throttle.Position.unit
#> 1      0.7205312     precision                      13                      %
#>   Rpm.value Rpm.unit GPS.PDOP.value GPS.PDOP.unit GPS.Altitude.value
#> 1  783.2137    u/min            1.2     precision           97.22765
#>   GPS.Altitude.unit track.length          track.begin            track.end
#> 1                 m      8.51826 2019-11-25T16:13:34Z 2019-11-25T16:33:56Z
#>   sensor.type sensor.engineDisplacement sensor.model                sensor.id
#> 1         car                      1699        A 170 559e22c2e4b07207d8977998
#>   sensor.fuelType sensor.constructionYear sensor.manufacturer track.appVersion
#> 1        gasoline                    2004       Mercedes Benz                 
#>   track.touVersion O2.Lambda.Voltage.ER.value O2.Lambda.Voltage.ER.unit
#> 1                                          NA                          
#>   MAF.value MAF.unit O2.Lambda.Voltage.value O2.Lambda.Voltage.unit
#> 1        NA                               NA                       
#>                    geometry                 track.id
#> 1 POINT (7.648313 51.94246) 5ddcdd4a44ea85025cfdf878
tracks_df[5,]
#>                         id                time Calculated.MAF.value
#> 5 5ddcdd4a44ea85025cfdf87f 2019-11-25 16:13:55             3.539522
#>   Calculated.MAF.unit Intake.Pressure.value Intake.Pressure.unit CO2.value
#> 5                 g/s                    31                  kPa   2.73427
#>   CO2.unit Intake.Temperature.value Intake.Temperature.unit GPS.VDOP.value
#> 5     kg/h                        9                       c              1
#>   GPS.VDOP.unit GPS.Accuracy.value GPS.Accuracy.unit Consumption.value
#> 5     precision                  4                 %          1.163519
#>   Consumption.unit GPS.Bearing.value GPS.Bearing.unit GPS.Speed.value
#> 5              l/h          325.8774              deg        25.10554
#>   GPS.Speed.unit Engine.Load.value Engine.Load.unit Speed.value Speed.unit
#> 5           km/h          31.59199                %          25       km/h
#>   GPS.HDOP.value GPS.HDOP.unit Throttle.Position.value Throttle.Position.unit
#> 5            0.7     precision                      13                      %
#>   Rpm.value Rpm.unit GPS.PDOP.value GPS.PDOP.unit GPS.Altitude.value
#> 5  768.4252    u/min            1.2     precision           99.73602
#>   GPS.Altitude.unit track.length          track.begin            track.end
#> 5                 m      8.51826 2019-11-25T16:13:34Z 2019-11-25T16:33:56Z
#>   sensor.type sensor.engineDisplacement sensor.model                sensor.id
#> 5         car                      1699        A 170 559e22c2e4b07207d8977998
#>   sensor.fuelType sensor.constructionYear sensor.manufacturer track.appVersion
#> 5        gasoline                    2004       Mercedes Benz                 
#>   track.touVersion O2.Lambda.Voltage.ER.value O2.Lambda.Voltage.ER.unit
#> 5                                          NA                          
#>   MAF.value MAF.unit O2.Lambda.Voltage.value O2.Lambda.Voltage.unit
#> 5        NA                               NA                       
#>                    geometry                 track.id
#> 5 POINT (7.647379 51.94342) 5ddcdd4a44ea85025cfdf878

Plotting

sfTrack and sfTracks has basic plotting features:

plot(track)

plot(tracks)

Intersection plotting is also included extending sf intersections:

intersection.sfTrack(track1, track2)
#> although coordinates are longitude/latitude, st_intersection assumes that they are planar