Skip to content

Commit

Permalink
Merge pull request #72 from sisl/feature-extraction
Browse files Browse the repository at this point in the history
[WIP] New feature extraction mechanism
  • Loading branch information
MaximeBouton committed Mar 20, 2020
2 parents 94a1dd8 + 5be7210 commit 9ea672e
Show file tree
Hide file tree
Showing 23 changed files with 743 additions and 848 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ os:
- osx
- windows
julia:
- 1.0
- 1.3
- 1

notifications:
email: false
Expand Down
5 changes: 5 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ repo = "https://github.com/sisl/AutomotiveDrivingModels.jl.git"
version = "0.7.12"

[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
Expand All @@ -12,6 +13,10 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Records = "5984c134-fa48-5ed5-a57f-fc2f6936871f"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Tricks = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"

[compat]
julia = "1.3"

[extras]
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Expand Down
4 changes: 2 additions & 2 deletions docs/src/Roadways.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ The `Lane` data structure represent a driving lane in the roadway. The default l
has_prev
next_lane_point
prev_lane_point
n_lanes_left
n_lanes_right
n_lanes_left(roadway::Roadway, lane::Lane)
n_lanes_right(roadway::Roadway, lane::Lane)
leftlane(::Roadway, ::Lane)
rightlane(::Roadway, ::Lane)
```
Expand Down
15 changes: 15 additions & 0 deletions docs/src/Vec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Vec

`Vec` is a submodule of AutomotiveDrivingModels that provides several vector types, named after their groups. All types are immutable and are subtypes of ['StaticArrays'](https://github.com/JuliaArrays/StaticArrays.jl)' `FieldVector`, so they can be indexed and used as vectors in many contexts.

* `VecE2` provides an (x,y) type of the Euclidean-2 group.
* `VecE3` provides an (x,y,z) type of the Euclidean-3 group.
* `VecSE2` provides an (x,y,theta) type of the special-Euclidean 2 group.

```julia
v = VecE2(0, 1)
v = VecSE2(0,1,0.5)
v = VecE3(0, 1, 2)
```

Additional geometry types include `Quat` for quaternions, `Line`, `LineSegment`, and `Projectile`.
100 changes: 87 additions & 13 deletions docs/src/feature_extraction.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Feature Extraction

AutomotiveDrivingModels.jl implements a feature extraction pipeline to extract information from pre-recorded simulation
in a `QueueRecord` or `ListRecord`. (see Records.jl for info on the data structure)
AutomotiveDrivingModels.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 frame (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](https://github.com/JuliaData/DataFrames.jl).

```@docs
extract_features
```

!!! warning
Work in progress, the feature extraction functionalities are being redesigned
Follow [#72](https://github.com/sisl/AutomotiveDrivingModels.jl/pull/72) for more information
PRs for documenting feature extraction are more than welcome

## Finding neighbors

Expand All @@ -29,9 +32,9 @@ When computing the distance to a neighbor, one might want to choose different re
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.

```@docs
VehicleTargetPoint,
VehicleTargetPointCenter,
VehicleTargetPointFront,
VehicleTargetPoint
VehicleTargetPointCenter
VehicleTargetPointFront
VehicleTargetPointRear
```

Expand All @@ -43,10 +46,81 @@ It stores the result in a `FrenetRelativePosition` object.
FrenetRelativePosition
```

## Lane Features
## Implementing Your Own Feature Function

In AutomotiveDrivingModels, features are functions. The current interface supports three methods:
- `myfeature(::Roadway, ::Entity)`
- `myfeature(::Roadway, ::Frame, ::Entity)`
- `myfeature(::Roadway, ::Vector{<:Frame}, ::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 frame 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.

```julia
function distance_to_rear_neighbor(roadway::Roadway, scene::Frame, ego::Entity)
neighbor = find_neighbor(scene, roadway, veh, 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:

```julia
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

```@docs
get_lane_width
get_markerdist_left
get_markerdist_right
posgx
posgy
posgθ
posfs
posft
posfϕ
vel(roadway::Roadway, veh::Entity)
velfs
velft
velgx
velgy
time_to_crossing_right
time_to_crossing_left
estimated_time_to_lane_crossing
iswaiting
iscolliding
distance_to
acc
accfs
accft
jerk
jerkft
turn_rate_g
turn_rate_f
isbraking
isaccelerating
lane_width
markerdist_left
markerdist_right
road_edge_dist_left
road_edge_dist_right
lane_offset_left
lane_offset_right
n_lanes_left(roadway::Roadway, veh::Entity)
n_lanes_right(roadway::Roadway, veh::Entity)
has_lane_left
has_lane_right
lane_curvature
dist_to_front_neighbor
front_neighbor_speed
time_to_collision
```
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# About
# AutomotiveDrivingModels

This is the documentation for AutomotiveDrivingModels.jl.

Expand Down
92 changes: 57 additions & 35 deletions src/AutomotiveDrivingModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ using StaticArrays
using Distributions
using Reexport
using Random
using DataFrames
using Tricks: static_hasmethod

@reexport using Records

Expand Down Expand Up @@ -124,11 +126,7 @@ export
include("states/interface.jl")
include("states/vehicle_state.jl")

export
TrajdataFrame,
TrajdataState,
Trajdata,
TrajdataVehicleIterator
export Trajdata

include("states/trajdatas.jl")

Expand Down Expand Up @@ -162,6 +160,57 @@ include("collision-checkers/parallel_axis.jl")

## Feature Extraction

export AbstractFeature,
EntityFeature,
FrameFeature,
TemporalFeature,
extract_features,
extract_feature,
featuretype,

# provided feature functions
posgx,
posgy,
posgθ,
posfs,
posft,
posfϕ,
vel,
velfs,
velft,
velgx,
velgy,
time_to_crossing_right,
time_to_crossing_left,
estimated_time_to_lane_crossing,
iswaiting,
iscolliding,
distance_to,
acc,
accfs,
accft,
jerk,
jerkft,
turn_rate_g,
turn_rate_f,
isbraking,
isaccelerating

include("feature-extraction/features.jl")

export lane_width,
markerdist_left,
markerdist_right,
road_edge_dist_left,
road_edge_dist_right,
lane_offset_left,
lane_offset_right,
has_lane_left,
has_lane_right,
lane_curvature

include("feature-extraction/lane_features.jl")

export
VehicleTargetPoint,
VehicleTargetPointFront,
Expand All @@ -173,39 +222,13 @@ export
get_neighbor_fore,
get_neighbor_rear,
get_headway,
# get_neighbor_fore_along_lane,
# get_neighbor_fore_along_left_lane,
# get_neighbor_fore_along_right_lane,
# get_neighbor_rear_along_lane,
# get_neighbor_rear_along_left_lane,
# get_neighbor_rear_along_right_lane,
FrenetRelativePosition,
get_frenet_relative_position,
get_lane_width,
get_markerdist_left,
get_markerdist_right
dist_to_front_neighbor,
front_neighbor_speed,
time_to_collision

include("feature-extraction/neighbors_features.jl")
include("feature-extraction/lane_features.jl")

export
AbstractFeature,
FeatureValue,
FeatureState,
is_feature_valid,
is_symbol_a_feature,
allfeatures,
symbol2feature,
AbstractFeatureExtractor,
FeatureExtractor,
SubsetExtractor,
StandardizingExtractor,
pull_features!,
rec_length

include("feature-extraction/interface.jl")
include("feature-extraction/features.jl")
include("feature-extraction/features_extractors.jl")

export
LidarSensor,
Expand Down Expand Up @@ -262,7 +285,6 @@ export
ProportionalLaneTracker,
LatLonSeparableDriver,
Tim2DDriver,
track_lane!,
SidewalkPedestrianModel,
LaneChangeChoice,
LaneChangeModel,
Expand Down
5 changes: 0 additions & 5 deletions src/actions/accel_turnrate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,3 @@ function propagate(veh::Entity{VehicleState,D,I}, action::AccelTurnrate, roadway
posG = VecSE2(x, y, θ)
VehicleState(posG, roadway, v)
end
function Base.get(::Type{AccelTurnrate}, rec::SceneRecord, roadway::Roadway, vehicle_index::Int, pastframe::Int=0)
accel = get(ACC, rec, roadway, vehicle_index, pastframe)
turnrate = get(TURNRATEG, rec, roadway, vehicle_index, pastframe)
AccelTurnrate(accel, turnrate)
end
6 changes: 1 addition & 5 deletions src/actions/lat_lon_accel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,4 @@ function propagate(veh::Entity{VehicleState, D, I}, action::LatLonAccel, roadway
veh = VehicleState(posG, roadway, v₂)
return veh
end
function Base.get(::Type{LatLonAccel}, rec::SceneRecord, roadway::Roadway, vehicle_index::Int, pastframe::Int=0)
accel_lat = get(ACCFT, rec, roadway, vehicle_index, pastframe)
accel_lon = get(ACCFS, rec, roadway, vehicle_index, pastframe)
LatLonAccel(accel_lat, accel_lon)
end

9 changes: 3 additions & 6 deletions src/behaviors/lane_change_models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,14 @@ struct LaneChangeChoice
end
Base.show(io::IO, a::LaneChangeChoice) = @printf(io, "LaneChangeChoice(%d)", a.dir)

function get_lane_offset(a::LaneChangeChoice, rec::SceneRecord, roadway::Roadway, vehicle_index::Int, pastframe::Int=0)
get_lane_offset(a, rec[pastframe], roadway, vehicle_index)
end
function get_lane_offset(a::LaneChangeChoice, scene::Frame, roadway::Roadway, vehicle_index::Int)
if a.dir == DIR_MIDDLE
posf(scene[vehicle_index].state).t
return posf(scene[vehicle_index].state).t
elseif a.dir == DIR_LEFT
convert(Float64, get(LANEOFFSETLEFT, scene, roadway, vehicle_index))
return lane_offset_left(roadway, scene[vehicle_index])
else
@assert(a.dir == DIR_RIGHT)
convert(Float64, get(LANEOFFSETRIGHT, scene, roadway, vehicle_index))
return lane_offset_right(roadway, scene[vehicle_index])
end
end

Expand Down
2 changes: 1 addition & 1 deletion src/behaviors/tim_2d_driver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function observe!(driver::Tim2DDriver, scene::Frame{Entity{S, D, I}}, roadway::R
lane_change_action = rand(driver.mlane)

laneoffset = get_lane_offset(lane_change_action, scene, roadway, vehicle_index)
lateral_speed = convert(Float64, get(VELFT, scene, roadway, vehicle_index))
lateral_speed = velf(scene[vehicle_index]).t

if lane_change_action.dir == DIR_MIDDLE
target_lane = get_lane(roadway, ego)
Expand Down
4 changes: 2 additions & 2 deletions src/behaviors/tim_lane_changer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ function observe!(model::TimLaneChanger, scene::Frame{Entity{S, D, I}}, roadway:
veh_ego = scene[vehicle_index]
v = vel(veh_ego.state)

left_lane_exists = convert(Float64, get(N_LANE_LEFT, rec, roadway, vehicle_index)) > 0
right_lane_exists = convert(Float64, get(N_LANE_RIGHT, rec, roadway, vehicle_index)) > 0
left_lane_exists = has_lane_left(roadway, veh_ego)
right_lane_exists = has_lane_right(roadway, veh_ego)
fore_M = find_neighbor(scene, roadway, veh_ego,
targetpoint_ego = VehicleTargetPointFront(),
targetpoint_neighbor = VehicleTargetPointRear(),
Expand Down
2 changes: 1 addition & 1 deletion src/collision-checkers/minkowski.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

######################################

function cyclic_shift_left!(arr::AbstractVector, d::Int, n::Int=length(a))
function cyclic_shift_left!(arr::AbstractVector, d::Int, n::Int)
#=
Perform a cyclic rotation of the elements in the array, in place
d = amount to shift
Expand Down

0 comments on commit 9ea672e

Please sign in to comment.