Simulation

Simulations can be run using the simulate! function. A simulation updates the initial scene forward in time. Each simulation step consists of the following operations:

  • call the observe! function for each vehicle to update their driver model given the current scene
  • sample an action from the driver model by calling rand on the driver model.
  • update the state of each vehicle using the sampled action and the propagate method.
  • repeat for the desired number of steps

There are two main ways to call the simulate! function:

  • simulate!(scene::Frame{E}, roadway::R, models::Dict{I,M}, nticks::Int64, timestep::Float64; rng::AbstractRNG = Random.GLOBAL_RNG, scenes::Vector{Frame{E}} = [Frame(E, length(scene)) for i=1:nticks+1], callbacks = nothing) which simply returns a vector of scenes. This vector can be pre-allocated and passed as a keyword argument. The randomness of the simulation can be controlled by passing a random number generator.
  • simulate!(rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M}, nticks::Int, callbacks::C) which fills in a given QueueRecord object. The QueueRecord data structure is defined in Records.jl. This methods is slower and suffers from type stability issues. It will be deprecated in future releases.

See the tutorials for examples.

AutomotiveDrivingModels.simulate!Function

DEPRECATION WARNING: this version of simulate! is now deprecated.

simulate!(scene::Frame{E}, roadway::R, models::Dict{I,M<:DriverModel}, nticks::Int64, timestep::Float64; rng::AbstractRNG = Random.GLOBAL_RNG, scenes::Vector{Frame{E}} = [Frame(E, length(scene)) for i=1:nticks+1], callbacks=nothing)

Run nticks steps of simulation with time step dt and return a vector of scenes from time step 0 to nticks.

simulate!(::Type{A}, rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M<:DriverModel}, nticks::Int)
simulate!(rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M<:DriverModel}, nticks::Int)

Run nticks of simulation and place all nticks+1 scenes into the QueueRecord

simulate!(::Type{A},rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M}, nticks::Int, callbacks::C) where {S,D,I,A,R,M<:DriverModel,C<:Tuple{Vararg{Any}}}
simulate!(rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M}, nticks::Int, callbacks::C) where {S,D,I,A,R,M<:DriverModel,C<:Tuple{Vararg{Any}}}

Callback objects can also be passed in the simulate! function.

source
simulate!(
    scene::Frame{E}, roadway::R, models::Dict{I,M},
    nticks::Int64, timestep::Float64,
    scenes::Vector{Frame{E}}, actions::Union{Nothing, Vector{Frame{A}}} = nothing;
    rng::AbstractRNG = Random.GLOBAL_RNG, callbacks = nothing
) where {E<:Entity,A<:EntityAction,R,I,M<:DriverModel}

Simulate the entities in scene along a roadway for a maximum of nticks time steps of size timestep. Returns the number of successfully performed timesteps.

At each time step, models is used to determine the action for each agent. scenes and actions are pre-allocated vectors of Frames containing either Entitys (for scenes) or EntityActions (for actions). If actions is equal to nothing (default), the action history is not tracked. scenes must always be provided.

callbacks is an array of callback functions which are invoked before the simulation starts and after every simulation step. Any callback function can cause an early termination by returning true (the default return value for callback functions should be false). The random number generator for the simulation can be provided using the rng keyword argument, it defaults to Random.GLOBAL_RNG.

source
Run a simulation and store the resulting scenes in the provided QueueRecord.

Only the ego vehicle is simulated; the other vehicles are as they were in the provided trajdata Other vehicle states will be interpolated

source
AutomotiveDrivingModels.get_actions!Function
get_actions!(actions::Vector{A}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I, M},) where {S,D,I,A,R,M<:DriverModel}

Fill in actions with the actions of each agent present in the scene. It calls observe! and rand for each driver models. actions will contain the actions to apply to update the state of each vehicle.

source
AutomotiveDrivingModels.tick!Function
tick!(scene::EntityFrame{S,D,I}, roadway::R, actions::Vector{A}, Δt::Float64) where {S,D,I,A,R}

update scene in place by updating the state of each vehicle given their current action in actions. It calls the propagate method for each vehicle in the scene.

source

Callbacks

One can define callback functions that will be run at each simulation step. The callback function can terminate the simulation by returning true. The default return value of a callback function should be false. Callback functions are also useful to log simulation information.

To run a custom callback function in the simulation loop, you must implement a custom callback type and an associated run_callback method for that type with the following signature

function AutomotiveDrivingModels.run_callback(
    cb::ReachGoalCallback,
    scenes::Vector{Frame{E}},
    actions::Vector{Frame{A}},
    roadway::R,
    models::Dict{I,M},
    tick::Int,
    ) where {E<:Entity,A<:EntityAction,R,I,M<:DriverModel}
end

The scenes object holds a snapshot of a scene at each timestep in the range 1:tick, and the actions object holds a frame of EntityActions which record the action of each vehicle for the time steps 1:(tick-1).

Here is an example of a callback that checks if a vehicle's longitudinal position has reached some goal position and stops the simulation if it is the case.

struct ReachGoalCallback # a callback that checks if vehicle veh_id has reach a certain position 
    goal_pos::Float64
    veh_id::Int64
end 

function AutomotiveDrivingModels.run_callback(
    cb::ReachGoalCallback,
    scenes::Vector{Frame{E}},
    actions::Vector{Frame{A}},
    roadway::R,
    models::Dict{I,M},
    tick::Int,
    ) where {E<:Entity,A<:EntityAction,R,I,M<:DriverModel}
    veh = get_by_id(last(scenes), cb.veh_id)
    return veh.state.posF.s > cb.goal_pos 
end

A callback for collision is already implemented: CollisionCallback.

AutomotiveDrivingModels.run_callbackFunction
# TODO: this should be removed, but where to document the function then?
run_callback(callback::Any, scenes::Vector{F}, roadway::R, models::Dict{I,M}, tick::Int) where {F,I,R,M<:DriverModel}    
run_callback(callback::Any, rec::EntityQueueRecord{S,D,I}, roadway::R, models::Dict{I,M}, tick::Int) where {S,D,I,R,M<:DriverModel}

run callback and return whether simlation should terminate A new method should be implemented when defining a new callback object.

source

Others