10.6 Triggers
An ASAM OpenSCENARIO 1.2.0 trigger is mapped to the boolean expression that evaluates to the equivalent logical function as the original trigger. Such boolean expression can then be used to trigger new behavior in a few different ways:
-
Event object
-
Wait statement
-
Until modifier
The most direct conversion to this version of ASAM OpenSCENARIO is to create an event
which has a different meaning than an ASAM OpenSCENARIO 1.2.0 Event
).
In this case, the expression can be named and referred to from other parts of the scenario.
Conversion of an ASAM OpenSCENARIO 1.2.0 Event
is possible if the action that is triggered by it is instant, meaning a duration of 0 s simulation time.
This is how it looks using an event:
car1
is met, depending on the distance between car1
and the ego. car1: car
do:
car1.drive() with:
speed(50kph)
on car1.object_distance(ego, direction: longitudinal, mode: bounding_box) < 10 m:
call log_info("Too near.")
Within an event handler of this version of ASAM OpenSCENARIO (on ) only instant actions can be used.
|
If the motivation for defining an Event
in ASAM OpenSCENARIO 1.2.0 is primarily to compose a sequence of events, it can be easier formulated using a serial
operator combined with wait
or until
:
serial
operator and wait
serial:
wait car.object_distance(ego, direction: longitudinal, mode: bounding_box) < 10 m
car.drive() with:
speed(0kph, at:end)
serial
operator and until
serial:
car.drive() with:
speed(50kph)
until(car.object_distance(ego, direction: longitudinal, mode: bounding_box) < 10 m)
car.drive() with:
speed(0kph, at:end)
Here, as soon as the condition is met, we are free to use actions with non-zero duration.
10.6.1 Condition
Condition
has the following attributes:
-
name
-
delay
Can be mapped withwait
. -
conditionEdge
Can be mapped with the following constructs:-
rise
-
fall
-
10.6.1.1 ParameterCondition
ParameterCondition
works in conjunction with ParameterAction
and allows for checking of parameter values.
The same functionality can be achieved using the variable fields, like counter
.
actor my_car:
var counter: int = 0
on object_distance(ego, direction: longitudinal, mode: bounding_box) < 10 m:
call increment_counter()
do serial:
my_car.drive() with:
speed([40kph..60kph])
until(my_car.counter >= 3)
my_car.reach_speed(0kph)
In ASAM OpenSCENARIO 1.2.0 all runtime variables are of type string , but comparison and rules allow for comparison to a numeric value.
|
10.6.1.2 TimeOfDayCondition
environment.datetime >= environment.local_to_unix_time(year: 2021, month: 12, day: 17, hour: 18 minute: 59, second: 22)
Date and time in the scenario are greater than given local time.
In this version of ASAM OpenSCENARIO this condition can be used for a static check of the date and time.
Value of environment.datetime
is not updated during the scenario run, so it cannot trigger the dynamic behavior.
10.6.1.3 UserDefinedValueCondition
This condition allows for creating triggers based on values provided by the simulation environment.
Such values are accessible in this version of ASAM OpenSCENARIO using external
methods.
scenario dut.test_drive:
def external_value() -> float is external cpp("my_new_kpi.cpp")
serial:
wait external_value() > 4.0
drive() with:
speed(0kph, at:end)
10.6.1.4 StoryboardElementStateCondition
Scenarios and actions in this version of ASAM OpenSCENARIO provide the default .start
and .end
events.
StoryBoardElementStateCondition
can be mapped to the start
and end
events of an appropriate scenario.
Simple composition of scenario elements, especially when performed by the same actor, is more easily expressed with serial
and parallel
temporal operators.
scenario storyboard_element_state:
ego: car
car_1: car
car_2: car
do parallel:
ego.drive() with:
lane(left_of: car_1)
speed([40kph..80kph])
maneuver_group_1: car_1.drive() with:
position([30m..50m], ahead_of: ego)
lane(same_as: ego, at: end)
serial:
car_2.drive() until (@maneuver_group_1.end)
car_2.reach_speed(0kph)
10.6.2 ByEntityConditions
ByEntityCondition
defines a condition, which entities can trigger the evaluation of this condition as well as a TriggeringEntitiesRule
that specifies if all listed entities must fulfill the condition or whether just one entity is sufficient to fulfill the condition.
10.6.2.1 CollisionCondition
Condition that becomes true when an entity is in collision with the specified TriggeringEntities
.
var speed_on_crash: speed = 0
on ego.time_to_collision(car_1) == 0s or ego.time_to_collision(car_2) == 0s:
speed_on_crash = sample(ego.speed)
10.6.2.2 TimeHeadwayCondition
var low_headway: bool = false
do serial:
car_1.drive() with:
speed([80kph..100kph])
until(low_headway == true)
car_1.slow_down()
on car_1.time_headway(car_2) < 2s:
record(name: 'headway', expression: car_1.time_headway(car_2), unit: s, text: 'Low headway time')
call set_headway(true)
Emitted when time headway between car_1
and car_2
becomes less than 2 seconds.
Type of distance calculation for headway is the distance between the reference points.
10.6.2.3 TimeToCollisionCondition
do serial:
car_1.drive() with:
speed([80kph..120kph])
until car_1.time_to_collision(car_2) < 3s:
car_1.reach_speed(0kph)
Emitted when the time to collision (based on the current motion of entities) between car_1
and car_2
becomes less than 3 seconds.
The distance used for calculating the time to collision of the two vehicles is the distance between their bounding boxes (freespace
parameter).
10.6.2.4 AccelerationCondition
do serial(30s):
leading_vehicle.drive() with:
speed(0kph, at:start)
speed(200kph, at:end)
leading_vehicle.drive() with:
speed([120kph..150kph], at:end)
on leading_vehicle.acceleration.translational.norm() > 2mpsps:
record(leading_vehicle.speed,
unit: kph,
text: 'High acceleration at speed')
Emitted when the acceleration of leading_vehicle
vehicle becomes greater than 2 m/s^2.
10.6.2.5 SpeedCondition
do parallel:
serial:
car_1.drive() with:
speed([40kph..60kph])
lane(same_as: car_2)
until(car_2.speed < 30kph)
car_1.drive() with:
speed(30kph)
lane(1, left_of: car_2)
car_2.drive() with:
speed([25kph..50kph])
Emitted when the speed of car_2
becomes less than 30 kph.
10.6.2.6 RelativeSpeedCondition
def substract_velocity(v1: translational_velocity_3d, v2: translational_velocity_3d) -> translational_velocity_3d is expression translational_velocity_3d (x: v1.x - v2.x, y: v1.y - v2.y, z: v1.z - v2.z)
do parallel:
serial:
car_1.drive() with:
speed([40kph..60kph])
until(substract_velocity(car_1.velocity.translational, car_2.velocity.translational).norm() > 10kph)
car_1.drive() with:
speed(car_2.speed, at:end)
car_2.drive() with:
speed([25kph..50kph])
Emitted when the relative speed between car_1
and car_2
becomes larger than 10 kph.
10.6.2.7 ReachPositionCondition and DistanceCondition
scenario stop_near_point:
def substract_position(p1: position_3d, p2: position_3d) -> position_3d is expression position_3d(x: p1.x - p2.x, y: p1.y - p2.y, z: p1.z - p2.z)
car_1: vehicle
keep(car_1.vehicle_category == car)
pos_1: position_3d
do serial:
car_1.drive() with:
speed([40kph..60kph])
until(substract_position(car_1.pose.position, pos_1).norm() < 5m)
car_1.drive() with:
speed(0kph, at:end)
Both conditions can be converted in a similar manner:
-
DistanceCondition
Is more general and can expressgreater than
orequal
distance to the determined position. -
ReachPosition
Tolerance is interpreted asless than
.
10.6.2.8 RelativeDistanceCondition
scenario move_away:
car_1: car
car_2: car
do parallel:
serial:
car_1.drive() with:
speed([40kph..60kph])
lane(1, left_of: car_2)
until(ego.object_distance(car_2, mode: bounding_boxes, direction: lateral) < 1m)
car_1.drive() with:
lane(2, left_of: car_2)
serial(duration: 20s):
car_2.drive() with:
speed([-5, 10]kph, faster_than: car_1)
car_2.drive() with:
lateral(distance: 0.75m, right_of: car_1, measure_by: right_to_left, at:end)
car_2.drive() with:
lateral(distance: 0m, measure_by: center_to_center, at:end)
The lateral distance of car_1
to car_2
becomes less than 1 m, measured between bounding boxes (freespace
).
If Cartesian distance is required, a conversion similar to DistanceCondition
can be used.