组合 [17277]
ROS 1 - 节点 vs. Nodelets [17278]
在ROS 1中,您可以将代码编写为 ROS节点 或 ROS nodelet。ROS 1节点被编译为可执行文件。另一方面,ROS 1 nodelet被编译为共享库,然后由容器进程在运行时加载。 [17279]
ROS 2 - 统一API [17280]
在ROS 2中,编写代码的推荐方式类似于nodelet - 我们称之为 Component
。这使得向现有代码添加常见概念变得容易,例如 生命周期。ROS 1中的最大缺点是具有不同的API,而在ROS 2中通过使用相同的API来避免了这个问题。 [17281]
注解
仍然可以使用类似节点的"编写自己的main"的方式,但对于常见情况,不建议这样做。 [17282]
通过使进程布局成为部署时的决策,用户可以在以下选项之间进行选择: [17283]
此外,ros2 launch
可以通过专门的启动操作来自动化这些操作。 [17286]
编写组件 [17287]
由于组件仅构建为共享库,因此它没有 main
函数(请参见 Talker源代码 )。组件通常是 rclcpp::Node
的子类。由于它无法控制线程,因此不应在构造函数中执行任何长时间运行或阻塞的任务。相反,它可以使用计时器来获取周期性通知。此外,它还可以创建发布器、订阅器、服务器和客户端。 [17288]
使此类成为组件的一个重要方面是,该类使用来自 rclcpp_components
包的宏进行注册(请参见源代码的最后一行)。这使得在将其库加载到正在运行的进程中时,组件可以被发现-它充当了一种入口点。 [17289]
另外,一旦创建了一个组件,它必须在索引中注册,以便工具能够发现它。 [17290]
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中执行或启动它。 [17291]
使用组件 [17292]
composition 包中包含了几种不同的使用组件的方法。最常见的三种方法是: [17293]
启动一个 (generic container process) 并调用容器提供的 ROS 服务 load_node。ROS 服务将加载由传递的包名和库名指定的组件,并在运行的进程中开始执行它。除了通过编程方式调用 ROS 服务,您还可以使用 command line tool 来使用传递的命令行参数调用 ROS 服务。 [17294]
创建一个 custom executable,其中包含在编译时已知的多个节点。这种方法要求每个组件都有一个头文件(对于第一种情况并非严格需要)。 [17295]
创建一个启动文件,并使用``ros2 launch``创建一个包含多个组件的容器进程。 [17296]