Main Content

Work with Basic ROS 2 Messages

ROSmessagesare the primary container for exchanging data in ROS 2. Publishers and subscribers exchange data using messages on specifiedtopicsto carry data between nodes. For more information on sending and receiving messages, seeExchange Data with ROS 2 Publishers and Subscribers

To identify its data structure, each message has amessage type。For example, sensor data from a laser scanner is typically sent in a message of typesensor_msgs/LaserScan。Each message type identifies the data elements that are contained in a message. Every message type name is a combination of a package name, followed by a forward slash /, and a type name:

MATLAB® supports many ROS 2 message types that are commonly encountered in robotics applications. This example examines some of the ways to create, inspect, and populate ROS 2 messages in MATLAB.

Prerequisites:开始使用ROS2,Connect to a ROS 2 Network

Find Message Types

UseexampleHelperROS2CreateSampleNetworkto populate the ROS 2 network with three nodes and setup sample publishers and subscribers on specific topics.

exampleHelperROS2CreateSampleNetwork

Useros2 topic list -tto find the available topics and their associated message type.

ros2topiclist-t
Topic MessageType _____________________ _________________________________ {'/parameter_events'} {'rcl_interfaces/ParameterEvent'} {'/pose' } {'geometry_msgs/Twist' } {'/rosout' } {'rcl_interfaces/Log' } {'/scan' } {'sensor_msgs/LaserScan' }

To find out more about the topic message type, useros2messageto create an empty message of the same type.ros2messagesupports tab completion for the message type. To quickly complete message type names, type the first few characters of the name you want to complete, and then press theTabkey.

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

The created message,scanData, has many fields associated with data that you typically received from a laser scanner. For example, the minimum sensing distance is stored in therange_minproperty and the maximum sensing distance inrange_maxproperty.

You can now delete the created message.

clearscanData

To see a complete list of all message types available for topics and services, useros2 msg list

Explore Message Structure and Get Message Data

ROS 2 messages are represented as structures and the message data is stored in fields. MATLAB provides convenient ways to find and explore the contents of messages.

Useros2 msg showto view the definition of the message type.

ros2msgshowgeometry_msgs/Twist
# This expresses velocity in free space broken into its linear and angular parts. Vector3 linear Vector3 angular

If you subscribe to the/posetopic, you can receive and examine the messages that are sent.

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'

Usereceiveto acquire data from the subscriber. Once a new message is received, the function returns it and stores it in theposedatavariable. Specify a timeout of 10 seconds for receiving messages.

poseData = receive(poseSub,10)
poseData =struct with fields:MessageType: 'geometry_msgs/Twist' linear: [1x1 struct] angular: [1x1 struct]

The message has a type ofgeometry_msgs/Twist。There are two other fields in the message:linearand。你可以看到这些消息的值fields by accessing them directly.

poseData.linear
ans =struct with fields:MessageType: 'geometry_msgs/Vector3' x: 0.0206 y: -0.0468 z: -0.0223
poseData.angular
ans =struct with fields:MessageType: 'geometry_msgs/Vector3' x: -0.0454 y: -0.0403 z: 0.0323

You can see that each of the values of these message fields is actually a message in itself.geometry_msgs/Twistis a composite message made up of twogeometry_msgs/Vector3messages.

Data access for these nested messages works exactly the same as accessing the data in other messages. Access thexcomponent of thelinearmessage using this command:

xPose = poseData.linear.x
xPose = 0.0206

Set Message Data

You can also set message property values. Create a message with typegeometry_msgs/Twist

twist = ros2message("geometry_msgs/Twist")
twist =struct with fields:MessageType: 'geometry_msgs/Twist' linear: [1x1 struct] angular: [1x1 struct]

The numeric properties of this message are initialized to0by default. You can modify any of the properties of this message. Set the linear.yfield to 5.

twist.linear.y = 5;

You can view the message data to make sure that your change took effect.

twist.linear
ans =struct with fields:MessageType: 'geometry_msgs/Vector3' x: 0 y: 5 z: 0

Once a message is populated with your data, you can use it with publishers and subscribers.

Copy Messages

ROS 2 messages are structures. They can be copied directly to make a new message. The copy and the original messages each have their own data.

Make a new empty message to convey temperature data, then make a copy for modification.

tempMsgBlank = ros2message("sensor_msgs/Temperature"); tempMsgCopy = tempMsgBlank
tempMsgCopy =struct with fields:MessageType: 'sensor_msgs/Temperature' header: [1x1 struct] temperature: 0 variance: 0

Modify thetemperatureproperty of tempMsg and notice that the contents oftempMsgBlankremain unchanged.

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

It may be useful to keep a blank message structure around, and only set the specific fields when there is data for it before sending the message.

thermometerNode = ros2node("/thermometer"); tempPub = ros2publisher(thermometerNode,"/temperature","sensor_msgs/Temperature"); tempMsgs(10) = tempMsgBlank;% Pre-allocate message structure arrayforiMeasure = 1:10% Copy blank message fieldstempMsgs(iMeasure) = tempMsgBlank;% Record sample temperaturetempMsgs(iMeasure).temperature = 20+randn*3;% Only calculate the variation once sufficient data observedifiMeasure >= 5 tempMsgs(iMeasure).variance = var([tempMsgs(1:iMeasure).temperature]);end% Pass the data to subscriberssend(tempPub,tempMsgs(iMeasure))enderrorbar([tempMsgs.temperature],[tempMsgs.variance])

Figure contains an axes object. The axes object contains an object of type errorbar.

Save and Load Messages

You can save messages and store the contents for later use.

Get a new message from the subscriber.

poseData = receive(poseSub,10)
poseData =struct with fields:MessageType: 'geometry_msgs/Twist' linear: [1x1 struct] angular: [1x1 struct]

Save the pose data to a MAT file using thesavefunction.

save("poseFile.mat","poseData")

Before loading the file back into the workspace, clear theposeDatavariable.

clearposeData

Now you can load the message data by calling theloadfunction. This loads theposeDatafrom above into themessageDatastructure.poseDatais a data field of the struct.

messageData = load("poseFile.mat")
messageData =struct with fields:poseData: [1x1 struct]

ExaminemessageData.poseDatato see the message contents.

messageData.poseData
ans =struct with fields:MessageType: 'geometry_msgs/Twist' linear: [1x1 struct] angular: [1x1 struct]

You can now delete the MAT file.

delete("poseFile.mat")

Disconnect From ROS 2 Network

Remove the sample nodes, publishers, and subscribers from the ROS 2 network.

exampleHelperROS2ShutDownSampleNetwork

Next Steps