Skip to main content

Include a matlab activity in a model

PRESENTATION

This tutorial can be done from the Start to use Sim4Sys with a simple model (blackbox) model of car.

Prerequisites

News skills that you will acquire

On Designer:

  • Import a Matlab and use its function,
  • Use variable with a multiplicity *,
  • Use a periodic flow "when",
  • Include external libraries,
  • Build Configuration Edition.

On Virtual Bench:

  • Use continious triggers,
  • Concept on "Clock",
  • Create mappings with a list,
  • Use a new Context elements: Decorative elements (e.g. a pedestrian crossing), Polysensor.

Duration

4h

INTRODUCTION

In this tutorial we're going to handle an emergency braking. When getting closer to an obstacle such as a pedestrian or another car, we want the car to brake without the user's action. We already have a service called SpeedManagement. This service takes requests into account, and brake or accelerate according to those. In our new implementation, we want to :

  • Detect close elements.
  • Determine if the speed and the distance to those elements are safe.
  • Brake accordingly.

Within these 3 steps, we only request to brake in the last one. Therefore, the idea is to create a new service, called EmergencyBrakeManagement which asks the SpeedManagement to brake when it needs to.

USING MATLAB

In this tutorial, we will be using a matlab file which will determine the braking distance of the vehicle. In order for papyrus to "understand" this matlab file, you will be given a .xml file which describe the inputs and outputs of the matlab function. This is what papyrus will use to map the file into your model. In our case, the file is called calculation_braking_distance.xml (you can find it in the ExtraLibs resource pack : New > Other > Sim4Sys > Extra Libraries), and needs to be placed into the folder of your project (In our case, ".../Tutorial6/") for it to work. It is good practice to create a special folder for activities description like this .xml file. As an example, you can store it in a new folder as "...Tutorial6/activities/". By refreshing the view of your project's folder in papyrus it should look like this:

Activities folder

CREATE A NEW USE CASE

We first need to create the EmergencyBrakeManagement service

  • Open the Car Structure diagram, in which all services are displayed.
  • Add a new service in the diagram, and name it EmergencyBrakeManagement.
  • In the new service, open the Relevant Phases Diagram, and add new Standard Use life phase in the diagram.

We can now add a new use case

  • Go into the new UCD diagram.
  • Create a New Use Case "Brake automatically in case of emergency"
  • Add the needed users
Usecase Diagram
  • In this newly created usecase, add two user stories :
    • "An_obstacle_is_detected"
    • "the_vehicle_brakes_automatically_in_case_of_emergency"
'Emergency Braking' user stories

CREATE NEW TYPES

  • Before completing the user stories, create three new types:
    • a DataType RoadUserType, with eight Decimal attributes dx1, dy1, dx2, dy2, dx3, dy3, dx4 and dy4
    • a DataType ListOfRoadUsersType, with a RoadUserType attribute RoadUsers (choose Many for Multiplicity parameter)
    • an Enumeration ActivationType, with two Enumeration Literal deactivated and activated
Types created

CREATE NEW FLOWS AND INTERFACES

  • Open the FromEnv diagram of the EmergencyBrakeManagement service.
  • Create two new interfaces (I_an_obstacle_is_detected and I_when) with two new flows (an_obstacle_is_detected and when) as shown below (be careful with the arguments of these new flows !):
FromEnv diagram

In order for our new service to have all the necessary information, we need to get the speed of the vehicle. This data is acquired in the SpeedManagement service. Therefore we need to transmit this speed data from the SpeedManagement service to the EmergencyBrakeManagement service. For this we will have to go back to the diagram called "The driver is informed of the car speed" in the SpeedManagement service. In this diagram we already have the speed received from the simulation. In the below step we will transmit this speed:

  • Add a new lifeline on the diagram.
  • Select EmergencyBrakeManagementBB service.
Lifeline Selection, New button
  • Then, click OK.

  • Go back to the diagram, and add a state.

  • Then trace a flow going from the SpeedManagement lifeline to the EmergencyBrakeManagement

  • Add the following interface:

Creating an interface to transmit the speed

You should now have a diagram like this one:

The_car_speed_is_acquired Service Diagram with speed transmission

USER STORY An_obstacle_is_detected

  • Go back to the EmergencyBrakeManagement service.
  • In the Overview tab, double Click on the user story An_obstacle_is_detected
  • Complete the user story with the flow an_obstacle_is_detected and two new internal activities calculate_braking_distance and determine_emergency_braking_status as shown below:
'An obstacle is detected in front of the vehicle' Sequence diagram
  • Create two new variables:

    • a Decimal variable braking_distance (init value : 0.0)
    • an ActivationType variable emergency_braking_status (init value: deactivated)
  • Right click on the activity calculate_braking_distance

  • Select Edit > Complete Activity > Matlab Model

  • Select calculation_braking_distance.m file and click on Next

  • On this window:

    • Select the variable which need to match the In Speed. With the previous step, we now have the speed because it has been transmitted from the SpeedManagement service thanks to the transmit_car_speed flow. Therefore you need to choose transmit_car_speed_value for the Matlab model input.
    • Select the variable braking_distance fot the Matlab model output.
    • Click on Finish
Matlab mapping for 'calculate_the_braking_distance'
  • Right click on the activity "determine_the_emergency_braking_status"
  • Select Edit > Complete Activity > C++ Code
  • Past the code below:
DecimalType minimum_distance;
DecimalType temp_distance;

if(an_obstacle_is_detected_value.RoadUsers.size()>0)
{
minimum_distance = an_obstacle_is_detected_value.RoadUsers[0].dx1;
for(unsigned int i=0; i<an_obstacle_is_detected_value.RoadUsers.size(); i++)
{
minimum_distance = std::min(minimum_distance, an_obstacle_is_detected_value.RoadUsers[i].dx1);
minimum_distance = std::min(minimum_distance, an_obstacle_is_detected_value.RoadUsers[i].dx2);
minimum_distance = std::min(minimum_distance, an_obstacle_is_detected_value.RoadUsers[i].dx3);
minimum_distance = std::min(minimum_distance, an_obstacle_is_detected_value.RoadUsers[i].dx4);
}


if(minimum_distance < braking_distance*1.7)
{
emergency_braking_status = ActivationType::activated;
}
else
{
emergency_braking_status = ActivationType::deactivated;
}
}
else
{
emergency_braking_status = ActivationType::deactivated;
}

If needed, this script will turn the variable emergency_braking_status to activated.

  • Generate the state machine

USER STORY the_vehicle_brakes_automatically_in_case_of_emergency

Remember, in the introduction, we told you that the EmergencyBrakeManagement service would not be in charge of affecting the speed in any way. We need to let the SpeedManagement service know that. For this, we will have to add a SpeedManagement lifeline in our diagram to which we will send the request to brake with emergency (only if the emergency_braking_status is activated).

  • Add the SpeedManagement lifeline as done previously.
  • Complete the user story with:
    • A flow when from the Environment to our service that will allow us to have a trigger at each time step.
    • A guard condition checking if the emergency_braking_status is activated.
    • A flow between the two services lifelines to transmit the request to brake.
Creating an interface to request emergency brake

The diagram should look like this:

the_vehicle_brakes_automatically_in_case_of_emergency diagram

We now need to manage the reception of this request in the SpeedManagement service.

  • Go into the SpeedManagement service.
  • Create a new user story, especially for this case.
Creating the emergency_brake_request_is_received story
  • Open the new user story
  • Add the EmergencyBrakeManagement lifeline
  • Add states for both of the services
  • Recreate the emergency_brake_is_requested as a starting event for this diagram.
  • Add a guard condition in which you will check if the speed is still positive.
  • If it's the case, create the internal activity brake_in_case_of_emergency in which we will change the car_acceleration value, as done previously. car_acceleration = -5.0;
  • Following the same way of sending back the acceleration to the simulation than before, trace the send_car_acceleration flow back to the environment.
  • If we are in the case where the speed have reach 0, we need to create a guard condition for this, but this time using the set_null_acceleration internal activity used before.
emergency_brake_request_is_received diagram
  • Generate the state machine

BUILDING PROJECT

  • First, you need to check that you have generated the state machines of each (created or modified) diagram.
  • Then generate the code (Overview > View Menu > Generate code).
note

If you have the community version of Designer (free version), please build the executable via Hub4sys as shown on this page.

In order to build the project you will have to go into the properties of the generated code. In C/C++ Build > Settings:

  • Go into Cygwin C++ Compiler > Includes.
  • Add the path of the folder in which you can find your matlab .h. In our case, it is calculation_braking_distance.h that can be find in the folder ".../ExtraLibs/matlab/include"
  • Go into Cygwin C++ Linker > Libraries.
Adding include path
  • Add the path of the folder in which you can find your matlab .a generated. In our case, the folder is ".../ExtraLibs/matlab/lib"
  • Add the library name. In our case, it is called libcalculation_braking_distance.
Adding library name and path

SIMULATION MAPPING

Adding the when flow as a clock flow
  • Create a new simu to model mapping for the flow an_obstacle_is_detected_mapping :
Edit simu to model mapping
  • Select variable after creating a new simu to model mapping (in this case, we have selected 'List of detection' related to the polysensor element)
Select variable
  • In the scene2D context, Drag&Drop a polysensor element from the menu.

  • Attach the polysensor to the car :

    • select both the car and the polysensor (by pressing Ctrl)
    • right-click and choose "Attach"
  • Add the created simu to model mapping to the polysensor

  • Modify the polysensor properties values as shown in green below (for example, the relativeX and relativeY coordinates depend on the position of the car) :

    • Note that the polysensor field radius parameter value sets the maximum emergency braking distance, since obstacle detection is sensor-dependent.
Polysensor properties
  • To simulate an emergency braking case, we are going to add a pedestrian crossing the road.

  • Drag&Drop a pedestrian on the scene :

    • The pedestrian must be placed in front of the car at the distance you want.
  • You can also add some decoratives elements in this context, like a road sign, a pedestrianCrossing element and roadPavement elements boarding the road, as you can see on this screenshot :

Scenario screenshot
  • In the timeline context, add an acceleration request whose value is set to a profile like this one:
Acceleration requests value
  • Add the acceleration Receive flow for the both elements.

Now the scenario is ready to play: you can connect the executable by clicking on the WebSocket button and click on play in Run mode.

The vehicle should brake automatically when the pedestrian is detected by the polysensor.

We can also note an area of amelioration. In our model, the user can still accelerate when the emergency brake is being activated. For this not to happen, we would need to have a priority system in our requests, where the emergency brake prevents all other requests to be taken into account. We can think of guard conditions for example.