Composition
ROS 1 - 节点与 Nodelet
在 ROS 1 中,你可以将代码编写为 ROS node or as a ROS nodelet. ROS 1 节点被编译成可执行文件。 另一方面,ROS 1 节点被编译成共享库,然后在运行时由容器进程加载。
ROS 2 - 统一 API
在 ROS 2 中,建议编写代码的方式类似于 nodelet - 我们称之为“组件”。 这样可以轻松地将常见概念添加到现有代码中,例如 life cycle. ROS 1 中最大的缺点是拥有不同的 API,而 ROS 2 则避免了这种情况,因为两种方法都使用相同的 API。
Note
仍然可以使用类似节点的“编写自己的主要内容”样式,但对于常见情况,不建议这样做。
通过将进程布局作为部署时决策,用户可以选择:
在单独的进程中运行多个节点,具有进程/故障隔离的好处,并且更容易调试单个节点
在单个进程中运行多个节点,具有较低的开销和可选的更高效的通信 (see Intra Process Communication).
此外,可以使用“ros2 launch”通过专门的启动操作自动执行这些操作。
编写组件
由于组件仅内置于共享库中,因此它没有“main”函数 (see Talker source code). 组件通常是“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")
举个例子, check out this tutorial
Note
为了使 component_container 能够找到所需的组件,必须从具有相应工作区的 shell 执行或启动它。
使用组件
The composition 包中包含几种如何使用组件的不同方法。 最常见的三种是:
Start a (generic container process) and call the ROS service load_node offered by the container. 然后,ROS 服务将加载传递的包名和库名指定的组件,并在运行进程中开始执行它。 除了通过编程方式调用 ROS 服务外,您还可以使用 command line tool 使用传递的命令行参数调用 ROS 服务
Create a custom executable 包含编译时已知的多个节点。 这种方法要求每个组件都有一个头文件(对于第一种情况来说,这不是严格需要的)。
创建启动文件并使用“ros2 launch”创建一个加载多个组件的容器进程。