Feature Extraction
AutomotiveSimulator.jl provides useful functions to extract information from a scene.
Feature Extraction Pipeline
The function extract_features
can be used to extract information from a list of scenes. It takes as input a vector of scenes (which could be the output of simulate
), as well as a list of feature functions to use. The output is a dictionary of DataFrame from DataFrames.jl.
AutomotiveSimulator.extract_features
— Functionextract_features(features, roadway::Roadway, scenes::Vector{<:Scene}, ids::Vector{I}) where I
Extract information from a list of scenes. It returns a dictionary of DataFrame objects.
Inputs
features
: a tuple of feature functions. The feature types supported areEntityFeature
,SceneFeature
andTemporalFeature
. Check the documentation for the list of available feature functions, and how to implement you own feature function.roadway::Roadway
: the roadway associated to the scenes.scenes::Vector{<:Scene}
: the simulation data from which we wish to extract information from. Each scene in the vector corresponds to one time step.ids::Vector{I}
: a list of entity IDs for which we want to extract the information.
Output
A dictionary mapping IDs to DataFrame
objects. For a given ID, the DataFrame's columns correspond to the name of the input feature functions. The row correspond to the feature value for each scene (time history).
Example:
roadway = gen_straight_roadway(4, 100.0)
scene_0 = Scene([
Entity(VehicleState(VecSE2( 0.0,0.0,0.0), roadway, 10.0), VehicleDef(AgentClass.CAR, 5.0, 2.0), 1),
Entity(VehicleState(VecSE2(10.0,0.0,0.0), roadway, 10.0), VehicleDef(AgentClass.CAR, 5.0, 2.0), 2),
])
scene_1 = Scene([
Entity(VehicleState(VecSE2( 10.0,0.0,0.0), roadway, 10.0), VehicleDef(AgentClass.CAR, 5.0, 2.0), 1),
Entity(VehicleState(VecSE2(20.0,0.0,0.0), roadway, 10.0), VehicleDef(AgentClass.CAR, 5.0, 2.0), 2),
])
dfs = extract_features((posgx, iscolliding), roadway, [scene_0, scene_1], [1,2])
dfs[1].posgx # history of global x position for vehicle of ID 1
Finding neighbors
Finding neighbors of an entity is a common query and can be done using the find_neighbor
function. This function allows to find the neighbor of an entity within a scene using a forward search method. The search algorithm moves longitudinally along a given lane and its successors (according to the given road topology). Once it finds a car it stops searching and return the results as a NeighborLongitudinalResult
AutomotiveSimulator.NeighborLongitudinalResult
— TypeNeighborLongitudinalResult
A structure to retrieve information about a neihbor in the longitudinal direction i.e. rear and front neighbors on the same lane. If the neighbor index is equal to nothing
it means there is no neighbor.
Fields
ind::Union{Nothing, Int64}
index of the neighbor in the sceneΔs::Float64
positive distance along the lane between vehicles positions
The find_neighbor
function accepts different keyword argument to search front or rear neighbors, or neighbors on different lanes.
AutomotiveSimulator.find_neighbor
— Functionfind_neighbor(scene::Scene, roadway::Roawday, ego::Entity; kwargs...)
Search through lanes and road segments to find a neighbor of ego
in the scene
. Returns a NeighborLongitudinalResult
object with the index of the neighbor in the scene and its relative distance.
Arguments
scene::Scene
the scene containing all the entitiesroadway::Roadway
the road topology on which entities are drivingego::Entity
the entity that we want to compute the neighbor of.
Keyword arguments
lane::Union{Nothing, Lane}
the lane on which to search the neighbor, if different from the ego vehicle current lane, it uses the projection of the ego vehicle on the given lane as a reference point. If nothing, returns nothing.rear::Bool = false
set to true to search for rear neighbor, search forward neighbor by defaultmax_distance::Float64 = 250.0
stop searching after this distance is reached, if the neighbor is further than max_distance, returns nothingtargetpoint_ego::VehicleTargetPoint
the point on the ego vehicle used for distance calculation, seeVehicleTargetPoint
for more infotargetpoint_neighbor::VehicleTargetPoint
the point on the neighbor vehicle used for distance calculation, seeVehicleTargetPoint
for more infoids_to_ignore::Union{Nothing, Set{I}} = nothing
a list of entity ids to ignore for the search, ego is always ignored.
When computing the distance to a neighbor, one might want to choose different reference points on the vehicle (center to center, bumper to bumper, etc...). AutomotiveSimulator provides the VehicleTargetPoint
types to do so. One can choose among three possible instances to use the front, center, or rear point of a vehicle to compute the distance to the neighbor.
AutomotiveSimulator.VehicleTargetPoint
— TypeVehicleTargetPoint
Defines a point on an entity that is used to measure distances. The following target points are supported and are subtypes of VehicleTargetPoint:
VehicleTargetPointFront
VehicleTargetPointCenter
VehicleTargetPointRear
The method targetpoint_delta(::VehicleTargetPoint, ::Entity)
can be used to compute the delta in the longitudinal direction to add when considering a specific target point.
AutomotiveSimulator.VehicleTargetPointCenter
— TypeVehicleTargetPointCenter <: VehicleTargetPoint
Set the target point at the center of the entity.
AutomotiveSimulator.VehicleTargetPointFront
— TypeVehicleTargetPointFront <: VehicleTargetPoint
Set the target point at the front (and center) of the entity.
AutomotiveSimulator.VehicleTargetPointRear
— TypeVehicleTargetPointFront <: VehicleTargetPoint
Set the target point at the front (and center) of the entity.
To get the relative position of two vehicles in the Frenet frame, the get_frenet_relative_position
can be used. It stores the result in a FrenetRelativePosition
object.
AutomotiveSimulator.get_frenet_relative_position
— Functionget_frenet_relative_position(veh_fore::Entity, veh_rear::Entity, roadway::Roadway)
return the Frenet relative position between the two vehicles. It projects the position of the first vehicle onto the lane of the second vehicle. The result is stored as a FrenetRelativePosition
.
Lower level: getfrenetrelativeposition(posG::VecSE2{Float64}, roadind::RoadIndex, roadway::Roadway; maxdistancefore::Float64 = 250.0, # max distance to search forward [m] maxdistancerear::Float64 = 250.0, # max distance to search backward [m] improvementthreshold::Float64 = 1e-4, )
Project the given point to the same lane as the given RoadIndex. This will return the projection of the point, along with the Δs along the lane from the RoadIndex. The returned type is a FrenetRelativePosition
object.
AutomotiveSimulator.FrenetRelativePosition
— TypeFrenetRelativePosition
Contains information about the projection of a point on a lane. See get_frenet_relative_position
.
Fields
origin::RoadIndex
original roadindex used for the projection, contains the target lane ID.target::RoadIndex
roadindex reached after projectionΔs::Float64
longitudinal distance to the original roadindext::Float64
lateral distance to the original roadindex in the frame of the target laneϕ::Float64
angle with the original roadindex in the frame of the target lane
Implementing Your Own Feature Function
In AutomotiveSimulator, features are functions. The current interface supports three methods:
myfeature(::Roadway, ::Entity)
myfeature(::Roadway, ::Scene, ::Entity)
myfeature(::Roadway, ::Vector{<:Scene}, ::Entity)
For each of those methods, the last argument correspond to the entity with one of the ID given to the top level extract_features
function. Creating a new feature consists of implementing one of those methods for your feature function.
As an example, let's define a feature function that returns the distance to the rear neighbor. Such feature will use the second method since it needs information about the whole scene to find the neighbor. If there are not rear neighbor then the function will return missing
. DataFrame
are designed to handled missing values so it should not be an issue.
function distance_to_rear_neighbor(roadway::Roadway, scene::Scene, ego::Entity)
neighbor = find_neighbor(scene, roadway, ego, rear=true)
if neighbor.ind === nothing
return missing
else
return neighbor.Δs
end
end
Now you can use your feature function in extract features, the name of the function is used to name the column of the dataframe:
dfs = extract_features((distance_to_rear_neighbor,), roadway, scenes, [1])
dfs[1].distance_to_rear_neighbor # contains history of distances to rear neighor
!!!note If the supported methods are limiting for your use case please open an issue or submit a PR. It should be straightforward to extend the extract_features
function to support other methods, as well as adding new feature trait.
List of Available Features
AutomotiveSimulator.posgx
— Functionposgx(roadway::Roadway, veh::Entity)
returns x position in the global frame
AutomotiveSimulator.posgy
— Functionposgy(roadway::Roadway, veh::Entity)
returns y position in the global frame
AutomotiveSimulator.posgθ
— Functionposgθ(roadway::Roadway, veh::Entity)
returns heading in the global frame
AutomotiveSimulator.posfs
— Functionposfs(roadway::Roadway, veh::Entity)
returns longitudinal position in Frenet frame
AutomotiveSimulator.posft
— Functionposft(roadway::Roadway, veh::Entity)
returns lateral position in Frenet frame
AutomotiveSimulator.posfϕ
— Functionposfϕ(roadway::Roadway, veh::Entity)
returns heading relative to centerline of the lane
AutomotiveSimulator.vel
— Methodvel(roadway::Roadway, veh::Entity)
returns the velocity of veh
AutomotiveSimulator.velfs
— Functionvelfs(roadway::Roadway, veh::Entity)
returns the longitudinal velocity in the Frenet frame
AutomotiveSimulator.velft
— Functionvelft(roadway::Roadway, veh::Entity)
returns the lateral velocity in the Frenet frame
AutomotiveSimulator.velgx
— Functionvelgx(roadway::Roadway, veh::Entity)
returns the velocity in the x direction of the global frame
AutomotiveSimulator.velgy
— Functionvelgy(roadway::Roadway, veh::Entity)
returns the velocity in the y direction of the global frame
AutomotiveSimulator.time_to_crossing_right
— Functiontime_to_crossing_right(roadway::Roadway, veh::Entity)
time before crossing the right lane marker assuming constant lateral speed.
AutomotiveSimulator.time_to_crossing_left
— Functiontime_to_crossing_left(roadway::Roadway, veh::Entity)
time before crossing the left lane marker assuming constant lateral speed.
AutomotiveSimulator.estimated_time_to_lane_crossing
— Functionestimated_time_to_lane_crossing(roadway::Roadway, veh::Entity)
minimum of the time to crossing left and time to crossing right.
AutomotiveSimulator.iswaiting
— Functioniswaiting(roadway::Roadway, veh::Entity)
returns true if the vehicle is waiting (if the velocity is 0.0)
AutomotiveSimulator.iscolliding
— Functioniscolliding(roadway::Roadway, scene::Scene, veh::Entity)
returns true if the vehicle is colliding with another vehicle in the scene.
AutomotiveSimulator.distance_to
— Functiondistance_to(egoid)
generate a feature function distancetoegoid.
distance_to_$egoid(roadway, scene, veh)
returns the distance between veh and the vehicle of id egoid in the scene.
AutomotiveSimulator.acc
— Functionacc(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the history of acceleration of the entity of id vehid using finite differences on the velocity. The first element is missing
.
AutomotiveSimulator.accfs
— Functionaccfs(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the history of longitudinal acceleration in the Frenet frame of the entity of id vehid using finite differences on the velocity. The first element is missing
.
AutomotiveSimulator.accft
— Functionaccft(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the history of lateral acceleration in the Frenet frame of the entity of id vehid using finite differences on the velocity. The first element is missing
.
AutomotiveSimulator.jerk
— Functionjerk(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the jerk history of the entity of id vehid using finite differences on acceleration (which uses finite differences on velocity). The first two elements are missing.
AutomotiveSimulator.jerkft
— Functionjerkft(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the lateral jerk history in the Frenet frame of the entity of id vehid using finite differences on acceleration (which uses finite differences on velocity). The first two elements are missing.
AutomotiveSimulator.turn_rate_g
— Functionturn_rate_g(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the turn rate history in the Frenet frame of the entity of id vehid using finite differences on global heading. The first element is missing.
AutomotiveSimulator.turn_rate_f
— Functionturn_rate_g(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
returns the turn rate history in the Frenet frame of the entity of id vehid using finite differences on heading in the Frenet frame. The first element is missing.
AutomotiveSimulator.isbraking
— Functionisbraking(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
history of braking events: true when the acceleration is negative. The first element is missing.
AutomotiveSimulator.isaccelerating
— Functionisaccelerating(roadway::Roadway, scenes::Vector{<:Scene}, vehid)
history of acceleration events: true when the acceleration is positive The first element is missing.
AutomotiveSimulator.lane_width
— Functionlane_width(roadway::Roadway, veh::Entity)
Returns the width of the lane where veh
is.
AutomotiveSimulator.markerdist_left
— Functionmarkerdist_left(roadway::Roadway, veh::Entity)
distance of veh
to the left marker of the lane
AutomotiveSimulator.markerdist_right
— Functionmarkerdist_left(roadway::Roadway, veh::Entity)
distance of veh
to the right marker of the lane
AutomotiveSimulator.road_edge_dist_left
— Functionroad_edge_dist_left(roadway::Roadway, veh::Entity)
feature function, extract the lateral distance to the left edge of the road
AutomotiveSimulator.road_edge_dist_right
— Functionroad_edge_dist_right(roadway::Roadway, veh::Entity)
feature function, extract the lateral distance to the right edge of the road
AutomotiveSimulator.lane_offset_left
— Functionlane_offset_left(roadway::Roadway, veh::Entity)
returns the distance to the left lane border, if there are no left lane returns missing
AutomotiveSimulator.lane_offset_right
— Functionlane_offset_right(roadway::Roadway, veh::Entity)
returns the distance to the right lane border, if there are no right lane returns missing
AutomotiveSimulator.n_lanes_left
— Methodn_lanes_left(roadway::Roadway, veh::Entity)
return the numbers of lanes to the left of veh
AutomotiveSimulator.n_lanes_right
— Methodn_lanes_right(roadway::Roadway, veh::Entity)
return the numbers of lanes to the right of veh
AutomotiveSimulator.has_lane_left
— Functionhas_lane_left(roadway::Roadway, veh::Entity)
Return true if veh
has a lane on its left.
AutomotiveSimulator.has_lane_right
— Functionhas_lane_right(roadway::Roadway, veh::Entity)
Return true if veh
has a lane on its right.
AutomotiveSimulator.lane_curvature
— Functionlane_curvature(roadway::Roadway, veh::Entity)
Return the curvature of the lane at veh
's position. Return missing if the curvature is NaN
AutomotiveSimulator.dist_to_front_neighbor
— Functiondist_to_front_neighbor(roadway::Roadway, scene::Scene, veh::Entity)
Feature function to extract the longitudinal distance to the front neighbor (in the Frenet frame). Returns missing
if there are no front neighbor.
AutomotiveSimulator.front_neighbor_speed
— Functionfront_neighbor_speed(roadway::Roadway, scene::Scene, veh::Entity)
Feature function to extract the velocity of the front neighbor. Returns missing
if there are no front neighbor.
AutomotiveSimulator.time_to_collision
— Functiontime_to_collision(roadway::Roadway, scene::Scene, veh::Entity)
Feature function to extract the time to collision with the front neighbor. Returns missing
if there are no front neighbor.