在 ROS 中,节点是用于对其他实体进行分组的实体。例如:节点内部可以组织有发布者、订阅者、服务器、客户端。节点简化了组织和代码重用,因为它们可以以不同的方式组成。本篇谈ROS和DDS中间有一种“域参与者”与节点类同,它们之间的传送效率问题。
参与者是一种 DDS 实体。参与者还对其他实体进行分组,如发布者、订阅者、数据写入者、数据读取者等。创建更多参与者会增加应用程序的开销:
由于这些原因,参与者是重量级实体。
注意:这实际上可能取决于 DDS 供应商,其中一些供应商在参与者之间共享这些资源(例如 OpenSplice)。然而,许多 DDS 供应商不执行这种优化(例如:RTI Connext 和 Fast-RTPS),实际上建议每个进程只创建一个参与者。
在 ROS 中,上下文是 init-shutdown 循环的非全局状态。它还封装了节点和其他实体之间的共享状态。在大多数应用程序中,一个进程中只有一个 ROS 上下文。
节点和 DDS 参与者之间存在一对一的映射关系。这简化了原始实现,因为 DDS 参与者提供了许多与 ROS 节点等效的功能。这种方法的缺点是创建许多参与者会带来开销。此外,域参与者的最大数量相当少。例如,在 RTI Connext 中,每个域限制为 120 名参与者。
该提案的目标是通过避免每个节点创建一个参与者来提高整体性能。如果可能,将避免 API 更改。
除了在 Foxy 之前使用的一对一节点到参与者映射之外,还有两种选择:
第二种方法更加灵活,允许多个参与者在一个应用程序中为需要它的人提供,例如域桥应用。因此,选择了一对一的参与者到上下文映射。
当多个节点在单个进程中运行时,可以通过不同的选项对它们进行分组 - 从每个节点的单独上下文,到在同一上下文中对几个节点进行分组,再到对所有节点使用单个上下文。对于大多数应用程序,只创建一个上下文。
如果不使用节点到参与者的一对一映射,则需要额外的发现信息才能将其他实体与节点匹配,例如发布者、订阅者等。可以使用多种方法来共享此信息。建议的方法使用一个主题。每个参与者发布一条消息,其中包含将实体与节点匹配所需的所有信息。消息结构如下:
当一个实体被更新时(例如:一个发布者被创建或销毁),一个新的消息被发送。
客户端和服务器的识别根据主题名称的 ROS 约定进行(请参阅主题和服务名称映射到 DDS)。
本主题被视为实现细节,并非所有 rmw 实现都必须使用它。因此,所有必要的逻辑都必须在 rmw 实现本身或上游包中。在 rcl 中实现此逻辑将使其成为 API 的一部分,而不是实现细节。
为避免代码重复,rmw_dds_common 包提供了此逻辑的通用实现。
ros_discovery_info
以前,每个节点可能有不同的安全工件。这是可能的,因为每个节点都映射到一个参与者。新方法允许为每个进程指定不同的安全工件。有关更多详细信息,请参阅 ROS 2 安全飞地。
在创建订阅时可以设置一个 ignore_local_publications 选项。该选项可避免从同一节点内的发布者接收消息。这并未在所有 rmw 实现中实现(例如:FastRTPS)。
在此更改之后,实现此功能将不那么直接。需要添加一些额外的逻辑来识别发布者是从哪个节点创建的。