Сообщения 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'} {'/pose' } {'geometry_msgs/Twist' } {'/scan' } {'sensor_msgs/LaserScan' }
Чтобы узнать больше о типе сообщения темы, используйте ros2message
создать пустое сообщение того же типа. ros2message
заполнение клавишей Tab поддержек для типа сообщения. Чтобы быстро завершить имена типа сообщения, введите первые несколько символов имени, вы хотите завершить, и затем нажать клавишу TAB.
scanData = ros2message("sensor_msgs/LaserScan")
scanData = struct with fields:
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:
linear: [1x1 struct]
angular: [1x1 struct]
Сообщение имеет тип geometry_msgs/Twist
. В сообщении существует два других поля: linear
и angular
. Вы видите значения этих полей сообщения путем доступа к ним непосредственно.
poseData.linear
ans = struct with fields:
x: 0.0457
y: -0.0015
z: 0.0300
poseData.angular
ans = struct with fields:
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:
linear: [1x1 struct]
angular: [1x1 struct]
Числовые свойства этого сообщения инициализируются к 0
по умолчанию. Можно изменить любое из свойств этого сообщения. Установите linear.y
поле к 5.
twist.linear.y = 5;
Можно просмотреть данные о сообщении, чтобы убедиться, что изменение вступило в силу.
twist.linear
ans = struct with fields:
x: 0
y: 5
z: 0
Если сообщение заполняется с вашими данными, можно использовать его с издателями и подписчиками.
Сообщения ROS 2 являются структурами. Они могут быть скопированы непосредственно, чтобы сделать новое сообщение. Копия и исходные сообщения у каждого есть их собственные данные.
Сделайте новое пустое сообщение, чтобы передать температурные данные, затем сделать копию для модификации.
tempMsgBlank = ros2message("sensor_msgs/Temperature");
tempMsgCopy = tempMsgBlank
tempMsgCopy = struct with fields:
header: [1x1 struct]
temperature: 0
variance: 0
Измените the temperature
свойство tempMsg и уведомления, что содержимое tempMsgBlank
останьтесь неизменными.
tempMsgCopy.temperature = 100
tempMsgCopy = struct with fields:
header: [1x1 struct]
temperature: 100
variance: 0
tempMsgBlank
tempMsgBlank = struct with fields:
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:
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:
linear: [1x1 struct]
angular: [1x1 struct]
Можно теперь удалить файл MAT.
delete("poseFile.mat")
Удалите демонстрационные узлы, издателей и подписчиков от сети ROS 2.
exampleHelperROS2ShutDownSampleNetwork