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 thanorequaldistance 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.