组合

ROS 1 - 节点 vs. Nodelets

在ROS 1中,您可以将代码编写为 ROS节点ROS nodelet。ROS 1节点被编译为可执行文件。另一方面,ROS 1 nodelet被编译为共享库,然后由容器进程在运行时加载。

ROS 2 - 统一API

在ROS 2中,编写代码的推荐方式类似于nodelet - 我们称之为 Component。这使得向现有代码添加常见概念变得容易,例如 生命周期。ROS 1中的最大缺点是具有不同的API,而在ROS 2中通过使用相同的API来避免了这个问题。

注解

仍然可以使用类似节点的"编写自己的main"的方式,但对于常见情况,不建议这样做。

通过使进程布局成为部署时的决策,用户可以在以下选项之间进行选择:

  • 以独立进程运行多个节点,具有进程/故障隔离的优点,以及更容易调试单个节点。

  • 在单个进程中运行多个节点,具有较低的开销和可选择的更高效的通信(参见 进程内通信)。

此外,ros2 launch 可以通过专门的启动操作来自动化这些操作。

编写组件

由于组件仅构建为共享库,因此它没有 main 函数(请参见 Talker源代码 )。组件通常是 rclcpp::Node 的子类。由于它无法控制线程,因此不应在构造函数中执行任何长时间运行或阻塞的任务。相反,它可以使用计时器来获取周期性通知。此外,它还可以创建发布器、订阅器、服务器和客户端。

使此类成为组件的一个重要方面是,该类使用来自 rclcpp_components 包的宏进行注册(请参见源代码的最后一行)。这使得在将其库加载到正在运行的进程中时,组件可以被发现-它充当了一种入口点。

另外,一旦创建了一个组件,它必须在索引中注册,以便工具能够发现它。

add_library(talker_component SHARED src/talker_component.cpp)
rclcpp_components_register_nodes(talker_component "composition::Talker")
# To register multiple components in the same shared library, use multiple calls
# rclcpp_components_register_nodes(talker_component "composition::Talker2")

注解

为了使组件容器能够找到所需的组件,必须在已经加载了相应工作空间的shell中执行或启动它。

使用组件

composition 包中包含了几种不同的使用组件的方法。最常见的三种方法是:

  1. 启动一个 (generic container process) 并调用容器提供的 ROS 服务 load_node。ROS 服务将加载由传递的包名和库名指定的组件,并在运行的进程中开始执行它。除了通过编程方式调用 ROS 服务,您还可以使用 command line tool 来使用传递的命令行参数调用 ROS 服务。

  2. 创建一个 custom executable,其中包含在编译时已知的多个节点。这种方法要求每个组件都有一个头文件(对于第一种情况并非严格需要)。

  3. 创建一个启动文件,并使用``ros2 launch``创建一个包含多个组件的容器进程。