0. 简介
消息是ROS中交换数据的主要容器。主题和服务使用消息在节点之间传输数据。为了标识其数据结构,每条消息都有一个消息类型。例如,来自激光扫描仪的传感器数据通常以sensor_msgs/LaserScan
类型的消息发送。每种消息类型标识消息中包含的数据元素。每个消息类型名称都是一个包名称。
MATLAB支持在机器人应用程序中经常遇到的许多ROS消息类型。这个例子展示了在MATLAB中创建、探索和填充ROS消息的一些方法。
1. 查找消息类型
初始化ROS主节点和全局节点
rosinit
Launching ROS Core…
Done in 0.37599 seconds.
Initializing ROS master on http://172.29.217.11:53161.
Initializing global node /matlab_global_node_29455 with NodeURI http://dcc083455glnxa64:37683/ and MasterURI http://localhost:53161.
使用exampleHelperROSCreateSampleNetwork使用另外三个节点以及示例发布者和订阅者填充ROS网络。
网络上有各种节点,它们都有一些主题和关联的发布者和订阅者。
您可以通过调用rostopic list查看可用主题的完整列表。
rostopic list
/pose
/rosout
/scan
/tf
如果您想了解更多关于通过/scan主题发送的数据类型的信息,请使用rostopic info命令来检查它。/scan的消息类型为sensor_msgs/LaserScan
rostopic info /scan
Type: sensor_msgs/LaserScan
Publishers:
/node_3 (http://dcc083455glnxa64:36623/)
Subscribers:
/node_1 (http://dcc083455glnxa64:42445/)
/node_2 (http://dcc083455glnxa64:39859/)
命令输出还告诉您哪些节点正在发布和订阅主题。要了解有关发布者和订阅者的信息,请参见调用和提供ROS服务。
若要了解有关主题消息类型,rosmessage支持消息类型的TAB补全。若要完成消息类型名称,请键入要完成的名称的前几个字符,然后按Tab键。
scandata = rosmessage("sensor_msgs/LaserScan","DataFormat","struct")
scandata = struct with fields:
MessageType: ‘sensor_msgs/LaserScan’
Header: [1x1 struct]
AngleMin: 0
AngleMax: 0
AngleIncrement: 0
TimeIncrement: 0
ScanTime: 0
RangeMin: 0
RangeMax: 0
Ranges: [0x1 single]
Intensities: [0x1 single]
要查看主题和服务可用的所有消息类型的完整列表,请使用rosmsg list
2. 消息结构获取
ROS消息是对象,消息数据存储在属性中。MATLAB具有方便的方法来查找和探索消息的内容。
如果订阅了/pose主题,则可以接收和检查发送的消息。
posesub = rossubscriber("/pose","DataFormat","struct")
posesub =
Subscriber with properties:
TopicName: ‘/pose’
LatestMessage: []
MessageType: ‘geometry_msgs/Twist’
BufferSize: 1
NewMessageFcn: []
DataFormat: ‘struct’
使用receive从订阅者获取数据。一旦接收到新消息,函数将返回该消息并将其存储在posedata变量中(第二个参数是以秒为单位的超时)。
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/Vector3。geometry_msgs/Twist是由两条geometry_msgs/Vector3消息组成的复合消息。
xpos = posedata.Linear.X
xpos = 0.0457
如果希望快速总结消息中包含的所有数据,请调用rosShowDetails函数。rosShowDetails适用于任何类型的消息,并递归地显示所有消息数据字段。
rosShowDetails(posedata)
ans =
‘
MessageType : geometry_msgs/Twist
Linear
MessageType : geometry_msgs/Vector3
X : 0.04571669482429456
Y : -0.001462435127715878
Z : 0.03002804688888001
Angular
MessageType : geometry_msgs/Vector3
X : -0.03581136613727846
Y : -0.007823871737372501
Z : 0.04157355251890671’
rosShowDetails在调试期间和希望快速查看消息内容时提供帮助。
3. 设置消息信息
ROS 消息是结构。可以直接复制它们以生成新的消息。副本和原始消息都有自己的数据。创建一条类型为geometry_msgs/Twist的消息。
twist = rosmessage("geometry_msgs/Twist","DataFormat","struct")
twist = struct with fields:
MessageType: ‘geometry_msgs/Twist’
Linear: [1x1 struct]
Angular: [1x1 struct]
缺省情况下,此消息的数字字段初始化为0。您可以修改此消息的任何属性。例如Y等于5。
twist.Linear.Y = 5;
查看消息数据以确保您的更改生效
twist.Linear
ans = struct with fields:
MessageType: ‘geometry_msgs/Vector3’
X: 0
Y: 5
Z: 0
一旦用您的数据填充了消息,您就可以将其用于发布者、订阅者和服务。参见“与ROS发布者和订阅者交换数据”和“调用和提供ROS服务”示例。然后就可以通过publish发布我们设置的消息信息了
thermometerNode = ros2node("/thermometer");
tempPub = ros2publisher(thermometerNode,"/twist","sensor_msgs/geometry_msgs/Twist");
tempMsgs(10) = twist; % Pre-allocate message structure array
for iMeasure = 1:10
% Copy blank message fields
tempMsgs(iMeasure) = twist;
% Record sample message
tempMsgs(iMeasure).Linear.Y = 20+randn*3;
% Only calculate the variation once sufficient data observed
if iMeasure >= 5
tempMsgs(iMeasure).Linear.X= var([tempMsgs(1:iMeasure).Linear.Y]);
end
% Pass the data to subscribers
send(tempPub,tempMsgs(iMeasure))
end
errorbar([tempMsgs.Linear.Y],[tempMsgs.Linear.X])
4. 保存和加载消息
您可以保存消息并存储内容以供以后使用。
例如从订阅者获取一条新消息。
posedata = receive(posesub,10)
然后使用MATLAB的保存函数将姿态数据保存到MAT文件中。
save('posedata.mat','posedata')
在将文件加载回工作空间之前,清除posedata变量。
clear posedata
现在可以通过调用load函数加载消息数据。这将从上面将posedata加载到messageData结构中。Posedata是结构的一个数据字段。
messageData = load('posedata.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文件