Behavior Layer

This layer is responsible for the decision-making that structures the driver behavior. The core of this process is based on a Behavior Tree as a control architecture. The execution follows a directed rooted tree where internal nodes control the execution flow and leaf nodes are either conditions or decisions.

Control Nodes (internal): - fallback operator ($?$): executes each of its child nodes in turn until one of them succeeds. Returns successful child status (RUNNING or SUCCESS). If it runs out of children returns FAILURE. - sequence operator ($->$) progressively ticks over each of its children so long as each child returns SUCCESS. If one child FAILs, the sequence halts an returns FAIL - paralell operator ($=>$) ticks every child every time the parallel is run. Returns FAILURE if any FAILURE. Returns SUCCESS if all children return SUCCESS.

Leaf Nodes: - Condition: evaluation rules based on the vehicle self state and the estimated traffic state. - Decision: coordinate the vehicle motion by selecting when to start or to end low-level driving tasks in the form of maneuvers (to be handled in the next layer). - Subtree: composition node that includes another Behavior Tree starting from the root.

Example: In the following root tree (left) the vehicle decides to stop (stop maneuver) after a condition testing if the vehicle reached the goal. Otherwise, the vehicle continues driving (drive tree).

The behavior of each vehicle running the model is defined by a root tree provided by the user as input. The Behavior Layer works as the engine that executes the user-defined trees, and provides access to the estimated traffic state using a blackboard paradigm to support decisions. The output of this layer is the selected maneuver, and a configuration.

Behavior Trees DSL

The model includes a user-oriented DSL adapted from the classical Behavior Tree architecture with a simplified set of rules applicable to the context of ADS testing. Each scenario requires the construction of a root tree that can connect reusable sub-trees and give to a specific vehicle a unique behavior for a particular scenario (we name it the Scenario Tree). We model a set of reusable trees to cover common scenarios (Drive, Lane-Change, Handle Traffic Lights, etc). Trees can be modified according to new scenario requirements, and custom trees can be added to the pool of sub-trees.

Syntax:

Control nodes:
    ? 
    ->
    =>
Leaf nodes:
    condition <node_name> ( <condition>( <attribute>=<value> , ...) )
    maneuver <node_name> ( <mconfig>( <attribute>=<value> , ...) )
    subtree <tree_name> (<node_override>)

*Node override during composition is optional.

Condition Nodes

The condition nodes depend on a set of evaluation functions based on the estimated Traffic State (see Section Traffic State Estimation). These conditions are added to the Behavior Model to support the Behavior Trees. Sample condition functions that can be reused are available in the reference implementation, but they can be expanded by the user by implementing new functions and evaluating the Traffic State. Action conditions modify the state of the vehicle and return Success.

Basics

condition attributes description
sim_time
t (s)
min=0 (s)
max=infinity (s)
Returns True if simulation time matches given time t or is within min and max values.
Using exact time will have a tolerance based on the planner rate. If max is not given, infinity is assumed.
vehicle_state vid, zid Checks if vehicle state has reached long and lateral values at minimum.
If no vid or zid is assigned, defaults to self ID.
delta_vehicle_state s_pos
s_vel
s_acc
d_pos
d_vel
d_acc
Checks if vehicle state has reached delta values at minimum. Always compare between self the the vehicle with vid (or per occupancy zone)
wait t(s) Wait given time before moving to next node (used to delay reactions).
interrupt - Returns False. Can be used to interrupt a sequence.

Notes:

  • sim_time can be useful to delay certain actions at the beginning of the scenario. However, as the timeline advances, using simulation time to control the flow is prone to error and scenario drift (when scenario deviates from intended design). We recommend using Metrics and Interaction Conditions as the main form of control.
  • vehicle_state and delta vehicle_state are low level conditions that can be used when Traffic Interactions and Metric conditions are not adequate. We recommend using conditions with higher level of abstraction as much as possible.

Routing and Driving Mission

condition attributes description
reached_goal distance (m)=40 Checks if the vehicle has reached or passed the goal point (see Routing)
at_lane_change_segment - Checks if the vehicle is inside a zone where it needs to change lanes to conintue on route
target_lane lid Checks if given lane is the target lane.
out_of_route - Checks if vehicle is out of planned route.

Traffic Interactions
For some conditions, the target vehicle can be identified by vid, lid (vehicle in lane), or zid (vehicle in zone). If no vehicle is given, assumes self. For example, vehicle_stopped means if self is not moving, vehicle_stopped(lid=RIGHT) means if vehicle on the right lane is not moving.

condition attributes description
vehicle_stopped vid,lid,zid Checks if vehicle is not moving.
vehicle_moving vid,lid,zid Checks if vehicle is moving.
vehicle_yielding vid,lid,zid
distance=1
vel=0.01
Checks if vehicle is stopped and at yielding position (stop line or right before conflicint lanelet). Vel and distance (from the stop line) are thresholds to define the yielding state.
A small velocity threshold can used to account for noise in the estimation.
vehicle_parked vid,lid,zid
distance=0.5
vel=0.01
Checks if vehicle has stopped and at parking position. Vel and distance (offset from the center of the lane) are thresholds to define the parked state.
A small velocity threshold can used to account for noise in the estimation.
lv_stopped - Same as vehicle_stopped, but targets the leading vehicle.
lv_moving - Same as vehicle_moving, but targets the leading vehicle.
lv_parked - Same as vehicle_parked, but targets the leading vehicle.
can_lane_change lid,
gap=20(m)
time_gap=2(s)
Checks if there is space for a lane change based on given lid or target lane set by Action in the.
is_ego vid,lid,zid Checks if vehicle is Ego.

Metrics

condition attributes description
time_gap vid,lid,zid
min,max
Returns true based on min and max time distance to given vehicle (in Frénet)
gap vid,lid,zid
min, max
Returns true based on min and max gap distance to given vehicle (in Frénet)
distance vid,lid,zid
min, max
Returns true based on min and max distance to given vehicle (in Cartesian)
longitudinal_distance vid,lid,zid
min,max
Returns true based on min and max absolute distance to given vehicle in Frénet (if vehicle is on the path).
Note this is the absolute difference, and is always positive (unlike gap).
lateral_distance vid,lid,zid
min,max
Returns true based on min and max absolute lateral distance to given vehicle in Frénet (if vehicle is on the path).
Note this is the absolute difference, and is always positive (unlike gap).

Road and Regulatory Elements

condition attributes description
approaching_intersection distance=30 Checks if vehicle is approaching a regulated intersection. Threshold is given in distance to intersection.
approaching_stop_sign distance=30 Checks for generic stop definition (useful when map is incomplete and does not contain a proper regulatory element). Threshold is given in distance to intersection.
intersection_type type Checks if vehicle approaching intersection from given type. Type can be RIGHT_OF_WAY, ALL_WAY_STOP, TRAFFIC_LIGHT, or PEDESTRIAN_CROSS.
yield_role Checks if vehicle approaching intersection and has a yielding role
intersection_occupied vid Checks if intersection of any type (RightOfWay, TrafficLight or AllWayStop) has crossing vehicles (moving). Optional vid returns true only if given vehicle is present.
row_occupied vid
distance=1
Checks if RightOfWay intersection has approaching vehicles in the lanelets with right of way.
vid: returns true only if given vehicle is present.
distance: max distance from the intersection
aws_occupied vid
distance=1
Checks if AllWayStop intersection has vehicles in yielding lanelets.
vid: returns true only if given vehicle is present.
distance: max distance from the intersection.
aws_yield vel00.03
wait_time=5
risk_probability=0.05
Checks if AllWayStop intersection has vehicles yielding with priority. False otherwise (meaning self has priority)
vid: returns true only if given vehicle is present.
vel: velocity thereshold to consider a vehicle is moving.
wait_time: max wait time on a deadlock before moving.
risk_probability: after wait_time in deadlock, the probability of taking the risk and moving first from 0 (never move) to 1 (always move).
lane_occupied time=5
distance=30
Checks if current lane is occupied (if there is a vehicle ahead).
Limited to maximum time and distance as thresholds.
traffic_light_state color Checks if state of the traffic light (applicable to current lanelet) matches the given color state. Example traffic_light_state(color='RED').

Actions

condition attributes description
action_set_target_lane
action_reroute
action_turn_signal_left state Change left turn signal state. Will toggle on/off if no state is given. state= TRUE/FALSE or 1/0 or ON/OFF
action_turn_signal_right state Change right turn signal state. Will toggle on/off if no state is given. state= TRUE/FALSE or 1/0 or ON/OFF
action_head_light state Change headligh state. Will toggle on/off if no state is given. state= TRUE/FALSE or 1/0 or ON/OFF

lane_occupied | time_gap, distance_gap | returns True if there is a vehicle in the following range. The following range is defined by the time_gap (default 2 seconds) or distance_gap (default 30 m) should_cutin| target_lane_id* | returns True if the target lane during a lane change maneuver(target_lane_id) is reachable and has a vehicle.

reached_gap | target_lane_id, 'meters' | returns True if range between self and vehicle on target lane (target_lane_id) is above a treshold (meters). sim_time | tmin, tmax | returns True if simulaton time fits between two values (tmin, tmax). If only one value is povided, the other is assumed to be $∞$. traffic_light_red | distance | returns true if there is a traffic light ahead (by distance) with Red state. traffic_light_green: | distance | returns true if there is a traffic light ahead (by distance) with Green state.

*Mandatory

Maneuver Nodes

Maneuver nodes represent a decision, and outputs this decision to the Maneuver Layer of the model. This Layer contains a set of Maneuver Models to be activated. Similar to Condition Nodes, new maneuvers can be added.

Sample maneuver nodes:

maneuver m_1(MVelKeepConfig())
maneuver m_2(MFollowConfig())
maneuver m_3(MLaneSwerveConfig())
maneuver m_4(MCutInConfig())
maneuver m_5(MStopConfig())
maneuver m_6(MReverseConfig())

Maneuver models can have optional or mandatory configuration nodes. For example, a vehicle performing a lane swerve must have a target lane id (-1 for right lane, +1 for left lane). A vehicle performing velocity Keeping can have the target velocity defined, a target range, or can be ommmited for default road values. All attributes per Maneuver and how parameter values are sampled are described in the Maneuver Layer Section.

maneuver m_1(MVelKeepConfig())
maneuver m_2(MVelKeepConfig(vel=MP(16))
maneuver m_3(MLaneSwerveConfig(target_lid=-1) or maneuver m_3(MLaneSwerveConfig(target_lid=LEFT)

Examples

Example1:

The drive tree provides basic driving decisions that can be reused across multiple scenario. Vehicles that do not require a scenario specific behavior can use this sample as a root tree.

behaviortree drive_tree:
    ?
        ->
            condition c_goal ( reached_goal( threshold=35 ) )
            maneuver m_stop_goal ( MStopConfig(type=2) )
        ->
            condition c_redlight ( traffic_light_red( threshold=40 ) )
            maneuver m_stop_redlight ( MStopConfig( type=3 ) )
        ->
            condition c_busy_lane( lane_occupied() )
            maneuver m_follow_lead ( MFollowConfig() )
        maneuver m_keepvelocity ( MVelKeepConfig( vel=MP(10.0,10,6), lat_target=LT(0.0,3) ) )

Now, we create two additional trees for vehicles driving with different target velocities. Both Trees reuse the sub-tree drive. However, during the composition we override the m_velocitykeeping node by assigning different velocities (16m/s and 10m/s respectively).

behaviortree st_drivefast:
    ->
        subtree drive( m_keepvelocity=MVelKeepConfig(vel=MP(16)))
behaviortree st_driveslow:
    ->
        subtree drive( m_keepvelocity=MVelKeepConfig(vel=MP(10)))

Example 2:

In this example we define a reusable behavior for the lane change, and create a scenario tree for a vehicle. The vehicle will drive normally (drive tree) until the simulation time reaches 3 seconds and the control flow will alternate to the reusable lane change tree.

behaviortree st_lanechange:
    ?
        ->
            condition lc( sim_time (repeat=False, tmin=3, tmax=10))
            subtree lanechange()
        subtree drive()
Behaviortree lanechange:
    ?
        ->
            condition c_should_cutin( should_cutin(target_lane_id=-1) )
            maneuver m_cutin( MCutInConfig(target_lid=-1) )
        maneuver m_lane_swerve( MLaneSwerveConfig(target_lid=-1) )

Note: The reference implementation in the GeoScenario Server contians a set of sample trees.