Main Content

Work with Basic ROS Messages

This example shows various ways to create, explore, and populate ROS messages in MATLAB®, that are commonly encountered in robotics applications.

Messages are the primary container for exchanging data in ROS. Topics and services use messages to carry data between nodes. (SeeExchange Data with ROS Publishers and SubscribersandCall and Provide ROS Servicesfor more information on topics and services)

Prerequisites:Get Started with ROS,Connect to a ROS Network

确定它的数据结构,每个消息都有一个message 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:

Find Message Types

Initialize the ROS master and global node.

rosinit
Launching ROS Core... ...Done in 3.6551 seconds. Initializing ROS master on http://192.168.178.1:54553. Initializing global node /matlab_global_node_11113 with NodeURI http://ah-csalzber:65499/

UseexampleHelperROSCreateSampleNetworkto populate the ROS network with three additional nodes and sample publishers and subscribers.

exampleHelperROSCreateSampleNetwork

There are various nodes on the network with a few topics and affiliated publishers and subscribers.

You can see the full list of available topics by callingrostopiclist.

rostopiclist
/pose /rosout /scan /tf

If you want to know more about the type of data that is sent through the/scantopic, use therostopic infocommand to examine it./scanhas a message type ofsensor_msgs/LaserScan.

rostopicinfo/scan
Type: sensor_msgs/LaserScan Publishers: * /node_3 (http://ah-csalzber:63490/) Subscribers: * /node_1 (http://ah-csalzber:63478/) * /node_2 (http://ah-csalzber:63484/)

The command output also tells you which nodes are publishing and subscribing to the topic. To learn about publishers and subscribers, seeCall and Provide ROS Services.

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

For better efficiency when creating messages or communicating, use messages in structure format.

scandata = rosmessage("sensor_msgs/LaserScan","DataFormat","struct")
scandata =struct with fields:MessageType: 'sensor_msgs/LaserScan' Header: [1×1 struct] AngleMin: 0 AngleMax: 0 AngleIncrement: 0 TimeIncrement: 0 ScanTime: 0 RangeMin: 0 RangeMax: 0 Ranges: [0×1 single] Intensities: [0×1 single]

The created messagescandata通常有很多属性相关的数据received from a laser scanner. For example, the minimum sensing distance is stored in theRangeMinfield, and the maximum sensing distance is inRangeMax.

To see a complete list of all message types available for topics and services, userosmsglist.

Explore Message Structure and Get Message Data

ROS对象、消息和消息数据stored in properties. MATLAB features convenient ways to find and explore the contents of messages.

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

posesub = rossubscriber("/pose","DataFormat","struct")
posesub = Subscriber with properties: TopicName: '/pose' LatestMessage: [] MessageType: 'geometry_msgs/Twist' BufferSize: 1 NewMessageFcn: [] DataFormat: 'struct'

Usereceiveto get data from the subscriber. Once a new message is received, the function will return it and store it in theposedatavariable (the second argument is a time-out in seconds).

posedata = receive(posesub,10)
posedata =struct with fields:MessageType: 'geometry_msgs/Twist' Linear: [1×1 struct] Angular: [1×1 struct]

The message has a type ofgeometry_msgs/Twist. There are two other fields in the message:LinearandAngular. You can see the values of these message fields by accessing them directly:

posedata.Linear
ans =struct with fields:MessageType: 'geometry_msgs/Vector3' X: -0.0139 Y: 0.0120 Z: 0.0311
posedata.Angular
ans =struct with fields:MessageType: 'geometry_msgs/Vector3' X: -0.0481 Y: -0.0416 Z: 0.0475

Each of the values of these message fields is actually a message in itself. The message type for these isgeometry_msgs/Vector3.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:

xpos = posedata.Linear.X
xpos = -0.0139

If you want a quick summary of all the data contained in a message, call therosShowDetailsfunction.rosShowDetailsworks on messages of any type and recursively displays all the message data fields.

rosShowDetails(posedata)
ans = ' MessageType : geometry_msgs/Twist Linear MessageType : geometry_msgs/Vector3 X : -0.01389779508053391 Y : 0.01202784270710855 Z : 0.03111508851002852 Angular MessageType : geometry_msgs/Vector3 X : -0.04807425225858586 Y : -0.04161264917171002 Z : 0.04748016671848904'

rosShowDetailshelps you during debugging and when you want to quickly explore the contents of a message.

Set Message Data

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

twist = rosmessage("geometry_msgs/Twist","DataFormat","struct")
twist =struct with fields:MessageType: 'geometry_msgs/Twist' Linear: [1×1 struct] Angular: [1×1 struct]

The numeric fields of this message are initialized to0by default. You can modify any of the properties of this message. Set theLinear.Yentry equal to5.

twist.Linear.Y = 5;

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, subscribers, and services. See theExchange Data with ROS Publishers and SubscribersandCall and Provide ROS Servicesexamples.

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: [1×1 struct] Angular: [1×1 struct]

Save the pose data to a MAT file using MATLAB'ssavefunction.

save('posedata.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('posedata.mat')
messageData =struct with fields:posedata: [1×1 struct]

ExaminemessageData.posedatato see the message contents.

messageData.posedata
ans =struct with fields:MessageType: 'geometry_msgs/Twist' Linear: [1×1 struct] Angular: [1×1 struct]

You can now delete the MAT file.

delete('posedata.mat')

Arrays in Messages

Some messages from ROS are stored in or contain arrays of other messages.

In your workspace, the variabletfcontains a sample message. (TheexampleHelperROSCreateSampleNetworkscript created the variable.) In this case, it is a message of typetf/tfMessageused for coordinate transformations.

tf
tf =struct with fields:MessageType: 'tf/tfMessage' Transforms: [1×53 struct]

tfhas two fields:MessageTypecontains a standard data array, andTransformscontains an object array. There are 53 messages stored inTransforms, and all of them have the same structure.

ExpandtfinTransformsto see the structure:

tf.Transforms
ans=1×53 struct array with fields:MessageType Header ChildFrameId Transform

Each object inTransformshas four properties. You can expand to see theTransformfield ofTransforms.

tformFields = tf.Transforms.Transform

Note:The command output returns 53 individual answers, since each object is evaluated and returns the value of itsTransformfield. This format is not always useful, so you can convert it to a cell array with the following command:

cellTransforms = {tf.Transforms.Transform}
cellTransforms=1×53 cell array{1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct}

This puts all 53 object entries in a cell array, enabling you to access them with indexing.

In addition, you can access array elements the same way you access standard MATLAB vectors:

tf.Transforms(5)
ans =struct with fields:MessageType: 'geometry_msgs/TransformStamped' Header: [1×1 struct] ChildFrameId: '/imu_link' Transform: [1×1 struct]

Access the translation component of the fifth transform in the list of 53:

tf.Transforms(5).Transform.Translation
ans =struct with fields:MessageType: 'geometry_msgs/Vector3' X: 0.0599 Y: 0 Z: -0.0141

Shut Down ROS Network

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

exampleHelperROSShutDownSampleNetwork

Shut down the ROS master and delete the global node.

rosshutdown
Shutting down global node /matlab_global_node_11113 with NodeURI http://ah-csalzber:65499/ Shutting down ROS master on http://192.168.178.1:54553.

Next Steps