最新消息:

第1章 初识MATLAB-ROS工具箱——1.5 基本ROS消息的使用

ROS1/一代机器人系统 少儿编程 1586浏览 0评论

1.5 基本ROS消息的使用

1.5.1 引言

在ROS数据交换中消息是最主要的容器,主题(通过发布器和订阅器交换数据)和服务(请求和提供服务)都是使用消息在节点之间传递数据。
每个消息都有消息类型来确认数据结构,例如,激光扫描仪的传感器数据通常以“typesensor_msgs/LaserScan”的消息类型传递。每一个消息类型都确定了包含在消息中的数据元素。每个消息类型的名称都由包名、斜杠“/”和类型名组成,如下图5.1所示。


第1章 初识MATLAB-ROS工具箱——1.5 基本ROS消息的使用
图5.1


MATLAB支持在机器人学应用领域常见的许多ROS消息类型,在本例中,你将会在MATLAB中尝试几种创建、探索和发布ROS消息的方法。
预备知识:开始使用ROS和连接到ROS网络。

1.5.2 查找消息类型

初始化ROS主控节点和全局变量代码运行如下:
rosinit 

Initializing ROS master onhttp://bat5136glnxa64.mathworks.com:11311/. Initializing global node /matlab_global_node_8332 with NodeURIhttp://bat5136glnxa64:33534/
使用“exampleHelperROSCreateSampleNetwork”指令给ROS网络填充三个节点和发布器、订阅器例子。代码运行示例:
exampleHelperROSCreateSampleNetwork
现在系统中有了若干不同的节点和主题以及相关的发布器和订阅器。
你可以使用“rostopic list”查看所有可用的主题,“/scan”存在主题列表当中。
rostopic list /pose /rosout /scan
如果你想要进一步了解通过“/scan”主题传递的数据类型,可以使用“rostopic info/scan”指令检查。“/scan”的消息类型是“sensor_msgs/LaserScan”。代码运行示例:
rostopic info /scan Type: sensor_msgs/LaserScan

Publishers:

  • /node_3 (http://bat5136glnxa64:41995/)

Subscribers:

  • /node_1 (http://bat5136glnxa64:37841/)

/node_2 (http://bat5136glnxa64:55609/)
该指令的输出还可以看出哪些节点发布和订阅该主题,学习更多有关发布器和订阅器,请查阅通过发布器和订阅器交换数据。
为了查找更多有关主题的消息类型,可通过创建相同类型的空消息,使用“rosmessage”函数:
scandata = rosmessage('sensor_msgs/LaserScan') scandata =

ROS LaserScan message with properties:

 MessageType: 'sensor_msgs/LaserScan'
      Header: [1x1 Header]
    AngleMin: 0
    AngleMax: 0

AngleIncrement: 0 TimeIncrement: 0 ScanTime: 0 RangeMin: 0 RangeMax: 0 Ranges: [0x1 single] Intensities: [0x1 single]
创建的消息“scandata”拥有许多与激光扫描仪接收的数据相关的属性,例如,最小的传感器距离存在“RangeMin”属性,最大传感器距离存储在“RangeMax”属性。
如果你想要定义消息的类型,可以使用“rostype”指令,该指令可以方便的使用一系列消息类型。“rostype”支持tap键填充指令并能够寻找与先前的字符创匹配的消息类型。代码运行示例:
scantype = rostype.sensor_msgs_LaserScan scantype =

sensor_msgs/LaserScan
使用这个字符串,可以创建一个与之前的消息相同类型的空消息:
scandata = rosmessage(scantype) scandata =

ROS LaserScan message with properties:

   MessageType: 'sensor_msgs/LaserScan'
        Header: [1x1 Header]
      AngleMin: 0
      AngleMax: 0
AngleIncrement: 0
 TimeIncrement: 0
      ScanTime: 0
      RangeMin: 0
      RangeMax: 0
        Ranges: [0x1 single]
   Intensities: [0x1 single]

使用“rosmsg list”查看主题和服务所能使用的所有消息类型:
rosmsg list ackermann_msgs/AckermannDrive ackermann_msgs/AckermannDriveStamped actionlib_msgs/goalID actionlib_msgs/goalStatus actionlib_msgs/GoalStatusArray adhoc_communication/BroadcastCMgrRobotUpdate adhoc_communication/BroadcastCMgrRobotUpdateRequest adhoc_communication/BroadcastCMgrRobotUpdateResponse adhoc_communication/BroadcastString adhoc_communication/BroadcastStringRequest adhoc_communication/BroadcastStringResponse adhoc_communication/CMgrDimensions adhoc_communication/CMgrRobotUpdate adhoc_communication/ChangeMCMembership adhoc_communication/ChangeMCMembershipRequest adhoc_communication/ChangeMCMembershipResponse adhoc_communication/ExpAuction adhoc_communication/ExpCluster adhoc_communication/ExpFrontier adhoc_communication/ExpFrontierElement adhoc_communication/GetGroupState adhoc_communication/GetGroupStateRequest adhoc_communication/GetGroupStateResponse adhoc_communication/GetNeighbors adhoc_communication/GetNeighborsRequest adhoc_communication/GetNeighborsResponse adhoc_communication/MmControl adhoc_communication/MmListOfPoints adhoc_communication/MmMapUpdate adhoc_communication/MmPoint

1.5.3 探索消息结构和获取消息数据

ROS消息是对象,消息数据存储在属性里,MATLAB提供了方便的方法发现和探索消息里的内容。
如果你要订阅了“/scan”主题,你可以接收和检测被传输的数据。代码运行示例:
posesub = rossubscriber('/pose') posesub =

Subscriber with properties: posesub = rossubscriber('/pose')

    TopicName: '/pose'
  MessageType: 'geometry_msgs/Twist'
LatestMessage: [0x1 Twist]
   BufferSize: 1
NewMessageFcn: []

使用“receive”函数,能够从订阅器获得数据,一旦接收到新的消息,函数返回并存储数据到“posedata”变量。代码运行示例:
posedata = receive(posesub, 10) posedata =

ROS Twist message with properties:

MessageType: 'geometry_msgs/Twist'
     Linear: [1x1 Vector3]
    Angular: [1x1 Vector3]

消息的类型是“geometry_msgs/Twist”,消息中含有两个字段:“Linear”和“Angular”,你可以直接地获取消息中这些字段的值,代码运行示例:
posedata.Linear ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: 0.0438
          Y: 0.0385
          Z: 0.0520

posedata.Angular ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: -0.0288
          Y: 0.0484
          Z: 0.0528

显然,消息中的字段的每一个数值事实上本身也是个消息,消息类型是“geometry_msgs/Vector3”。“ geometry_msgs/Twist”的消息由两个“geometry_msgs/Vector3”类型的消息组成。
获得这些嵌套的消息的方法其实和获得其它消息一样,例如,获得“Linear”的组成“X”的指令:
xpos = posedata.Linear.X xpos =

0.0438

“showdetails”函数可以快速的查看消息中包含的全部数据,“showdetails”对所有消息类型均可用,并且循环地显示消息的数据属性。
showdetails(posedata)
Linear X : 0.0438049105 Y : 0.03847741206 Z : 0.052015073 Angular X : -0.02882663895 Y : 0.04838687119 Z : 0.05278724967
“showdetails”能够帮助你在调试的时候,快速地查看消息中的内容。

1.5.4 设定消息数据

你还能够设定消息属性的值,创建“geometry_msgs/Twist”类型的消息:
twist = rosmessage(rostype.geometry_msgs_Twist) twist =

ROS Twist message with properties:

MessageType: 'geometry_msgs/Twist'
     Linear: [1x1 Vector3]
    Angular: [1x1 Vector3]

消息的属性值会被默认设置为“0”,你可以任意的修改消息的属性值,例如设置“Linear.Y”的值为5。
twist.Linear.Y = 5;
显示消息的数据确认所做的修改的效果:
twist.Linear ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: 0
          Y: 5
          Z: 0

一旦消息被填充数据,你可以通过“publishers”,“ subscribers”,“ services”使用消息。查看通过发布器和订阅器交换数据和请求和提供服务的例子。

1.5.5 复制消息

有两种方式复制消息中的内容:
① 可以创建一个“reference copy”,复制的消息和原消息共享同样的数据
② 可以创建一个“deep copy”,复制的消息和原消息拥有各自的消息。
当想要在不同的函数和对象之间共享消息数据时,“reference copy”是非常有用的,而如果你想要独立的复制消息,“deep copy”是必须的方法。
使用赋值符“=”创建“reference copy”,这种方法创建的变量与原变量拥有一样的消息内容。代码运行示例:
twistCopyRef = twist twistCopyRef =

ROS Twist message with properties:

MessageType: 'geometry_msgs/Twist'
     Linear: [1x1 Vector3]
    Angular: [1x1 Vector3]

修改“twistCopyRef”的字段“Linear.Z”,发现“twist”中的相应字段的内容也发生变化:
twistCopyRef.Linear.Z = 7; twist.Linear ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: 0
          Y: 5
          Z: 7

创建一个“twist”的“deep copy”,这样在改变复制消息的内容的时候不会影响原数据。使用“copy”指令创建新消息“twistCopyDeep”:
twistCopyDeep = copy(twist) twistCopyDeep =

ROS Twist message with properties:

MessageType: 'geometry_msgs/Twist'
     Linear: [1x1 Vector3]
    Angular: [1x1 Vector3]

修改“twistCopyDeep”消息的字段“Linear.X”的内容,注意到“twist”中相应的字段没有变化:
twistCopyDeep.Linear.X = 100; twistCopyDeep.Linear ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: 100
          Y: 5
          Z: 7

twist.Linear ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: 0
          Y: 5
          Z: 7

1.5.6 保存和下载消息

你可以保存消息的内容用于后期使用。
从订阅器获得新消息:
posedata = receive(posesub,10) posedata =

ROS Twist message with properties:

MessageType: 'geometry_msgs/Twist'
     Linear: [1x1 Vector3]
    Angular: [1x1 Vector3]

使用MATLAB的“save”函数,保存姿态数据到.mat文件。
save('posedata.mat','posedata')
在重新加载文件到工作空间之前,清除“posedata”变量:
clear posedata
现在可以调用“load”函数载入消息数据,上述“posedata”数据将被载入“messageData”结构中,“posedata”是该结构的数据字段:
messageData = load('posedata.mat') messageData =

posedata: [1x1 Twist]

检查“messageData.posedata”查看消息的内容:
messageData.posedata ans =

ROS Twist message with properties:

MessageType: 'geometry_msgs/Twist'
     Linear: [1x1 Vector3]
    Angular: [1x1 Vector3]

删除MAT文件的方法如下:
delete('posedata.mat')

1.5.7 消息中的对象阵列

ROS中的一些消息存放在对象阵列中,这与典型的数据阵列不同。
在工作空间中,“tf”变量包含了一些样本消息(“exampleHelperROSCreateSampleNetwork”脚本创建该变量),本例中,这是一个表示坐标变换的:
tf tf =

ROS tfMessage message with properties:

MessageType: 'tf/tfMessage'
 Transforms: [53x1 TransformStamped]

“tf”拥有两个字段:“MessageType”包含了标准的数据阵列,“Transforms”包含了对象阵列。“Transforms”里包含了53个对象,每一个对象具有相同的结构。
展开“tf”的“Transforms“查看其结构:
tf.Transforms ans =

53x1 ROS TransformStamped message array with properties:

MessageType
Header
ChildFrameId
Transform

从代码的运行输出可以看出,“Transforms”里的每一个对象都有四个属性,查看其中的“Transform”字段:
tf.Transforms.Transform ans =

ROS Transform message with properties:

MessageType: 'geometry_msgs/Transform'
Translation: [1x1 Vector3]
   Rotation: [1x1 Quaternion]

Use showdetails to show the contents of the message

ans =

ROS Transform message with properties:

MessageType: 'geometry_msgs/Transform'
Translation: [1x1 Vector3]
   Rotation: [1x1 Quaternion]

Use showdetails to show the contents of the message

ans =

ROS Transform message with properties:

MessageType: 'geometry_msgs/Transform'
Translation: [1x1 Vector3]
   Rotation: [1x1 Quaternion]

...
注意,得到53个独立的输出,因为每一个对象都被评估并返回各自的“Transform”字段的值。这种格式并不总是有效,你可以转换如下的方法:
cellTransforms = {tf.Transforms.Transform} cellTransforms =

Columns 1 through 4

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

Columns 5 through 8

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

Columns 9 through 12

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

Columns 13 through 16

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

Columns 17 through 20

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

Columns 21 through 24

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

Columns 25 through 28

[1x1 Transform]    [1x1 Transform]    [1x1 Transform]    [1x1 Transform]

...
该方法将53个对象实体放到一个单元阵列中,这允许用户通过索引的方式访问每个对象实体。
此外,用户还可用访问标准的MATLAB向量的方法访问对象阵列的元素。
tf.Transforms(5) ans =

ROS TransformStamped message with properties:

 MessageType: 'geometry_msgs/TransformStamped'
      Header: [1x1 Header]
ChildFrameId: '/imu_link'
   Transform: [1x1 Transform]

用户可以通过下述方法访问单个阵列元素的属性:
tf.Transforms(5).Transform.Translation ans =

ROS Vector3 message with properties:

MessageType: 'geometry_msgs/Vector3'
          X: 0.0599
          Y: 0
          Z: -0.0141

1.5.8 关闭ROS网络

从ROS网络中移除示例节点、发布器、订阅器:
exampleHelperROSShutDownSampleNetwork
关闭ROS主控节点并删除全局节点:
rosshutdown Shutting down global node /matlab_global_node_8332 with NodeURIhttp://bat5136glnxa64:33534/Shutting down ROS master onhttp://bat5136glnxa64.mathworks.com:11311/.

1.5.9 下一步

如何处理图像、点云和激光扫描仪的消息,1.6 专业ROS消息的使用(下回分解)。

转自公众号:
Robot404

您必须 登录 才能发表评论!