飞道的博客

【轻量级开源ROS 的机器人设备(4)】--(3)通信实现

297人阅读  评论(0)

前文链接

【轻量级开源ROS 的机器人设备(4)】--(2)通信实现_无水先生的博客-CSDN博客

六、数据流

        数据流 虽然 XML-RPC 为远程方法调用提供了一种简单而干净的协议,但其冗长和以文本为中心的编码使其不适合高带宽和低延迟任务。数据流就是这种情况,例如由传感器或执行器发送的数据流。 ROS 为此类流定义了自定义二进制协议;这允许在节点之间传输原始数据,所需的消息长度最小(带宽最大化)并且几乎没有处理时间(延迟最小化)。有关主题和服务消息语法的详细信息 。

6.1 类型描述符

         数据流基于特定类型的消息交换,在注册时由主题/服务指定(参见上一节)。消息是一系列值,按照类型描述符定义的顺序排列。 ROS中有两种,主题描述符和服务描述符。我们将首先考虑主题描述符,因为服务类型只是一个简单的扩展。 主题类型 ROS 主题消息描述符被编写为纯文本文件,其中文件名与类型名称一致,加上 .msg 扩展名。

        每行都可以定义一个强类型变量,其中类型可以是原始类型,也可以是另一个消息类型描述符的名称,甚至可以是任何此类类型的数组(固定或变量)。因此,消息可以嵌套,并且由于是强类型,它们的流式传输得到简化(无需处理动态类型)。描述符还可以声明原始类型的常量名称。      

        清单 4.3 显示了 rosgraph_msgs/msg/Log.msg 的内容,而清单 4.4 是其干净的扩展版本,由 rosmsg show 生成。

        服务类型 虽然主题是单向的,因此只需要定义一种消息类型,但服务以请求/响应方式工作


  
  1. 1 ##
  2. 2 ## Severity level constants
  3. 3 ##
  4. 4 byte DEBUG= 1 #debug level
  5. 5 byte INFO= 2 #general level
  6. 6 byte WARN= 4 #warning level
  7. 7 byte ERROR= 8 #error level
  8. 8 byte FATAL= 16 #fatal/critical level
  9. 9 ##
  10. 10 ## Fields
  11. 11 ##
  12. 12 Header header
  13. 13 byte level
  14. 14 string name # name of the node
  15. 15 string msg # message
  16. 16 string file # file the message came from
  17. 17 string function # function the message came from
  18. 18 uint32 line # line the message came from
  19. 19 string[] topics # topic names that the node publishes

Listing 4.3: Contents of rosgraph_msgs/msg/Log.msg


  
  1. byte DEBUG= 1
  2. 2 byte INFO= 2
  3. 3 byte WARN= 4
  4. 4 byte ERROR= 8
  5. 5 byte FATAL= 16
  6. 6 std_msgs/Header header
  7. 7 uint32 seq
  8. 8 time stamp
  9. 9 string frame_id
  10. 10 byte level
  11. 11 string name
  12. 12 string msg
  13. 13 string file
  14. 14 string function
  15. 15 uint32 line
  16. 16 string[] topics

Listing 4.4: Clean, expanded contents of rosgraph_msgs/msg/Log.ms

        因此,服务涉及两种类型,一种用于请求,一种用于响应。服务类型描述符的存储方式与主题类型类似,但扩展名为 .srv。描述符被 -- 分隔线分成两部分,其中第一部分是请求消息描述符,第二部分是响应消息描述符。清单 4.5 是 dynamic_reconfigure/srv/Reconfigure.srv 内容的示例,而清单 4.6 是其干净的扩展版本,由 rossrv show 生成。

        散列 因为节点之间的描述符文本可能不同,而它们的名称可以相同,所以必须有一种方法来确定两个节点是否实际上共享相同的类型。对于此类任务,选择 MD5 和来比较两种不同的类型描述。比较函数对每个类型描述符执行以下操作:

1.评论被删除;

2. 去除空格;

3.去除依赖包名;

4. 常量移到变量声明之前,保持它们的排列;

5. 对于嵌套类型,计算它们的散列文本并按照它们出现的顺序附加到当前散列文本;

6.计算整个哈希文本的MD5和。如果 MD5 和相同,则两个描述符相等。


  
  1. 1 Config config
  2. 2 ---
  3. 3 Config config
  4. Listing 4.5: Contents of dynamic_reconfigure/srv/Reconfigure.srv

  
  1. 1 dynamic_reconfigure/Config config
  2. 2 dynamic_reconfigure/BoolParameter[] bools
  3. 3 string name
  4. 4 bool value
  5. 5 dynamic_reconfigure/IntParameter[] ints
  6. 6 string name
  7. 7 int32 value
  8. 8 dynamic_reconfigure/StrParameter[] strs
  9. 9 string name
  10. 10 string value
  11. 11 dynamic_reconfigure/DoubleParameter[] doubles
  12. 12 string name
  13. 13 float64 value
  14. 14 dynamic_reconfigure/GroupState[] groups
  15. 15 string name
  16. 16 bool state
  17. 17 int32 id
  18. 18 int32 parent
  19. 19 ---
  20. 20 dynamic_reconfigure/Config config
  21. 21 dynamic_reconfigure/BoolParameter[] bools
  22. 22 string name
  23. 23 bool value
  24. 24 dynamic_reconfigure/IntParameter[] ints
  25. 25 string name
  26. 26 int32 value
  27. 27 dynamic_reconfigure/StrParameter[] strs
  28. 28 string name
  29. 29 string value
  30. 30 dynamic_reconfigure/DoubleParameter[] doubles
  31. 31 string name
  32. 32 float64 value
  33. 33 dynamic_reconfigure/GroupState[] groups
  34. 34 string name
  35. 35 bool state
  36. 36 int32 id
  37. 37 int32 parent
  38. Listing 4.6: Clean, expanded contents of dynamic_reconfigure/srv/Reconfigure.srv

  
  1. ROS type C99 type
  2. uint8 uint8_t
  3. uint16 uint16_t
  4. uint32 uint32_t
  5. uint64 uint64_t
  6. int8 int8_t
  7. int16 int16_t
  8. int32 int32_t
  9. int64 int64_t
  10. time uros_time_t
  11. duration uros_time_t
  12. string struct UrosString { size_t length; char *datap; };
  13. type[] struct UrosTcpRosArray { uint32_t length; void *entriesp; };
  14. byte uint8_t
  15. char char
  16. uint uint32_t
  17. int int32_t
  18. Table 4.1: ROS to C type mapping

6.2 消息数据结构:( Message structure )

        消息以小端二进制形式序列化。这使得市场上大多数小端 CPU 架构(例如基于 x86 或 ARM 设计的架构)的处理变得简单。因此,数据流消息很像 C 结构变量的序列化;例如,在 x86 架构上,消息是变量本身的一对一转储,因为内存中的 8 位字段对齐(相比之下,ARM 内核为 32 位)。

        基本类型可以直接映射到 C 类型,如表 4.1 所示。可变长度数组和字符串(字符数组)是一种特殊情况,因为它们提供 uint32 长度的条目数,后跟序列化条目本身。相比之下,固定长度数组被视为指定类型的条目序列。任何嵌套类型都被扩展为它们各自的基本类型或数组。

        在刚刚描述的消息内容之前,uint32 值预计内容本身的总长度。

6.3 话题消息:Topic messages

        主题消息简单地遵循上面描述的长度+内容方案,因为主题涉及相同类型的单向消息。 “你好,世界!”的一个例子std_msgs/String 类型的消息如图 4.4 所示。流偏移量以粗体字写为十六进制索引;如果可打印,值将写为 ASCII 字符,否则将写为十六进制数字。右侧的注释表示正在流式传输的特定字段及其人类可读的值。


  
  1. 00 01 02 03 uint32 message_length
  2. 11 00 00 00 17
  3. 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 string data
  4. 0D 00 00 00 H e l l o , W o r l d ! 13 "Hello, World!"
  5. Figure 4.4: Dump of a "Hello, World!" message of type std_msgs/String

  
  1. 00 01 02 03 uint32 message_length
  2. 10 00 00 00 16
  3. 04 05 06 07 08 09 0 A 0 B int64 a
  4. D2 04 00 00 00 00 00 00 1234
  5. 0 C 0 D 0 E 0 F 10 11 12 13 int64 b
  6. 2 E 16 00 00 00 00 00 00 5678
  7. Figure 4.5: Dump of a call to service of type rospy_tutorials/ AddTwoInts

        服务消息 服务请求的序列化方式与主题消息相同。相反,响应的序列化需要考虑响应的状态,它可以是实际的响应值,也可以是错误消息。

        在响应之前发送一个所谓的 ok 字节。如果为 1,则表示后面的流数据是预期的服务响应类型。如果为 0 则表示在处理请求时发生错误,后面的流值是字符串类型,代表人类可读的错误文本。

        rospy_tutorials/AddTwoInts服务请求和响应示例如图4.5和图4.6所示。相反,可以在图 4.7 中看到报告未知错误的服务响应。

6.4 连接头 Connection header

        一旦主题/服务客户端和相关服务器连接,它们就必须就流参数达成一致。它们包括主题/服务名称和类型、多个服务请求的可能性、带宽优化的使用等。所有这些参数都由连接标头设置,连接标头是两个端点在整个流的最开始发送的特殊消息。首先,客户端发送一个标头,作为一个请求。然后服务器将使用另一个标头进行回复,该标头充当响应。

        连接标头由字段组成。它们像字符串一样被编码,因此告诉字符串长度的 uint32 在字符串字符之前发送。该值遵循 field=value 格式,其中可用字段及其语义取决于主题/服务请求/响应标头。连接标头由一个包含整个标头长度的 uint32 引入,就像普通消息一样。


  
  1. 00 uint8 ok
  2. 01 acknowledge
  3. 01 02 03 04 uint32 message_length
  4. 08 00 00 00 8
  5. 05 06 07 08 09 0A 0B 0C int64 sum
  6. 00 1B 00 00 00 00 00 00 6912

 Figure 4.6: Dump of the response to the service call of Figure 4.5


  
  1. Figure 4.6: Dump of the response to the service call of Figure 4.5
  2. 00 uint8 ok
  3. 00 error
  4. 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 string error_text
  5. 0D 00 00 00 U n k n o w n e r r o r 13 "Unknown error"

 Figure 4.7: Dump of a service error response

        表 4.2 总结了连接标头的字段及其存在,在主题、服务或错误标头 (X) 中,其中一些是可选的 ((X))或者可以通过请求标头探测(字段值等于 *)。
        图 4.8 和图 4.9 分别显示了 /turtlesim 节点的 /turtle1/command_velocity 的请求和响应连接头,通过 turtlesim_teleop 节点。


  
  1. 00 01 02 03 uint32 header_length
  2. 91 00 00 00 145
  3. 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A ( string field)
  4. 13 00 00 00 c a l l e r i d = / t u r t l e s i m
  5. 1B 1C 1D 1E 1F 20 21 22 23 24 25 ( string field)
  6. 27 00 00 00 m d 5 s u m =
  7. 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35
  8. 9 d 5 c 2 d c d 3 4 8 a c 8 f 7
  9. 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45
  10. 6 c e 2 a 4 3 0 7 b d 6 3 a 1 3
  11. 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 ( string field)
  12. 0D 00 00 00 t c p _ n o d e l a y = 0
  13. 57 58 59 5A 5B 5C 5D 5E 5F 60 ( string field)
  14. 1F 00 00 00 t o p i c =
  15. 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79
  16. / t u r t l e 1 / c o m m a n d _ v e l o c i t y
  17. 7A 7B 7C 7D 7E 7F 80 81 82 ( string field)
  18. 17 00 00 00 t y p e =
  19. 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94
  20. t u r t l e s i m / V e l o c i t y

                Figure 4.8: Dump of a connection header request


  
  1. 00 01 02 03 uint32 header_length
  2. A5 00 00 00 165
  3. 04 05 06 07 08 09 0A 0B 0C 0D 0E 0 F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E
  4. 13 00 00 00 c a l l e r i d = / t e l e o p _ t u r t l e
  5. 1 F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C
  6. 0A 00 00 00 l a t c h i n g = 0
  7. 2D 2E 2 F 30 31 32 33 34 35 36 37
  8. 27 00 00 00 m d 5 s u m =
  9. 38 39 3A 3B 3C 3D 3E 3 F 40 41 42 43 44 45 46 47
  10. 9 d 5 c 2 d c d 3 4 8 a c 8 f 7
  11. 48 49 4A 4B 4C 4D 4E 4 F 50 51 52 53 54 55 56 57
  12. 6 c e 2 a 4 3 0 7 b d 6 3 a 1 3
  13. 58 59 5A 5B 5C 5D 5E 5 F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E
  14. 32 00 00 00 m e s s a g e _ d e f i n i t i o n =
  15. 6 F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D
  16. f l o a t 3 2 l i n e a r \n
  17. 7E 7 F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D
  18. f l o a t 3 2 a n g u l a r \n
  19. 8E 8 F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9 F A0 A1 A2 A3 A4 A5 A6 A7 A8
  20. 17 00 00 00 t y p e = t u r t l e s i m / V e l o c i t y

        Figure 4.9: Dump of a response to the connection header in Figure 4.8


转载:https://blog.csdn.net/gongdiwudu/article/details/128323480
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场