Сообщения ROS являются основным контейнером для обмена данными в ROS 2. Издатели и подписчики обмениваются данными с помощью сообщений по заданным темам для переноса данных между узлами. Для получения дополнительной информации об отправке и получении сообщений см. раздел Обмен данными с издателями и подписчиками ROS 2.
Для идентификации структуры данных каждое сообщение имеет тип сообщения. Для примера данные датчика от лазерного сканера обычно отправляются в сообщении типа sensor_msgs/LaserScan
. Каждый тип сообщения определяет элементы данных, содержащиеся в сообщении. Каждое имя типа сообщения представляет собой комбинацию имени пакета, за которой следует косая черта/и имя типа:
MATLAB ® поддерживает многие типы сообщений ROS 2, которые обычно встречаются в приложениях робототехники. В этом примере рассматриваются некоторые способы создания, просмотра и заполнения сообщений ROS 2 в MATLAB.
Необходимые условия: Запуск с ROS 2, Подключение к сети ROS 2
Использование exampleHelperROS2CreateSampleNetwork
заполнение сети ROS 2 тремя узлами и настройка выборочных издателей и подписчиков по конкретным темам.
exampleHelperROS2CreateSampleNetwork
Использование ros2 topic list -t
для поиска доступных тем и связанных с ними типов сообщений.
ros2 topic list -t
Topic MessageType _____________________ _________________________________ {'/parameter_events'} {'rcl_interfaces/ParameterEvent'}
Чтобы узнать больше о типе сообщения темы, используйте ros2message
для создания пустого сообщения того же типа. ros2message
поддерживает заполнение клавишей Tab для типа сообщения. Чтобы быстро заполнить имена типов сообщений, введите первые несколько символов имени, которое вы хотите заполнить, и нажмите клавишу Tab.
scanData = ros2message("sensor_msgs/LaserScan")
scanData = struct with fields:
MessageType: 'sensor_msgs/LaserScan'
header: [1x1 struct]
angle_min: 0
angle_max: 0
angle_increment: 0
time_increment: 0
scan_time: 0
range_min: 0
range_max: 0
ranges: 0
intensities: 0
Созданное сообщение, scanData
, имеет много полей, связанных с данными, которые вы обычно получали от лазерного сканера. Для примера минимальное расстояние измерения сохранено в range_min
свойство и максимальное расстояние измерения в range_max
свойство.
Теперь можно удалить созданное сообщение.
clear scanData
Чтобы просмотреть полный список всех типов сообщений, доступных для тем и служб, используйте ros2 msg list
.
Сообщения ROS 2 представлены в виде структур, и данные сообщения хранятся в полях. MATLAB предоставляет удобные способы поиска и исследования содержимого сообщений.
Использование ros2 msg show
для просмотра определения типа сообщения.
ros2 msg show geometry_msgs/Twist
# This expresses velocity in free space broken into its linear and angular parts. Vector3 linear Vector3 angular
Если вы подписываетесь на /pose
Вы можете получать и просматривать отправленные сообщения.
controlNode = ros2node("/base_station"); poseSub = ros2subscriber(controlNode,"/pose","geometry_msgs/Twist")
poseSub = ros2subscriber with properties: TopicName: '/pose' LatestMessage: [] MessageType: 'geometry_msgs/Twist' NewMessageFcn: [] History: 'keeplast' Depth: 10 Reliability: 'reliable' Durability: 'volatile'
Использование receive
для получения данных от абонента. После получения нового сообщения функция возвращает его и сохраняет в posedata
переменная. Задайте тайм-аут 10 секунд для приема сообщений.
poseData = receive(poseSub,10)
poseData = struct with fields:
MessageType: 'geometry_msgs/Twist'
linear: [1x1 struct]
angular: [1x1 struct]
Сообщение имеет тип geometry_msgs/Twist
. В сообщении есть два других поля: linear
и angular
. Значения этих полей сообщений можно просмотреть путем непосредственного доступа к ним.
poseData.linear
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
x: 0.0457
y: -0.0015
z: 0.0300
poseData.angular
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
x: -0.0358
y: -0.0078
z: 0.0416
Можно увидеть, что каждое из значений этих полей сообщения фактически само по себе является сообщением. geometry_msgs/Twist
является составным сообщением, состоящим из двух geometry_msgs/Vector3
сообщений.
Доступ к данным для этих вложенных сообщений работает в точности так же, как и доступ к данным в других сообщениях. Доступ к x
компонент linear
сообщение с помощью этой команды:
xPose = poseData.linear.x
xPose = 0.0457
Можно также задать значения свойств сообщения. Создайте сообщение с типом geometry_msgs/Twist
.
twist = ros2message("geometry_msgs/Twist")
twist = struct with fields:
MessageType: 'geometry_msgs/Twist'
linear: [1x1 struct]
angular: [1x1 struct]
Числовые свойства этого сообщения инициализируются в 0
по умолчанию. Можно изменить любые свойства этого сообщения. Установите inear.y
l поле до 5.
twist.linear.y = 5;
Можно просмотреть данные сообщения, чтобы убедиться, что ваше изменение вступило в эффект.
twist.linear
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
x: 0
y: 5
z: 0
Как только сообщение заполнено вашими данными, вы можете использовать его с издателями и подписчиками.
Сообщения ROS 2 являются структурами. Они могут быть скопированы непосредственно, чтобы сделать новое сообщение. Каждая копия и исходные сообщения имеют свои данные.
Сделайте новое пустое сообщение, чтобы передать данные о температуре, а затем сделайте копию для изменения.
tempMsgBlank = ros2message("sensor_msgs/Temperature");
tempMsgCopy = tempMsgBlank
tempMsgCopy = struct with fields:
MessageType: 'sensor_msgs/Temperature'
header: [1x1 struct]
temperature: 0
variance: 0
Измените temperature
свойство tempMsg и заметьте, что содержимое tempMsgBlank
оставить без изменений.
tempMsgCopy.temperature = 100
tempMsgCopy = struct with fields:
MessageType: 'sensor_msgs/Temperature'
header: [1x1 struct]
temperature: 100
variance: 0
tempMsgBlank
tempMsgBlank = struct with fields:
MessageType: 'sensor_msgs/Temperature'
header: [1x1 struct]
temperature: 0
variance: 0
Может оказаться полезным хранить пустую структуру сообщений и устанавливать определенные поля только при наличии данных для них перед отправкой сообщения.
thermometerNode = ros2node("/thermometer"); tempPub = ros2publisher(thermometerNode,"/temperature","sensor_msgs/Temperature"); tempMsgs(10) = tempMsgBlank; % Pre-allocate message structure array for iMeasure = 1:10 % Copy blank message fields tempMsgs(iMeasure) = tempMsgBlank; % Record sample temperature tempMsgs(iMeasure).temperature = 20+randn*3; % Only calculate the variation once sufficient data observed if iMeasure >= 5 tempMsgs(iMeasure).variance = var([tempMsgs(1:iMeasure).temperature]); end % Pass the data to subscribers send(tempPub,tempMsgs(iMeasure)) end errorbar([tempMsgs.temperature],[tempMsgs.variance])
Можно сохранять сообщения и хранить содержимое для дальнейшего использования.
Получите новое сообщение от абонента.
poseData = receive(poseSub,10)
poseData = struct with fields:
MessageType: 'geometry_msgs/Twist'
linear: [1x1 struct]
angular: [1x1 struct]
Сохраните данные положения в файл MAT с помощью save
функция.
save("poseFile.mat","poseData")
Перед загрузкой файла обратно в рабочую область очистите poseData
переменная.
clear poseData
Теперь вы можете загрузить данные сообщения, позвонив load
функция. Это загружает poseData
сверху в messageData
структура. poseData
- поле данных struct.
messageData = load("poseFile.mat")
messageData = struct with fields:
poseData: [1x1 struct]
Исследуйте messageData.poseData
для просмотра содержимого сообщения.
messageData.poseData
ans = struct with fields:
MessageType: 'geometry_msgs/Twist'
linear: [1x1 struct]
angular: [1x1 struct]
Теперь можно удалить файл MAT.
delete("poseFile.mat")
Удалите примеры узлов, издателей и подписчиков из сети ROS 2.
exampleHelperROS2ShutDownSampleNetwork