exponenta event banner

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

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

Предпосылки

  • В этом примере требуется Coder™ MATLAB.

  • Необходимо иметь доступ к компилятору C/C + +, который настроен правильно. Вы можете использоватьmex -setup cpp для просмотра и изменения компилятора по умолчанию. Дополнительные сведения см. в разделе Изменение компилятора по умолчанию.

Обзор

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

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

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

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

  • Определите код MATLAB, который не поддерживает генерацию кода C++, и измените код MATLAB для использования функций или конструкций, поддерживающих генерацию кода.

  • Создайте объект конфигурации кодера MATLAB и укажите оборудование как '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 и roshutdown выполняются только один раз в сеансе 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 с использованием "Robot Operating System (ROS)" оборудование. Установите HardwareImplementation.ProdHWDeviceType параметр объекта конфигурации кодера MATLAB для предполагаемого аппаратного обеспечения развертывания. Например, при развертывании сгенерированного кода на компьютере под управлением 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-by-1 и trajMsg.Positions имеет размеры N-by-1. В этом примере публикуются две точки траектории на одно соединение.

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

  • Исключение входного аргумента updateRate путем непосредственного указания его в теле функции.

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

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

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

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

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

Изменение rospublisher, rosmessage и rosrate для использования структур сообщений. trajectory_msgs/JointTrajectory структура сообщения имеет поле, JointNames, которая относится к типу строки ячейки. Поля сообщений этого типа не поддерживаются для генерации кода из-за ограничений кодера MATLAB. Для создания кода для 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 с использованием "Robot Operating System (ROS)" оборудование. Установите HardwareImplementation.ProdHWDeviceType параметр объекта конфигурации кодера MATLAB для предполагаемого аппаратного обеспечения развертывания. Например, при развертывании сгенерированного кода на компьютере под управлением 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.