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

时间:2022-12-15 17:50:57

前文链接

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

三、 通信概要

        概述 ROS 的通信层是 ros_comm 堆栈的一部分,遵循发布/订阅范式,如图 2.2 所示。网络,也称为计算图,涉及多个物理或虚拟节点,它们被分配了一个唯一的名称。节点是从其输入收集数据、执行计算并为其输出生成数据的过程。每个节点专用于特定功能,不依赖于其他节点的存在(纯模块化设计)。一个节点可以发布一些主题,其他节点可以订阅这些主题;服务以类似的方式工作。主题和服务被分配了一个已知类型,与它们各自的 ROS 包(例如,std_msgs/Float)一起交付。例如,考虑一个简单的自主漫游车,配备两个电机、一组距离传感器和托管 ROS 框架的大脑计算机。一个可能的 ROS 网络可以由每个传感器或*的节点以及机器人大脑的节点组成。让我们假设每个 sensor_X 节点发布一个名为 sensor_X/distance 的主题,其中 X 是传感器本身的标识符。该实现以固定速率对实际传感器测量的值进行采样,将其转换为为主题公布的表示形式,然后将编组消息发送给主题订阅者。以类似的方式,每个 wheel_Y 节点都订阅一个名为 wheel_Y/speed 的主题,参考第 Y 个车轮的速度。该实现不断接收订阅的主题消息,将其未编组的速度值转换为电压,并将后者应用于车轮直流电机以获得通信速度。相反,大脑节点订阅所有 sensor_X/distance 主题,并发布所有 wheel_Y/speed 主题。它的实现可以遵循一个合适的逻辑,该逻辑通过传感器测量的距离来确定车轮速度,例如在避开障碍物的同时移动机器人。现在读者应该可以推断出它的通信流程。

        还可以存在一些全局声明的服务(一种特殊的请求/响应主题)和参数。例如,大脑节点发布了service sleeping 如果机器人处于空闲状态则回复 true,否则回复 false机器人完全可以运行。这样,ensor_X 和 wheel_Y 节点就可以调用休眠服务,如果响应是,则关闭它们的硬件模块真的。同样,一个名为max_speed 的全局参数保存最大速度值,用于校准车轮模块的行为。
        一个特殊的节点,即主节点,在将发布者和订阅者连接在一起时充当集中调度器。它跟踪发布/订阅主题/服务,在当前的实现中,它也是集中式的全局定义参数的目录(参数服务器)。
        与主节点的通信是通过交换XML-RPC 消息,通过远程过程调用。主题与服务对等点之间的数据流以自定义协议 TCPROS 编码。两个都下面将详细解释这些协议。 ROS连接地址以 URI 格式发送。

四、远程过程

        远程过程调用 ROS 节点能够调用远程过程,可通过节点自身公开的 API 调用。远程过程调用是通过使用 XML-RPC 协议执行的,它是 XML 规范的一个子集(有关其 XML 模式和 DTD,请参阅附录 B.1)。这些调用用于管理计算图的状态和一些全局设置,不适用于实际数据流(使用 TCPROS 或 UDPROS)。 XML-RPC 之所以被 ROS 的设计者选中,是因为它支持的语言非常多。使用 XML 作为其基础使得它易于人为调试,其纯文本的特性使其不受传输层编码格式的影响;事实上,它被封装在 HTTP 传输中,它更喜欢纯文本内容。此外,XML-RPC 调用是无状态的,这是一种简化控制逻辑的属性,因为没有状态需要跟踪。在语言方面,它的 XML 标签遵循严格的语法规则,并且没有任何属性。这些特性使它的解析比 XML 容易得多,同时保留了它的大部分优点。

4.1  角色

         每个 ROS 节点都托管一个 XML-RPC 服务器。根据角色的不同,可调用方法集也不同,它们由适当的 API 定义。主 API 公开由唯一主节点管理的方法,例如用于(取消)注册主题和服务的方法。 Slave API 声明了由通用节点(Slave)管理的方法,例如请求建立主题流,或关闭命令。参数服务器 API 由唯一的参数服务器使用,它管理共享全局参数的集中目录。(有关 API 的详细信息在其它文中给出)。

4.2 值的类型

        值类型 在 XML-RPC 中,方法参数和返回值包含在值实体中,并且只能属于一小组类型(值子项):

• string 是一个 ASCII 字符串。这是默认值类型,除非另有说明。唯一的非法字符是 & 和 <,分别编码为 & 和 <。

•  int 或 i4 是一个 32 位有符号整数,以十进制表示,如果为负数,则以 - 为前缀。

•  布尔值可以是 0 或 1。

• double 是一个实数,以十进制表示,如果为负数,则以 - 为前缀。

•  dateTime.iso8601 是日期/时间值,采用 ISO-8601 格式。

•  base64 是使用 Base64 算法编码的二进制字符串。

• array 是一个值列表,全局包含在一个数据实体中。

• struct,也叫map,是一个关联集合。每个条目都是一个成员,具有名称字符串和通用值。

4.3 请求和响应( Request 和 response)

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

        请求和响应远程过程调用包括两个阶段:请求和响应。调用者(客户端)将方法请求发送给被调用者(服务器),后者处理它。处理完成后,被调用者返回一个response,如果成功可以是调用结果,如果不成功则返回fault。请求由 methodCall 实体引入,其方法名称由 methodName 字符串指定。在方法名称之后,params 实体包含一个参数子项列表,其中每个子项都包含一个值。列出的 params 是方法参数,取决于 API 规范。通常,第一个参数是计算图中调用节点的名称。响应包含远程方法返回的值。在 ROS 中,值是一个包含三个字段的数组。第一个字段,状态代码,是具有以下值之一的整数:

• -1 如果调用者出错,例如由于错误的 API 方法名称、参数或类型。该方法根本不执行。

• 如果远程执行方法调用失败则为 0 节点。

• 1 如果调用成功。

        第二个字段是状态字符串,一个人类可读的文本,解释了状态代码值的原因。它的值是可选的(可以为空)。第三个字段,返回值,包含返回的实际 XML-RPC 值通过方法调用。其含义由特定的API定义。如果响应是 XML-RPC 故障,则表示存在硬错误,通常是一个不符合 XML-RPC 的请求。图 4.1 显示了 XML-RPC 调用 getPid() 的示例,其中请求和响应转储分别在清单 4.1 和清单 4.2 中。

1 POST /RPC2 HTTP/1.1
2 Content-Type: text/xml
3 Content-Length: 178
4
5 <?xml version="1.0"?>
6 <methodCall>
7 <methodName>getPid</methodName>
8 <params>
9 <param>
10 <value><string>/rosnode</string></value>
11 </param>
12 </params>
13 </methodCall>

                 Listing 4.1: Example of getPid() XML-RPC call contents over HTTP

1 HTTP/1.1 200 OK
2 Content-Type: text/xml
3 Content-Length: 309
4
5 <?xml version="1.0"?>
6 <methodResponse>
7 <params>
8 <param>
9 <value>
10 <array>
11 <data>
12 <value><i4>1</i4></value>
13 <value></value>
14 <value><i4>6544</i4></value>
15 </data>
16 </array>
17 </value>
18 </param>
19 </params>
20 </methodResponse>

        Listing 4.2: Example of getPid() XML-RPC response contents over HTTP

五、链接模式

        连接模式 节点本身没有任何用途,需要以某种方式连接到其他节点。下面展示了一个通用的通信模式,让一个节点连接到它的对等节点,并最终实例化所需的主题数据流。一种特殊情况涉及服务调用。在将节点引入计算图后,该节点必须将其发布和/或订阅的主题注册到主节点。

        每个主题发布者通过 registerPublisher() 远程过程调用注册,而每个主题订阅者通过 registerSubscriber() 调用注册。因此,Master 是无所不知的,可以将同一主题的发布者和订阅者连接在一起。每当节点将其订阅的主题注册到主节点时,成功的响应包括已注册的发布者 URI 列表。然后调用者节点可以连接到这些发布者以接收主题消息。每当新的发布者向 Master 注册时,Master 都会向订阅者发出 publisherUpdate() 调用,并提供可用发布者 URI 的更新列表。主题消息流由 TCPROS 协议交换。

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

        一个对称的案例是注销。出版商通过注销对主节点的 unregisterPublisher() 远程过程调用,同时订阅者通过 unregisterSubscriber() 调用取消注册。由方式,由发布者和订阅者关闭任何已建立的数据流对于未注册的主题。
        服务的工作方式略有不同。可以发布相同的服务多个节点,但只考虑最后一个广告。一个
愿意调用服务的节点首先由Master查找服务URI,通过 lookupService() 远程调用。然后,它实际上调用了服务通过适当的请求消息提供者。服务提供者进程请求并生成响应消息,如果成功;否则,一个回复带有错误消息的响应。所有这些消息都被交换通过 TCPROS 协议,其中响应以附加的 ok 为首byte(区分成功或失败)。

六、 Data streams(后续文章... ... )