Программирование MATLAB для генерации кода

Этот пример показывает рекомендуемый рабочий процесс для генерации независимого исполняемого файла из кода MATLAB®, который содержит интерфейсы ROS.

Необходимые условия

  • Этот пример требует MATLAB Coder™.

  • У вас должен быть доступ к компилятору C/C++, который сконфигурирован правильно. Можно использовать mex -setup cpp просмотреть и изменить компилятор по умолчанию. Для получения дополнительной информации см. Компилятор Значения по умолчанию Изменения.

Обзор

Подмножество функций MATLAB ROS, таких как rossubscriber, rospublisher, и rosrate поддержите генерацию Кода С++. Чтобы создать автономный узел ROS из кода MATLAB, выполните эти шаги:

  • Создайте функцию точки входа для того, чтобы создать автономное приложение. Функция точки входа не должна иметь никаких входных параметров и не должна возвращать выходные параметры.

  • Добавьте %#codegen директива к функции MATLAB, чтобы указать, что это предназначается для генерации кода. Эта директива также позволяет анализатору кода MATLAB идентифицировать предупреждения и ошибки, характерные для MATLAB для генерации кода.

  • Измените функции ROS, чтобы использовать структуры сообщения.

  • Идентифицируйте код MATLAB, который не поддерживает генерацию Кода С++ и изменяет код MATLAB, чтобы использовать функции или построения та генерация кода поддержки.

  • Создайте настройку MATLAB Coder, возражают и задают оборудование как 'Robot Operating System (ROS)'.

  • Используйте codegen команда, чтобы сгенерировать независимый исполняемый файл.

Сгенерируйте код для подписчика

Рассмотрите следующий код MATLAB.

function mynode(numIterations)
%mynode Receive and display sensor_msgs/JointState messages
rosinit;

% Trajectory points to be published
sub = rossubscriber("/servo");

% Display position 
for k = 1:numIterations
    msg = receive(sub);
    if ~isempty(msg.Position > 0)
        disp(msg.Position(1))
    else
        disp("Received empty message..");
    end
end
rosshutdown;
end

Этот код MATLAB получает sensor_msgs/JointState сообщения опубликованы к /servo тема и отображения первый элемент положения в цикле. Функция имеет входной параметр, который определяет номер итераций. Чтобы создать автономный узел ROS, измените код можно следующим образом:

  • Устраните входной параметр numIterations использование while цикл.

  • Добавьте %#codegen директива.

  • Задайте тип сообщения для rossubscriber вызвать.

  • Используйте структуры сообщения вместо классов сообщений.

  • Устраните rosinit и rosshutdown вызовы, которые не генерируют код.

  • Замените disp функция, которая не поддерживает генерацию кода с fprintf.

Обратите внимание на то, что вы выполняете rosinit и функции rosshutdown только однажды в сеансе работы с MATLAB. Избегайте rosinit и rosshutdown функции для кода предназначаются для автономного развертывания. В автономном развертывании отдельные узлы ROS, как ожидают, не запустят или остановят ведущее устройство ROS. Если необходимо включать rosinit и roshutdown вызовы в вашем коде MATLAB для интерпретированного выполнения, объявите их, когда значение внешних параметров функционирует во главе вашей функции точки входа.

Функция точки входа не может взять входные параметры или возвратить выходные параметры. Автономный исполняемый файл узла ROS предназначается, чтобы быть запущенным вне MATLAB, такой как от системного терминала команды, и поэтому не может взять входные параметры MATLAB или возвратить MATLAB выходные параметры.

Устранить входной параметр numIterations, замените for цикл с бесконечным while цикл. Для автономного развертывания сгенерированный узел, как ожидают, запустится, пока вы не отключите его внешне. Хорошая методика программирования должна заменить for циклы с while цикл для автономного развертывания.

rossubscriber функционируйте нуждается в типе сообщения, который будет задан как время компиляции, постоянное для генерации кода. Функция использует эту информацию, чтобы создать тип сообщения возврата для receive вызовы. rossubscriber функционируйте генерация кода поддержек для структур сообщения только. Чтобы возвратить структуру сообщения, задайте аргумент пары "имя-значение", "DataFormat","struct", при создании подписчика.

После того, как вы измените код, код MATLAB для функции точки входа следующие:

function mynode
%mynode Receive and display sensor_msgs/JointState messages
%#codegen

% Trajectory points to publish
sub = rossubscriber("/servo","sensor_msgs/JointState","DataFormat","struct");

% Display position 
while (1) 
    msg = receive(sub);
    if ~isempty(msg.Position > 0)
        fprintf("Position = %f\n",msg.Position(1))
    else
        fprintf("Received empty message..\n");
    end
end
end

Создайте настройку MATLAB Coder, которая использует "Robot Operating System (ROS)" оборудование. Установите HardwareImplementation.ProdHWDeviceType параметр настройки MATLAB Coder возражает для намеченного оборудования развертывания. Например, если вы развертываетесь, сгенерированный код к компьютеру Windows установил HardwareImplementation.ProdHWDeviceType к "Intel->x86-64 (Windows64)". Чтобы сгенерировать код, выполните следующие команды:

cfg = coder.config("exe");
cfg.Hardware = coder.hardware("Robot Operating System (ROS)");
cfg.Hardware.DeployTo = "Localhost"; 
cfg.Hardware.BuildAction = "Build and run";
cfg.HardwareImplementation.ProdHWDeviceType = "Intel->x86-64 (Windows64)";
cfg.HardwareImplementation.ProdLongLongMode = true; % Use 'long long' for Int64 or Uint64 data types
codegen mynode -config cfg

Можно отправить сообщения в mynode используя следующую команду на терминале ROS:

rostopic pub /servo sensor_msgs/JointState -r 1 "{header:{seq: 0, stamp:{secs: 0,nsecs: 0},frame_id:""},name:["joint"],position:[150.0,100.0],velocity:[0.0,0.0],effort:[0,0]}"

Сгенерируйте код для издателя

Рассмотрите следующий код MATLAB.

function mypubnode(updateRate)
%mypubnode Publish joint trajectory messages

% Create publisher 
pub = rospublisher("/traj","trajectory_msgs/JointTrajectory");

% Create a message 
msg = rosmessage("trajectory_msgs/JointTrajectory");
msg.JointNames{1} = 'Left';
msg.JointNames{2} = 'Right';
trajMsg = rosmessage("trajectory_msgs/JointTrajectoryPoint");
r = rosrate(updateRate);
while (1)
    msg.Header.Stamp = rostime("now");
    x = rand;
    y = rand;
    trajMsg.Positions = [x y -x -y];
    msg.Points = [trajMsg trajMsg];
    send(pub,msg);
    waitfor(r);
end
end

Этот код MATLAB публикует trajectory_msgs/JointTrajectory сообщения к /traj тема. Можно установить сообщение, публикующее уровень внешне. trajectory_msgs/JointTrajectory сообщение является вложенным сообщением, которое имеет следующие подполя:

>> rosmsg show trajectory_msgs/JointTrajectory
std_msgs/Header Header
char[] JointNames
JointTrajectoryPoint[] Points

Сообщение может вместить несколько соединений и несколько точек траектории. Если количество соединений является M, и количество точек траектории для каждого соединения является N, trajMsg имеет размерности M-1 и trajMsg.Positions имеет размерности N-1. В данном примере опубликуйте две точки траектории на соединение.

Функция имеет входной параметр, который определяет номер итераций. Чтобы создать автономный узел ROS, измените код можно следующим образом:

  • Устраните входной параметр updateRate путем прямого определения его в теле функции.

  • Добавьте %#codegen директива.

  • Используйте структуры сообщения вместо классов сообщений.

  • Устраните любые поля сообщения, которые используют строки ячейки, чтобы подготовиться к генерации кода.

  • Вырастите поля переменного размера структур сообщения в правильной размерности.

Устранить входной параметр updateRate, задайте частоту обновления с помощью постоянного литерала в теле функции точки входа. Изменить updateRate, необходимо регенерировать код от функции точки входа.

Измените rospublisher, rosmessage и rosrate функции, чтобы использовать структуры сообщения. trajectory_msgs/JointTrajectory обменивайтесь сообщениями структура имеет поле, JointNames, который имеет строку ячейки типа. Обменивайтесь сообщениями поля этого типа не поддерживаются для генерации кода из-за ограничений MATLAB Coder. Для того, чтобы сгенерировать код для mypubnode функционируйте, избегайте использования JointNames поля в генерации кода, использующей coder.target функция.

Исходный mypubnode функция выращивает поля переменного размера структур сообщения в неправильной размерности. Как рисунок, создайте сообщение типа trajectory_msgs/JointTrajectory в командной строке MATLAB. Обратите внимание на то, что первая размерность полей переменного размера имеет размер 0, в то время как второе измерение имеет размер 1:

msg = rosmessage('trajectory_msgs/JointTrajectory')

msg = 

  ROS JointTrajectory message with properties:

    MessageType: 'trajectory_msgs/JointTrajectory'
         Header: [1×1 Header]
         Points: [0×1 JointTrajectoryPoint]
     JointNames: {0×1 cell}

  Use showdetails to show the contents of the message

Поля с размерностями 0 1 растут в первой размерности. Оригинальный код выращивает Points и Positions поля во втором измерении, которое работает в интерпретированном режиме, но не поддерживается для генерации кода. Вы получаете следующее сообщение об ошибке, при попытке вырастить поля переменного размера структуры сообщения в неправильной размерности:

??? This assignment writes a 'trajectory_msgs_JointTrajectoryPointStruct_T' value into a 'struct_T' type. Code generation
does not support changing types through assignment. Check preceding assignments or input type specifications for type
mismatches.

После того, как вы измените код, код MATLAB для функции точки входа следующие:

function mypubnode
%mypubnode Publish joint trajectory messages
%#codegen

% Create publisher 
pub = rospublisher("/traj","trajectory_msgs/JointTrajectory","DataFormat","struct");

% Create a msg 
msg = rosmessage("trajectory_msgs/JointTrajectory","DataFormat","struct");
if isempty(coder.target)
    msg.JointNames{1} = 'Left';
    msg.JointNames{2} = 'Right';
end
trajMsg = rosmessage("trajectory_msgs/JointTrajectoryPoint","DataFormat","struct");
r = rosrate(1);
while (1)
    msg.Header.Stamp = rostime("now","DataFormat","struct");
    x = rand;
    y = rand;
    trajMsg.Positions = [x; y; -x; -y]; % Grow variable-size fields in the correct dimension
    msg.Points = [trajMsg; trajMsg];    % Grow variable-size fields in the correct dimension
    send(pub,msg);
    waitfor(r);
end
end

Создайте настройку MATLAB Coder, которая использует "Robot Operating System (ROS)" оборудование. Установите HardwareImplementation.ProdHWDeviceType параметр настройки MATLAB Coder возражает для намеченного оборудования развертывания. Например, если вы развертываетесь, сгенерированный код к компьютеру Windows установил HardwareImplementation.ProdHWDeviceType к "Intel->x86-64 (Windows64)". Чтобы сгенерировать код выполняют следующие команды:

cfg = coder.config("exe");
cfg.Hardware = coder.hardware("Robot Operating System (ROS)");
cfg.Hardware.DeployTo = "Localhost";
cfg.Hardware.BuildAction = "Build and run";
cfg.HardwareImplementation.ProdHWDeviceType = "Intel->x86-64 (Windows64)";
cfg.HardwareImplementation.ProdLongLongMode = true; % Use 'long long' for Int64 or Uint64 data types
codegen mypubnode -config cfg

Можно исследовать содержимое сообщений, опубликованных mypubnode использование rostopic echo /traj команда на терминале ROS.

Похожие темы