# 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 will generate variants of a `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 a 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, and 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 the `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 European New Car Assessment Programme (Euro NCAP) test protocol as the seed scenario. A scenario can contain any number of actors and collision instances. However, this example generates a variant based on only the first collision instance that occurs between the Ego vehicle and the specified Target actor.

Generate Variant of Seed Scenario - Modify the seed scenario by using the helper functions H`elperScenarioVariant`, `HelperActorVariation`, and `HelperEventVariation`. These helper functions enable you to generate variants of the seed scenario by altering the dimensions of the actors in the scenario, the collision point, and the speed of the ego actor. Use the `HelperActorVariation` object and its methods for specifying actor variation parameters such as the speed and the dimension.` `Use the `HelperEventVariation` object and its method for specifying the event variation parameters such as the collision point and radius of curvature of ego trajectory at turns. The collision point specifies the relative position on the front edge of the ego vehicle that collides first with the left corner $\left({\mathit{T}}_{\mathrm{xl}},{\mathit{T}}_{\mathrm{yl}}\right)$ on the front edge of the target actor. The collision point (CP) and $\left({\mathit{T}}_{\mathrm{xl}},{\mathit{T}}_{\mathrm{yl}}\right)$ is related by the equation,

`$\mathrm{CP}=\text{\hspace{0.17em}}\frac{|{\mathit{E}}_{\mathrm{xl}}-{\mathit{T}}_{\mathrm{xl}}|+|{\mathit{E}}_{\mathrm{yl}}-{\mathit{T}}_{\mathrm{yl}}|}{\mathit{Ego}\text{\hspace{0.17em}}\mathit{width}}$`

The value of collision point must be in the range $\left(0,1\right)$. Use the `addCollision` method of the `HelperEventVariation` object to add collision event to the generated scenario variants. You can either specify a new collision point or fix the collision point as 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

Generate the CPTA Nearside turn Euro NCAP scenario by using the helper function `helperCreateNCAPScenario`. The actor dimensions, positions, speed values, and trajectories are set as per the Euro NCAP test protocol requirements. The scenario has an ego vehicle and an actor. The 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

Extact 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. To extract the scenario data from the `scenarioDescriptor` object, use the `HelperScenarioVariant` function.

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

The `HelperScenarioVariant` function generates an object with the following properties:

• ScenarioData: A structure containing information about the seed scenario. The information includes details about the roads, junctions, actors, and their trajectories.

• VariantGenerator: This property is set by the helper function `generateVariants`. It stores the parameters of the generated scenario variant.

• ActorVariation: This property is set by the helper function `HelperActorVariation`. It stores the new actor parameters defined for generating the variation of the seed scenario. The actor parameters are the dimensions and speed of the ego and the target vehicles in the seed scenario.

• EventVariation: This property is set by the helper function `HelperEventVariation`. It stores the new event parameters defined for generating the variation of the seed scenario. The event parameters are the collision point and the radius of curvature of the ego trajectory at road turns.

• MethodForVariations: Specifies the modification method used for adjusting the collision time in the generated scenario variant. The default value is "`WaitTime`". The collision time in the generated scenario variant is maintained same as that of the seed scenario by making either the slower actor to wait at its first waypoint for a particular amount of time. If the new ego speed value causes 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. Similarly, if the target actor arrives at the collision point ahead of the ego vehicle, the generated variant makes the target actor wait at its first waypoint.

`scenarioVariantParameter = HelperScenarioVariant(seedScenarioDescriptor)`
```scenarioVariantParameter = HelperScenarioVariant with properties: ScenarioData: [1x1 struct] VariantGenerator: [] ActorVariations: [] SceneVariations: [] EventVariations: [] MethodForVariations: "WaitTime" ```

### Modify Actor Dimension and Speed

Specify the `ActorID` values of the ego vehicle and the target actor whose parameters has to be modified. You can find the `ActorID` values and the names of the ego vehicle and the target actor by inspecting the `Actors` property of the `scenario` 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" ```

Create an object to store the new actor dimensions and speed values by using the helper function `HelperActorVariation`.

`actorVariationParameter = HelperActorVariation()`
```actorVariationParameter = HelperActorVariation with properties: ActorVariationGraph: [] ```

Use the `addDimensionVariation`, `addMultiVariation`, and `addSpeedVariation` methods of the `HelperActorVariation` object to specify different actor parameters required to generate the scenario variant.

• To generate a scenario variant with new vehicle dimensions, use the `addDimensionVariation` method. You can use this method to specify new dimension values for one or more vehicles in the scenario.

• To generate a scenario variant with new vehicle speed values, use the `addSpeedVariation` method. You can use this method to specify new speed values for one or more vehicles in the scenario.

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

The specified values are stored in the `ActorVariationGraph` property of the `HelperActorVariation` object. The `ActorVariationGraph` property is a structure with field values `SpeedObj` and `DimensionObj`. The new speed values are stored to the `SpeedObj` field and the new dimension values are stored to the `DimensionObj` field. The number of rows in the structure is same as the number of scenario variants defined using the `addDimensionVariation`, `addMultiVariation`, and `addSpeedVariation` methods. Each row in the structure stores the parameters for generating a new scenario variant.

Step 1: Define the parameters to generate four different scenario variants by modifying the speed, dimension, or both of one or more vehicles in the seed scenario.

Scenario Variant 1: Specify New Speed for Ego Vehicle

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 `HelperActorVariation` object, `actorVariationParameter`.

```newEgoSpeed = 17; addSpeedVariation(actorVariationParameter,{egoID},{newEgoSpeed}); disp(actorVariationParameter)```
``` HelperActorVariation with properties: ActorVariationGraph: [1x1 struct] ```

Inspect the `ActorVariationGraph` property of the `HelperActorVariation` object. You can notice that the `ActorID` value of the ego vehicle and new ego speed value are stored in the `ActorVariationGraph` property.

`actorVariationParameter.ActorVariationGraph`
```ans = struct with fields: SpeedObj: [1x1 HelperSpeedVariation] ```
`actorVariationParameter.ActorVariationGraph.SpeedObj`
```ans = HelperSpeedVariation with properties: ActorID: {[1]} Speed: {[17]} ActorVariationGraph: [] ```

Scenario Variant 2: Specify New Dimension for Ego Vehicle

Specify the new dimension value 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 `HelperActorVariation` object, `actorVariationParameter` by using the `addDimensionVariation` method.

`addDimensionVariation(actorVariationParameter,{egoID},{egoDimensions});`

Inspect the `ActorVariationGraph` property of the `HelperActorVariation` object. You can notice that the `ActorID` value of the ego vehicle and new ego dimension value are stored in the `ActorVariationGraph` property.

`actorVariationParameter.ActorVariationGraph`
```ans=1×2 struct array with fields: SpeedObj DimensionObj ```
`actorVariationParameter.ActorVariationGraph.DimensionObj`
```ans = [] ```
```ans = HelperDimensionVariation with properties: Dimension: {[1x1 struct]} ActorID: {[1]} ActorVariationGraph: [] ```

Scenario Variant 3: Specify New Dimensions for Ego and Target Vehicle

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 `HelperActorVariation` object, `actorVariationParameter` by using the `addMultiVariation` method.

`addMultiVariation(actorVariationParameter,{egoID,targetID},Dimension={{egoDimensions},{targetDimensions}});`

Inspect the `ActorVariationGraph` property of the `HelperActorVariation` object. You can notice that the `ActorID` and the new dimension values are stored in the `ActorVariationGraph` property.

`actorVariationParameter.ActorVariationGraph`
```ans=1×3 struct array with fields: SpeedObj DimensionObj ```

Scenario Variant 4: Specify New Dimensions and Speed Value for Ego Vehicle

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

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

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

`newEgoSpeed = 11;`

Store the new dimension and speed values to the `HelperActorVariation` object, `actorVariationParameter` by using the `addMultiVariation` method.

`addMultiVariation(actorVariationParameter,{egoID},Dimension={egoDimensions},Speed={newEgoSpeed});`

Inspect the `ActorVariationGraph` property of the `HelperActorVariation` object. You can notice that the size of the structure stored in the `ActorVariationGraph` property increases with the number of the scenario variants defined. Each row in the structure stores the parameters for a new scenario variant.

`actorVariationParameter.ActorVariationGraph`
```ans=1×4 struct array with fields: SpeedObj DimensionObj ```

Step 2: Store the defined actor variation parameters to the `ActorVariations` property of the `HelperScenarioVariant` object.

`scenarioVariantParameter.ActorVariations = actorVariationParameter;`

Step 3: Specify the event parameters for the generated scenario variants by using the helper function `HelperEventVariation`. The helper creates a `HelperEventVariation` object to store the event variation parameters.

`eventVariationParameter = HelperEventVariation();`

You can adjust the radius of curvature of the ego trajectory at road turns and modify the collision points by using the `addTrajectoryTurnVariation` and `addCollision` method of the `HelperEventVariation` object, respectively.

If the trajectory of the ego vehicle is a curved path, the radius of curvature of the trajectory can vary 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 `addTrajectoryTurnVariation` function to modify the radius of curvature of the ego trajectory if the ego vehicle travels on a road with turns. To adjust the radius of curvature of the ego trajectory, use the syntax

`addTrajectoryTurnVariation(eventVariationParameter,scenarioVariantParameter,egoID,targetID);`

Define the collision point to add to the scenario variants by using the helper function `HelperEventVariation`. The function generates a `HelperEventVariation` object with property `InteractionEventGraph`. The property is a structure with field values `TrajectoryTurnObj` and `CollisionObj`. The function uses the `CollisionObj` field to store the desired collision point in the generated scenario variant.

Use the `addCollision` method of the `HelperEventVariation` object to fix the collision point in the generated scenario variants as same as that of the seed scenario.

`addCollision(eventVariationParameter,scenarioVariantParameter,egoID,targetID);`

Alternatively, you can also use the `addCollision` method to modify the collision point. In that case, you must specify the new collision point value as input to the `addCollision` method by using the syntax

`addCollision(eventVariationParameter,scenarioVariantParameter,egoID,targetID,CollisionPoint=value);`

For example, if the new collision point value is 0.3, the syntax must be,

`addCollision(eventVariationParameter,scenarioVariantParameter,egoID,targetID,CollisionPoint=0.3);`

Step 4: Store the defined event variation parameter to the `EventVariation` property of the `HelperScenarioVariant` object.

`scenarioVariantParameter.EventVariations = eventVariationParameter`
```scenarioVariantParameter = HelperScenarioVariant with properties: ScenarioData: [1x1 struct] VariantGenerator: [] ActorVariations: [1x1 HelperActorVariation] SceneVariations: [] EventVariations: [1x1 HelperEventVariation] MethodForVariations: "WaitTime" ```

Step 5: Generate the scenario variants by using the helper function `generateVariants`.

The `generateVariants` function generates the scenario variants and stores them as `scenarioDescriptor` objects. The output of the `generateVariants` function is a cell array of `scenarioDescriptor` objects. The `scenarioDescriptor` object in each row of the cell stores the parameters for a scenario variant.

```warning("off","SVG:OldSpeedEqualsNewSpeed"); scenarioVariantDescriptors = generateVariants(scenarioVariantParameter)```
```scenarioVariantDescriptors=4×1 cell array {1x1 variantgenerator.internal.ScenarioDescriptor} {1x1 variantgenerator.internal.ScenarioDescriptor} {1x1 variantgenerator.internal.ScenarioDescriptor} {1x1 variantgenerator.internal.ScenarioDescriptor} ```
`warning("on","SVG:OldSpeedEqualsNewSpeed");`

Convert the `scenarioDescriptor` object to a `drivingScenario` object by using the `getScenario` function.

```variantScenario = cell(1,4); for i = 1:size(scenarioVariantDescriptors,1) variantScenario{i} = getScenario(scenarioVariantDescriptors{i},Simulator="DrivingScenario"); end```

Step 6: Visualize the seed scenario and the generated scenario variants.

```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 and Dimension"];```

Plot the seed scenario and the generated variants by using the helper function `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 same as that of the seed scenario for all the generated scenario variants.

```helperVisualizeVariants(seedScenario,variantScenario(1:length(variantScenario)),... "Generated Scenario Variants",... 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 file names to export each of the generated scenario variant.

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

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

```warning("off", "driving:scenario:ExportOpenScenarioODWarning"); for i = 1:size(variantScenario,2) export(variantScenario{i},"OpenSCENARIO",strcat(fileName(i),".xosc")); end warning("on", "driving:scenario:ExportOpenScenarioODWarning");```

### Further Exploration

You can also use 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 validate that a collision event occur in the input scenario. Use the helper function `helperCheckScenario` to check if the seed scenario meets the following requirements.

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

• The actors have atleast 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 helper function `helperCheckScenario` 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 the output returned by the helper function `helperCheckScenario` is 0, you can modify the seed scenario to a valid scenario by using the helper function `helperSetScenarioCollision`.

`if ~scenarioCheckPassed`

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

`end`

The `helperSetScenarioCollision` function modifies the scenario according to the following 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 last 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 vehicle do not collide but have intersecting trajectories, `helperSetScenarioCollision` checks if a collision is possible by modifying the wait time of the target vehicle. If possible, the function modifies the wait time of the target vehicle to create a collision event. Otherwise, the function returns an error.

You can now use the validated seed scenario as input to this example and generate the variants of the custom seed scenario by modifying the actor and the event parameters.

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