# 18 · 组合节点 (Composable Node) 完全指南 > **目标**: 理解 ROS2 Composable Node 设计,能把多个节点合并到同一进程,降低延迟与开销。 --- ## 目录 - [1. 是什么](#1-是什么) - [2. 为什么需要](#2-为什么需要) - [3. 工作原理](#3-工作原理) - [4. C++ 实现(.so 库)](#4-c-实现so-库) - [5. Container 启动](#5-container-启动) - [6. Python 等价做法](#6-python-等价做法) - [7. 性能对比](#7-性能对比) - [8. 何时用](#8-何时用) - [9. 推荐阅读](#9-推荐阅读) --- ## 1. 是什么 **Composable Node** = 把多个 ROS 节点装到**同一个进程**(共享内存)。 ``` 传统模式: ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Process1 │ │ Process2 │ │ Process3 │ │ Node A │ │ Node B │ │ Node C │ └──────────┘ └──────────┘ └──────────┘ │ DDS │ │ DDS │ │ DDS │ └─────┴────────┴────────┴────────┘ (跨进程通信,微秒级延迟) Composable 模式: ┌────────────────────────────┐ │ Single Process │ │ Node A │ Node B │ Node C │ │ (shared memory) │ └────────────────────────────┘ │ DDS │ (只有出/入本进程时走 DDS) ``` ## 2. 为什么需要 | 场景 | 传统模式延迟 | Composable 延迟 | 提升 | |---|---|---|---| | 5 节点 pipeline | ~500μs | ~50μs | **10x** | | 高频 sensor fusion | ~1ms | ~100μs | **10x** | | 大量小消息 | 频繁拷贝 | 共享指针 | **CPU 降 30%** | 其他好处: - 启动快(避免 fork) - 内存共享(零拷贝) - 调试简单(单进程,单 gdb) ## 3. 工作原理 ROS2 Composable = C++ **共享库(.so)** + **Container 进程**。 1. 把节点代码编译成 .so 库(`libmy_component.so`) 2. Container 进程(`component_container_mt`)加载 .so 3. Container 实例化组件(无需 fork) 4. 组件间用**进程内 publish/subscribe**(不经过 DDS) ## 4. C++ 实现(.so 库) **`my_pkg/src/my_component.cpp`**: ```cpp #include "rclcpp_components/register_node_macro.hpp" class MyComponent : public rclcpp::Node { public: explicit MyComponent(const rclcpp::NodeOptions & options) : Node("my_component", options) {} }; RCLCPP_COMPONENTS_REGISTER_NODE(MyComponent) ``` **`CMakeLists.txt`**: ```cmake add_library(my_component SHARED src/my_component.cpp) ament_target_dependencies(my_component rclcpp) rclcpp_components_register_node(my_component "my_component") install(TARGETS my_component ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin ) ``` ## 5. Container 启动 ```bash # 1. 单线程 container(调试用) ros2 component standalone --container-type standalone # 2. 多线程 container(生产用) ros2 component standalone --container-type multithreaded # 3. 在已有 container 里加载组件 ros2 component load # 例: ros2 component load /ComponentManager my_pkg my_component ``` ### Launch 文件 ```python from launch_ros.actions import ComposableNodeContainer from launch_ros.descriptions import ComposableNode container = ComposableNodeContainer( name='my_container', namespace='', package='rclcpp_components', executable='component_container_mt', composable_node_descriptions=[ ComposableNode( package='my_pkg', plugin='my_pkg::MyComponent', name='node_a', ), ComposableNode( package='my_pkg', plugin='my_pkg::MyComponent', name='node_b', ), ], ) ``` ## 6. Python 等价做法 Python **不支持**真正的 Composable Node(必须用 C++ .so)。但有等价做法: ```python # 同进程多节点(共享内存,但仍走 DDS 内部) import rclpy from rclpy.executors import MultiThreadedExecutor rclpy.init() node_a = NodeA() node_b = NodeB() executor = MultiThreadedExecutor(num_threads=4) executor.add_node(node_a) executor.add_node(node_b) executor.spin() ``` Python 多节点同进程 + MultiThreadedExecutor 是 ROS2 Python 等价的 Composable 做法。 ## 7. 性能对比 | 维度 | 传统多进程 | C++ Composable | Python 多线程 | |---|---|---|---| | 启动时间 | 慢(每个进程 fork) | 快(动态加载) | 中 | | 进程间延迟 | ~100μs (DDS) | ~5μs (shared mem) | ~10μs | | 内存 | 每进程独立 | 共享 | 共享 | | 调试 | gdb attach 多个 | gdb 单进程 | gdb 单进程 | | 灵活性 | 高(可单独 kill) | 低(同进程) | 低 | ## 8. 何时用 **用 Composable**: - 同一 pipeline 多个节点(image → process → control) - 高频消息流(>100Hz) - 延迟敏感(机器人控制回路) **不用 Composable**: - 节点可独立部署(某些在 PC,某些在 RK3506) - 需要单独 kill 重启某些节点 - 节点崩溃隔离(传统模式崩溃只影响一个进程) ## 9. 推荐阅读 - [ROS2 Composition 设计稿](https://design.ros2.org/articles/composition.html) - [ROS2 Humble Composition 教程](https://docs.ros.org/en/humble/Tutorials/Intermediate/Launch/Using-Event-Handlers.html) - [ros2 component CLI](https://docs.ros.org/en/humble/Tutorials/Intermediate/Composition.html) - [`py_lifecycle_composable` 包](../src/py_lifecycle_composable/README.md) --- --- ## 📖 阅读路径导航 > 💡 这是仓库 `doc/` 下所有文档的推荐阅读顺序。[返回 README 总导航](../README.md#-23-篇文档怎么读) > > ⏱ **本文预计阅读时间**: 25 分钟 > 📍 **当前位置**: 第 9 / 24 篇 - ⏮ **上一篇**: [Lifecycle Node](../17-lifecycle.md) - ⏭ **下一篇**: [QoS 全解](../19-qos.md)