В этом примере показан рекомендуемый рабочий процесс для генерации автономного исполняемого файла из кода MATLAB ®, который содержит интерфейсы ROS.
Этот пример требует MATLAB Coder™.
Вы должны иметь доступ к компилятору C/C + +, который настроен правильно. Можно использовать mex -setup cpp
чтобы просмотреть и изменить компилятор по умолчанию. Для получения дополнительной информации см. раздел «Изменение компилятора по умолчанию».
Подмножество функций ROS MATLAB, таких как 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
topic и отображает первый элемент положения в цикле. Функция имеет входной параметр, которая устанавливает количество итераций. Чтобы создать отдельный узел 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
цикл для автономного развертывания.
The rossubscriber
Для генерации кода функции требуется, чтобы тип сообщения был задан как временная константа компиляции. Функция использует эту информацию для создания возврата типа сообщения для receive
вызовы. The 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
тема. Частоту публикации сообщений можно установить внешне. The 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
функций для использования структур сообщений. The trajectory_msgs/JointTrajectory
структура сообщения имеет поле, JointNames
, который относится к строке камер типа. Поля сообщений этого типа не поддерживаются для генерации кода из-за ограничений MATLAB Coder. Для порядка кода для mypubnode
функции, избегайте использования JointNames
поля в генерации кода с помощью функции coder.targe.
Исходный 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.