主要内容

使用消息结构提高ROS的性能

这个示例演示了ROS消息结构的使用,以及它们与消息对象的优点和区别。

当执行初始创建、从rosbag文件读取消息结构、访问嵌套属性以及在ROS网络上执行通信操作时,消息结构比对象具有更好的性能。此外,在通过MATLAB Coder™生成代码时,消息结构是唯一支持的消息格金宝app式。

消息结构基础知识

ROS消息对象是针对每个消息类型专门定义的类的实例。

msgobj = rosmessage(“nav_msgs /路径”);班级(msgobj)
ans = ' ros.msggen.nav_msgs.Path '

对象属性包含消息的数据,每个对象类型具有定义的函数,该函数特定于ROS消息。

showdetails (msgObj)
标题邮票SEC:0 NSEC:0 SEQ:0 FlaseID:姿势

为了提高使用ROS消息的性能,引入了ROS消息结构。每个消息都是一个MATLAB®结构数据类型,具有与ROS消息对象属性相同的字段。

msgStruct = rosmessage (“nav_msgs /路径”“DataFormat”“结构”
msgStruct =结构体字段:MessageType: 'nav_msgs/Path'报头:[1x1 struct]
类(msgStruct)
ans =“结构”

更新现有代码以使用结构

为了更新使用对象的现有代码,提供了两个常用的工作流程和更新它们所需的步骤。

通信工作流程

此示例代码显示如何通过ROS网络发送和接收消息。

%设置ROS网络罗斯尼特
启动ROS核心……用时0.87623秒。在http://192.168.0.10:60500上初始化ROS master。使用NodeURI http://dcc327509glnxa64:33783/初始化全局节点/matlab_global_node_86688
stringPub = rospublisher (“/喋喋不休”“std_msgs /字符串”);stringub = Rossubscriber(“/喋喋不休”“std_msgs /字符串”);%设置消息字段并发送消息stringMsg = rosmessage (“std_msgs /字符串”);stringmsg.data =.“Hello World !”;发送(stringPub stringMsg)%等待消息被接收,然后检查值暂停(2)showdetails(stringsub.latestmessage)
数据:Hello World!

如何更新

设置发布者和订阅者的数据格式名称值参数。

stringPub = rospublisher (“/喋喋不休”“std_msgs /字符串”“DataFormat”“结构”);stringub = Rossubscriber(“/喋喋不休”“std_msgs /字符串”“DataFormat”“结构”);

的数据格式更新rosmessage函数。

stringMsg = rosmessage (“std_msgs /字符串”“DataFormat”“结构”);stringmsg.data =.“Hello World !”;发送(stringPub stringMsg)

或者,rosmessage可以使用发布者的对象函数。此语法生成遵循发布者中设置的格式的消息,这是确保消息和发布者之间兼容性的最有效方法。

stringMsg = rosmessage (stringPub);stringmsg.data =.“Hello World !”;发送(stringPub stringMsg)

因为结构没有对象函数,所以提供了新的函数来处理常见的ROS消息任务。要显示结构消息的详细信息,请使用rosShowDetails函数。要查看提供的所有新函数,请转到消息处理函数

%等待消息被接收,然后检查值(2)暂停rosShowDetails (stringSub.LatestMessage)
ans = ' MessageType: std_msgs/String Data: Hello World!'

读rosbag工作流

有关读取消息的示例rosbag,越多DataFormat的名称-值参数readMessages功能和您用于发送这些消息的任何发布商。

从ROSBAG提取消息msgtype =.“nav_msgs /测程法”;袋= rosbag (“ex_multiple_topics.bag”);BAGSELECT =选择(包,“MessageType”, msgType);odomMsgs = readMessages (bagSelect,“DataFormat”“结构”);odommsg = odommsgs {1}
odomMsg =结构体字段:message: 'nav_msgs/Odometry' Header: [1x1 struct] ChildFrameId: 'base_footprint' Pose: [1x1 struct] Twist: [1x1 struct]
创建发布者并发送第一条消息Odompub = Rospublisher(“/”奥多姆,msgtype,“DataFormat”“结构”);发送(odomPub odomMsg)

消息处理函数

由于ROS消息对象上的函数不能用于消息结构,因此引入了新的函数来处理消息。此列表包括用于从特定消息读取数据或向特定消息写入数据的函数。

行为变化

处理类vs.结构行为

转换代码时需要考虑的一个重要问题是,ROS消息对象是句柄,这意味着当作为函数的输入提供消息对象时,消息对象是通过引用传递的。如果在函数中修改了消息,则该修改也适用于MATLAB®工作空间中的消息。

msgobj = rosmessage(“geometry_msgs / pose2d”);[1 2 3];exampleHelperWritePoseToMsgObj (msgObj姿势)disp (msgObj)
ROS Pose2D消息具有属性:MessageType: 'geometry_msgs/Pose2D' X: 1 Y: 2 Theta: 3使用showdetails显示消息的内容
功能exampleHelperWritePoseToMsgObj pointMsg (pointMsg,姿势)。X =姿势(1);pointMsg。Y =姿势(2);pointMsg。θ=构成(3);结束

消息结构仅在输入功能时通过它们的值。如果在函数中修改了邮件结构,则该修改仅适用于该功能范围内的结构。要使修改可用功能,必须返回消息结构。

msgStruct = rosmessage (“geometry_msgs / pose2d”“DataFormat”“结构”);[1 2 3];%如果没有返回,消息结构将不会改变exampleHelperWritePoseToMsgObj (msgStruct姿势)disp (msgStruct)
MessageType:'geometry_msgs / pose2d'x:0 y:0 theta:0
当从函数返回时,消息可以被覆盖。msgStruct = exampleHelperWritePoseToMsgStruct(msgStruct, pose);disp (msgStruct)
MessageType: 'geometry_msgs/Pose2D' X: 1 Y: 2 Theta: 3
功能pointMsg = exampleHelperWritePoseToMsgStruct(pointMsg,pose)X =姿势(1);pointMsg。Y =姿势(2);pointMsg。θ=构成(3);结束

这也适用于专门的消息处理函数。更新消息值的write函数现在有输出参数来提供更新的消息结构。

形象= imread (“imageMap.png”);%消息对象味精= rosmessage (“sensor_msgs /形象”);味精。编码='rgb8';writeImage(味精、图像)imshow (readImage(味精))

图中包含一个轴对象。axis对象包含一个image类型的对象。

%消息结构味精= rosmessage (“sensor_msgs /形象”“DataFormat”“结构”);味精。编码='rgb8';味精= rosWriteImage(味精、图像);imshow (rosReadImage(味精))

时间和持续时间

ROS时间和持续时间消息结构不能像时间和持续时间对象那样支持操作符重载。金宝app算术和比较操作应该通过将时间或持续时间结构转换为数值秒值,执行操作,然后在必要时重新创建时间或持续时间结构来完成。

%定期更新与对象的消息时间戳味精= rosmessage (“std_msgs / header”);Runfor = Rosduration(2);tNow = rostime (“现在”);tEnd = tNow + runFor;尽管tNow < tEnd msg。邮票= tNow;%信息可以在这里发送暂停(1)tnow = rostime(“现在”);结束%使用结构定期更新消息时间戳味精= rosmessage (“std_msgs / header”“DataFormat”“结构”);runFor = 2;tNow = rostime (“现在”“DataFormat”“结构”);tnowsec = tnow.sec + tnow.nsec * 1e-9;Tendsec = Tnowsec + Runfor;尽管tNowSec < tEndSec msg。邮票= tNow;%信息可以在这里发送暂停(1)tnow = rostime(“现在”“DataFormat”“结构”);tnowsec = tnow.sec + tnow.nsec * 1e-9;结束

数据字段胁迫

对于ROS消息对象,数据字段有特定的类型。当设置数据字段值时,如果可能,将输入转换为正确的类型。否则,如果不能进行转换,则返回一个错误。

味精= rosmessage (“std_msgs / Int8”);msg.data = 20;类(msg.Data)
ans ='int8'

ROS消息结构固有地接受任何数据类型或字段名而不会出错。

味精= rosmessage (“std_msgs / Int8”“DataFormat”“结构”);味精。Data =“测试”
msg =.结构体字段:MessageType: 'std_msgs/Int8' Data: 'Test'
msg.data = 20;类(msg.Data)
ans =“双”

相反,当试图通过ROS网络发送消息时,会出现无效的数据类型错误。

酒吧= rospublisher (“/ int_topic”“std_msgs / Int8”“DataFormat”“结构”);发送(PUB,MSG)
使用ros.publisher / send(第290行)出错(第290行)错误发布具有Type STD_MSGS / INT8主题名称/ INT_TOPIC的消息。由:使用ROS.Internal.node /发布字段'数据'错误引起的类型错误类型;预计INT8。

为防止错误,请确保消息是使用邮件定义的正确数据类型。

rosmsg显示std_msgs / Int8
INT8数据

其他性能技巧

使用消息结构是加快发送和检索ROS消息的良好的第一步。结构还提高了在嵌套消息中设置和访问数据的性能。下面的代码演示了使用嵌套字段发送多个消息。

%设置网络(对所有示例重用publisher)酒吧= rospublisher (“/ goal_path”“nav_msgs /路径”“DataFormat”“结构”);给机器人发送新的路径nPtsOnPath = 100;iPaths = 1:15 pathMsg = rosmessage(pub);IPTS = 1:NPTSONPATH PATHMSG.PASE(IPTS)= ROSMESSAGE(“geometry_msgs / PoseStamped”“DataFormat”“结构”);pathMsg.Poses .Pose.Position(进行)。X = ipath +进行;pathMsg.Poses .Pose.Position(进行)。Y = iPaths-iPts;pathMsg.Poses .Pose.Position(进行)。进行Z = (ipath +) / 10;结束发送(酒吧,pathMsg)结束

重用的消息

如果在循环中创建和修改消息,并且每次迭代都设置相同的数据字段,则只创建一次消息会更快。将消息的创建移到循环之外,并在每个迭代中在循环内部重用相同的消息。

%设置要使用的消息pathMsg = rosmessage(酒吧);poseMsg = rosmessage (“geometry_msgs / PoseStamped”“DataFormat”“结构”);给机器人发送新的路径nPtsOnPath = 100;ipath = 1:15iPts = 1: nptonpath pathMsg.Poses(iPts) = poseMsg;pathMsg.Poses .Pose.Position(进行)。X = ipath +进行;pathMsg.Poses .Pose.Position(进行)。Y = iPaths-iPts;pathMsg.Poses .Pose.Position(进行)。进行Z = (ipath +) / 10;结束发送(酒吧,pathMsg)结束

提取用于操作的嵌套消息

当读取或设置嵌套消息中的多个字段时,请在读取或设置字段之前提取嵌套消息。

%设置要使用的消息pathMsg = rosmessage(酒吧);poseMsg = rosmessage (“geometry_msgs / PoseStamped”“DataFormat”“结构”);ptMsg = poseMsg.Pose.Position;%提取嵌套消息给机器人发送新的路径nPtsOnPath = 100;ipath = 1:15进行= 1:nPtsOnPath%在设置嵌套消息之前设置字段ptMsg。X = ipath +进行;ptMsg。Y = iPaths-iPts;ptMsg。进行Z = (ipath +) / 10;poseMsg.Pose.Position = ptMsg;pathMsg.Poses(进行)= poseMsg;结束发送(酒吧,pathMsg)结束

预分配消息结构数组

对于相对较大的消息数组,在循环中设置值时,预分配结构数组可以提高性能。当数组每次迭代都是固定长度时,使用此方法。

%设置要使用的消息pathMsg = rosmessage(酒吧);poseMsg = rosmessage (“geometry_msgs / PoseStamped”“DataFormat”“结构”);ptMsg = poseMsg.Pose.Position;%提取嵌套消息%preallocate路径数组nPtsOnPath = 100;pathmsg.pose(nptsonpath)= posemsg;给机器人发送新的路径ipath = 1:15进行= 1:nPtsOnPath%在设置嵌套消息之前设置字段ptMsg。X = ipath +进行;ptMsg。Y = iPaths-iPts;ptMsg。进行Z = (ipath +) / 10;poseMsg.Pose.Position = ptMsg;pathMsg.Poses(进行)= poseMsg;结束发送(酒吧,pathMsg)结束

现在可以关闭ROS网络。

rosshutdown
使用NodeURI http://dcc327509glnxa64:33783/关闭全局节点/matlab_global_node_86688