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
randon the driver model. - update the state of each vehicle using the sampled action and the
propagatemethod. - 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 givenQueueRecordobject. TheQueueRecorddata 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! — FunctionDEPRECATION 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.
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.
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
AutomotiveDrivingModels.get_actions! — Functionget_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.
AutomotiveDrivingModels.tick! — Functiontick!(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.
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}
endThe 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
endA callback for collision is already implemented: CollisionCallback.
AutomotiveDrivingModels.run_callback — Function# 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.
AutomotiveDrivingModels.CollisionCallback — TypeCollisionCallbackTerminates the simulation once a collision occurs
Others
reset_hidden_states!(models::Dict{Int,M}) where {M<:DriverModel}reset hidden states of all driver models in models