Trajectory data¶
Trajectory data is data where the state of individual GTUs is stored at some (ir)regular interval. The state can be a number of properties of the GTU such as position and speed, but also any other user-specified information. To gather trajectory data there is a separate java project ots-kpi
. The sampler is also used to derive key performance indicators from trajectory data, which is discussed in section Performance indicators. This project is independent from the OTS simulation and is also used to gather trajectories and key performance indicators with other simulation environments. Before key performance indicators are discussed, this section discusses how trajectory data is gathered and defined using the sampler.
The Sampler
is the central coordinator of trajectory data. As it operates stand-alone, it uses a set of light-weight interfaces to represent GTUs, nodes, routes, lanes, etc. A specific implementation of Sampler
that connects the sampler with a specific simulation environment provides content for such interfaces. Furthermore, the implementation implements a few abstract methods that the sampler uses, as such implementations are simulation environment specific. For OTS itself the implementation is RoadSampler
and accompanying classes, each of which wraps an OTS class. For example the interface GtuData
is implemented by GtuDataRoad
, which wraps a LaneBasedGtu
to supply the information as requested by the sampler. Similar wrapping classes can be used for other simulation environments, possibly working with a data bus rather than directly with the simulation environment.
The sampler stores trajectory information for regions of space-time that are registered to it as SpaceTimeRegion
. A space-time region is spatially confined to a single lane. Gathering information over multiple space-time regions is done using a Query
, which is discussed in the next section. Many space-time regions can be registered to the sampler, including space-time regions that overlap in space and/or time. When a space-time region is registered to the sampler, the sampler will request the implementing class to schedule start and stop recording commands at the right time on a particular lane as a whole. When receiving such commands from the implementation, the sampler will check if recording was not already started, or whether stopping should be skipped for an overlapping space-time region.
Sampler ⌊ {Space-time region} ⌊ Lane ⌊ Trajectory group ⌊ {Trajectory} ⌊ {Extended data types} ⌊ {Filter data types}
As GTUs move in, over and out of a lane, they record a Trajectory
within a TrajectoryGroup
coupled with the lane. This means that one such trajectory only covers the part that a GTU moves over the lane consecutively. Due to lane changes, one GTU can thus result in multiple Trajectory
's within a TrajectoryGroup
. Moving in, over or out of a lane happens as the simulation environment specific implementation calls methods processGtuAddEvent(…)
, processGtuMoveEvent(…)
or processGtuRemoveEvent(…)
of the Sampler
. The RoadSampler
does so as a response to internal OTS events as discussed in section Event producers and listeners. A trajectory has several arrays of equal length inside that contain position, speed, acceleration and time data. Additional data of equal length is found in optional extended data types. The Trajectory
can supply individual values at a particular index, or entire arrays. This includes an underlying storage type for the base and extended data types, which may be different from the eventual output type. For example, internally values may be stored in a float[]
, while the output is FloatDurationVector
from DJUNITS. The Trajectory
can also supply total length and total duration, which is sufficient for some basic performance indicators, and doesn’t require the whole data to be processed.
Trajectory ⌊ {Position} ⌊ {Speed} ⌊ {Acceleration} ⌊ {Time} ⌊ {Extended data} ⌊ {Data} ⌊ {Filter data} ⌊ {Data}
Extended data types are sub classes of ExtendedDataType
. They are added to all trajectories by the Sampler
upon creation of a new Trajectory
(in processGtuAddEvent(…)
) if the extended data type is registered to the Sampler
. The Trajectory
stores the data, but the extended data type manages the storage in its methods. For most purposes the class ExtendedDataTypeFloat
or one of its available sub classes is suitable, in particular for DJUNITS data types. It takes care of storage management, increasing the storage array when needed. The sub classes only need to implement two conversion methods from float to the specific type, for a single value or for the entire array. The classes shown below for duration, length and speed do exactly this. These classes are abstract as it is still not determined what is actually stored in the extended data type. Extensions of these classes can for example determine the time-to-collision, the driver workload, or any other value based on a GTU. With the super classes taking care of data management, these implementation only need to define a single getValue(…)
method to obtain the value from a GTU. Class ExtendedDataTypeNumber
is useful for dimensionless values. Class ExtendedDataTypeString
can be used for String
values. Finally, ExtendedDataTypeList
stores values in an internal List
, which is conceptually easier but less efficient.
Extended data type ⌊ Extended data type float ⌊ Extended data type duration ⌊ Extended data type length ⌊ Extended data type speed ⌊ Extended data type number ⌊ Extended data type string ⌊ Extended data type list
A final important part of the Sampler
are the filter data types. These define data attached to a Trajectory
that is singular by nature, rather than the time-sampled trajectory data. The primary purpose of this data is to allow trajectory filtering. For example, one could be interested in the travel time along a certain route, or between a given origin-destination pair. To this end filter data types have an accept(…)
method. This is closely related to the Query
’s as explained in the next section. Similarly to extended data types, filter data types are registered to a Sampler
, and included with a Trajectory
when it is created in processGtuAddEvent(…)
.
Filter data type ⌊ Filter data cross-section ⌊ Filter data destination ⌊ Filter data GTU type ⌊ Filter data origin ⌊ Filter data route
So far this section has described how trajectories are created, and how extended data and filter data can be added to the trajectories. The next section discusses how key performance indicators can be derived from the trajectories. Another approach is ex post processing of trajectories. The SamplerData
(obtain as Sampler.getSamplerData()
) has methods named writeToFile(…)
, which stores all trajectory data within the sampler to a comma-separated text file. This uses the Table
functionality from DJUTILS, which means the data can also be read as a Table
using CsvData.readData(...)
. Each line contains: trajectory number, link id, lane id, GTU id, time, position, speed, acceleration, extended data…, filter data…. Note that the trajectory number is a simple counter to identify individual trajectories. Usually the movement of a single GTU is spread over multiple such trajectories. Filter data is only stored in the first row of each trajectory. Finally data can be compessed as zip. Below is some example output of two trajectories. The trajectories include filter data type ‘Length’ and extended data types for ‘Rho’, ‘V0’, and ‘T’.
traj#,linkId,laneId,gtuId,t,x,v,a,Length,Rho,V0,T … 4323,AB,laneAB2,2398,3267.500,3967.532,33.433,-0.199,,0.000,34.135,1.057 4323,AB,laneAB2,2398,3268.000,3984.224,33.334,-0.194,,0.000,34.135,1.060 4323,AB,laneAB2,2398,3268.500,4000.867,33.237,-0.189,,0.000,34.135,1.062 4324,AB,laneAB2,2396,3251.000,3784.761,30.041,0.727,4.190,0.000,37.346,0.676 4324,AB,laneAB2,2396,3251.500,3799.873,30.404,0.701,,0.000,37.346,0.686 4324,AB,laneAB2,2396,3252.000,3815.162,30.755,0.675,,0.000,37.346,0.697 …