ROS 和 ROS2 架构和通信

ROS 和 ROS2 架构和通信

  • 1. ROS 架构设计
    • 1.1 OS 层
    • 1.2 中间层
    • 1.3 应用层
  • 2. ROS 的通信机制
    • 2.1 话题通信机制
      • 2.1.1 Talker 注册
      • 2.1.2 Listener 注册
      • 2.1.3 ROS Master 进行信息匹配
      • 2.1.4 Listener 发送连接请求
      • 2.1.5 Talker 确认连接请求
      • 2.1.6 Listener 尝试与 Talker 建立网络连接
      • 2.1.7 Talker 向 Listener 发布数据
    • 2.2 服务通信机制
      • 2.2.1 Talker 注册
      • 2.2.2 Listener 注册
      • 2.2.3 ROS Master 进行信息匹配
      • 2.2.4 Listener 尝试与 Talker 建立网络连接
      • 2.2.5 Talker 向 Listener 发布数据
    • 2.3 参数管理机制
      • 2.3.1 Talker 设置变量
      • 2.3.2 Listener 查询参数值
      • 2.3.3 ROS Master 向 Listener 发送参数值
    • 2.4 话题与服务的区别
  • 3. ROS 2 的系统架构
    • 3.1 OS 层
    • 3.2 中间层
    • 3.3 应用层
  • 4. ROS 2 的关键中间件----DDS
  • 5. ROS 2 的通信模型
    • 5.1 参与者(Participant)
    • 5.2 发布者(Publisher)
    • 5.3 订阅者(Subscriber)
    • 5.4 数据写入器(DataWriter)
    • 5.5 数据读取器(DataReader)
    • 5.6 话题(Topic)
    • 5.7 质量服务原则(Quality of Service)
  • 6. 什么是 RPC
    • 6.1 本地过程调用
    • 6.2 远程过程调用
      • 6.2.1 大致过程如下
    • 6.3 RPC 与 TCP

Reference:

  1. 胡春旭 《ROS 机器人开发实践》
  2. What is ROS 2.0 ?
  3. 什么是RPC?
  4. Connected: An Internet Encyclopedia — RPC Protocol Overview

1. ROS 架构设计

ROS 架构如下图所示,可以将其分为三个层次:OS 层、中间层和应用层。
ROS 和 ROS2 架构和通信_第1张图片

1.1 OS 层

ROS 并不是传统意义上的操作系统,无法像 Windows、Linux 一样直接运行在计算机硬件智商,而是需要依托于Linux 系统。所以在 OS 层,我们可以直接使用 ROS 官方支持度最好的 Ubuntu 操作系统,也可是使用 macOS, Arch, Debian 等操作系统。

1.2 中间层

Linux 是一个通用系统,并没有针对机器人开发提供特殊的中间件,所以 ROS 在中间层做了大量工作,其中最重要的就是基于 TCPROS/UDPROS 的通信系统。ROS 的通信系统基于 TCP/UDP 网络,在此智商进行了再次封装,也就是 TCPROS/UDPROS。通信系统使用 发布/订阅、客户端/服务器 等模型,实现多种通信机制的数据传输。

除了 TCPROS/UDPROS 的通信机制外,ROS 还提供一直进程内的通信方法-----Nodelet,可以为多进程通信提供一种更优化的数据传输方式,适合对数据传输实时性方面有较高要求的应用。

在通信机制上,ROS 提供了大量机器人开发相关的库,如数据类型定义、坐标变换、运动控制等,可以提供给应用层使用。

1.3 应用层

在应用层,ROS 需要运行一个管理者-----Master,负责管理整个系统的正常运行。ROS 社区内共享了大量的机器人应用功能包,这些功能包内的模块以节点为单位运行,以 ROS 标准的输入输出作为接口,开发者不需要关注模块的内部实现机制,只需要了解接口规则即可实现复用,极大地提高了开发效率。

2. ROS 的通信机制

接下来着重研究 ROS 的核心----分布式通信机制

ROS 是一个分布式框架,为用户提供多节点(进程)之间的通信服务,所有软件功能和工具都建立在这种分布式通信机制上,所以 ROS 的通信机制是最底层也是最核心的技术。在大多数应用场景下,尽管我们不需要关注底层通信的实现机制,但是了解其相关原理一定会帮助我们在开发过程中更好的使用 ROS。以下就 ROS 最核心的三种通信机制进行介绍。

2.1 话题通信机制

话题在 ROS 中使用最为频繁,其通信模型也较为复杂。如下图所示,在 ROS 中有两个节点:一个是发布者 Talker,另一个是订阅者 Listener。两个节点分别发布、订阅同一个话题,启动顺序没有强制要求,此处假设 Talker 首先启动,可分成图中所示的七步来分析建立通信的详细过程。

ROS 和 ROS2 架构和通信_第2张图片

2.1.1 Talker 注册

Talker 启动,通过 1234 端口使用 RPC 向 ROS Master 注册发布者的信息,包含所发布消息的话题名;ROS master 会将节点的注册信息加入注册列表中。

2.1.2 Listener 注册

Listener 启动,同样通过 RPC 像 ROS Master 注册订阅者的信息,包含需要订阅的话题名。

2.1.3 ROS Master 进行信息匹配

Master 根据 Listener 的订阅信息从注册列表中进行查找,如果没有找到匹配的发布者,则等待发布者的加入;如果找到匹配的发布者信息,则通过 RPC 向 Listener 发布 Talker 的 RPC 地址信息。

2.1.4 Listener 发送连接请求

Listener 接收到 Master 发回的 Talker 地址信息,尝试通过 RPC 向 Talker 发送连接请求,传输订阅的话题名、消息类型以及通信协议(TCP/UDP)。

2.1.5 Talker 确认连接请求

Talker 接收到 listener 发送的连接请求后,继续通过 RPC 向 Listener 确认链接信息,其中包含自身的 TCP 地址信息。

2.1.6 Listener 尝试与 Talker 建立网络连接

Listener 接收到确认信息后,使用 TCP 尝试与 Talker 建立网络连接。

2.1.7 Talker 向 Listener 发布数据

成功建立连接后,Talker 开始向 Listener 发送话题消息数据。

从上面的分析中可以发现,前五个步骤使用的通信协议都是 RPC,最后发布数据的过程才使用到 TCP。ROS Master 在节点建立连接的过程中起到了重要作用,但是并不参与节点之间最终的数据传输。

2.2 服务通信机制

服务是一种带有应答的通信机制,通信原理如下图所示,与话题的通信相比,其减少了 Listener 与 Talker 之间的 RPC 通信。

ROS 和 ROS2 架构和通信_第3张图片

2.2.1 Talker 注册

Talker 启动,通过 1234 端口使用 RPC 向 ROS Master 注册发布者的信息,包含所发布消息的话题名;ROS master 会将节点的注册信息加入注册列表中。

2.2.2 Listener 注册

Listener 启动,同样通过 RPC 像 ROS Master 注册订阅者的信息,包含需要订阅的服务名。

2.2.3 ROS Master 进行信息匹配

Master 根据 Listener 的订阅信息从注册列表中进行查找,如果没有找到匹配的服务提供者,则等待该服务提供者的加入;如果找到匹配的服务提供者信息,则通过 RPC 向 Listener 发布 Talker 的 TCP 地址信息。

2.2.4 Listener 尝试与 Talker 建立网络连接

Listener 接收到确认信息后,使用 TCP 尝试与 Talker 建立网络连接,并发送服务的请求数据。

2.2.5 Talker 向 Listener 发布数据

Talker 接收到服务请求和参数后,开始执行服务功能,执行完成后,向 Listener 发送应答数据。

2.3 参数管理机制

参数类似于 ROS 中的全局变量,由 ROS Master 进行管理,其通信机制较为简单,不涉及 TCP/UDP 的通信。
ROS 和 ROS2 架构和通信_第4张图片

2.3.1 Talker 设置变量

Talker 使用 RPC 向 ROS Master 发送参数设置数据,包含参数名和参数值;ROS Master 会将参数名和参数值保存到参数列表中。

2.3.2 Listener 查询参数值

Listener 通过 RPC 向 ROS Master 发送参数查找请求,包含索要查找的参数名。

2.3.3 ROS Master 向 Listener 发送参数值

Master 根据 Listener 的查找请求从参数列表中进行查找,查找到参数后,使用RPC 将参数数值发送给 Listener。

这里需要注意的是,如果 Talker 向 Master 更新参数值,Listener 在不重新查询参数值的情况下是无法知晓参数值已经被更新的。所以在很多场景中,需要一种动态参数更新机制。

2.4 话题与服务的区别

话题和服务是 ROS 中最基础也是使用最多的通信方法,具体总结如下:

条目 话题 服务
同步性 异步 同步
通信模型 发布/订阅 客户端/服务器
反馈机制
底层协议 ROSTCP/ROSUDP ROSTCP/ROSUDP
缓冲区
实时性
节点关系 多对多 一对多(一个Server)
使用场景 弱逻辑处理,多数据传输 强逻辑处理,少数据传输

总之,话题是 ROS 中基于 发布/订阅 模型的异步通信模式,这种方式将信息的产生和使用双方解耦,常用于不断更新的、含有较少逻辑处理的通信数据;而服务多用于处理 ROS 中的同步通信,采用 客户端/服务器 模型,常用于数据量较小但有强逻辑处理的数据交换。

3. ROS 2 的系统架构

ROS 2 重新设计了系统架构,图再搬来一次。
ROS 和 ROS2 架构和通信_第5张图片

3.1 OS 层

ROS 1 主要构建在 Linux 上;ROS 2 支持构建的系统主要包括 Linux、Windows、macOS、RTOS,甚至没有操作系统的裸机。

3.2 中间层

ROS 中最重要的一个概念就是计算图中的“节点”,它可以让开发者并行开发低耦合的功能模块,并且便于二次复用。ROS 1 的通信系统基于 TCPROS/UDPROS,而 ROS 2 的通信系统基于 DDS。DDS 是一种分布式实时系统中数据 发布/订阅 的标准解决方案。ROS 2 内部提供了 DDS 的抽象层实现,用户无需关注底层 DDS 的提供厂家。

在 ROS 1 架构中,Nodelet 和 TCPROS/UDPROS 是并列的层次,可以为同一个进程中的多个节点提供一种更优化的数据传输方式。ROS 2 中也保留了类似的数据传输方式,命名为“Intra-process”,同样独立于 DDS。

3.3 应用层

ROS 1 强依赖与 ROS Master,因此可以想象,一旦 Master 宕机,整个系统会面临怎样的窘境。但是在 ROS 2 架构中,让人根根于怀的 Master 终于消失了,节点之间使用一种称为 “Discovery” 的发现机制来帮助彼此建立连接。

4. ROS 2 的关键中间件----DDS

DDS(Data Distribution Service),即数据分发服务,2004年由对象管理组织OMG(Object Management Group)发布,是一种专门为实时系统设计的数据 分发/订阅 标准。

DDS 最早应用于美国海军,解决舰船复杂网络环境中大量软件升级的兼容性问题,目前已经成为美国国防部的强制标准,同时广泛应用于国防、民航、工业控制等领域,成为分布式实时系统中数据发布/订阅的标准解决方案。

其技术关键是以数据为核心的 发布/订阅 模型(Data-Centric Publish-Subscribe ,DCPS),这种 DCPS 模型创建了一个“全局数据空间”(global data space)的概念,所有独立的应用都可以访问。

5. ROS 2 的通信模型

ROS 1的通信模型主要包含话题、服务等通信机制,ROS 2的通信模型会稍显复杂,加入了很多DDS的通信机制。如下图所示:
ROS 和 ROS2 架构和通信_第6张图片基于 DDS 的 ROS 2 通信模型包含以下几个关键概念。

5.1 参与者(Participant)

在 DDS 中,每一个发布者或者订阅者都成为参与者,对应于一个使用 DDS 的用户,可以使用某种定义好的数据类型来 读/写 全局数据空间。

5.2 发布者(Publisher)

数据发布的执行者,支持多种数据类型的发布,可以与多个数据写入器(DataWriter)相联,发布一种或多种主题(Topic)的消息。

5.3 订阅者(Subscriber)

数据订阅的执行者,支持多种数据类型的订阅,可以与多个数据读取器(DataReader)相联,订阅一种或多种主题(Topic)的消息。

5.4 数据写入器(DataWriter)

上层应用向发布者更新数据的对象,每个数据写入器对应一个特定的Topic,类似于ROS 1中的一个消息发布者。

5.5 数据读取器(DataReader)

上层应用从订阅者读取数据的对象,每个数据读取器对应一个特定的Topic,类似于ROS 1中的一个消息订阅者。

5.6 话题(Topic)

和 ROS 1 中的概念类似,话题需要定义一个名称和一种数据结构,但 ROS 2 中的每个话题都是一个实例,可以存储该话题中的历史消息数据。

5.7 质量服务原则(Quality of Service)

简称 QoS Policy,这是 ROS 2 中新增的、也是非常重要的一个概念,控制各方面与底层的通信机制,主要从时间限制、可靠性、持续性、历史记录这几个方面,满足用户针对不同场景的数据需求。
ROS 和 ROS2 架构和通信_第7张图片

  • 实时性增强:数据必须在 deadline 之前完成更新;
  • 持续性增强:DDS 可以为 ROS 2 提供数据历史服务,新加入的节点也可以获取发布者发布的所有历史数据;
  • 可靠性增强:配置可靠性原则,用户可以根据需求选择性能模式(BEST_EFFORT)或者稳定模式(RELIABLE)。

6. 什么是 RPC

RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务,而不需要了解底层网络技术的思想。RPC 是一种技术思想而非一种规范或协议(按理来说 RPC 也是一种协议才对?)。

6.1 本地过程调用

如果需要将本地 student 对象的 age+1,可以实现一个 addAge() 方法,将 student 对象传入,对年龄进行更新之后返回即可,本地方法调用的函数体通过函数指针来指定。

6.2 远程过程调用

上述操作的过程中,如果 addAge() 这个方法在服务端,执行函数的函数体在远程机器上,该如何告诉机器需要调用这个方法呢?

  1. 首先客户端需要告诉服务器,需要调用的函数,这里函数和进程 ID 存在一个映射,客户端远程调用时,需要查一下函数,找到对应的 ID,然后执行函数的代码;
  2. 客户端需要把本地参数传给远程函数,本地调用的过程中直接压栈即可,但是在远程调用过程不再在同一个内存里,无法直接传递函数的参数,因此需要客户端把参数转换成字节流,传给服务端,然后服务端将字节流转换成自身能读取的格式,是一个序列化和反序列化的过程。
  3. 数据准备好了之后,如何进行传输?网络传输层需要把调用的 ID序列化后的参数传给服务器,然后把计算好的结果序列化传给客户端,因此 TCP 层即可完成上述过程,gRPC 中采用的是 HTTP2 协议。

6.2.1 大致过程如下

Client端
// Student student = Call(ServerAddr, addAge, student)

  1. 将这个调用映射为 Call ID;
  2. 将 Call ID,student(params) 序列化,以二进制形式打包;
  3. 把 2 中得到的数据包发送给 ServerAddr,这需要使用网络传输层;
  4. 等待服务器返回结果;
  5. 如果服务器调用成功,那么就将结果反序列化,并赋给 student,年龄更新。

Server 端

  1. 在本地维护一个 Call ID 到函数指针的映射 call_id_map,可以用 Map callIdMap;
  2. 等待客户端请求;
  3. 得到一个请求后,将其数据包反序列化,得到 Call ID;
  4. 通过在 callIdMap 中查找,得到相应的函数指针;
  5. 将 student(params) 反序列化后,在本地调用 addAge() 函数,得到结果;
  6. 将 student 结果序列化后通过网络返回给 Client。

ROS 和 ROS2 架构和通信_第8张图片

6.3 RPC 与 TCP

RFC 1831 中记录的远程过程调用(Remote Procedure Call, RPC) 协议旨在以与 TCP 不同的方式扩展 IP。TCP 的目标是大数据流的传输(比如文件下载),而 RPC 是为网络编程而设计的。

RPC 的关键特征有:

  • Request-reply:RPC 是一个 请求-应答 协议,可以表现出此类协议的典型“乒乓”行为。这不是 RPC 设计的基础(因为多个请求可以是未完成的,应答可以以任何顺序出现),但是大多数程序将发出单个 RPC 请求,然后阻塞等待应答。
  • UDP 或 TCP 传输:RPC 实际上是通过 UDP 或 TCP 进行操作的。RPC/UDP 是一种无连接、无状态的协议。RPC/TCP 较慢,但提供可靠的有状态连接。
  • 标准化的数据表示:RPC 使用 eXternal Data Representation(XDR) 协议对其数据进行编码,该协议记录在RFC 1832 中,它标准化了整数、浮点数和字符串的格式,允许不同类型的计算机无缝地增强信息。
  • 身份验证:RPC 支持将一台机器上的调用程序验证为另一台机器上的目标子例程。身份验证可以以几种不同的模式进行操作。在 NFS 操作过程中,身份验证通常采用将 UNIX 用户和 group IDs 传递给文件服务器进行权限检查的形式。

RPC 服务对接:
TCP 和 UDP 都依赖众所周知的 port numbers 来执行服务会合。例如,TCP TELNET 服务在 port 21 上可用,FTP 在端口 23 上可用,SMTP 在 port 25 上可用,等等。连接到 TCP 和 UDP 服务只需要连接到正确的 port number。

RPC 在这个过程中引入了另一个步骤,将服务与给定的 port number 分离。它使用一个名为 PORTMAP 或 RPCBIND 的特殊 RPC 服务来实现这一点。这些在 RFC 1833 中记录的绑定协议通常被称为 portmapper,它们在 RPC 服务中是唯一的,因为它们有自己的指定 port(port 111)。运行在任意 port number 上的其他 RPC 服务可以使用到 port 111 的 RPC 调用来注册自己。portmapper 提供其他 RPC 调用以允许服务查找。

这种设计最重要的结果是,portmapper 必须是第一个启动的 RPC 程序,并且必须保持恒定的操作。

RPC 本质上不一定是 TCP,或者说常见的 RPC 是基于 TCP 的或使用 TCP 之上的某种协议的。

你可能感兴趣的:(ROS,分布式,linux)