使用快速 DDS 发现服务器作为发现协议 [社区贡献]

目标 本教程将介绍如何使用 快速 DDS 发现服务器 发现协议。

辅导水平: 高级

时间 20 分钟

背景介绍

从 ROS 2 Eloquent Elusor 开始 快速 DDS 发现服务器 快速 DDS 发现服务器(Fast DDS Discovery Server)协议是一项提供集中式动态发现机制的功能,与 DDS 默认使用的分布式机制不同。本教程介绍如何使用快速 DDS 发现服务器功能作为发现通信来运行一些 ROS 2 示例。

要获取更多有关可用发现配置的信息,请查看 下列文件 或阅读 快速 DDS 发现服务器特定文档.

"(《世界人权宣言》) 简单发现协议 中定义的标准协议。 DDS 标准.不过,在某些情况下,它也有已知的缺点。

  • 它不 规模 因为随着新节点的增加,交换数据包的数量也会大幅增加。

  • 它要求 多播 在某些情况下可能无法可靠运行的功能,如 WiFi。

"(《世界人权宣言》) 快速 DDS 发现服务器 提供了一种客户端-服务器架构,允许节点通过中间服务器相互连接。每个节点作为 发现客户与一个或多个 发现服务器 并从中接收发现信息。这样可以减少与发现相关的网络流量,而且不需要组播功能。

.././././_images/ds_explanation.svg

这些发现服务器可以是独立的、复制的或相互连接的,以便在网络上建立冗余,避免出现单点故障。

快速 DDS 发现服务器 v2

最新的 ROS 2 Foxy Fitzroy 版本(2020 年 12 月)包含一个新版本,即快速 DDS 发现服务器的第 2 版。该版本包含一项新的过滤功能,可进一步减少发送的发现消息数量。该版本使用不同节点的主题来决定两个节点是希望通信,还是可以不匹配(即不发现对方)。下图显示了发现信息的减少情况:

.././././_images/ds1vs2.svg

这种架构大大减少了服务器和客户端之间发送的信息数量。从下图中可以看出,在发现阶段的网络流量减少情况如下 RMF 诊所演示 所示:

././././_images/discovery_server_v2_performance.svg

为了使用这一功能,可以使用 与会者的 XML 配置.还可以使用 fastdds 工具 和一个 环境变量就是本教程中使用的方法。有关发现服务器配置的更详细说明,请访问 快速 DDS 发现服务器文档.

先决条件

本教程假定您拥有 ROS 2 Foxy(或更新版本)。 安装.如果您安装的 ROS 2 版本低于 Foxy,则无法使用 fastdds 工具。因此,为了使用发现服务器,您可以更新版本库以使用不同的 Fast DDS 版本,或使用 快速 DDS XML QoS 配置.

运行本教程

"(《世界人权宣言》) 说者-听者 ROS 2 演示创建了一个 话匣子 节点,每秒发布一条 "hello world "信息,以及一个 听众 节点来监听这些信息。

采购 ROS 2 您将获得 CLI 工具的访问权限 fastdds.通过该工具可以 探索工具可用于启动发现服务器。该服务器将管理连接到它的节点的发现过程。

重要

不要忘记 源 ROS 2 在每一个新航站楼中。

设置发现服务器

首先启动一个 ID 为 0、端口为 11811(默认端口)的发现服务器,并监听所有可用接口。

打开一个新终端并运行

fastdds discovery --server-id 0

启动监听节点

执行监听器演示,监听 /chatter 主题。

在新终端中,设置环境变量 ros_discovery_server(发现服务器 到发现服务器的位置。(不要忘了在每个新终端中都源化 ROS 2)。

export ROS_DISCOVERY_SERVER=127.0.0.1:11811

启动监听节点。使用参数 --remap 节点:=listener_discovery_server 为本教程更改节点名称。

ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_discovery_server

这将创建一个 ROS 2 节点,它将自动为发现服务器创建一个客户端,并连接到之前创建的服务器进行发现,而不是使用组播。

启动通话节点

打开一个新终端,设置 ros_discovery_server(发现服务器 环境变量,以便节点启动发现客户端。

export ROS_DISCOVERY_SERVER=127.0.0.1:11811
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_discovery_server

现在您应该可以看到对话者发布 "hello world "信息,而监听者接收这些信息。

演示发现服务器的执行

到目前为止,还没有证据表明这个示例和标准的 "通话者-监听者 "示例的运行方式不同。为了清楚地证明这一点,请运行另一个未连接到发现服务器的节点。运行一个新的监听器(在 /chatter 默认情况下是 topic),并检查它是否连接到已在运行的通话程序。

ros2 run demo_nodes_cpp listener --ros-args --remap __node:=simple_listener

新的监听节点不应接收 "hello world "信息。

最后,为了验证一切运行正常,可以使用简单发现协议(默认的 DDS 分布式发现机制)创建一个新的通话程序。

ros2 run demo_nodes_cpp talker --ros-args --remap __node:=simple_talker

现在你应该看到 简单监听器 节点接收来自 simple_talker 的其他信息,但不包括 对话者发现服务器.

可视化工具 rqt_graph

"(《世界人权宣言》) rqt_graph 工具可用于验证本示例的节点和结构。请记住,要使用 rqt_graph 发现服务器协议(即查看 监听器发现服务器对话者发现服务器 节点)的 ros_discovery_server(发现服务器 环境变量。

高级用例

以下各节将介绍发现服务器的不同功能,让您可以通过网络构建一个强大的发现服务器。

服务器冗余

通过使用 fastdds 工具,可以创建多个发现服务器。发现客户端(ROS 节点)可根据需要连接多个服务器。这样,即使某些服务器或节点意外关闭,冗余网络也能正常工作。下图显示了一个提供服务器冗余的简单架构。

.././././_images/ds_redundancy_example.svg

在多个终端中运行以下代码,与冗余服务器建立通信。

fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811
fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888

--server-id N 是指id为N的服务器。 ros_discovery_server(发现服务器服务器 0 必须排在首位,服务器 1 位居第二。

export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker
export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener

现在,如果其中一台服务器发生故障,仍有发现能力可用,节点之间仍能相互发现。

备份服务器

快速 DDS 发现服务器允许创建具有备份功能的服务器。这样,服务器就能在关机时恢复上次保存的状态。

.././././_images/ds_backup_example.svg

在不同终端运行以下代码,与备份服务器建立通信。

fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811 --backup
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener

在发现服务器的工作目录(启动时所在的目录)中创建几个备份文件。这两个 SQLite 文件和两个 json 文件包含启动新服务器所需的信息,并能在发生故障时恢复故障服务器的状态,从而避免再次发生发现过程,且不会丢失信息。

发现分区

与发现服务器的通信可以拆分,以便在发现信息中创建虚拟分区。这意味着,只有在两个端点之间有一个共享的发现服务器或一个发现服务器网络时,它们才会知道对方。我们将以两个独立服务器为例进行说明。下图显示了该架构。

.././././_images/ds_partition_example.svg

有了这种模式 听众 1 将连接到 谈话者 1谈话者 2因为他们分享 服务器 1. 听众 2 将与 谈话者 1 当他们分享 服务器 2.但是 听众 2 将听不到来自 谈话者 2 因为它们不共享任何发现服务器或发现服务器,包括通过冗余发现服务器之间的连接间接共享。

在 localhost 上运行第一个服务器,默认端口为 11811。

fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811

在另一个终端运行第二个服务器,使用另一个端口(本例中为 11888 端口)监听 localhost。

fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888

现在,在不同的终端运行每个节点。使用 ros_discovery_server(发现服务器 环境变量来决定连接到哪个服务器。请注意 id 必须匹配.

export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_1
export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_1
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_2
export ROS_DISCOVERY_SERVER=";127.0.0.1:11888"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_2

我们应该看看 听众 1 正在接收来自两个通话节点的信息,而 听众 2谈话者 2 因此不会收到来自它的信息。

备注

一旦两个端点(ROS 节点)发现了对方,它们之间就不需要发现服务器网络来监听对方的信息了。

ROS 2 自省

"(《世界人权宣言》) ROS 2 命令行界面 支持多种自省工具来分析 ROS 2 网络的行为。这些工具(即 玫瑰2 背包 记录, 玫瑰2 主题 清单等)对了解 ROS 2 工作网络很有帮助。

这些工具大多使用 DDS 简单发现功能与每个现有参与者交换主题信息(使用简单发现功能时,网络中的每个参与者都相互连接)。然而,新的发现服务器 v2 实施了一种网络流量减少方案,限制不共享主题的参与者之间的发现数据。这意味着,节点只有在拥有主题写入器或主题读取器的情况下,才会接收主题的发现数据。由于大多数 ROS 2 CLI 都需要网络中的一个节点(其中有些依赖于运行中的 ROS 2 守护进程,有些则创建了自己的节点),因此使用发现服务器 v2 时,这些节点将无法获得所有网络信息,从而限制了它们的功能。

发现服务器 v2 功能允许每个参与者作为一个 超级客户一种 客户 连接到 服务器,从中接收所有可用的发现信息(而不是只接收所需的信息)。从这个意义上说,ROS 2 自省工具可以配置为 超级客户从而发现网络中使用发现服务器协议的每一个实体。

备注

在本节中,我们使用 参与者 作为 DDS 实体。每个 DDS 参与者 对应于 ROS 2 背景是 DDS 的 ROS 2 抽象。 节点 是依赖 DDS 通信接口的 ROS 2 实体: 数据写入器数据阅读器.每个 参与者 可容纳多个 ROS 2 节点。有关这些概念的更多详情,请访问 节点到参与者映射设计文件

无守护进程工具

有些 ROS 2 CLI 工具不使用 ROS 2 守护进程。为了让这些工具与发现服务器连接并接收所有主题信息,它们需要作为一个 超级客户 连接到 服务器.

按照之前的配置,建立一个带有通话器和监听器的简单系统。首先,运行一个 服务器:

fastdds discovery -i 0 -l 127.0.0.1 -p 11811

然后,在不同的终端运行通话器和监听器:

export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker

继续使用 ROS 2 CLI --无守护进程 选项。新节点将与现有服务器连接,并了解每个主题。导出 ros_discovery_server(发现服务器 不需要,因为 ROS 2 工具将通过 fastrtps_default_profiles_file.

export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml
ros2 主题列表 --no-daemon
ros2 node info /talker --no-daemon --spin-time 2

快速 DDS 发现服务器与简单发现协议的比较

为了比较执行节点,使用 简单发现 协议(用于分布式发现的默认 DDS 机制)或 发现服务器在本实验中,我们提供了两个脚本,分别执行一个通话者和多个监听者,并分析这段时间内的网络流量。在本实验中 鲨鱼 必须安装在系统中。为了避免使用进程内模式,配置文件是必须的。

备注

这些脚本仅在 Linux 上受支持,并且需要一个发现服务器关闭功能,该功能仅在比 ROS 2 Foxy 提供的版本更新的版本中可用。要使用该功能,请使用 Fast DDS v2.1.0 或更高版本编译 ROS 2。

这些脚本的功能是用于高级目的的参考资料,用户可以自行研究。

运行 bash 脚本,路径为 setup.bash 文件作为 ROS 2 的参数。这将生成用于简单发现的流量跟踪。使用第二个参数执行相同的脚本 服务器.它将生成使用发现服务器的跟踪。

备注

取决于您的 tcpdump该脚本可能需要 苏都 读取网络设备流量的特权。

两次执行完成后,运行 Python 脚本生成类似下图的图表。

$ 出口 fastrtps_default_profiles_file="no_intraprocess_configuration.xml";
$ 苏都 敲击 generate_discovery_packages.bash ~/ros2/install/local_setup.bash
$ 苏都 敲击 generate_discovery_packages.bash ~/ros2/install/local_setup.bash 服务器
$ python3 discovery_packets.py
././././_images/discovery_packets.svg

该图是特定实验运行的结果。读者可以执行脚本并生成自己的结果进行比较。不难看出,使用发现服务后,网络流量减少了。

流量的减少是由于避免了每个节点在宣布自己的同时还要等待网络上其他节点的响应。这在大型架构中会产生大量流量。这种方法减少的流量会随着节点数量的增加而增加,因此这种架构比简单发现协议方法更具可扩展性。

新的 Fast DDS Discovery Server v2 自以下日期起可用 快速 DDS v2.0.2,取代了旧版的发现服务器。在新版本中,那些不共享主题的节点将自动互不发现,从而节省了连接它们及其端点所需的全部发现数据。上述实验并未显示这种情况,但即便如此,由于 ROS 2 节点隐藏了基础架构主题,流量的大量减少也是显而易见的。