关于组件

ROS 1- Nodes vs. Nodelets [Alyssa@9696]

在ROS 1中,你可以把你的代码写成一个 ROS node 或者 ROS nodelet 。ROS 1 nodes被编译成可执行文件。另一方面,ROS 1 nodelets 被编译成一个共享库,然后在运行时由容器进程加载。 [Alyssa@9697]

ROS 2 - 统一API [Alyssa@9698]

ROS 2推荐用类似于nodelet的方式编写代码,我们将它称作 Component 。这样可以更容易的向现有代码中添加一些通用概念,例如 生命周期(life cycle) 。在ROS 2中避免了不同API的最大缺点,因为两种方法在ROS 2中使用相同的API。 [Alyssa@9699]

注解

仍然可以使用 "编写自己的main函数" 的节点状样式,但对于通常情况,不建议使用。 [Alyssa@9700]

通过使流程布局成为部署时决策,用户可以在以下两者之间进行选择: [待校准@9701]

  • 在单独的进程中运行多个节点,具有进程/故障隔离以及更容易调试单个节点和 [待校准@9702]

  • 在单个进程中运行多个节点,开销更低,通讯效率更高 (见 进程内通讯 )。 [Alyssa@9703]

此外, ros2 launch 可以通过专门的launch动作使这些动作自动化。 [待校准@9704]

编写一个组件 [Alyssa@9705]

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

使这样的类成为组件的一个重要方面是,类使用来自包 rclcpp_components 的宏注册自身 (请参阅源文件中的最后一行)。这使得组件在其库被加载到正在运行的进程中时可以被发现 -- 它充当一种入口点。 [待校准@9707]

此外,一旦创建了一个组件,它必须在索引中注册才能被工具发现。 [待校准@9708]

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")

注解

为了使component_container能够找到所需的组件,它必须在已经source了相应工作空间的终端中执行或启动(launch)。 [Alyssa@9709]

使用组件

composition 包里包含几种不同的组件使用方法。三个最常见的是: [Alyssa@9711]

  1. 启动一个 ( 通用容器进程 ) 并调用容器提供的ROS服务 load_node 。然后,ROS服务将加载由传递的包名和库名指定的组件,并开始在正在运行的进程中执行它。您还可以使用带有传递的命令行参数的 命令行工具 调用ROS服务,而不是以编程的方式调用ROS服务。 [Alyssa@9712]

  2. 创建包含多个在编译时已知的节点的 用户可执行文件 。这种方法要求每个组件都有一个头文件 (第一种情况并不严格需要)。 [Alyssa@9713]

  3. 创建一个launch文件并使用 ros2 launch 创建容器进程来加载多个组件。 [Alyssa@9714]