Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

eProsima

This guide is mostly outdated: While it still works at its core, regarding e.g. the general code structure or using varargin, all examples using readers and writers, as well as compiled DDS IDL data types, are outdated when you work with the eProsima version of the lab. Matlab Setup currently explains how to set things up for eProsima, parts of it may be put below this paragraph in the future.

RTI DDS

This example is a guideline on how to write a Matlab script that, together with the Middleware, communicates with a vehicle. This tutorial is based on our platoon example (which is just a series of vehicles following a preset path without much logic behind that behavior), which you can find in

...

The Middleware will wake your script up regularly to perform a computation with the currently given values, and you just need to respond in a proper way. This allows you to focus on problem solving instead of timing and communication. Always ensure that the middleware's period in the LCC "Parameters" tab is set according to your expectations in the HLC.

Setup

The structure of your code

Your function head may differ, but you must use varargin as your last parameter to pass vehicle IDs to your script. This allows you to define, for your script, which vehicle(s) it should be responsible for. Any previous parameters you define are your own 'custom' parameters and need to be specified as additional parameters in the Lab Control Centers' UI before starting your script (if you wish to start it using the UI).

...

Info

The parameter middleware_domain_id only exists in the eprosima branch and will not be added to the RTI Branch anymore! Don't use this parameter if you use RTI DDS. Furthermore, the examples below use the RTI DDS syntax. eProsima syntax can be found here.


In other words: If your function head looks like this

...

Varargin covers the vehicle IDs that your script should be responsible for. The DDS Domain ID to communicate with the Middleware only via shared memory is middleware_domain_id, its default value is 1. To be compatible with the LCC, which expects these two parameters to be available on calling your script, you should always put them as the last two parameters in your function head as specified above.

What your HLC scripts need to include

Import the init script

You can see the sample code below. What you should do:

...

Expand
titleCode Sample


Code Block
linenumberstrue
function main_vehicle_ids(middleware_domain_id, varargin) % middleware_domain_id only for eProsima + Matlab
	% Set the matlab domain ID for communicating with the middleware (which is always 1)
    matlabDomainID = 1;

	% Clear command window, store path of current script, go to that path
    clc
    script_directoy = fileparts([mfilename('fullpath') '.m']);
    cd(script_directoy)

    % Set the path of the init script relative to the path of your script (or absolute), assert that it exists, add it to the path so that it can be found and than call it
	% Then go back to the script directory
    init_script_path = fullfile('../', '/init_script.m');
    assert(isfile(init_script_path), 'Missing file "%s".', init_script_path);
    addpath(fileparts(init_script_path));
    [matlabParticipant, stateReader, trajectoryWriter, systemTriggerReader, readyStatusWriter, trigger_stop] = init_script(matlabDomainID);
    cd(script_directoy)

	% Remember the set vehicle IDs in a new variable
    vehicle_ids = varargin;

    %% Use a waitset for the reader of vehicle states, which is later used to indicate if a new computation should be started
	% The waitset makes sure that take() or read() from the reader's storage does not return if no new data is available (until the timeout is reached, here 10 seconds
	% so that one can still check for a stop signal regularly)
    stateReader.WaitSet = true;
    stateReader.WaitSetTimeout = 10;

    %% Do not display figures
    set(0,'DefaultFigureVisible','off');


Tell the Middleware that your script is ready to operate

You must send a ReadySignal message after initialization - only the ID string matters, which must be of the form "hlc_" + vehicle_id, where the latter is the ID of the vehicle the HLC and thus your script is responsible for:

...

This message tells the Middleware that your script is now ready to operate and to receive its data. Thus, at this point, your reader for vehicle states (here stateReader) should be initialized so that it can receive the data.

Consider the timing signals

This is very important. There are two signals you must consider: Start and stop signals. You have to check regularly for the stop signal, and once for the start signal:

...

Info
titleImportant

The Middleware might already have been stopped by a stop signal while you are waiting for the next start signal in form of a VehicleStateList. It is thus important to set a timeout for stateReader that is not too high, so that you can check for stop signals in between waiting for a new start signal. On the other hand, you want to react as fast as possible to a new start signal, so the waiting time should also not be too low - only consider stop signals if you can be sure that you should have received a new start signal by that time, i.e. after 10 seconds.

Receive information about your vehicle

Information about your vehicle are contained in the VehicleStateList messages, which include the current states and observations of all vehicles as well as the current time. This signal is supposed to be the start signal for the HLC, so computation should start using this data directly after the message was received. 

...

Expand
titleCode Sample


Code Block
linenumberstrue
...
% Read the current vehicle information from the according reader, if such data is available
% Due to the set waitset, you wait for up to 10 seconds at take(...) if no data is available
sample = VehicleStateList;
status = 0;
stateSampleCount = 0;
sampleInfo = DDS.SampleInfo;
[sample, status, stateSampleCount, sampleInfo] = stateReader.take(sample);

% Check if any new message was received, then proceed with handling the data, computing your solution and finally sending back a command to the vehicle(s) your script controls
if stateSampleCount > 0 
    ...


Send commands to your vehicle

You need to send vehicle command messages as a result of your computation including the vehicle ID to the Middleware, which propagates these to the vehicle. The implementation of the computation of e.g. the vehicle's trajectory is not explained here and depends on your task. You are only given an example of how to send a simple trajectory here.

...

Expand
titleCode sample


Code Block
linenumberstrue
%Create msg of type trajectory
trajectory = VehicleCommandTrajectory;

% Set the vehicle ID
trajectory.vehicle_id = uint8(vehicle_id);

% In this example, we only send one trajectory point (which is not sufficient for interpolation)
trajectory_points = [];
point1 = TrajectoryPoint;

% This trajectory point should be considered in the future, so add some nanoseconds to the current time, then set the time stamp for the trajectory point
% t_eval here is the time that we got from the middleware in the VehicleStateList message - you are not supposed to use your own clock / timer (else you would have trouble working with simulated time)
time = t_eval + 400000000;
stamp = TimeStamp;
stamp.nanoseconds = uint64(time);
point1.t = stamp;

% Set other trajectory values - position and velocity in 2D coordinates
point1.px = trajectory_point(1);
point1.py = trajectory_point(2);
point1.vx = trajectory_point(3);
point1.vy = trajectory_point(4);

% Append to the list of all trajectory points
trajectory_points = [trajectory_points [point1]];
trajectory.trajectory_points = trajectory_points;

% Send the trajectory to the vehicle
trajectoryWriter.write(trajectory);


Further Information

Bash script / Deploy Using the LCC

If you want to start your script using a bash script, you can do it like this:

...

Usually, you would want to start it using the LCC instead, which takes care of these things for you.

Deploying with Matlab GUI

See here: If, within the setup tab, you do not select any script but leave the script field empty, only the Middleware gets started. You can then start your own script from within the Matlab GUI, it should detect the Middleware (if you set the correct number of vehicles, the Middleware will, if deployed locally, wait for HLC messages for all vehicles that are currently online).

How to Actually Start Your Script

As mentioned before, the Middleware takes care of timing. As soon as your script has told it that it is ready to operate, the Middleware should appear in the Timer Tab in the LCC. Then, you can start the simulation by sending a start signal (press on the start button). Of course, you need to deploy / start the simulation to start the Middleware before you start the timer (and, if you do not use the Matlab GUI, your selected Matlab script as well).

...