Main Content

Generate Scenario Variants for Testing AEB Pedestrian Systems

This example shows how to generate variants of a car-to-pedestrian collision scenario that you can use for testing automated emergency braking (AEB) systems. In this example, you generate variants of a European New Car Assessment Programme (Euro NCAP®) Car-to-Pedestrian Turning Adult (CPTA) Nearside Turn collision scenario by modifying the collision point, the speed, and the dimensions of the actors in the scenario. The collision point is position on the ego vehicle at which the ego vehicle and target actor collide. This example assumes that the ego vehicle and the target actor always collide at 90 degrees to one another, and that the target actor collides with a point on the front edge of the ego vehicle.

  • If the ego vehicle collides with a target actor multiple times, this example generates scenario variants based on only the first collision instance.

  • If the ego vehicle collides with multiple target actors at different times in a scenario, this example generates scenario variants for only one target actor. You can specify which target actor to consider for generating the scenario variants.

This example uses drivingScenario object to create a seed scenario and provides helper functions to generate the variants from the seed scenario. The rest of the example demonstrates the steps involved in generating the scenario variants.

Generate Seed Scenario - Create a collision scenario by using the helperCreateNCAPScenario helper function. The helper function generates the CPTA Nearside Turn test scenario of the Euro NCAP test protocol. A scenario can contain any number of actors and collision instances. This example generates a variant based on the first collision instance that occurs between the vehicle and the specified actor.

Generate Variant of Seed Scenario - Modify the seed scenario by using the HelperScenarioVariant helper function. This helper functions enable you to generate variants of the seed scenario by altering the dimensions of the actors in the scenario, the collision point, or the speed of the ego actor. The collision point specifies the relative position on the front edge of the ego vehicle that first collides with the left corner (Txl,Tyl) on the front edge of the target actor. The collision point (CP) (Txl,Tyl) equation:

CP=|Exl-Txl|+|Eyl-Tyl|Egowidth

The value of the collision point must be in the range [0, 1]. Use createCollisionVariant object function of the HelperScenarioVariant object to add a collision event to the generated scenario variants. You can either specify a new collision point for the variant or fix the collision point as the same as that of the seed scenario.

Simulate and Visualize Scenario Variants - Simulate and display the generated scenario variants by using the plot function.

Generate Seed Scenario

Create a drivingScenario object of the CPTA Nearside Turn Euro NCAP seed scenario by using the helperCreateNCAPScenario helper function. The function sets the actor dimensions, positions, speed values, and trajectories as per the Euro NCAP test protocol standards. The scenario contains an ego vehicle and an actor. The target actor is a pedestrian, which is the moving target that collides with the ego vehicle. The collision occurs only once during the simulation time.

seedScenario = helperCreateNCAPScenario("CPTANearsideTurn");

Create Object to Store Variant Parameters

Extract information about the seed scenario by using the getScenarioDescriptor function. The getScenarioDescriptor function creates a ScenarioDescriptor object that stores information about the actors in the seed scenario, their trajectories, and the collision event. However, the properties of the ScenarioDescriptor object are hidden.

seedScenarioDescriptor = getScenarioDescriptor(seedScenario,Simulator="DrivingScenario");

The HelperScenarioVariant object has these properties:

  • ScenarioData — Contains information about the seed scenario, as a structure. The information includes details about the roads, junctions, actors, and actor trajectories.

  • VariantGenerator — Stores the parameters of the generated scenario variant.

  • MethodForVariations — Modification method to use for adjusting the collision time in the generated scenario variant. The default value is "WaitTime", which maintains the collision time of the seed scenario by making the actor which would arrive at the collision point first, to wait at its first waypoint for a particular amount of time. For example, if the new ego speed value would cause the ego vehicle to arrive at the collision point ahead of the target actor, then the generated variant makes the ego vehicle wait at its first waypoint. However, if the target actor would arrive at the collision point ahead of the ego vehicle, the generated variant makes the target actor wait at its first waypoint.

  • ValidScenarioFlag which checks for the compatibility among the defined inputs for start position, speed, yaw and waypoints.

scenarioVariantParameter = HelperScenarioVariant(seedScenarioDescriptor)
scenarioVariantParameter = 
  HelperScenarioVariant with properties:

           ScenarioData: [1×1 struct]
       VariantGenerator: []
    MethodForVariations: "WaitTime"
          ValidScenario: []

Modify Actor Dimension and Speed

Specify the ActorID values of the ego vehicle and the target actor for which you want to modify parameters. You can find the ActorID values and the names of the ego vehicle and the target actor by inspecting the Actors property of the drivingScenario object.

egoID = 1;
targetID = 2;
table([seedScenario.Actors.ActorID],[seedScenario.Actors.Name],VariableNames={'ActorID','Name'})
ans=1×2 table
    ActorID                Name            
    _______    ____________________________

    1    2     "Ego"    "Target Pedestrian"

Use the addDimensionVariation, addSpeedVariation and addMultiVariation object functions of the HelperScenarioVariant object to specify the actor parameters required to generate the scenario variant.

  • To generate a scenario variant with new actor dimensions, use the addDimensionVariation function. You can use this function to specify new dimension values for one or more actors in the scenario.

  • To generate a scenario variant with new actor speed values, use the addSpeedVariation function. You can use this function to specify new speed values for one or more actors in the scenario.

  • To generate a scenario variant with both new speed and dimension values, use the addMultiVariation function. You can use this function to specify new speed and dimension values for one or more actors in the scenario.

Define the parameters for generating four scenario variants by modifying the speed, dimension, or both of one or more actors in the seed scenario.

1) Create a scenario variant by specifying new ego vehicle speed

Specify the new speed value for the ego vehicle in meters per second. Use the addSpeedVariation method to store the new speed values to the HelperScenarioVariation object scenarioVariantParameter.

newEgoSpeed = 5;
addSpeedVariation(scenarioVariantParameter,egoID,struct('egoSpeed',newEgoSpeed));

2) Create a scenario variant by specifying new ego vehicle dimensions

Specify the new dimension values for the ego vehicle as a structure. The unit for the dimension is in meters.

egoDimensions = struct(Length=2,Height=3);

Store the new ego dimension values to the HelperScenarioVariation object scenarioVariantParameter by using the addDimensionVariation object function.

addDimensionVariation(scenarioVariantParameter,egoID,struct('egoDimension',egoDimensions));

3) Create a scenario variant by specifying new ego vehicle and target actor dimensions

Specify the new dimension value for the ego and the target vehicle as a structure. The unit for the dimension is in meters.

egoDimensions = struct(Length=2,Height=3);
targetDimensions = struct(Length=1.5,Width=1,Height=1.8);

Store the new dimension values to the HelperScenarioVariation object scenarioVariantParameter by using the addMultiVariation method.

addActorMultiVariation(scenarioVariantParameter,[egoID,targetID],...
    Dimension=struct('egoDimension',egoDimensions,'targetDimension',targetDimensions));

4) Create a scenario variant by specifying new ego vehicle dimensions, speed and trajectory

Specify the new dimension for the ego vehicle as a structure. The unit for dimensions are in meters.

egoDimensions = struct(Length=2,Height=3);

Specify the new speed value for the ego vehicle in meters per second.

newEgoSpeed = 35;

If the trajectory of the ego vehicle is a curved path, the radius of curvature of the trajectory can also be varied depending on the speed of the ego vehicle. The radius of curvature of the ego trajectory increases for higher speed values and decreases for lower speed values. Use the 'helperGenerateTrajectoryatTurn' function to modify the radius of curvature of an actors' trajectory. The method returns a set of wayPoints and yaw values required to generate the necessary trajectory.

[newWaypoints, newYaw] = helperGenerateTrajectoryatTurn(seedScenarioDescriptor, egoID, newEgoSpeed);

Store the new dimension, speed, wayPoints and yaw values to the HelperScenarioVariation object scenarioVariantParameter by using the addMultiVariation function.

addActorMultiVariation(scenarioVariantParameter,egoID,Dimension=struct('egoDimension',egoDimensions),...
    Speed = struct('egoSpeed',ones(size(newWaypoints, 1), 1)*newEgoSpeed),Waypoints = struct('Waypoints',newWaypoints), Yaw = struct('Yaw',newYaw));

Define the collision properties to add to the scenario variants by using the helper function 'getCollisionData' and 'createCollisionVariant'

Extract the collision properties from the seed scenario using the 'getCollisionData' feature into. Specify the ego and target IDs to only get details of collision between the specified pair.

collisionsInScenario = getCollisionData(seedScenarioDescriptor, Actor1ID=egoID, Actor2ID=targetID)
collisionsInScenario = struct with fields:
     Actor1ID: 1
     Actor2ID: 2
    Collision: [1×1 variantgenerator.internal.Collision]

Use the extracted collision details in 'collisionsInScenario' to recreate similar collision in variants. 'createCollisionVariant' accepts a collision object, that stores all the information related to the collision in the seed scenario.

createCollisionVariant(scenarioVariantParameter, collisionsInScenario.Collision, Actor1CollisionFraction=0.5, Actor2CollisionFraction=0);

Alternatively, you can use the 'createCollisionVariant' object function to modify the collision point. In that case, you must specify the new collision point value to the 'createCollisionVariant' function by using this syntax, where value is the relative position of the collision point on the actor.

createCollisionVariant(scenarioVariantParameter,CollisionObj, Actor1CollisionFraction=value);

For example, to specify the new collision point value of 0.3, the syntax must be,

createCollisionVariant(scenarioVariantParameter,CollisionObj, Actor1CollisionFraction=0.3);

Generate the scenario variants by using the generateVariants helper function.

The generateVariants function generates the scenario variants and stores them as ScenarioDescriptor objects. The generateVariants function outputs a cell array of ScenarioDescriptor objects. The ScenarioDescriptor object in each cell contains the parameters for a scenario variant.

scenarioVariantDescriptors = generateVariants(scenarioVariantParameter)
scenarioVariantDescriptors=1×4 object
  1×4 ScenarioDescriptor array with properties:

    status

Convert the ScenarioDescriptor object to a drivingScenario object by using the getScenario function.

numVariants=size(scenarioVariantDescriptors,2);
variantScenario = repelem(drivingScenario,numVariants);
for iter = 1:numVariants
    variantScenario(iter) = getScenario(scenarioVariantDescriptors(iter),Simulator="DrivingScenario");
end

Visualize the Seed scenario and the Generated Scenario variants.

variationTitle is a list of titles that depict the variant being generated. These tiles will be added to the respective plot while visualizing the variations.

variationTitle=["Scenario Variant 1: Change Ego Speed";
    "Scenario Variant 2: Change Ego Vehicle Dimension";
    "Scenario Variant 3: Change Ego and Target Actor dimensions";
    "Scenario Variant 4: Change Ego Speed, Trajectory and Dimension"];

Plot the seed scenario and the generated variants by using helperVisualizeVariants. You can notice the variations in the speed values of the ego vehicle and the dimensions of the actor. Also, the collision point remains the same as that in the seed scenario for all the generated scenario variants.

helperVisualizeVariants(seedScenario,variantScenario(1:length(variantScenario)),...
    FigureTitle="Generated Scenario Variants",...
    GridPlotTitles=variationTitle,Mode="StandardFit",Row=2,Column=3,SimulationStepTime=0,...
    Legend="off",Waypoints="on",ActorIndicators=targetID);

Export Generated Scenario Variants to ASAM OpenSCENARIO Format

To export the generated scenario variants to the ASAM OpenSCENARIO® file format, use the export function of the drivingScenario object. The function writes the files to the current working directory.

Specify the filenames to export each of the generated scenario variants.

fileName = ["VariantEgoSpeed"; "VariantEgoDimension"; "VariantActorDimensions"; "VariantEgoSpeedandDimension"];

Use the getScenario function to create a drivingScenario object from a ScenarioDescriptor object. Every iteration of the loop creates a variant scenario using the variant ScenarioDescriptor object and further exports the scenario object to an OpenSCENARIO file.

for i = 1:size(variantScenario,2)
    export(variantScenario(i),"OpenSCENARIO",strcat(fileName(i),".xosc"));
end

Further Exploration

You can also use the procedure in this example to generate variants of a custom seed scenario. If you want to generate variants of a custom seed scenario, you must ensure that the input scenario is stored as a drivingScenario object and verify that a collision event occurs in the input scenario. Use the helperCheckScenario helper function to check if your seed scenario meets the these requirements.

  • The ego vehicle and a desired target actor in the scenario collide.

  • The actors have at least three waypoints along their trajectories.

  • The actors travel at a constant speed.

Create a ScenarioDescriptor object to extract scenario information from the custom seed scenario. Then, use the helperCheckScenario helper function to validate the seed scenario. The function returns a value of 1 if the seed scenario is a valid scenario. Otherwise, it returns 0.

seedScenarioDes = getScenarioDescriptor(seedScenario,Simulator="DrivingScenario");

scenarioCheckPassed = helperCheckScenario(egoID,targetID,seedScenarioDes);

If helperCheckScenario returns a 0, you can modify the seed scenario to create a valid scenario by using the helperSetScenarioCollision helper function.

if ~scenarioCheckPassed

seedScenarioDescriptor = helperSetScenarioCollision(egoID,targetID,seedScenarioDes,method="WaitTime");

end

The helperSetScenarioCollision function modifies the scenario according to the these rules:

  • If the ego vehicle or target actor has only two waypoints, the helperSetScenarioCollision function adds the third waypoint at the midpoint between them, and sets its speed value to that of the preceding waypoint.

  • If the ego vehicle or target actor does not travel with a constant speed starting from the first waypoint, the helperSetScenarioCollision function sets their speed values to a constant value of 80 kmph and 10 kmph, respectively.

  • If the ego vehicle and the target actor do not collide, but have intersecting trajectories, helperSetScenarioCollision checks if a collision is possible by modifying the wait time of the target actor. If possible, the function modifies the wait time of the target vehicle to create a collision event. Otherwise, the function returns an error.

Once you have a validated seed scenario, you can specify it as input to this example and generate variants of the custom seed scenario by modifying the actor and the event parameters.

You can also use the createCollisionVariant function to modify the collision point in different ways. You can use the following name-value pairs to create custom collisions:

  • Actor1CollisionFraction — To fix collision point on Actor1

  • Actor2CollisionFraction — To fix collision point on Actor2

  • VariationType — To fix the parameter that should be changed to create the variation. Possible inputs are 'WaitTime', 'EntryTime' and 'WayPoints'

For example, if the new actor1 collision point value is 0.8, and we want to change the actor wayPoints to achieve the desired variation, the syntax must be,

createCollisionVariant(scenarioVariantParameter,CollisionObj,Actor1CollisionFraction=0.8,VariationType="WayPoints");

Note that when variation type is set to 'WayPoints', make sure that ego and target vehicle are starting on a straight road. WayPoint variation changes the starting position of the ego or the target and keeps collision consistent by pushing back one of the actors in a straight line.

References

[1] European New Car Assessment Programme (Euro NCAP). Test Protocol – AEB VRU systems. Version 3.0.4. EuroNCAP, April 2021. Available from: https://cdn.euroncap.com/media/62795/euro-ncap-aeb-vru-test-protocol-v304.pdf.

See Also

Functions

Related Topics