Traffic lights modeling and control
Modeling
Terminology
Traffic-light box
A traffic-light box is defined as set of bulbs packed together in a single box. The examples of different traffic-light boxes are given below.
Logical traffic-light
A Logical traffic-light group is defined as one or more boxes in a junction where common bulbs, i.e., bulbs with the same icon and color, have the same state (on, off, or flashing) simultaneously. Two boxes that control the same direction, either by redundancy (i.e., having common bulbs) or by complementing each other (i.e., having different bulbs that together determine the required vehicle behavior), should be considered a single logical traffic-light.
In the above image:
- The two boxes that control the right turn, highlighted with pink ovals, should be considered a single logical traffic-light.
- The two boxes controlling the straight and left directions, highlighted with green ovals, should be considered a single logical traffic-light.
In the above image, the right turn is controlled by both the two-right-arrow box highlighted in red, and the three-iconless-bulbs box highlighted in blue (which also controls the straight direction), hence, these two boxes are considered as a part of the same logical traffic-light. In addition, the box highlighted in purple provide redundancy to the boxes highlighted in red and blue, so they too are part of the same logical traffic-light.
OSC representation
Bulb
A single bulb within a traffic-light box is represented by the struct msp_traffic_light_bulb. It has a color, an icon, and a map_id.
enum bulb_icon_kind: [
unknown,
none,
arrow_straight,
arrow_left,
arrow_slight_left,
arrow_right,
arrow_slight_right,
arrow_uturn,
pedestrian,
walk,
dont_walk,
bicycle,
countdown
]
enum bulb_color_kind: [
unknown,
red,
yellow,
green,
blue,
white
]
# Represents a single bulb
#
struct msp_traffic_light_bulb:
var map_id: string
var icon: bulb_icon_kind
var color: bulb_color_kind
The ‘map_id’ is the ID assigned to the bulb by the native map. It may be empty either if the native map does not assign such IDs or if they are not required by the SSP for simulation control.
Traffic-light box
A traffic-light box is represented by the struct msp_physical_traffic_light.
# Represents a physical traffic light box
#
struct msp_physical_traffic_light:
var internal_id: uint
var map_id: string
var bulbs: list of msp_traffic_light_bulb
var logical_tl: msp_traffic_light
internal_id: The index of this traffic-light box inlogical_tl.tl_boxes, which is unique per logical traffic-light (msp_traffic_light).map_id: The ID assigned to the traffic-light box by the native map. It may be empty either if the native map does not assign such IDs or if they are not required by SSP for simulation control. The simulation level of control (box granularity or logical-TL granularity) is determined by the configuration flagconfig.sim.tl_api_level.bulbs: List of bulbs in this traffic-light box.logical_tl- The logical traffic-light containing this physical box. It cannot be null; everymsp_physical_traffic_lightmust be associated with alogical_tl, even if it is the only single box in the logical traffic-light.
A traffic-light box is not associated with a state. The traffic-light state is managed at the logical traffic-light level. To control traffic-light boxes separately, they must be added to the map (by the MSP) as separate logical traffic lights. In this case, coordinating the identical states of boxes in the same logical traffic-light becomes the responsibility of the scenario writer. For example, given two identical boxes in a logical traffic-light, Foretify does not provide a way to control them separately (e.g., to model a malfunction where one box is broken).
Logical traffic-light
A logical traffic-light is represented by the struct msp_traffic_light.
# msp_traffic_signal is the base struct for traffic signals:
# dynamic - msp_traffic_light
# static - msp_traffic_sign
#
struct msp_traffic_signal:
# 'id' is unique within each subtype.
var id: uint
enum bulb_state_kind: [
unknown,
is_off,
is_on,
is_flashing
]
# A logical traffic-light, represents a set of physical traffic-light "boxes" (msp_physical_traffic_light).
# Its bulbs/state is a union of the bulbs of its member boxes.
#
struct msp_traffic_light inherits msp_traffic_signal:
var map_id: string
var bulbs: list of msp_traffic_light_bulb
var bulbs_state: list of bulb_state_kind
var tl_boxes: list of msp_physical_traffic_light
map_id: A unique map_id field over allmsp_traffic_lightinstances. This ID must be provided by the MSP.bulbs: A union of bulbs from all traffic-light boxes in this logical traffic-light.bulbs_state: Bulbs_state[i] is the current state of bulbs[i].tl_boxes: The traffic-light boxes that compose this logical traffic-light.
Accessing traffic-lights from a scenario
The top.map.traffic_lights is a list of all logical traffic-lights in the map.
extend map:
# All traffic lights in map. traffic_lights[n].id == n
#
var traffic_lights: list of msp_traffic_light
In a scenario traffic-lights may be obtained via two road_elements: road_with_traffic_light and internal_road.
road_with_traffic_light element
The road_with_traffic_light element represents a section of road before a traffic-light. The element ends at the stop line associated with the traffic-light and starts at a distance of up to map_config.road_with_sign_max_length (default is 100m) before the traffic light, or less if there is a junction at a shorter distance.
In the below image, the traffic-light stop lines are on the internal_roads, so for each junction entry, three overlaid road_with_traffic_light elements (colored pink) are visible, one for each turn direction (right, left, and straight).
If a traffic-light is associated with stop-lines at different road offsets (e.g., left turn stop-line is not at the same offset as straight direction stop-line controlled by the same traffic-light), then it will be correspondingly associated with multiple road_with_traffic_light instances.
Generally, a traffic-light controls a junction entry. However, in some cases, a traffic-light is located in the middle of a road, such as a traffic-light that protects a pedestrian crosswalk or a ramp metering light. A boolean field, road_with_traffic_light.controls_junction_entry, can be used to constrain this property.
internal_road element
The internal_road route_element represents an internal road inside a junction, connecting a junction's entry road (one_way_road road_element) to a junction's exit road (one_way_road road_element).
The internal_road has two fields that refer to the traffic light that controls it:
-
traffic_light_id: The ID of the controllingmsp_traffic_light(logical traffic light). It is -1 if the internal_road is not controlled by a traffic-light (a singlemsp_traffic_lightmay control multipleinternal_roads from the same in-road). -
road_with_traffic_light_id: The ID of theroad_with_traffic_lightroad_element corresponding to the traffic-light and stop line relevant to this internal_road. It is -1 if theinternal_roadis not controlled by a traffic light.
In the following scenario, the SUT and an NPC both drive on the same path through a traffic-light-controlled junction connection. The NPC stops with the front gap of 5 meters before the stop line (regardless of the traffic light state) and then continues driving.
import "$FTX/env/basic/exe_platforms/model_ssp/config/model_sumo_config.osc"
extend test_config:
set map = "$FTX_PACKAGES/maps/M510_FTX_TrafficSignals_Simple.xodr"
extend sim_config:
set tl_api_level = logical
extend top.main:
car1: vehicle
# traffic-light controlled path that crosses a junction
route_with_tl: roads_follow_in_junction_with_tl
# a path (longer than 5m plus sut-length) that ends at the stop line of the traffic light
path_to_stop_line: road_with_traffic_light with:
keep(it.length > sut.car.bbox.length + 5m)
keep(it.id == route_with_tl.internal_road.road_with_traffic_light_id)
do parallel(duration: [15..25]s, overlap: equal, run_mode: best_effort):
car1_drive: serial:
# stop with front of car 5 meters before the stop line
car1.drive() with:
along(path_to_stop_line, end_offset: 5m + sut.car.bbox.length / 2, at: end)
speed([0..2]kph, at: end)
# drive through the junction
car1.drive() with:
car1_dest: along(route_with_tl.out_road, at: end)
override(car1_dest, run_mode: best_effort) # may be limitted by SUT driving in front
car1_speed: speed(30kph, at: end)
override(car1_speed, run_mode: best_effort) # may be limitted by SUT driving in front
sut_drive: serial:
sut.car.drive() with:
along(route_with_tl.in_road, at: start)
sut_dest: along(route_with_tl.out_road, at: end)
override(sut_dest, run_mode: best_effort) # may be limitted by NPC driving in front
Traffic-light control
Foretify offers two types of TL control mechanisms:
- Actions: Predefined atomic declarative scenarios that are invoked from within a ‘do’ block.
- Methods: In the context of a scenario, methods can be invoked upon the triggering of events. For more information, see Native methods.
All the traffic-light control actions and methods control the state of an msp_traffic_light, i.e., a logical traffic-light. We offer control at three levels:
- Explicitly change the state of specific bulbs. For more information, see Controlling specific bulbs and Action traffic_light.set_light_bulb.
- Change the semantic state of the traffic-light for a given internal road.
- Change the semantic state of the traffic-light for all controlled driving directions.
Actor traffic_light
Actions that control the state of an msp_traffic_light are defined under the traffic_light actor. A traffic_light actor is not limited to controlling a single traffic-light; its actions take the ID of the controlled traffic-light as an argument (see examples in the subsections below).
Initial traffic-lights state
The initial state of all traffic lights is controlled by the configuration variable top.config.sim.default_tl_color of type enum traffic_lights_default_color.
# Defines options for setting the default color of all traffic-lights on simulation start
#
enum traffic_lights_default_color: [
none, # Traffic lights will start in their default state as defined by simulator
green, # All traffic lights will be initialized to a "green" state
red # All traffic lights will be initialized to a "red" state
]
- green: All green bulbs of all traffic-lights are turned on, while all other bulbs are turned off.
- red: All red bulbs of all traffic lights are turned on, while all other bulbs are turned off.
- none: Traffic lights will start in their default state as defined by the simulator.
The default value is green. It can be changed by the following ways:
- From the scenario:
extend sim_config:
set default_tl_color = red
- From the Foretify command line:
--set config.sim.default_tl_color=none
Controlling specific bulbs
Action traffic_light.set_light_bulb
Specific bulbs can be controlled via traffic_light.set_light_bulb action:
scenario traffic_light.set_light_bulb:
traffic_light_id: uint with:
bulb_color: bulb_color_kind with:
keep(it != unknown)
bulb_state: bulb_state_kind with:
keep(it != unknown)
bulb_kind: bulb_icon_kind with:
keep(default it == none)
# In case there are multiple bulbs of the same color and icon, the bulb_number can be used to specify which bulb to set
# numbering starts from 0 (the first bulb of the same color and icon)
#
bulb_number: uint with:
keep(default it == 0)
- traffic_light_id: The ID of the
msp_traffic_lightto change. - bulb_color: The color of the bulb to modify.
- bulb_kind: The icon of the bulb to modify (default is
none). - bulb_number: If there are multiple bulbs in the traffic-light with the same color and icon, they can be distinguished by this argument. Bulbs are expected to be ordered from top to bottom or from left to right for horizontal or vertical bulb formations. For example, in the “four left arrows box” (see ‘Traffic light box’ examples above), there are two yellow left-arrow bulbs.
- bulb_state: The requested state of the bulb identified by the other fields.
If the requested bulb (specified by
<bulb_color, bulb_number, bulb_state>) does not exist, the set request is not passed to the simulator.
We enhance the previous example by setting the traffic-light at the beginning of the scenario with the red bulb on and all other bulbs off (only the green bulb needs to be actively turned off because it is initially on due to the default initial state). Then, after the NPC stops, we turn the red bulb off and the green bulb on.
import "$FTX/env/basic/exe_platforms/model_ssp/config/model_sumo_config.osc"
extend test_config:
set map = "$FTX_PACKAGES/maps/M510_FTX_TrafficSignals_Simple.xodr"
extend sim_config:
set tl_api_level = logical
extend top.main:
tl: traffic_light
car1: vehicle
# traffic-light controlled path that crosses a junction
route_with_tl: roads_follow_in_junction_with_tl
# a path (longer than 5m plus sut-length) that ends at the stop line of the traffic light
path_to_stop_line: road_with_traffic_light with:
keep(it.length > sut.car.bbox.length + 5m)
keep(it.id == route_with_tl.internal_road.road_with_traffic_light_id)
do parallel(duration: [15..25]s, overlap: equal, run_mode: best_effort):
car1_drive: serial:
# start with red light
r1: tl.set_light_bulb(path_to_stop_line.traffic_light_id, red, is_on)
g1: tl.set_light_bulb(path_to_stop_line.traffic_light_id, green, is_off)
# stop with front of car 5 meters before the stop line
car1.drive() with:
along(path_to_stop_line, end_offset: 5m + sut.car.bbox.length / 2, at: end)
speed([0..2]kph, at: end)
# change the light to green
r2: tl.set_light_bulb(path_to_stop_line.traffic_light_id, red, is_off)
g2: tl.set_light_bulb(path_to_stop_line.traffic_light_id, green, is_on)
# drive through the junction
car1.drive() with:
car1_dest: along(route_with_tl.out_road, at: end)
override(car1_dest, run_mode: best_effort) # may be limitted by SUT driving in front
car1_speed: speed(30kph, at: end)
override(car1_speed, run_mode: best_effort) # may be limitted by SUT driving in front
sut_drive: serial:
sut.car.drive() with:
along(route_with_tl.in_road, at: start)
sut_dest: along(route_with_tl.out_road, at: end)
override(sut_dest, run_mode: best_effort) # may be limitted by NPC driving in front
Limitations
For now, we do not provide a way to constraint the bulb color and icon, so one cannot verify the existence of the bulb they are trying to set.
Controlling semantic state per internal_road
enum semantic_traffic_light_state enumerates the available semantic states of a traffic-light
Foretify introduces the following semantic states as values of enum semantic_traffic_light_state:
# Rules imposed on traffic obeying the signal at a given point in time, in a given direction (e.g., TL state can have
# different meaning for traffic going straight and traffic going left).
# There should ba a one-to-one correspondence between <physical traffic-light state, controlled driving direction> to semantic state.
#
enum semantic_traffic_light_state: [
off, # Traffic light is turned off - state of all bulbs is 'is_off'.
stop, # Stop motion - typically red light.
stop_and_yield, # Stop and then yield to other traffic. For example, in US right turn in red light.
stop_constant, # A constant traffic light state that indicates the vehicle must stop and
# then yield to other traffic.
# E.g., in US a flashing red light.
attention, # Traffic signal is going to change to go
caution, # Vehicles obeying traffic rules may pass the signal.
# During this, you must yield to other traffic.
# This typically corresponds to a yellow light.
stop_attention, # Traffic signal is about to change to stop.
go, # Obeying traffic is allowed to drive but may need to yield to other traffic, typically green light.
go_exclusive, # Vehicles obeying traffic rules have exclusive right of way.
# All other crossing traffic participants are in a stop state.
# This typically corresponds to a green light.
non_functional, # Non-functional traffic-light. Can be used when a traffic-light is in an unrecognizable state
#(for example, when red and green lights are on together).
unknown, # Unknown state
unsupported # Traffic lights are not supported.
# This value cannot be used to set the state of a traffic light,
# but it can be used to retrieve the current state.
]
At a given time, the semantics of a traffic-light may differ for the various turn directions it controls.
Examples:
-
In the United States, a lit green icon-less bulb means
go_exclusive(protected) for straight and right directions. However, for left turns, it often means cars can go but without protection, meaning they must yield to oncoming traffic. Some states make an exception for left turns from or onto a one-way street, where the turn is protected. -
Similarly, in the US, a lit red icon-less bulb means ‘stop’ for left and straight drives, but in some states, it may mean ‘stop_constant’ for right turns (i.e., stop, and if there is no conflicting traffic, then go).
Map method ‘update_internal_road_tl_state()’
To control the semantic state of a traffic-light for a given turn direction, Foretify provides the map method update_internal_road_tl_state():
extend map:
# update the state of the traffic-light that controlls the given internal road according to the given semantic
# state in the turn-direction of the internal_road.
#
def update_internal_road_tl_state(internal_road: internal_road, state: semantic_traffic_light_state)-> bool
The valid semantic states of an internal_road
Since not all semantic_traffic_light_state values are applicable to all internal roads (e.g., go_exclusive may not be applicable to a left turn controlled by a standard traffic-light with three icon-less bulbs), Foretify introduces a set of Boolean fields to the internal_road road_element that provides this information:
# internal_road represents a junction-internal road connecting one inbound road to one outbound road.
#
struct internal_road inherits road_element:
...
...
...
# flag to indicate if 'stop' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_stop: bool
# flag to indicate if 'stop_and_yield' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_stop_and_yield: bool
# flag to indicate if 'stop_constant' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_stop_constant: bool
# flag to indicate if 'attention' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_attention: bool
# flag to indicate if 'caution' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_caution: bool
# flag to indicate if 'stop_attention' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_stop_attention: bool
# flag to indicate if 'go' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_go: bool
# flag to indicate if 'go_exclusive' is a valid semantic state for the traffic-light controlling this internal road
#
valid_tl_go_exclusive: bool
Note
For an internal_road that is not controlled by a traffic-light, all the above fields are ‘false’.
Implement the same scenario from the previous examples by controlling the traffic-lights using the map method update_internal_road_tl_state():
import "$FTX/env/basic/exe_platforms/model_ssp/config/model_sumo_config.osc"
extend test_config:
set map = "$FTX_PACKAGES/maps/M510_FTX_TrafficSignals_Simple.xodr"
extend sim_config:
set tl_api_level = logical
extend top.main:
car1: vehicle
# traffic-light controlled path that crosses a junction
route_with_tl: roads_follow_in_junction_with_tl with:
keep(it.internal_road.can_be_protected == true)
stop_state: semantic_traffic_light_state with:
keep((route_with_tl.internal_road.valid_tl_stop_constant and it == stop_constant) or
(route_with_tl.internal_road.valid_tl_stop and it == stop))
event tl1
# on tl1 update the traffic-light state for the internal road to stop_state (stop or stop_constant for right turn)
on @tl1:
var res := map.update_internal_road_tl_state(route_with_tl.internal_road, stop_state)
event tl2
# on tl2 update the traffic-light state for the internal road to go_exclusive
on @tl2:
var res := map.update_internal_road_tl_state(route_with_tl.internal_road, go_exclusive)
# a path (longer than 5m plus sut-length) that ends at the stop line of the traffic light
path_to_stop_line: road_with_traffic_light with:
keep(it.length > sut.car.bbox.length + 5m)
keep(it.id == route_with_tl.internal_road.road_with_traffic_light_id)
do parallel(duration: [15..25]s, overlap: equal, run_mode: best_effort):
car1_drive: serial:
# start with red light
emit tl1
# stop with front of car 5 meters before the stop line
car1.drive() with:
along(path_to_stop_line, end_offset: 5m + sut.car.bbox.length / 2, at: end)
speed([0..2]kph, at: end)
# change the light to green
emit tl2
# drive through the junction
car1.drive() with:
car1_dest: along(route_with_tl.out_road, at: end)
override(car1_dest, run_mode: best_effort) # may be limitted by SUT driving in front
car1_speed: speed(30kph, at: end)
override(car1_speed, run_mode: best_effort) # may be limitted by SUT driving in front
sut_drive: serial:
sut.car.drive() with:
along(route_with_tl.in_road, at: start)
sut_dest: along(route_with_tl.out_road, at: end)
override(sut_dest, run_mode: best_effort) # may be limitted by NPC driving in front
Mapping semantic to physical state
Currently, Foretify supports a single configuration that implements US California rules of the road. For more information, see Section 7: Laws and Rules of the Road - California DMV.
- off: All bulbs are turned off.
- unknown: All bulbs are set to an unknown bulb state.
- non_functional: All bulbs are flashing (if there is a single red bulb, it is turned off).
- stop: Turn the red light on, with priority given to the arrow bulb in the internal_road’s turn direction.
- stop_constant: Turn the red light to flashing, with priority given to the arrow bulb in the internal_road’s turn direction.
- attention: Not applicable.
- caution: The yellow icon-less bulb is flashing.
- stop_attention: Turn the yellow bulb on, with priority given to the arrow bulb in the internal_road’s turn direction.
- go_exclusive (protected): Turn the green bulb on, with priority given to the arrow bulb in the internal_road’s turn direction. (Note: "go_exclusive" is not applicable for left turns/U-turns if there is no green arrow bulb.)
- go (unprotected): Turn the green bulb on, with priority given to the arrow bulb in the internal_road’s turn direction. (Note: "go" is not applicable to straight and right turn directions.)
General information
- General:
- When turning an arrow bulb on/flashing, all other arrow bulbs in the same direction are turned off.
- When turning an icon-less bulb on/flashing, all other icon-less bulbs are turned off, and all arrow bulbs in the internal_road’s turn direction are turned off.
Map method 'get_internal_road_tl_state()'
A method to get the semantic state of a traffic-light associated with a specific internal_road:
extend map:
# get the semantic-state of the traffic-light that controls the given internal_road, for the turn-direction of the
# internal_road. If the internal_road is not controlled by a traffic-light, the function returns 'unknown'.
#
def get_internal_road_tl_state(internal_road: internal_road)-> semantic_traffic_light_state
Mapping physical to semantic state
Currently, we support a single configuration that implements US California rules of the road. For more information see, Section 7: Laws and Rules of the Road.
- If there are multiple lit (on or flashing) arrows in the internal_road’s direction, the state is non-functional.
- If there are multiple lit (on or flashing) icon-less bulbs, the state is non-functional.
- If the traffic-light has lit (on or flashing) arrow bulbs in the internal_road’s turn direction, they determine the semantics:
- steady red: stop
- flashing red: stop_constant
- steady yellow: stop_attention
- flashing yellow: go (unprotected)
- steady green: go_exclusive (protected)
- unknown: unknown
- If no arrow bulbs are lit, then the semantic is determined by the lit icon-less bulbs:
- steady red: stop
- flashing red: stop_constant
- steady yellow: stop_attention
- flashing yellow: caution
- steady green:
- For left and U-turn: go (unprotected)
- For straight and right: go_exclusive (protected)
- unknown: unknown
Any physical state not mentioned above is considered non-functional.
Relation between ‘update_internal_road_tl_state()’ and 'get_internal_road_tl_state()'
Given an internal_road occurrence IR and a semantic_traffic_light_state SS, we expect that after a successful call to update_internal_road_tl_state(IR, SS) (return value == true), a subsequent call to get_internal_road_tl_state(IR) will return SS. The traffic-light state change following a call to update_internal_road_tl_state takes effect in the time/simulation step.
Controlling semantic state for all controlled directions
Map method 'set_tl_direction_agnostic_state()'
Foretify introduces the following semantic states that apply to all directions controlled by a single logical traffic light at any given time:
# Allowed logical types to be set for a traffic-light, for all controlled roads/directions at once
#
enum direction_agnostic_tl_state: [
all_stop, # all red bulbs are turned on, and all other bulbs off
all_prepare_to_stop, # all yellow bulbs for which 'on' state is valid are turned on, and all other bulbs off
all_caution, # all yellow bulbs for which 'flashing' state is valid are set to flash, and all other bulbs off
all_go, # all green bulbs are turned on, and all other bulbs off
all_off # all bulbs are off
]
The map method set_tl_direction_agnostic_state() modifies the state of an msp_traffic_light to one of these states:
extend map:
# set the bulbs state of the attached traffic-light according to the given direction-agnostic state.
#
def set_tl_direction_agnostic_state(traffic_light_id: uint, logical_state: direction_agnostic_tl_state)
This example is yet another variant of the previous ones this time using map.set_tl_direction_agnostic_state() to control the traffic light:
import "$FTX/env/basic/exe_platforms/model_ssp/config/model_sumo_config.osc"
extend test_config:
set map = "$FTX_PACKAGES/maps/M510_FTX_TrafficSignals_Simple.xodr"
extend sim_config:
set tl_api_level = logical
extend top.main:
car1: vehicle
# traffic-light controlled path that crosses a junction
route_with_tl: roads_follow_in_junction_with_tl
# a path (longer than 5m plus sut-length) that ends at the stop line of the traffic light
path_to_stop_line: road_with_traffic_light with:
keep(it.length > sut.car.bbox.length + 5m)
keep(it.id == route_with_tl.internal_road.road_with_traffic_light_id)
event tl1
# on tl1 update the traffic-light state to all_stop (all red lights on, all other lights off)
on @tl1: map.set_tl_direction_agnostic_state(path_to_stop_line.traffic_light_id, all_stop)
event tl2
# on tl2 update the traffic-light state to all_go (all green lights on, all other lights off)
on @tl2: map.set_tl_direction_agnostic_state(path_to_stop_line.traffic_light_id, all_go)
do parallel(duration: [15..25]s, overlap: equal, run_mode: best_effort):
car1_drive: serial:
# start with red light
emit tl1
# stop with front of car 5 meters before the stop line
car1.drive() with:
along(path_to_stop_line, end_offset: 5m + sut.car.bbox.length / 2, at: end)
speed([0..2]kph, at: end)
# change the light to green
emit tl2
# drive through the junction
car1.drive() with:
car1_dest: along(route_with_tl.out_road, at: end)
override(car1_dest, run_mode: best_effort) # may be limitted by SUT driving in front
car1_speed: speed(30kph, at: end)
override(car1_speed, run_mode: best_effort) # may be limitted by SUT driving in front
sut_drive: serial:
sut.car.drive() with:
along(route_with_tl.in_road, at: start)
sut_dest: along(route_with_tl.out_road, at: end)
override(sut_dest, run_mode: best_effort) # may be limitted by NPC driving in front
Action traffic_light.set_light_state
The action traffic_light.set_light_state uses enum logical_traffic_light_state to modify the direction-agnostic semantic of an msp_traffic_light.
# Allowed logical types to be set for a traffic-light
# *** Deprecated, use direction_agnostic_tl_state instead
#
enum logical_traffic_light_state: [red, yellow, green]
- red: All red bulbs are turned on, and all other bulbs off.
- yellow: All yellow bulbs are turned on, and all other bulbs off.
- green: All green bulbs are turned on, and all other bulbs off.
# Will set the bulbs state of the attached traffic_light according to the given logical state
# *** Deprecated, use map.set_tl_direction_agnostic_state instead
#
scenario traffic_light.set_light_state:
properties(self, task: true)
traffic_light_id: uint with:
properties(it, positional: true)
logical_state: logical_traffic_light_state with:
properties(it, positional: true)
This example is another variant of the previous one, and includes controlling the msp_traffic_light with traffic_light.set_light_state action.
import "$FTX/env/basic/exe_platforms/model_ssp/config/model_sumo_config.osc"
extend test_config:
set map = "$FTX_PACKAGES/maps/M510_FTX_TrafficSignals_Simple.xodr"
extend sim_config:
set tl_api_level = logical
extend top.main:
tl: traffic_light
car1: vehicle
# traffic-light controlled path that crosses a junction
route_with_tl: roads_follow_in_junction_with_tl
# a path (longer than 5m plus sut-length) that ends at the stop line of the traffic light
path_to_stop_line: road_with_traffic_light with:
keep(it.length > sut.car.bbox.length + 5m)
keep(it.id == route_with_tl.internal_road.road_with_traffic_light_id)
do parallel(duration: [15..25]s, overlap: equal, run_mode: best_effort):
car1_drive: serial:
# start with red light
tl.set_light_state(path_to_stop_line.traffic_light_id, red)
# stop with front of car 5 meters before the stop line
car1.drive() with:
along(path_to_stop_line, end_offset: 5m + sut.car.bbox.length / 2, at: end)
speed([0..2]kph, at: end)
# change the light to green
tl.set_light_state(path_to_stop_line.traffic_light_id, green)
# drive through the junction
car1.drive() with:
car1_dest: along(route_with_tl.out_road, at: end)
override(car1_dest, run_mode: best_effort) # may be limitted by SUT driving in front
car1_speed: speed(30kph, at: end)
override(car1_speed, run_mode: best_effort) # may be limitted by SUT driving in front
sut_drive: serial:
sut.car.drive() with:
along(route_with_tl.in_road, at: start)
sut_dest: along(route_with_tl.out_road, at: end)
override(sut_dest, run_mode: best_effort) # may be limitted by NPC driving in front
Map method 'get_active_lights_colors_for_internal_road()'
A method to get the list of active (on or flashing) bulb colors of a traffic-light associated with a specific internal_road:
extend map:
# Returns the list of active (on or flashing) bulb colors of a traffic-light associated with a specific internal_road
#
def get_active_lights_colors_for_internal_road(internal_road: internal_road)-> list of bulb_color_kind





