From 43a18a3128805b70391ed7e087312527a343eeb5 Mon Sep 17 00:00:00 2001 From: MaximeBouton Date: Mon, 15 Apr 2019 16:13:41 -0700 Subject: [PATCH] simulation docs --- docs/src/simulation.md | 49 ++++++++++++++++++++++++++++++++++ docs/src/states.md | 16 +++++++++++ src/AutomotiveDrivingModels.jl | 1 - src/simulation/callbacks.jl | 5 ++++ src/simulation/simulation.jl | 22 +++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/docs/src/simulation.md b/docs/src/simulation.md index e69de29..f7d6c88 100644 --- a/docs/src/simulation.md +++ b/docs/src/simulation.md @@ -0,0 +1,49 @@ +# Simulation + +Simulation can be done using the `simulate!` function. +A simulation updates the initial scene forward in time. Each simulation step consists of the following operation: +- get the actions of each agent in the scene by calling `observe!` on their respective behavior model (see the behavior section for more information) +- update the scene forward using `tick!`. It consists in applying the individual actions of each agent and updates their states individually. The actions can be of different type for each vehicle. The state is updated by calling the `propagate` method associated to the corresponding action type. (This done automatically thanks to Julia's mutliple dispatch). See the action section for more information on the `propagate` method. +- repeat for the desired number of steps + +See the tutorials for examples. + +```@docs + get_actions! + tick! + simulate! +``` + +## Callbacks + +One can define callback function that will be run at each simulation step. The callback function can interrupt the simulation if it return `false`. It is also useful to log simulation information. + +To implement a custom callback function you must implement a type and the associated `run_callback` method. Here is an example of a callback that checks if a vehicle longitudinal position has reached some goal position and stops the simulation if it is the case. +```julia +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, rec::EntityQueueRecord{S,D,I}, + roadway::R, + models::Dict{I,M}, + tick::Int, + ) where {S,D,I,R,M<:DriverModel} + veh = get_by_id(rec[0], cb.veh_id) + return veh.state.posF.s > cb.goal_pos +end +``` + +A callback for collision is already implemented: `CollisionCallback`. + +```@docs + run_callback + CollisionCallback +``` + +## Others + +```@docs + reset_hidden_states! +``` \ No newline at end of file diff --git a/docs/src/states.md b/docs/src/states.md index e69de29..74548f8 100644 --- a/docs/src/states.md +++ b/docs/src/states.md @@ -0,0 +1,16 @@ +# States + +In this section of the documentation we explain the default vehicle state type provided by `AutomotiveDrivingModels` +as well as the data types used to represent driving scene. Most of the underlying structures are defined in `Records.jl`. +The data structure provided in ADM.jl are concrete instances of parametric types defined in Records. It is possible in principle to define your custom state definition and use the interface defined in ADM.jl. + +## Agent States + +Agents are represented by the entity data type provided by `Records.jl`. +The entity data type has three field: a state, a definition, and an id. + +The state of an entity usually describes physical quantity such as position and velocity. + + +## Scenes + diff --git a/src/AutomotiveDrivingModels.jl b/src/AutomotiveDrivingModels.jl index 7244f82..895c06a 100644 --- a/src/AutomotiveDrivingModels.jl +++ b/src/AutomotiveDrivingModels.jl @@ -147,7 +147,6 @@ export is_potentially_colliding, get_collision_time, get_first_collision, - get_time_and_dist_of_closest_approach, is_collision_free, get_distance, get_edge, diff --git a/src/simulation/callbacks.jl b/src/simulation/callbacks.jl index 2c20502..f4e71b6 100644 --- a/src/simulation/callbacks.jl +++ b/src/simulation/callbacks.jl @@ -1,4 +1,9 @@ # run callback and return whether simlation should terminate +""" + 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. +""" run_callback(callback::Any, rec::EntityQueueRecord{S,D,I}, roadway::R, models::Dict{I,M}, tick::Int) where {S,D,I,R,M<:DriverModel} = error("run_callback not implemented for callback $(typeof(callback))") function _run_callbacks(callbacks::C, rec::EntityQueueRecord{S,D,I}, roadway::R, models::Dict{I,M}, tick::Int) where {S,D,I,R,M<:DriverModel,C<:Tuple{Vararg{Any}}} diff --git a/src/simulation/simulation.jl b/src/simulation/simulation.jl index 810e7ed..d66c3fb 100644 --- a/src/simulation/simulation.jl +++ b/src/simulation/simulation.jl @@ -1,3 +1,9 @@ +""" + 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. +""" function get_actions!( actions::Vector{A}, scene::EntityFrame{S,D,I}, @@ -15,6 +21,11 @@ function get_actions!( actions end +""" + 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. +""" function tick!( scene::EntityFrame{S,D,I}, roadway::R, @@ -31,6 +42,10 @@ function tick!( return scene end +""" + reset_hidden_states!(models::Dict{Int,M}) where {M<:DriverModel} +reset hidden states of all driver models in `models` +""" function reset_hidden_states!(models::Dict{Int,M}) where {M<:DriverModel} for model in values(models) reset_hidden_state!(model) @@ -39,7 +54,14 @@ function reset_hidden_states!(models::Dict{Int,M}) where {M<:DriverModel} end """ + simulate!(::Type{A}, rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M}, nticks::Int) where {S,D,I,A,R,M<:DriverModel} + simulate!(rec::EntityQueueRecord{S,D,I}, scene::EntityFrame{S,D,I}, roadway::R, models::Dict{I,M}, nticks::Int) where {S,D,I,R,M<:DriverModel} 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. + """ function simulate!( ::Type{A},