您正在阅读的是旧版本但仍受支持的 ROS 2 文档。 Jazzy.

在单个进程中组合多个节点

目标 将多个节点组成一个进程。

辅导水平: 中级

时间 20 分钟

背景介绍

参见 概念文章.

有关如何编写可组合节点的信息、 查看此教程.

先决条件

本教程使用 rclcpp_components, ros2component, 构成图像工具 套餐。如果您按照 安装说明 这些软件应该已经安装。

运行演示

了解可用组件

要查看工作区中已注册和可用的组件,请在 shell 中执行以下命令:

玫瑰2 组成部分 类型

终端将返回所有可用组件的列表:

(... 部件  其他 套餐 这里)
构成
  构成::谈话者
  composition::Listener
  composition::NodeLikeListener
  组成::服务器
  composition::Client
(... 部件  其他 套餐 这里)

使用 ROS 服务与发布者和订阅者进行运行时组合

在第一个外壳中,启动组件容器:

玫瑰2 运行 rclcpp_components 组件容器

打开第二个 shell,通过 玫瑰2 命令行工具:

玫瑰2 组成部分 清单

你会看到组件的名称:

/ComponentManager

在第二个外壳中加载通话组件(见 话匣子 源代码):

玫瑰2 组成部分 负荷 /ComponentManager 构成 构成::谈话者

该命令将返回已加载组件的唯一 ID 和节点名称:

已装载 组成部分 1  '/ComponentManager'; 集装箱 网站 作为 '/talker';

现在,第一个 shell 应显示组件已加载的信息以及重复发布信息的信息。

在第二个 shell 中运行另一条命令来加载监听器组件(请参阅 听众 源代码):

玫瑰2 组成部分 负荷 /ComponentManager 构成 composition::Listener

终端将返回:

已装载 组成部分 2  '/ComponentManager'; 集装箱 网站 作为 '/listener';

"(《世界人权宣言》) 玫瑰2 命令行实用程序现在可以用来检查容器的状态:

玫瑰2 组成部分 清单

您将看到以下结果:

/ComponentManager
   1  /对话者
   2  /听众

现在,第一个 shell 应该会重复显示每条接收到的信息的输出。

使用带有服务器和客户端的 ROS 服务进行运行时组合

服务器和客户端的例子非常相似。

第一个外壳

玫瑰2 运行 rclcpp_components 组件容器

在第二个外壳中(见 服务器客户 源代码):

玫瑰2 组成部分 负荷 /ComponentManager 构成 composition::Server ros2 组成部分 负荷 /ComponentManager 构成 composition::Client

在这种情况下,客户端向服务器发送请求,服务器处理请求并回复一个响应,客户端打印收到的响应。

使用硬编码节点的编译时组合

该演示表明,可以重复使用相同的共享库来编译运行多个组件的单个可执行文件,而无需使用 ROS 接口。该可执行文件包含上述全部四个组件:通话器、监听器、服务器和客户端,这些都是在主函数中硬编码的。

在 shell 调用中(见 源代码):

玫瑰2 运行 构成 手动合成

这应该会显示来自交谈者和倾听者以及服务器和客户端这两对人的重复信息。

备注

手动组成的组件不会反映在 玫瑰2 组成部分 清单 命令行工具输出。

使用 dlopen 进行运行时合成

本演示介绍了运行时合成的另一种方法,即创建一个通用容器进程,明确传递要加载的库,而不使用 ROS 接口。该进程将打开每个库,并为库中的每个 "rclcpp::Node "类创建一个实例(如图 2 所示)。源代码).

玫瑰2 运行 构成 dlopen_composition `玫瑰2  词头 构成`/lib/libtalker_component.so `玫瑰2  词头 构成`/lib/liblistener_component.so

现在 shell 应该会重复显示每条发送和接收信息的输出。

备注

dlopen 组件不会反映在 玫瑰2 组成部分 清单 命令行工具输出。

使用发射行动进行合成

虽然命令行工具对调试和诊断组件配置很有用,但同时启动一组组件往往更方便。为了自动执行这一操作,我们可以使用 启动文件:

玫瑰2 启动 构成 composition_demo.launch.py

高级主题

在了解了组件的基本操作之后,我们可以讨论一些更高级的话题。

卸载组件

在第一个外壳中,启动组件容器:

玫瑰2 运行 rclcpp_components 组件容器

通过 玫瑰2 命令行工具:

玫瑰2 组成部分 清单

你会看到组件的名称:

/ComponentManager

在第二个 shell 中,我们将同时加载说话者和听话者:

玫瑰2 组成部分 负荷 /ComponentManager 构成 composition::Talker ros2 组成部分 负荷 /ComponentManager 构成 composition::Listener

使用唯一 ID 从组件容器中卸载节点。

玫瑰2 组成部分 卸载 /ComponentManager 1 2

终端应返回:

已卸载 组成部分 1  '/ComponentManager'; 卸载的集装箱 组成部分 2  '/ComponentManager'; 集装箱

在第一个 shell 中,验证通话者和监听者的重复信息是否已经停止。

重新映射容器名称和命名空间

组件管理器名称和命名空间可通过标准命令行参数重新映射:

玫瑰2 运行 rclcpp_components 组件容器 --ros-args -r __节点:=我的容器 -r __ns:=/ns

在第二个外壳中,可以使用更新后的容器名称加载组件:

玫瑰2 组成部分 负荷 /ns/MyContainer 构成 composition::Listener

备注

容器的命名空间重映射不会影响已加载的组件。

重新映射组件名称和命名空间

组件名称和命名空间可通过加载命令的参数进行调整。

在第一个外壳中,启动组件容器:

玫瑰2 运行 rclcpp_components 组件容器

如何重新映射名称和命名空间的一些示例。

重新映射节点名称:

玫瑰2 组成部分 负荷 /ComponentManager 构成 构成::谈话者 --节点名 Talker2

重新映射命名空间:

玫瑰2 组成部分 负荷 /ComponentManager 构成 构成::谈话者 --节点名称空间 /ns

对两者进行重新定位:

玫瑰2 组成部分 负荷 /ComponentManager 构成 构成::谈话者 --节点名 talker3 --节点名称空间 /ns2

现在使用 玫瑰2 命令行工具:

玫瑰2 组成部分 清单

在控制台中,你会看到相应的条目:

/ComponentManager
   1  /talker2
   2  /ns/talker
   3  /ns2/talker3

备注

容器的命名空间重映射不会影响已加载的组件。

将参数值传入组件

"(《世界人权宣言》) 玫瑰2 组成部分 负荷 命令行支持在构建节点时向节点传递任意参数。该功能的使用方法如下:

玫瑰2 组成部分 负荷 /ComponentManager 图像工具 image_tools::Cam2Image -p burger_mode:=

向组件传递附加参数

"(《世界人权宣言》) 玫瑰2 组成部分 负荷 命令行支持将特定选项传递给组件管理器,以便在构建节点时使用。目前,唯一支持的命令行选项是使用进程内通信实例化节点。该功能的使用方法如下:

玫瑰2 组成部分 负荷 /ComponentManager 构成 构成::谈话者 -e 使用内部流程通信:=

作为共享库的可组合节点

如果你想从一个软件包中导出一个可组合节点作为共享库,并在另一个可进行链接时组合的软件包中使用该节点,请在 CMake 文件中添加代码,导入下游软件包中的实际目标。

然后安装生成的文件并导出生成的文件。

在这里可以看到一个实际的例子: ROS Discourse - Ament 库共享最佳实践

组成非节点派生组件

在 ROS 2 中,组件可以更有效地利用系统资源,并提供了一个强大的功能,使您可以创建不与特定节点绑定的可重用功能。

使用组件的一个好处是,可以将非节点衍生功能创建为独立的可执行文件或共享库,并根据需要加载到 ROS 系统中。

要创建一个非源于节点的组件,请遵循以下指导原则:

  1. 实现一个构造函数,该构造函数将 rclcpp::NodeOptions&; 作为其参数。

  2. 实施 get_node_base_interface() 方法,该方法应返回一个 NodeBaseInterface::SharedPtr.您可以使用 get_node_base_interface() 方法提供此接口。

下面是一个不是从节点派生出来的组件的例子,它监听一个 ROS 主题: 节点类监听器组件.

有关此主题的更多信息,您可以参考以下内容 讨论.