Main Content

Simulate RoadRunner Scenarios with Actors Modeled in MATLAB

You can use the Simulink.ActorSimulation class for actor modeling and runtime data exchanges with RoadRunner. The sample code examples below show how to program a System object™ file to model scenarios with different kinds of actor behaviors, and then associate these behaviors to your scenario.

These examples assume that:

  • You have a RoadRunner license and the product is installed. For more information, see Install and Activate RoadRunner (RoadRunner).

  • You have a RoadRunner Scenario license and the product is installed.

  • You have created RoadRunner project folder named MyRoadRunnerProject. For more information, see RoadRunner Project and Scene System (RoadRunner).

  • You have created and saved a RoadRunner scene named MyExampleScene and a scenario named MyExampleScenario for your project.

Build Custom MATLAB System Object Behavior

Lane Following Actor Behavior

In this example you create a custom behavior, hVehicle.m as a MATLAB® System object file. In this behavior, the code reads the initial pose and velocity of an actor and updates them to make the actor follow a lane.

 MATLAB System object Code for Custom Lane Following Behavior

In the custom behavior:

  • This code defines the sample time.

            function st = getSampleTimeImpl(obj)
                st = createSampleTime( ...
                    obj, 'Type', 'Discrete', 'SampleTime', 0.02);
            end
  • The code in setupImpl is called only once, at the simulation start.

    • This code finds the scenario simulation object, which is the scenario with the actors in it.

                  obj.mScenarioSimulationHdl = ...
                      Simulink.ScenarioSimulation.find( ...
                          'ScenarioSimulation', 'SystemObject', obj);
    • This code uses Simulink.ScenarioSimulation.find function and finds the actor object and reflects the actor to which the behavior is attached.

                  obj.mActorSimulationHdl = Simulink.ScenarioSimulation.find( ...
                      'ActorSimulation', 'SystemObject', obj);
  • The code in stepImpl is executed during each time step of a scenario simulation.

    • This code gets the initial pose and velocity of the actor in the scenario.

                  velocity = obj.mActor.velocity;
                  dTimeUnit = obj.getSampleTimeImpl.SampleTime;
                  pose = obj.mActor.pose;
    • This code updates the pose.

                  pose(1,4) = pose(1,4) + velocity(1) * dTimeUnit; 
                  pose(2,4) = pose(2,4) + velocity(2) * dTimeUnit;
                  pose(3,4) = pose(3,4) + velocity(3) * dTimeUnit; 
      
                  obj.mActor.pose = pose;
    • This code updates RoadRunner actor in the scenario with the new pose values.

      obj.mActorSimulationHdl.setAttribute('Pose', pose);

Path Following Actor Group Behavior

In this example you create a custom behavior for an actor group comprising of a truck and a trailer. The custom behavior hTruckWithTrailer.m is written as a MATLAB System object file. In this behavior, the code reads the pose and velocity of the truck (parent) and updates the trailer (child) in such a way that the child remains at a constant distance behind the parent throughout the simulation.

 MATLAB System object Code for Custom Actor Group Behavior

  • The code in stepImpl is executed during each time step of a scenario simulation.

    In the above program, the code in stepImpl executes the following logic.

    • This code snippet sets a course for the truck (parent) by reading the target path structure.

                  path_action = obj.mActorSimulationHdl.getAction('PathAction');
                  if(~isempty(path_action))
                      obj.mActor.path = path_action.PathTarget.Path;
                      obj.mActor.numPts = path_action.PathTarget.NumPoints;
                      obj.mActor.currPt = 1;
                  end
    • This code snippet reads the target speed value.

                 speedChg_action = obj.mActorSimulationHdl.getAction('SpeedAction');
                   if(~isempty(speedChg_action))
                       tgtSpeed = speedChg_action.SpeedTarget.SpeedValue;
      
    • This code snippet updates the speed of the truck until it hits the target speed, and then maintains the same value.

                 if(obj.mActor.speed < obj.TargetSpeed)
                      obj.mActor.speed = obj.mActor.speed + obj.TargetAccel * obj.mDt;
                      if (obj.mActor.speed > obj.TargetSpeed)
                          obj.mActor.speed = obj.TargetSpeed;
                      end
                  end
      
    • This code snippet calculates the absolute displacement value that the truck must achieve in one time step.

                  ds = obj.mActor.speed * obj.mDt;
      
    • This code snippet calculates the distance from the current point to the next point on the path.

       totalDist = -obj.mActor.currPos;
                  for i = obj.mActor.currPt : obj.mActor.numPts-1                
                      pt1 = obj.mActor.path(i, :);
                      pt2 = obj.mActor.path(i+1, :);
                      prevDist = totalDist;
                      totalDist = totalDist + norm(pt1 - pt2);
      
    • This code snippet checks if the truck has hit the target point on the path during the current time step, and accordingly calculates the next point. The pose of the truck is updated, and then transformed with respect to the global reference frame.

                       if(totalDist > ds)
                          v = obj.mActor.path(i+1, :) - obj.mActor.path(i, :);
                          obj.mActor.unit_v = (v/norm(v));
                          .
                          .
                          obj.mActor.pose(4, 4) = 1;
                          break;
                      end
      
    • This code snippet updates the pose of the truck if no path is defined in RoadRunner Scenario.

                       if(totalDist > ds)
                          v = obj.mActor.path(i+1, :) - obj.mActor.path(i, :);
                          obj.mActor.unit_v = (v/norm(v));
                          .
                          .
                          obj.mActor.pose(4, 4) = 1;
                          break;
                      end
      
    • This code snippet writes the updated pose of the truck to the scenario.

                   obj.mActorSimulationHdl.setAttribute('Pose', obj.mActor.pose);
    • This code snippet implements the logic to calculate the position of the trailer (child) respective to the truck. The logic dictates that the child remain at a fixed distance behind the parent throughout the simulation.

                   obj.mActorSimulationHdl.setAttribute('Pose', obj.mActor.pose);
      
                  boundingBox = obj.mActor.actorModel.getAttribute('BoundingBox');
                  u = boundingBox.min;
                  y =[0 2*u(2) 0 1]';
                 
                  mat = obj.mActor.pose*y;
                  trailerPose = obj.mActor.pose;
                  trailerPose(13) = mat(1);
                  trailerPose(14) = mat(2);
                  trailerPose(15) = mat(3);

Actor Behavior Using User-Defined Actions

In this example, you create an actor behavior that processes user-defined actions received from a scenario. The custom behavior testUDA_ML.m is written as a MATLAB System object file. In this behavior, the code reads the custom parameters of a user-defined action, and then changes the pose of the relevant actor accordingly.

For an example of modeling actor behavior in MATLAB using user-defined actions, see Design Vehicle Following User-Defined Actions Scenario (RoadRunner Scenario).

Note

User-defined action parameters support all data types supported by RoadRunner scenarios. For more information, see Parameter Data Types (RoadRunner Scenario).

 MATLAB System object Code for Custom Behavior Using User-Defined Actions

In the custom behavior:

  • This code defines the interface of a MATLAB System object that uses user-defined actions.

             function interface = getInterfaceImpl(~)
                import matlab.system.interface.*;
                interface = ActorInterface();
                actionType = 'UserDefinedAction';
                actionName = 'CustomDrive';
                actionElements = struct('ThrottleLevel',"", 'SteeringAngle',"");
                newAction = matlab.system.interface.UserDefinedAction(actionName, actionElements);
                interface.addAction(actionType, newAction);
            end
  • This code defines the sample time.

            function st = getSampleTimeImpl(obj)
                st = createSampleTime( ...
                    obj, 'Type', 'Discrete', 'SampleTime', 0.02);
            end
  • The code in setupImpl is called only once, at the simulation start.

    • This code finds the scenario simulation object, which is the scenario containing the actor group.

                  sim = Simulink.ScenarioSimulation.find('ScenarioSimulation'); 
    • This code returns the actor object to which this behavior is attached.

                  actor = sim.get('ActorSimulation','SystemObject',obj);
  • The code in stepImpl is executed during each time step of a scenario simulation.

    • This code extracts the custom parameters of the user-defined actions in a scenario. It also sends out an Action Complete event that is processed by RoadRunner Scenario at the end of the action phase that uses user-defined actions.

                 function stepImpl(obj)
                  uda = obj.mActorHdl.getAction("UserDefinedAction", "CustomDrive");
                  for i = 1:length(uda)
                      obj.mThrottleLevel = eval(uda(i).Parameters.ThrottleLevel);
                      obj.mSteeringAngle = eval(uda(i).Parameters.SteeringAngle);
                      obj.mActorHdl.sendEvent('ActionComplete', uda(i).ActorAction.ActionID);
                  end
    • This code updates the current pose and velocity of the vehicle in accordance with the values of the custom parameters.

                  dTimeUnit = obj.getSampleTimeImpl.SampleTime;
                  pose = obj.mActorHdl.getAttribute('Pose');
      
                  maxSpeed = 50;
                  distance = dTimeUnit*obj.mThrottleLevel*maxSpeed/100;
                  angle = deg2rad(obj.mSteeringAngle);
       
                  pose(1,4) = pose(1,4) + distance*cos(angle);
                  pose(2,4) = pose(2,4) + distance*sin(angle);
      
                  obj.mActorHdl.setAttribute('Pose', pose);

Associate Actor Behavior in RoadRunner

This section describes how to associate any custom behavior to your actor.

  1. In your RoadRunner scenario, select the Library Browser and then the Behaviors folder. Then, right-click an empty space to create a new behavior. For this step, you can select any folder in the Library Browser.

    Menu to create a new behavior

  2. On the Attributes pane, set Platform to MATLAB/Simulink. As the File Name, use the location of your file hVehicle.m, hTruckWithTrailer.m or testUDA_ML.m.

    • If your MATLAB System object file is in your working folder, you can enter the name of your file together with its extension .m, for example hVehicle.m.

    • You can also use the full path to enter the location of your file, for example MyLocation\hVehicle.m.

    Attributes of the new behavior.

    This action creates a new behavior that you can attach to actors in your scenario. Rename the behavior as MyNewBehavior.

    Icon representing the new behavior created using MATLAB.

  3. For example, add a new CompactCar to your scenario MyExampleScenario.

  4. To associate the MATLAB System object behavior to a RoadRunner actor, select CompactCar. Then, in the Attributes section, in the Behavior box, add MyNewBehavior to CompactCar by clicking and dragging the behavior icon to the box.

    The vehicle and the new behavior that is attached to the vehicle.

  5. Use these commands to specify MyInstallationFolder as the path to your RoadRunner installation folder and create the connection between MATLAB and RoadRunner for only the first MATLAB installation.

    RRInstallationFolder = "MyInstallationFolder";
    s = settings;
    s.roadrunner.application.InstallationFolder.PersonalValue = RRInstallationFolder; 
    s.roadrunner.application.InstallationFolder.TemporaryValue = RRInstallationFolder;
  6. To open the RoadRunner project MyRoadRunnerProject from MATLAB, use this command.

    rrapp = roadrunner('MyProjectLocation');
  7. Open the scene MyExampleScene.

    rrapp.openScene('MyExampleScene');
  8. Open the scenario MyExampleScenario.

    rrapp.openScenario('MyExampleScenario');
  9. Get the simulation object to control simulation from MATLAB.

    ss = rrapp.createSimulation();

  10. Start the simulation from the command line.

    ss.set('SimulationCommand','Start');

    For more information about simulating your scenario in RoadRunner or controlling a scenario simulation using MATLAB, see Overview of Simulating RoadRunner Scenarios with MATLAB and Simulink.

Related Topics