Behavior#

Other simulated vehicles follow simple and realistic behaviors that dictate how they accelerate and steer on the road. They are implemented in the IDMVehicle class.

Longitudinal Behavior#

The acceleration of the vehicle is given by the Intelligent Driver Model (IDM) from [THH00].

\[\begin{split} \dot{v} &= a\left[1-\left(\frac{v}{v_0}\right)^\delta - \left(\frac{d^*}{d}\right)^2\right] \\ d^* &= d_0 + Tv + \frac{v\Delta v}{2\sqrt{ab}} \\ \end{split}\]

where \(v\) is the vehicle velocity, \(d\) is the distance to its front vehicle. The dynamics are parametrised by:

It is implemented in acceleration() method.

Lateral Behavior#

The discrete lane change decisions are given by the Minimizing Overall Braking Induced by Lane change (MOBIL) model from [KTH07]. According to this model, a vehicle decides to change lane when:

  • it is safe (do not cut-in):

\[ \tilde{a}_n \geq - b_\text{safe}; \]
  • there is an incentive (for the ego-vehicle and possibly its followers):

\[ \underbrace{\tilde{a}_c - a_c}_{\text{ego-vehicle}} + p\left(\underbrace{\tilde{a}_n - a_n}_{\text{new follower}} + \underbrace{\tilde{a}_o - a_o}_{\text{old follower}}\right) \geq \Delta a_\text{th}, \]

where

  • \(c\) is the center (ego-) vehicle, \(o\) is its old follower before the lane change, and \(n\) is its new follower after the lane change

  • \(a, \tilde{a}\) are the acceleration of the vehicles before and after the lane change, respectively.

  • \(p\) is a politeness coefficient, implemented as POLITENESS

  • \(\Delta a_\text{th}\) the acceleration gain required to trigger a lane change, implemented as LANE_CHANGE_MIN_ACC_GAIN

  • \(b_\text{safe}\) the maximum braking imposed to a vehicle during a cut-in, implemented as LANE_CHANGE_MAX_BRAKING_IMPOSED

It is implemented in the mobil() method.

Note

In the LinearVehicle class, the longitudinal and lateral behaviours are approximated as linear weightings of several features, such as the distance and speed difference to the leading vehicle.

API#

class highway_env.vehicle.behavior.IDMVehicle(road: Road, position: ndarray | Sequence[float], heading: float = 0, speed: float = 0, target_lane_index: int | None = None, target_speed: float | None = None, route: List[Tuple[str, str, int]] | None = None, enable_lane_change: bool = True, timer: float | None = None)[source]#

A vehicle using both a longitudinal and a lateral decision policies.

  • Longitudinal: the IDM model computes an acceleration given the preceding vehicle’s distance and speed.

  • Lateral: the MOBIL model decides when to change lane by maximizing the acceleration of nearby vehicles.

Parameters:
  • road – the road instance where the object is placed in

  • position – cartesian position of object in the surface

  • heading – the angle from positive direction of horizontal axis

  • speed – cartesian speed of object in the surface

ACC_MAX = 6.0#

Maximum acceleration.

COMFORT_ACC_MAX = 3.0#

Desired maximum acceleration.

COMFORT_ACC_MIN = -5.0#

Desired maximum deceleration.

DISTANCE_WANTED = 10.0#

Desired jam distance to the front vehicle.

TIME_WANTED = 1.5#

Desired time gap to the front vehicle.

DELTA = 4.0#

Exponent of the velocity term.

DELTA_RANGE = [3.5, 4.5]#

Range of delta when chosen randomly.

classmethod create_from(vehicle: ControlledVehicle) IDMVehicle[source]#

Create a new vehicle from an existing one.

The vehicle dynamics and target dynamics are copied, other properties are default.

Parameters:

vehicle – a vehicle

Returns:

a new vehicle at the same dynamical state

act(action: dict | str | None = None)[source]#

Execute an action.

For now, no action is supported because the vehicle takes all decisions of acceleration and lane changes on its own, based on the IDM and MOBIL models.

Parameters:

action – the action

step(dt: float)[source]#

Step the simulation.

Increases a timer used for decision policies, and step the vehicle dynamics.

Parameters:

dt – timestep

acceleration(ego_vehicle: ControlledVehicle, front_vehicle: Vehicle | None = None, rear_vehicle: Vehicle | None = None) float[source]#

Compute an acceleration command with the Intelligent Driver Model.

The acceleration is chosen so as to: - reach a target speed; - maintain a minimum safety distance (and safety time) w.r.t the front vehicle.

Parameters:
  • ego_vehicle – the vehicle whose desired acceleration is to be computed. It does not have to be an IDM vehicle, which is why this method is a class method. This allows an IDM vehicle to reason about other vehicles behaviors even though they may not IDMs.

  • front_vehicle – the vehicle preceding the ego-vehicle

  • rear_vehicle – the vehicle following the ego-vehicle

Returns:

the acceleration command for the ego-vehicle [m/s2]

desired_gap(ego_vehicle: Vehicle, front_vehicle: Vehicle | None = None, projected: bool = True) float[source]#

Compute the desired distance between a vehicle and its leading vehicle.

Parameters:
  • ego_vehicle – the vehicle being controlled

  • front_vehicle – its leading vehicle

  • projected – project 2D velocities in 1D space

Returns:

the desired distance between the two [m]

change_lane_policy() None[source]#

Decide when to change lane.

Based on: - frequency; - closeness of the target lane; - MOBIL model.

mobil(lane_index: Tuple[str, str, int]) bool[source]#

MOBIL lane change model: Minimizing Overall Braking Induced by a Lane change

The vehicle should change lane only if: - after changing it (and/or following vehicles) can accelerate more; - it doesn’t impose an unsafe braking on its new following vehicle.

Parameters:

lane_index – the candidate lane for the change

Returns:

whether the lane change should be performed

recover_from_stop(acceleration: float) float[source]#

If stopped on the wrong lane, try a reversing maneuver.

Parameters:

acceleration – desired acceleration from IDM

Returns:

suggested acceleration to recover from being stuck

target_speed: float#

Desired velocity.

class highway_env.vehicle.behavior.LinearVehicle(road: Road, position: ndarray | Sequence[float], heading: float = 0, speed: float = 0, target_lane_index: int | None = None, target_speed: float | None = None, route: List[Tuple[str, str, int]] | None = None, enable_lane_change: bool = True, timer: float | None = None, data: dict | None = None)[source]#

A Vehicle whose longitudinal and lateral controllers are linear with respect to parameters.

Parameters:
  • road – the road instance where the object is placed in

  • position – cartesian position of object in the surface

  • heading – the angle from positive direction of horizontal axis

  • speed – cartesian speed of object in the surface

TIME_WANTED = 2.5#

Desired time gap to the front vehicle.

act(action: dict | str | None = None)[source]#

Execute an action.

For now, no action is supported because the vehicle takes all decisions of acceleration and lane changes on its own, based on the IDM and MOBIL models.

Parameters:

action – the action

acceleration(ego_vehicle: ControlledVehicle, front_vehicle: Vehicle | None = None, rear_vehicle: Vehicle | None = None) float[source]#

Compute an acceleration command with a Linear Model.

The acceleration is chosen so as to: - reach a target speed; - reach the speed of the leading (resp following) vehicle, if it is lower (resp higher) than ego’s; - maintain a minimum safety distance w.r.t the leading vehicle.

Parameters:
  • ego_vehicle – the vehicle whose desired acceleration is to be computed. It does not have to be an Linear vehicle, which is why this method is a class method. This allows a Linear vehicle to reason about other vehicles behaviors even though they may not Linear.

  • front_vehicle – the vehicle preceding the ego-vehicle

  • rear_vehicle – the vehicle following the ego-vehicle

Returns:

the acceleration command for the ego-vehicle [m/s2]

steering_control(target_lane_index: Tuple[str, str, int]) float[source]#

Linear controller with respect to parameters.

Overrides the non-linear controller ControlledVehicle.steering_control()

Parameters:

target_lane_index – index of the lane to follow

Returns:

a steering wheel angle command [rad]

steering_features(target_lane_index: Tuple[str, str, int]) ndarray[source]#

A collection of features used to follow a lane

Parameters:

target_lane_index – index of the lane to follow

Returns:

a array of features

collect_data()[source]#

Store features and outputs for parameter regression.

target_speed: float#

Desired velocity.

class highway_env.vehicle.behavior.AggressiveVehicle(road: Road, position: ndarray | Sequence[float], heading: float = 0, speed: float = 0, target_lane_index: int | None = None, target_speed: float | None = None, route: List[Tuple[str, str, int]] | None = None, enable_lane_change: bool = True, timer: float | None = None, data: dict | None = None)[source]#
Parameters:
  • road – the road instance where the object is placed in

  • position – cartesian position of object in the surface

  • heading – the angle from positive direction of horizontal axis

  • speed – cartesian speed of object in the surface

target_speed: float#

Desired velocity.

class highway_env.vehicle.behavior.DefensiveVehicle(road: Road, position: ndarray | Sequence[float], heading: float = 0, speed: float = 0, target_lane_index: int | None = None, target_speed: float | None = None, route: List[Tuple[str, str, int]] | None = None, enable_lane_change: bool = True, timer: float | None = None, data: dict | None = None)[source]#
Parameters:
  • road – the road instance where the object is placed in

  • position – cartesian position of object in the surface

  • heading – the angle from positive direction of horizontal axis

  • speed – cartesian speed of object in the surface

target_speed: float#

Desired velocity.