首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

ros2_humble/src/ros2 源码详解

ros2_humble/src/ros2 源码详解

本文仅针对工作区中的 ros2_humble/src/ros2/:说明该目录下各 git 仓库的布局、包与源码目录习惯、阅读顺序与模块间关系。路径均相对于 ros2_humble/src/ros2/。工作区其它 src/ament 等见 ros2_humble_src_源码详细解释.md;调用栈设计见 ros2_humble_软件模块源码设计解析.md


1. 总体认识

1.1 目录形态

src/ros2/每一个一级子目录(如 rclrosidl)通常对应 GitHub 上独立仓库 的克隆根;其内部再含一个或多个 colcon 包(各包根目录有 package.xml)。因此:

  • 讨论「包名」时以 package.xml<name> 为准(可能与文件夹名略有差异)。
  • 讨论「仓库」时以 src/ros2/<仓库根>/ 为准。

1.2 功能分层(便于对照源码)

接口与生成中间件客户端库rcl_interfaces / common_interfacesrosidl_* / rosidl_typesupport_*rmwrmw_implementationrmw_fastrtps_* / rmw_cyclonedds_cpp / rmw_connextdds_*rcl / rcl_action / rcl_lifecyclerclcpp_*rclpy

编译依赖粗顺序rcutilsrosidl_*(生成器与 runtime)→ rmwrmw_* 实现 → rmw_implementationrclrclcpp / rclpy;之上再叠 geometry2rvizrosbag2 等。


2. 基础设施与工具库

仓库目录 源码要点
rcutils rcutils C:分配器、错误串、rcutils/types、日志宏、时间与原子等;几乎被所有下层依赖。
rcpputils rcpputils C++:SharedLibrary(RMW 动态加载)、环境变量、scope_exit 等。
rpyutils rpyutils Python 小工具,供 rclpy/构建脚本使用。
各类 *_vendor 各 vendor 包 yaml-cpp、spdlog、tinyxml、libyaml、mimick、pybind11 等固定版本打进工作区;头文件与库在 build/install 中供依赖包使用。
eigen3_cmake_module / python_cmake_module 同名包 仅 CMake 模块,无运行时库。
ament_cmake_ros ament_cmake_rosdomain_coordinator ROS 包专用 ament_cmake 扩展与域协调相关逻辑。
console_bridge_vendor vendor 日志桥接依赖。
orocos_kdl_vendor orocos_kdl_vendorpython_orocos_kdl_vendor KDL 库 vendor 与 Python 绑定构建。
performance_test_fixture 测试夹具 性能基准共用。

3. rcl/ 仓库 — ROS 客户端库(C)

路径 对外 API 实现源码(核心)
rcl rcl/rcl include/rcl/*.h src/rcl/*.c:与 init、context、node、arguments、remap、graph、wait、pub/sub、service、client、timer、guard_condition、logging 等一一对应;*_impl.h 为内部结构。
rcl_action rcl/rcl_action include/rcl_action/*.h src/rcl_action/*.c:Action 在 多个 rcl client + subscription 上组合实现。
rcl_lifecycle rcl/rcl_lifecycle 生命周期 C API 状态机与 transition 相关 .c
rcl_yaml_param_parser rcl/rcl_yaml_param_parser YAML 参数解析 供节点启动前装载参数文件。

阅读建议:从 rcl/include/rcl/init.hcontext.hnode.h 读契约,再对照 src/rcl/init.ccontext.cnode.c;发布路径读 publisher.c(先 rcl_node_resolve_namermw_create_publisher);调度读 wait.crcl_wait_set_impl_s 聚合 rmw_* 与 timer)。


4. rclcpp/ 仓库 — C++ 客户端库

路径 内容要点
rclcpp rclcpp/rclcpp include/rclcpp/node.hppexecutor.hpppublisher.hppsubscription.hppqos.hppparameter.hpptimer.hpp 等;executors/(单/多线程 executor);node_interfaces/(Node 能力拆分);contexts/experimental/ 实验 API;实现多在 src/ 同名或 *.cpp
rclcpp_action rclcpp/rclcpp_action C++ Action 客户端/服务端封装。
rclcpp_components rclcpp/rclcpp_components 组件节点component_managerNodeFactory 等,与动态库加载、同进程多节点相关。
rclcpp_lifecycle rclcpp/rclcpp_lifecycle LifecycleNode 与 executor 集成。

阅读建议node.hpp + node_interfaces/node_base.hpp 看清与 rcl_node_t 的持有关系;executor.hpp + executors/* 看清与 rcl_wait 的协作。


5. rclpy/ 仓库 — Python 客户端库

路径 内容要点
rclpy rclpy/rclpy rclpy/node.pypublisher.pysubscription.pyexecutors.pycontext.py 等与 rclcpp 概念对齐;impl/ 常为 C 扩展或底层绑定;lifecycle/ 子包对应生命周期。

阅读时可与 rcl 头文件对照:Python API 多为 rcl C API 的薄封装 + 类型转换


6. rmw/rmw_implementation/rmw_*

6.1 rmw/rmw

说明
rmw include/rmw/ 全部为 C API 声明rmw.hinit.htypes.h 等),独立 .so 实现;实现由具体 RMW 包提供。
rmw_implementation_cmake CMake 辅助:查找/声明依赖的 RMW 实现。

6.2 rmw_implementation/rmw_implementation

说明
rmw_implementation C++:运行时加载 librmw_*,将 rmw_create_* 等调用转发到已加载库;入口逻辑在 src/functions.cppload_library())。
test_rmw_implementation 对「当前加载的 RMW」做一致性测试。

6.3 rmw_fastrtps/rmw_cyclonedds/rmw_connextdds/rmw_dds_common/

仓库 说明
rmw_fastrtps rmw_fastrtps_shared_cpp Fast DDS 共用 C++ 实现。
rmw_fastrtps_cpp / rmw_fastrtps_dynamic_cpp 静态类型与动态类型的 RMW 实现入口。
rmw_cyclonedds rmw_cyclonedds_cpp CycloneDDS 实现;仓库内可有 shared_memory_support.md 等说明。
rmw_connextdds rmw_connextddsrmw_connextdds_commonrmw_connextddsmicrorti_connext_dds_cmake_module Connext 系与 CMake 探测。
rmw_dds_common rmw_dds_common DDS 各实现共享的 图、发现、工具 C++ 代码。

实现源码一般在各包的 src/ 下,文件名常含 rmw_*.cpp


7. rosidl/ 仓库 — 解析、生成与运行时(核心)

作用
rosidl_parser 解析 IDL。
rosidl_adapter .msg 等 → .idl
rosidl_cmake rosidl_generate_interfaces:串联各 generator 的 CMake 宏cmake/ 下多脚本。
rosidl_cli 命令行调生成器。
rosidl_generator_c / rosidl_generator_cpp 生成 C/C++ 消息体与辅助函数。
rosidl_runtime_c / rosidl_runtime_cpp 运行时类型type_support 结构体定义。
rosidl_typesupport_interface typesupport 插件接口。
rosidl_typesupport_introspection_c / rosidl_typesupport_introspection_cpp 内省式序列化 typesupport 实现与生成物。

阅读建议:先读 rosidl_cmake/cmake/rosidl_generate_interfaces.cmake 理解扩展点,再读 rosidl_runtime_c/include/rosidl_runtime_c/message_type_support_struct.h 理解 rmw 与消息的连接方式。


8. rosidl_defaultsrosidl_ddsrosidl_pythonrosidl_typesupportrosidl_typesupport_fastrtpsrosidl_runtime_py

仓库 作用
rosidl_defaults rosidl_default_generatorsrosidl_default_runtime 元包:拉齐默认生成器与运行时依赖。
rosidl_dds rosidl_generator_dds_idl 从 rosidl 生成 DDS IDL 相关产物。
rosidl_python rosidl_generator_py 生成 Python 消息模块。
rosidl_typesupport rosidl_typesupport_crosidl_typesupport_cpp 注册/封装具体 typesupport 实现。
rosidl_typesupport_fastrtps fastrtps_cmake_modulerosidl_typesupport_fastrtps_crosidl_typesupport_fastrtps_cpp 与 Fast DDS 对齐的 typesupport。
rosidl_runtime_py 单包 消息在 Python 运行时的工具函数。

9. 标准消息与接口定义

9.1 rcl_interfaces/

builtin_interfacesrcl_interfaceslifecycle_msgscomposition_interfacesrosgraph_msgsstatistics_msgsaction_msgstest_msgs 等子包:多为 .msg/.srv/.action + 生成代码,供参数服务、生命周期、统计、组件加载等使用。

9.2 common_interfaces/

geometry_msgs、sensor_msgs、std_msgs、nav_msgs、visualization_msgs 等各自独立子包;common_interfaces 为聚合依赖;sensor_msgs_py 提供 Python 侧辅助。

9.3 unique_identifier_msgstest_interface_filesexample_interfaces

专用 UUID 消息、测试用接口、教程用最小接口定义。


10. launch/launch_ros/

仓库 说明
launch launchlaunch_xmllaunch_yamllaunch_testinglaunch_pytestlaunch_testing_ament_cmaketest_launch_testing 通用 launch 描述、XML/YAML 前端、与 pytest/ament 的测试集成。
launch_ros launch_rosros2launchlaunch_testing_rostest_launch_ros Node/ComposableNode、参数、命名空间等 ROS 实体;ros2 launch 命令实现。

源码主体多为 Python*.py),位于各包内 launch/ 或包根约定目录。


11. ros2cli/ros2 命令行

ros2cli/ros2cli 提供插件发现与子命令分发;ros2topicros2noderos2param 各为独立包,源码通常在 ros2<name>/<包名>/<包名>/ 下的 CLI 实现模块,便于按需依赖、减小安装体积。


12. rosbag2/ — 录制与回放

除已在 ros2_humble_src_源码详细解释.md §3.10「rosbag2」 列出的包名外,本工作区仓库内还有:

说明
rosbag2_performance_benchmarking rosbag2_performance/rosbag2_performance_benchmarking:性能基准。
rosbag2_storage_evaluation 存储后端评估相关(若参与默认构建则随 colcon 图依赖)。

架构上:storage 插件接口rosbag2_storage)与 transport 写读路径rosbag2_transport)分离;压缩sqlite/mcap 以独立包+vend or 形式插入。


13. rviz/ — RViz2

rviz_common:框架与插件 API;rviz_rendering:渲染;rviz_default_plugins:默认显示类型;rviz2:可执行程序;*_vendor:Ogre、Assimp 等依赖。测试包tests / visual_testing_framework 命名。


14. geometry2/urdf/message_filters/

  • geometry2tf2 核心库、tf2_ros 节点封装、tf2_msgs、各 tf2_* 消息适配包及 tf2_tools、示例与元包 geometry2
  • urdfurdf 解析库、urdf_parser_plugin 插件接口。
  • message_filters:时间同步与过滤器模板库(常与 TF、感知链配合)。

15. ros2_tracing/sros2/system_tests/ros_testing/

仓库 说明
ros2_tracing tracetools 提供 tracepoint 宏;ros2tracetracetools_* 提供采集与 launch 集成;多 test_* 包。
sros2 sros2(CLI 与策略)、sros2_cmake(CMake 钩子)。
system_tests 端到端通信、CLI、QoS、安全、rclcpp 等系统级测试包。
ros_testing ros_testingros2test:测试基础设施。

16. demos/examples/realtime_support/tlsf/

  • demos:按功能拆分的可运行演示(composition、lifecycle、pendulum、topic_statistics 等),每包通常含 src/ 与 launch。
  • examples最小 API 示例,按 rclcpp / rclpy 与 topics、services、actions、executors 等子目录组织。
  • realtime_supportrttesttlsf_cpp 等与实时调度、分配器试验相关。
  • tlsf:TLSF 分配器包本体。

17. 与其它文档的关系

文档 与本篇关系
ros2_humble_src_源码详细解释.md 覆盖 整个 src/(含 ament、ros),本篇只深挖 src/ros2/
ros2_humble_软件模块源码设计解析.md rcl / rmw / rclcpp / rosidl / rcl_action 的设计细节与源码引用
ros2_humble_代码架构说明.md 分层总览与推荐阅读顺序。

18. 推荐阅读顺序(只读 src/ros2

  1. rmw/rmw/include/rmw/rmw.h(及 mainpage 注释)
  2. rcl/rclinit.ccontext_impl.hnode.cpublisher.cwait.c
  3. rclcpp/rclcppnode.hppexecutor.hppnode_interfaces/
  4. rosidl/rosidl_cmake + rosidl_runtime_c
  5. 任选一 rmw_fastrtps_cpprmw_cyclonedds_cpprmw_create_node 等实现
  6. ros2cli/ros2cli 插件入口,再任选一个子命令包

若上游在 src/ros2 中增删仓库或包,请以各目录下 package.xml<name> 为准更新本篇表格。


19. 从 src/ros2 目录反推 ROS 2 整体架构

从当前 src/ros2 的仓库拆分方式,可以直接看出 ROS 2 是一个“接口生成 + 中间件抽象 + 客户端库 + 工具生态”四层体系,而不是单一通信库:

19.1 架构骨架(由目录直接映射)

  1. 接口层(Interface Contracts)
    common_interfacesrcl_interfacesexample_interfacesunique_identifier_msgs

    • 提供跨包复用的 .msg/.srv/.action 契约。
    • 上层业务与下层传输通过“消息契约”解耦。
  2. 生成与类型支持层(IDL Toolchain)
    rosidlrosidl_defaultsrosidl_pythonrosidl_typesupportrosidl_typesupport_fastrtpsrosidl_dds

    • 将接口定义编译为 C/C++/Python 类型与 typesupport。
    • 让同一份接口可被多语言与多 RMW 实现消费。
  3. 通信抽象层(Middleware Abstraction)
    rmwrmw_implementationrmw_fastrtpsrmw_cycloneddsrmw_connextddsrmw_dds_common

    • rmw 定义统一 API,具体实现由 rmw_* 提供。
    • rmw_implementation 负责运行时装配(按环境与可用库选择实现)。
  4. 客户端运行时层(Client Runtime)
    rclrclcpprclpyrcl_loggingrcutilsrcpputils

    • rcl 承担 ROS 语义(context、node、wait、参数、重映射等)。
    • rclcpp/rclpy 提供用户编程模型(Node/Executor/Callback)。
  5. 系统能力与开发者体验层(System Capabilities)
    launchlaunch_rosros2clirosbag2rvizgeometry2sros2ros2_tracingsystem_tests

    • 覆盖启动、调试、录包回放、可视化、安全、性能观测、系统验证。
    • 说明 ROS 2 是“可运维的软件平台”,不只是 API 集。

19.2 两条主链路(源码视角)

  • 构建期主链路
    *.msg/*.srv/*.actionrosidl_* 生成器 → typesupport 库 → 编译进 rclcpp/rclpy 应用

  • 运行期主链路
    rclcpp/rclpy 节点 → rcl(wait/set、graph、参数)→ rmw 抽象 → 具体 rmw_* → DDS 实现

这两条链路在目录上被清晰拆开:rosidl* 负责“编译期类型世界”,rcl/rmw* 负责“运行期通信世界”。

19.3 目录拆分体现的关键设计原则

  • 可替换性rmw_* 多实现并存,验证“同上层 API 可替换底层 DDS”。
  • 可移植性rcl 为语言无关 C 层,rclcpp/rclpy 只是不同语言外观。
  • 可扩展性ros2clirvizrosbag2 都是插件/子包化拆分,便于按需安装。
  • 可验证性system_testsros_testingtest_interface_files 与 tracing/security 子树长期共存,说明测试不是附属品。
  • 工程化一致性:大量 *_vendor 与 CMake module 显示 ROS 2 对依赖版本与可重复构建的重视。

19.4 可执行的架构结论

基于 src/ros2 当前目录结构,可将 ROS 2 定义为:

一个以 IDL 契约 + 可替换中间件 + 多语言客户端库 + 完整工具链 组成的机器人软件平台架构。
其核心不是“某个单独库”,而是“从接口定义到运行运维”的全链路分层系统。

ros2_humble/src 整体架构图(目录反向分析)

ros2_humble/src 整体架构图(目录反向分析)

本文基于工作区实际目录 ros2_humble/src 进行分层抽象,用一张图展示“从构建基础到机器人应用工具链”的整体架构。


1. 架构总图

L0 基础构建与依赖层L1 通信中间件与抽象层L2 客户端运行时层L3 接口与代码生成层L4 系统能力与开发者工具层ament/*\n(ament_cmake, ament_index, ament_lint, ament_package)*_vendor + CMake modules\n(eigen3_cmake_module, python_cmake_module,\nspdlog/tinyxml/yaml/pybind11 ... )ros2/rmw\nRMW C 抽象接口ros2/rmw_implementation\n运行时选择/加载 RMWros2/rmw_fastrtps\nros2/rmw_cyclonedds\nros2/rmw_connextdds\n+ rmw_dds_commoneProsima/Fast-DDS\nCycloneDDS\n(及 iceoryx 等 IPC 相关能力)ros2/rcutils + rcpputils + rpyutilsros2/rcl\n(rcl, rcl_action, rcl_lifecycle,\nrcl_yaml_param_parser)ros2/rclcpp\n(rclcpp, components, lifecycle, action)ros2/rclpyros2/rcl_loggingcommon_interfaces\nrcl_interfaces\nexample_interfaces\nunique_identifier_msgs\n...rosidl / rosidl_defaults\nrosidl_python\nrosidl_typesupport*\nrosidl_ddslaunch + launch_rosros2cli + ros2cli_common_extensionsrosbag2rviz + ros-visualization/* (rqt/qt_gui)geometry2(tf2), urdf, message_filterssros2ros2_tracingros_testing + system_tests + demos/examples

2. 读图说明(简版)

  • L0 提供构建系统与第三方依赖管理,是整棵源码树的地基。
  • L1 把通信“抽象”和“具体 DDS 实现”解耦:上层只依赖 rmw,底层可切换实现。
  • L2 是开发者常直接接触的客户端运行时:C 层 rcl + C++/Python 封装。
  • L3 是接口工程化核心:消息/服务/动作定义经 rosidl 生成后接入运行时与中间件。
  • L4 是工程落地层:启动、命令行、录包、可视化、安全、追踪、系统测试。

3. 结论

src 目录可以看出,ROS 2 并非单一通信库,而是一个由 构建系统 + 接口生成 + 中间件抽象 + 多语言运行时 + 完整工具链 组成的分层机器人软件平台。

ROS 2 Humble src 模块功能与设计原理说明

ROS 2 Humble src 模块功能与设计原理说明

1. 文档目标与范围

本文档面向 ros2_humble/src/ 工作区,说明各核心模块的:

  • 功能定位(做什么)
  • 设计原理(为什么这样设计)
  • 关键组件(由哪些包/子系统构成)
  • 与其它模块的关系(如何协同)

src 目录属于“完整源码工作区”风格,既包含 ROS 2 核心,也包含 DDS 中间件、可视化工具、感知/规划扩展与第三方 vendor 包。


2. 总体架构(分层视角)

从下到上可抽象为 7 层:

  1. 通信实现层(DDS)
    由 Fast DDS、Cyclone DDS、Iceoryx 等实现实际网络传输、发现机制、QoS 落地。

  2. 中间抽象层(RMW)
    用统一接口屏蔽不同 DDS 实现差异,让上层不依赖具体中间件。

  3. 客户端基础层(RCL + Utilities)
    rclrcutilsrcl_logging 等提供节点运行最底层通用能力。

  4. 语言客户端层(rclcpp / rclpy)
    给开发者直接使用的 C++/Python API(Node、Publisher、Subscription、Service、Action 等)。

  5. 接口与类型系统层(rosidl)
    .msg/.srv/.action 编译成多语言类型支持,并适配不同中间件类型系统。

  6. 系统编排与工具层(launch / ros2cli / rosbag2 / tracing / sros2)
    负责系统启动、诊断、录包、安全与运维能力。

  7. 应用与生态层(rviz / rqt / tf2 / perception / planning / simulation)
    提供机器人应用开发常用功能与可视化交互能力。

设计原则概括:

  • 解耦:API 与传输实现分离(RCL/RMW/DDS 分层)
  • 可替换:可切换 DDS 实现,不改业务代码
  • 多语言:通过 rosidl 和统一抽象支持 C++/Python 等
  • 可观测:CLI、Tracing、Bag、RQt/RViz 形成闭环
  • 工程化:ament + vendor 保障可重现构建

3. 模块详解

3.1 ament:构建与包管理基础设施

功能

  • 提供 ROS 2 的标准构建系统(CMake/Python 包支持)
  • 统一包安装布局、导出依赖、测试集成
  • 提供 lint、benchmark、third-party vendor 接入能力

设计原理

  • “包为单元”构建:每个 ROS 包独立声明依赖,支持多包工作区增量构建。
  • 可组合宏体系ament_cmake 通过 CMake 宏封装编译、导出、测试,减少重复配置。
  • 可移植依赖管理:vendor 包将第三方库纳入统一构建图,降低环境差异。

关键价值

  • 是整个 src 工作区可构建、可测试、可发布的基座。

3.2 eProsima / eclipse-cyclonedds / eclipse-iceoryx:通信引擎

功能

  • Fast DDS、Cyclone DDS:实现 DDS 标准能力(发现、发布订阅、QoS、序列化传输)。
  • Iceoryx:面向共享内存场景,优化同机进程间高吞吐低延迟通信。

设计原理

  • DDS 作为传输层标准:ROS 2 不直接发 socket,而是复用成熟实时通信标准。
  • QoS 一等公民:可靠性、历史深度、deadline、durability 等由 DDS 原生支持。
  • 多实现并存:不同 DDS 实现有不同性能与兼容性特征,交由 RMW 统一抽象。

关键价值

  • 决定系统通信性能上限与实时行为稳定性。

3.3 ros2/rmw*:中间件抽象层

功能

  • 提供 ROS 2 到 DDS 的统一适配接口(rmw)。
  • 具体实现如 rmw_fastrtpsrmw_cycloneddsrmw_connextdds

设计原理

  • 桥接模式(Adapter):上层调用统一 RMW API,底层由不同实现完成。
  • 运行时可选实现:通过环境变量/配置切换 RMW,不改业务节点代码。
  • 最小公共能力集:抽象可移植 API,避免上层耦合某 DDS 私有特性。

关键价值

  • 实现“同一 ROS 2 应用,跨 DDS 引擎运行”。

3.4 ros2/rclrclcpprclpy:客户端核心 API

功能

  • rcl:语言无关核心逻辑(节点、上下文、参数、图信息等基础能力)。
  • rclcpp:C++ 客户端库,强调性能与类型安全。
  • rclpy:Python 客户端库,强调开发效率与脚本化。

设计原理

  • 分层封装rclcpp/rclpy 均基于 rcl,避免多语言重复实现底层逻辑。
  • Executor 驱动模型:通过执行器统一调度回调(订阅、服务、定时器、Action)。
  • Callback Group 并发控制:支持串行/并行回调组,降低数据竞争风险。

关键价值

  • 这是开发者最直接接触的核心编程接口层。

3.5 ros2/rosidl*common_interfacesexample_interfaces:接口与类型系统

功能

  • 解析并编译 .msg/.srv/.action,生成 C/C++/Python 类型与类型支持代码。
  • 提供常见标准接口(时间、几何、传感器、导航等消息基类)。

设计原理

  • IDL 驱动代码生成:接口声明与实现解耦,避免手写序列化/反序列化。
  • typesupport 插件机制:同一消息定义可适配多种中间件序列化后端。
  • 接口稳定优先:消息定义是跨节点契约,强调兼容性管理。

关键价值

  • 保证多语言节点之间、不同实现之间的数据互操作。

3.6 ros2/launchlaunch_ros:系统启动与编排

功能

  • 统一定义多进程/多节点启动逻辑。
  • 支持参数加载、命名空间、条件启动、生命周期管理、事件驱动动作。

设计原理

  • 声明式 + 脚本化混合:既可声明结构,也可用 Python 动态组装。
  • 事件驱动 orchestration:节点退出、启动成功等事件可触发后续动作。
  • 环境独立部署:同一应用可在仿真/实机/测试通过不同 launch 配置复用。

关键价值

  • 把“单节点代码”提升为“可运维系统”。

3.7 ros2/ros2cli*:命令行运维与调试入口

功能

  • 提供 ros2 topic/service/node/param/action/... 命令体系。
  • 支持图结构巡检、消息回显、参数操作、节点生命周期管理等。

设计原理

  • 插件式命令扩展:命令按功能分包扩展,便于生态持续增长。
  • 面向在线系统观察:无需改代码即可快速定位通信链路问题。

关键价值

  • 是开发/测试/线上排障的第一入口。

3.8 ros2/rosbag2:数据记录与回放

功能

  • 记录运行中 Topic 数据流并回放,支持离线分析与算法复现实验。
  • 支持不同存储后端与压缩策略。

设计原理

  • 存储后端抽象:避免绑定单一数据库格式。
  • 时间语义保真:尽量保持消息时间序列,服务可重复实验。
  • 数据闭环:与可视化、算法评估、回归测试联动。

关键价值

  • 把线上真实数据带回离线,支撑算法迭代和故障复盘。

3.9 ros2/rvizros-visualization/rqt*:可视化与交互调试

功能

  • RViz:3D 可视化(点云、TF、地图、机器人模型、路径等)。
  • RQt:插件化 GUI 工具集(图结构、topic 监控、参数等)。

设计原理

  • 插件机制:显示类型和工具可扩展。
  • 运行时观察:强调“在线系统状态透明化”。

关键价值

  • 大幅降低机器人系统调试门槛,提升问题定位效率。

3.10 ros2/geometry2(tf2)message_filtersurdfrobot_state_publisher 等通用能力

功能

  • tf2:坐标系变换树维护与时序查询。
  • message_filters:多 Topic 时间同步、策略过滤。
  • urdf/robot_state_publisher:机器人模型解析与关节状态发布。
  • pluginlib/class_loader:运行时插件发现与加载。

设计原理

  • 时空一致性:机器人问题本质是“在某时间、某坐标系下”的状态计算。
  • 组件化扩展:通过插件机制解耦算法框架与具体实现。

关键价值

  • 构成大多数机器人应用的“基础工具箱”。

3.11 ros-perceptionros-planning:感知与规划接口扩展

功能

  • 感知常用包(图像、激光几何等)提供传感器处理基础能力。
  • 规划相关接口(如 navigation_msgs)提供导航系统消息契约。

设计原理

  • 接口先行:先统一消息契约,再让不同算法模块可替换集成。
  • 解耦数据与算法:降低系统集成成本,提升生态兼容性。

关键价值

  • 支撑上层 SLAM、定位、导航、感知融合等系统构建。

3.12 gazebo-releaseosrfros2-rust:生态与跨语言扩展

功能

  • 仿真相关 vendor 包:为 Gazebo/数学库等提供可构建依赖。
  • OSRF 工具包:测试与通用工具支持。
  • Rust 接口(rosidl_rust):扩展 Rust 开发生态。

设计原理

  • vendor 固化版本:保障 CI 与团队环境一致性。
  • 跨语言生态:通过接口生成机制延伸到新语言。

关键价值

  • 提升工程可维护性与长期生态演进能力。

4. 关键运行链路(从应用代码到网络)

以“发布一个 Topic 消息”为例:

  1. 开发者在 rclcpp/rclpy 创建 Publisher 并发布消息。
  2. 消息类型由 rosidl 生成的 typesupport 提供序列化支持。
  3. rcl 调用 rmw 抽象接口。
  4. 具体 rmw_* 实现转发至 Fast DDS/Cyclone DDS。
  5. DDS 根据 QoS 与发现结果完成网络传输。
  6. 对端节点通过相反路径反序列化并触发回调。

这条链路体现了 ROS 2 的核心设计哲学:上层编程模型稳定,底层传输实现可替换


5. 设计原理总结(为什么这样分层)

  • 可替换性:通信实现会演化,必须隔离在 RMW/DDS 层。
  • 可移植性:同一应用可在不同硬件/系统/中间件运行。
  • 可维护性:接口定义、运行时、工具链分离,降低耦合爆炸。
  • 可观测性:CLI + Bag + Tracing + GUI 提供全链路诊断能力。
  • 可扩展性:插件机制、vendor 机制、多语言机制保障长期演进。

6. 学习与落地建议(按优先级)

如果你希望从“读源码”过渡到“可开发调试”,建议顺序:

  1. rclcpp/rclpy(节点、QoS、Executor)
  2. launch/launch_ros(系统编排)
  3. ros2cli + rosbag2(观测与复现)
  4. tf2 + urdf + robot_state_publisher(机器人基础)
  5. rmw + 一个 DDS 实现(性能与网络行为)
  6. RViz/RQt/Tracing(复杂系统诊断)

7. 附:目录到能力的快速映射

  • ament -> 构建与包管理
  • eProsima / eclipse-cyclonedds / eclipse-iceoryx -> 通信引擎
  • ros2/rmw* -> 中间件抽象层
  • ros2/rcl* -> 客户端核心
  • ros2/rosidl* -> 接口与代码生成
  • ros2/launch* -> 系统编排
  • ros2/ros2cli* -> CLI 工具链
  • ros2/rosbag2 -> 数据记录回放
  • ros2/rviz + ros-visualization/rqt* -> 可视化与交互调试
  • ros/ros-perception/ros-planning/ -> 机器人基础能力与应用扩展
  • gazebo-releaseosrfros2-rust -> 仿真、工程工具、跨语言生态

ros2_humble/src 源码详细解释

ros2_humble/src 源码详细解释

本文专门说明 ros2_humble/src/ 下各路径是什么、包含哪些 colcon 包、源码大致长什么样。目录级总览仍可与 ros2_humble_源码目录详细说明.md 对照阅读;运行时分层与模块设计见 ros2_humble_代码架构说明.mdros2_humble_软件模块源码设计解析.md


0. 阅读约定

概念 含义
组织目录 src/ 下第一级,如 ros2ament,对应 ros2.repos 里的仓库分组。
仓库目录 src/ros2/rcl,常为一个 git 仓库根;其下可有多个并列的 ROS 包。
colcon 包 package.xml 的目录;colcon build --packages-select <包名> 只编该包。
典型布局 C/C++ 包常见 include/<包名>/src/test/;Python 包常见 setup.py 与包名同名子目录。

下文路径均相对于 ros2_humble/src/


1. ament/ — 构建系统与索引

1.1 ament/ament_cmake/(多包仓库)

每个子目录是一个 ament_cmake 宏或辅助包,在其它包的 CMakeLists.txt 里通过 find_package(ament_cmake_...) 使用。

包名(目录) 作用
ament_cmake 元包,聚合常用 ament_cmake 组件。
ament_cmake_core ament_package() 等核心逻辑。
ament_cmake_export_* 导出依赖、include、库、接口、link flags、targets 等。
ament_cmake_gtest / gmock / google_benchmark 拉接测试框架。
ament_cmake_pytest / nose Python 测试。
ament_cmake_python 安装 Python 模块、混合包。
ament_cmake_test CTest 与 ament 测试集成。
ament_cmake_vendor_package 构建 vendor 第三方源码的模板。
ament_cmake_gen_version_h / version 版本头与版本号。
其它 ament_cmake_* include 路径、target 依赖、libraries 查询等细粒度 CMake 辅助。

1.2 ament/ament_index/

包名 作用
ament_index_cpp / ament_index_python 在 install 前缀下按资源类型查询包列表、前缀路径(RMW 实现、插件等依赖此机制)。

1.3 ament/ament_lint/

大量 ament_cmake_<linter>ament_<linter> 包(如 flake8、cppcheck、uncrustify):在构建或测试阶段对源码做风格/静态检查;ament_lint_auto 用于一键启用一组规则。

1.4 其它

包名 作用
ament_package 解析 package.xml,供构建与工具链使用。
googletest 内含 googlemockgoogletest 子包,提供 GTest 源码构建。
google_benchmark_vendor / uncrustify_vendor 固定上游版本的 vendor 包。

2. 中间件与底层依赖

2.1 eProsima/

路径 说明
Fast-CDR CDR 序列化库(通常无 ROS package.xml,作为 CMake 子工程被依赖)。
Fast-DDS DDS 实现本体;含大量 C++ 源码与 CMake。
foonathan_memory_vendor Fast-DDS 使用的内存库 vendor。

2.2 eclipse-cyclonedds/cyclonedds/

CycloneDDS 完整实现;colcon 包名一般为 cyclonedds(以该目录下 package.xml<name> 为准)。

2.3 eclipse-iceoryx/iceoryx/

iceoryx 2.x 仓库内常见 ROS 包(示例):iceoryx_hoofs(基础库)、iceoryx_posh(POSH 中间件)、iceoryx_binding_ciceoryx_integrationtesticeoryx_introspection 等;用于零拷贝/共享内存 IPC,与具体 RMW 功能绑定方式依版本而定。

2.4 gazebo-release/osrf/

与仿真、launch 测试基础设施相关,见 源码目录详细说明 §2.11–2.12


3. ros2/ — 核心栈(按仓库细拆)

src/ros2/ 的纵向详解(分层图、各仓库内 include/·src/ 习惯、阅读顺序):见 ros2_humble_src_ros2_源码详解.md。下列为与本节互补的速查表

3.1 ros2/rcl/ — RCL C 库

包名 路径 内容要点
rcl rcl/rcl 主体include/rcl/*.h 对外 API;src/rcl/*.c 实现 init、node、publisher、subscription、service、client、timer、wait、graph、remap 等。
rcl_action rcl/rcl_action Action 客户端/服务端 C API,内部组合 rcl 的 client/subscription。
rcl_lifecycle rcl/rcl_lifecycle 生命周期状态机 C API。
rcl_yaml_param_parser rcl/rcl_yaml_param_parser 解析参数 YAML 为 rcl 可用结构。

3.2 ros2/rclcpp/ — C++ 客户端库

包名 内容要点
rclcpp NodeExecutorPublisherSubscription、QoS、参数、node_interfaces 等绝大部分用户 API。
rclcpp_action C++ Action 封装。
rclcpp_components 组件节点(动态加载 .so、同进程多节点)。
rclcpp_lifecycle LifecycleNode 与 transition 服务封装。

3.3 ros2/rclpy/rcpputils/rcutils/rpyutils/

包名 内容要点
rclpy Python 绑定与运行时(常混合 C 扩展与纯 Python)。
rcutils 分配器、错误串、字符串、日志宏、时间与原子等 C 工具。
rcpputils C++ 工具:共享库加载、scope_exit、线程与文件系统小工具等。
rpyutils Python 通用辅助。

3.4 ros2/rmw* — 中间件抽象与实现

包名 内容要点
rmw 头文件 API(include/rmw/),无单独实现库。
rmw_implementation 加载 librmw_* 并转发符号;含 test_rmw_implementation 供一致性测试。
rmw_implementation_cmake CMake 辅助,供依赖 RMW 的包选择/检查实现。
rmw_fastrtps_cpp / rmw_fastrtps_dynamic_cpp / rmw_fastrtps_shared_cpp Fast DDS 相关 RMW;shared 为公共 C++ 实现片段。
rmw_cyclonedds_cpp Cyclone 的 RMW 实现。
rmw_connextddsrmw_connextdds_commonrmw_connextddsmicrorti_connext_dds_cmake_module Connext 系实现与 CMake 模块。
rmw_dds_common 多 DDS 实现共享的图、类型发现等逻辑。

3.5 ros2/rosidl/ 与关联包 — 接口与代码生成

ros2/rosidl/ 仓库内多包:

包名 作用
rosidl_parser 解析 .idl / 适配后的接口定义。
rosidl_adapter 将历史 .msg 等转为 .idl
rosidl_cmake rosidl_generate_interfaces 等 CMake 宏(生成流水线入口)。
rosidl_cli 命令行调用生成器。
rosidl_generator_c / rosidl_generator_cpp 生成 C/C++ 消息结构体与函数。
rosidl_runtime_c / rosidl_runtime_cpp 运行时类型与 type_support 结构。
rosidl_typesupport_interface typesupport 插件接口定义。
rosidl_typesupport_introspection_c / _cpp 基于内省的序列化路径;_tests 为测试包。

ros2/rosidl_defaults/rosidl_default_generatorsrosidl_default_runtime — 默认生成器与运行时依赖元包。

ros2/rosidl_dds/rosidl_generator_dds_idl:由 rosidl 生成 DDS IDL 相关产物。

ros2/rosidl_python/rosidl_generator_py:生成 Python 消息类。

ros2/rosidl_runtime_py:Python 侧消息工具。

ros2/rosidl_typesupport_fastrtps/fastrtps_cmake_modulerosidl_typesupport_fastrtps_crosidl_typesupport_fastrtps_cpp — 与 Fast DDS 绑定的 typesupport。

ros2/rosidl_typesupport/rosidl_typesupport_crosidl_typesupport_cpp — 具体 typesupport 实现注册与封装。

3.6 ros2/rcl_interfaces/ — 标准接口消息

包名 典型内容
builtin_interfaces TimeDuration 等。
lifecycle_msgscomposition_interfacesrosgraph_msgsstatistics_msgsaction_msgstest_msgs 生命周期、组件、图、统计、通用 Action 基础、测试消息。
rcl_interfaces 参数描述、SetParameters、Log 等消息/服务。

标准几何/传感器类消息多在 common_interfaces/(见 §3.7)。完整列表以 src/ros2/rcl_interfaces/ 下各子目录为准。

3.7 ros2/common_interfaces/

每个子目录通常是一个消息包:如 std_msgsgeometry_msgssensor_msgsnav_msgsvisualization_msgs 等;common_interfaces 为元依赖包;sensor_msgs_py 为 Python 辅助。

3.8 ros2/launch/ros2/launch_ros/

包名 作用
launch 通用 LaunchDescription、事件、子进程等。
launch_xml / launch_yaml 从 XML/YAML 构建 launch 描述。
launch_testinglaunch_pytestlaunch_testing_ament_cmake launch 与测试集成。
launch_ros NodeComposableNode、ROS 参数等实体。
ros2launch ros2 launch 命令入口。
launch_testing_rostest_launch_ros ROS 侧 launch 测试。

3.9 ros2/ros2cli/ — 命令行工具(多包)

每个 ros2<子命令> 常对应独立包,便于依赖隔离:

包名 对应命令/功能
ros2cli ros2 主入口与插件发现框架。
ros2action ros2 action
ros2component ros2 component
ros2doctor ros2 doctor
ros2interface ros2 interface
ros2lifecycle ros2 lifecycle
ros2multicast ros2 multicast
ros2node ros2 node
ros2param ros2 param
ros2pkg ros2 pkg
ros2run ros2 run
ros2service ros2 service
ros2topic ros2 topic
ros2cli_test_interfaces CLI 测试用接口。

3.10 ros2/rosbag2/ — 录制与回放

包名 作用
rosbag2 元包或顶层聚合。
rosbag2_cpp / rosbag2_py C++ 与 Python API。
rosbag2_storage 存储抽象接口。
rosbag2_storage_default_plugins 默认存储实现(如 sqlite)。
rosbag2_storage_mcapmcap_vendor MCAP 格式与依赖。
rosbag2_transport 实际订阅/发布与写盘调度。
rosbag2_compressionrosbag2_compression_zstdzstd_vendor 压缩与依赖。
rosbag2_interfaces 服务/消息定义。
sqlite3_vendorshared_queues_vendor 第三方 vendor。
ros2bag ros2 bag CLI。
rosbag2_testsrosbag2_test_commonrosbag2_storage_mcap_testdata 测试与夹具。

3.11 ros2/rviz/ — 可视化

包名 作用
rviz_common 核心数据模型与插件接口。
rviz_rendering 渲染抽象。
rviz_default_plugins 默认显示类型。
rviz2 应用程序入口。
rviz_ogre_vendorrviz_assimp_vendor 图形与模型格式依赖。
rviz_rendering_testsrviz_visual_testing_framework 测试支持。

3.12 ros2/ros2_tracing/

包名 作用
tracetools 在 rcl/rclcpp 等中插入的跟踪点(tracepoint)宏。
ros2tracetracetools_tracetracetools_readtracetools_launch 命令行与 launch 集成、读取 trace。
test_tracetoolstest_tracetools_launchtracetools_test 测试。

3.13 ros2/geometry2/ — TF2

包名 作用
tf2 核心变换库(C++)。
tf2_ros / tf2_ros_py 节点与话题封装。
tf2_msgs 消息定义。
tf2_py Python 绑定。
tf2_geometry_msgstf2_sensor_msgstf2_eigentf2_bullettf2_kdl 与各类几何/库的类型转换。
tf2_toolsexamples_tf2_py 工具与示例。
geometry2test_tf2 元包与测试。

3.14 ros2/demos/ — 演示节点

compositiondemo_nodes_cppdemo_nodes_pyimage_toolsintra_process_demolifecyclelogging_demopendulum_controltopic_statistics_demo 等:每个子目录多为独立可运行示例包,用于展示单一特性。

3.15 ros2/examples/ — 最小示例

rclcpp/rclpy/ 再分子目录:

  • topics:minimal_publisher / minimal_subscriber
  • services:minimal_service / minimal_client / async_client
  • actions:minimal_action_server / client
  • executors:multithreaded_executor、cbg_executor
  • composition:minimal_composition
  • timerswait_setguard_conditions

另有 launch_testing/launch_testing_examples:launch 测试示例。

3.16 ros2/system_tests/ros2/ros_testing/

包名 作用
test_communicationtest_rclcpptest_securitytest_quality_of_servicetest_clitest_cli_remapping 跨栈系统测试。
ros_testingros2test 测试框架与 ament 集成。

3.17 ros2/sros2/ros2/urdf/ros2/message_filters/

包名 作用
sros2sros2_cmake 安全策略生成与 CMake 钩子。
urdfurdf_parser_plugin URDF 解析与插件接口。
message_filters 时间同步过滤器。
unique_identifier_msgstest_interface_filesexample_interfaces 消息与测试接口定义。
*各类 _vendor 固定版本第三方库,供 rviz、yaml、logging 等使用。

4. ros/ — 与机器人模型、插件、教程相关

包名 作用
class_loaderpluginlibros2plugin 插件加载基础设施。
urdfdom URDF XML DOM 解析。
kdl_parserkdl_parser_py URDF → KDL 树。
robot_state_publisher 关节状态 → TF 广播。
resource_retrieverlibcurl_vendor 远程/本地资源获取。
ros_environment 发行版环境变量。
ros_tutorialsturtlesimroscpp_tutorials 等) 经典教程节点 ROS 2 移植。

5. ros-visualization/ — Qt 与 rqt

区域 包示例
python_qt_binding 在 ROS 中统一绑定 PyQt。
qt_gui_core qt_guiqt_gui_cppqt_dotgraphqt_gui_app 等:rqt 宿主与插件容器。
rqt/ rqtrqt_guirqt_gui_cpprqt_gui_pyrqt_py_common 元包与公共库。
rqt_* 各插件:rqt_graphrqt_consolerqt_plotrqt_bag(含 rqt_bag_plugins)等。
interactive_markers 交互式标记服务端库。
tango_icons_vendor 图标资源。

6. ros-perception/ros-planning/ros-tooling/ros2-rust/

  • image_commonlaser_geometry:感知管线常用库(见 源码目录详细说明)。
  • navigation_msgs:导航相关消息。
  • keyboard_handlerlibstatistics_collector:输入与统计采集。
  • ros2-rust/rosidl_rustrosidl_generator_rs,从接口生成 Rust。

7. 如何在本地核对「包名 ↔ 路径」

在已配置 ROS 2 环境的 shell 中(或仅浏览文件系统):

1
2
# 列出某目录下所有包名(需安装 fd 或自行用 find)
find ros2_humble/src/ros2 -name package.xml -exec grep -H '<name>' {} \;

或直接打开某目录下的 package.xml,其中 <name>...</name> 即为 colcon 包名(可能与目录名不同,以 <name> 为准)。


8. 延伸阅读

文档
ros2_humble_src_ros2_源码详解.md
ros2_humble_源码目录详细说明.md
ros2_humble_软件模块源码设计解析.md
ros2_humble_代码架构说明.md

本文基于当前工作区 src/ 实际内容整理;上游增删包后请以 find … package.xml 结果为准更新。

ROS 2 Humble 代码架构说明(本工作区 ros2_humble)

ROS 2 Humble 代码架构说明(本工作区 ros2_humble

本文档面向在本仓库中阅读 ROS 2 Humble 源码的学习路径,描述 ros2_humble 工作区的目录组织、运行时分层,以及各层之间的依赖关系。路径均相对于工作区根目录 ros2_humble/


1. 工作区顶层结构

目录 作用
src/ 所有上游源码(amentros2、DDS、可视化等),由 colcon 从此处编译
build/ 各包的中间构建产物
install/ 安装前缀;source install/setup.bash 后使用已编译包
log/ colcon 构建日志

源码按 组织/项目 拆在 src/ 下,而不是单一 monorepo。本环境中主要包括:

  • src/ros2/ — OSRF 维护的核心 ROS 2 栈(rcl、rclcpp、rosidl、rmw、launch、工具链等)
  • src/ament/ — 构建与元数据(ament_cmake、ament_index、lint 等)
  • src/eProsima/ — Fast-CDR、Fast-DDS 及内存 vendor 等
  • src/eclipse-cyclonedds/ — CycloneDDS
  • src/eclipse-iceoryx/ — iceoryx(零拷贝相关中间件组件)
  • src/ros-visualization/src/ros-planning/ 等 — 可视化与消息扩展

2. 运行时分层(自顶向下)

ROS 2 客户端库通过 RCL(ROS Client Library C) 访问 RMW(ROS Middleware) 抽象,再由具体 RMW 实现 调用 DDS 或其它传输。

应用层RCL 层 - C APIRMW 桥接具体 RMWDDS / 传输rclcpp 节点 / 组件rclpyrcl: init / node / pub sub / graph / waitrcl_actionrcl_lifecyclermw_implementation: 动态加载具体 RMW 库rmw_fastrtps_cpprmw_cyclonedds_cpprmw_connextddsFast-DDSCycloneDDS

要点:

  • rclcpp / rclpy:面向用户的 API;内部持有 rcl_* 结构并调用 rcl。
  • rcl:语言无关的 C 库;管理 contextnode、QoS、等待集、图发现等与“ROS 语义”强相关的逻辑。
  • rmw:纯 C 头文件定义的中间件抽象(src/ros2/rmw/rmw/include/rmw/)。
  • rmw_implementation:在运行时通过 共享库 加载选定的 rmw_* 实现(见下文)。

3. src/ros2 核心包分组

以下为阅读源码时常用的 mental map(非完整包列表)。

3.1 客户端库

路径示例 说明
rclcpp src/ros2/rclcpp/rclcpp/ C++ 节点、NodeExecutor、定时器、参数等
rclpy src/ros2/rclpy/rclpy/ Python 绑定与节点 API
rcl src/ros2/rcl/rcl/ C 层:init、context、node、publisher、subscription 等
rcl_action src/ros2/rcl/rcl_action/ Action 客户端/服务端的 C API
rcl_lifecycle src/ros2/rcl/rcl_lifecycle/ 生命周期状态机

Context 示例rcl_context_t 表示一次 ROS 初始化会话;零初始化、init、shutdown、fini 的流程见 src/ros2/rcl/rcl/src/rcl/context.crcl/init.h 文档注释。

3.2 中间件抽象与实现

说明
rmw RMW C 接口与类型定义
rmw_implementation 按环境变量/ament 索引选择并 dlopen 具体 RMW 库
rmw_fastrtps_cpp Fast-DDS 的 RMW 实现
rmw_cyclonedds_cpp CycloneDDS 的 RMW 实现
rmw_connextdds RTI Connext 的 RMW 实现
rmw_dds_common 多 DDS 实现共用的工具与类型

rmw_implementation 中的 load_library()src/ros2/rmw_implementation/rmw_implementation/src/functions.cpp)说明了选择逻辑摘要:优先 RMW_IMPLEMENTATION 环境变量,否则按 ament index 中注册的实现回退尝试加载。

3.3 接口与代码生成(rosidl)

区域 说明
rosidl_* .msg / .srv / .action 的生成器、运行时 C/C++ 类型、typesupport
rosidl_typesupport_* 为每种 RMW 提供序列化/反序列化绑定
rosidl_typesupport_fastrtps 与 Fast DDS 相关的 typesupport
rosidl_defaults 默认生成器组合

消息从 .msg 到可执行代码的路径:定义 → rosidl 生成 → typesupport → rmw 发布/订阅

3.4 基础设施库

说明
rcutils 分配器、字符串、错误状态、原子等 C 工具
rcpputils C++ 工具(如 SharedLibrary、环境变量)
rcl_interfaces 参数、日志等标准接口消息
rcl_logging 日志后端抽象与 spdlog 等集成
ament_index_cpp / ament_index_python 资源与前缀索引(含 RMW 插件注册)

3.5 启动、工具与生态

区域 说明
launch / launch_ros 声明式启动系统
ros2cli ros2 topic/node/... 命令行
rosbag2 录制与回放
geometry2 TF2
rviz 三维可视化
demos / examples 官方示例

4. 构建系统(ament + colcon)

  • 每个包根目录有 package.xml(依赖声明)和通常 CMakeLists.txtsetup.py(Python 包)。
  • ament_cmake 扩展了 CMake,统一导出 include、库依赖与测试。
  • 工作区根目录常用命令:colcon buildcolcon test;编译结果进入 build/install/

src/ament/ 提供 ament_packageament_cmake_*ament_lint_* 等,是 ROS 2 元构建的基础。


5. 与本工作区 src 树相关的第三方栈

位置 与 ROS 2 的关系
src/eProsima/Fast-DDS + Fast-CDR 默认/常用 DDS 栈之一;rmw_fastrtps 依赖
src/eclipse-cyclonedds/cyclonedds CycloneDDS;rmw_cyclonedds 依赖
src/eclipse-iceoryx/iceoryx 高性能进程间通信;与部分零拷贝路径相关

这些与 src/ros2 中的 *_vendor 包一起,构成完整的可编译工作区。


6. 推荐阅读顺序(针对本仓库)

  1. rmw/rmw/include/rmw/rmw.h 头内 \mainpage 注释:中间件原语总览。
  2. rcl/rcl/include/rcl/init.hrcl/context.h:进程级生命周期与 context。
  3. rclcpp/.../node.hpp:节点如何组合 rcl 与各 node_interfaces
  4. rmw_implementation/.../functions.cppload_library():RMW 如何被选中并加载。
  5. 任选 rmw_fastrtps_cpprmw_cyclonedds_cpprmw_create_* 系列实现,对照 rmw.h 中的声明。

7. 文档维护说明

  • 本文档描述的是 本工作区ros2_humble/src 下的 目录与依赖关系,不替代官方设计文档。
  • 若上游同步新增/移除仓库,以 src/ 实际目录为准,可据此更新各节表格与路径。

8. 延伸阅读

ros2_humble 目录与源码结构详细说明

ros2_humble 目录与源码结构详细说明

本文说明本工作区 ros2_humble/ 根目录及各 src/ 子树的组织方式、各仓库职责、与编译产物目录的关系。更偏「目录与包级」说明;分层调用关系见 ros2_humble_代码架构说明.md,模块内类/函数设计见 ros2_humble_软件模块源码设计解析.md

src/ 下各仓库内 colcon 包逐项说明(含 ament/ros2/rclrosbag2ros2cli 等):见姊妹篇 ros2_humble_src_源码详细解释.mdsrc/ros2/ 的源码结构、分层与阅读路径:见 ros2_humble_src_ros2_源码详解.md


1. 根目录一览

路径 说明
src/ ros2.repos(及可能的额外 clone)拉取的全部上游源码;colcon 只编译此处出现的包。
build/ 各包的 CMake/Python 构建中间目录,可删后重编colcon build 会再生)。
install/ 安装前缀;source install/setup.bash 后使用已安装包、消息与插件索引。
log/ colcon 每次构建的日志(stdout、事件等),便于排错。
ros2.repos vcstool 用的清单:列出各 git 仓库 URL 与分支/tag(本工作区为 Humble 相关版本)。

工作区不是单一 git 仓库,而是多仓库并列;版本以 ros2.repos 与各仓库内 package.xml 为准。


2. src/ 顶层组织(按目录)

下列目录为 src/第一级组织名,对应社区或厂商维护的仓库集合。

2.1 src/ament/ — 构建与元数据基础

子目录 作用简述
ament_cmake 扩展 CMake:ament_package()、测试、导出依赖等 ROS 2 包构建惯例。
ament_index 在 install 前缀内维护资源索引(包名、共享库前缀、RMW 实现注册等),供运行时查找。
ament_lint 代码风格与静态检查(uncrustify、pycodestyle、cppcheck 等)的 CMake 封装。
ament_package 解析 package.xml、Python 侧包元数据。
google_benchmark_vendor / googletest / uncrustify_vendor 将第三方依赖以 vendor 形式打入工作区,保证版本与可重复构建。

2.2 src/eProsima/ — Fast DDS 栈

子目录 作用简述
Fast-CDR CDR 序列化库,DDS 常用底层编码。
Fast-DDS eProsima 的 DDS 实现;与 rmw_fastrtps 配合。
foonathan_memory_vendor Fast-DDS 依赖的内存分配器库的 vendor 包装。

2.3 src/eclipse-cyclonedds/ — CycloneDDS

子目录 作用简述
cyclonedds Eclipse CycloneDDS 实现;与 rmw_cyclonedds_cpp 配合。

2.4 src/eclipse-iceoryx/ — iceoryx

子目录 作用简述
iceoryx 高性能进程间通信框架;与部分零拷贝、共享内存路径相关(依 RMW/配置而定)。

2.5 src/ros2/ — ROS 2 核心与官方生态(重点)

以下按功能分组列出当前工作区中 src/ros2/ 下各一级子目录(每个通常对应一个或多个 colcon 包)。

客户端库与 RCL 家族

目录 作用简述
rcl C 客户端库:init、context、node、pub/sub、service、client、timer、wait、graph 等。
rclcpp C++ 客户端库:NodeExecutor、组件、参数、QoS 封装等。
rclpy Python 客户端库。
rcl_interfaces 参数、日志等标准接口消息定义。
rcl_logging 日志后端抽象(如 spdlog)。
rcpputils C++ 工具(共享库加载、环境变量等)。
rcutils C 工具:分配器、错误串、日志宏、字符串等。
rpyutils Python 侧通用小工具。

中间件抽象与实现

目录 作用简述
rmw RMW C 头文件 API(无单独实现库)。
rmw_implementation 运行时加载具体 rmw_* 共享库并转发调用。
rmw_fastrtps Fast DDS 的 RMW 实现(C++)。
rmw_cyclonedds CycloneDDS 的 RMW 实现。
rmw_connextdds RTI Connext 的 RMW 实现。
rmw_dds_common 多 DDS RMW 共用的图与工具代码。

接口描述与代码生成(rosidl)

目录 作用简述
rosidl 核心:CMake 插件、rosidl_generate_interfaces、多种语言/ typesupport 生成器与运行时。
rosidl_dds 与 DDS IDL 相关的生成支持。
rosidl_defaults 默认启用的生成器组合。
rosidl_python Python 生成与运行时衔接。
rosidl_runtime_py Python 运行时辅助。
rosidl_typesupport typesupport 接口与实现(如 introspection)。
rosidl_typesupport_fastrtps 面向 Fast DDS 的 typesupport。

消息与示例

目录 作用简述
common_interfaces 常用标准消息(geometry、sensor 等)。
example_interfaces 教程用简单 .msg/.srv/.action
unique_identifier_msgs UUID 等标识消息。
test_interface_files 测试用接口定义。
examples / demos 官方示例与演示包。

启动、命令行、安全与测试

目录 作用简述
launch 通用启动框架(Python)。
launch_ros ROS 2 专用 launch 实体(节点、参数等)。
ros2cli ros2 命令行工具实现。
ros2cli_common_extensions 常用 CLI 扩展集合元包。
sros2 DDS 安全策略与 keystore 等工具。
ros2_tracing 与 LTTng 等跟踪集成。
ros_testing 测试框架辅助。
system_tests 跨包系统级测试。

工具链与 CMake 辅助

目录 作用简述
ament_cmake_ros 面向 ROS 包的 ament_cmake 变体/钩子。
eigen3_cmake_module / python_cmake_module 查找 Eigen、Python 的 CMake 模块。
console_bridge_vendor / libyaml_vendor / mimick_vendor / orocos_kdl_vendor / pybind11_vendor / spdlog_vendor / tinyxml_vendor / tinyxml2_vendor / yaml_cpp_vendor 第三方库 vendor,固定版本便于构建。
performance_test_fixture 性能测试夹具。
tlsf TLSF 内存分配器包(实时相关场景)。
realtime_support 实时性相关支持与示例。

几何、URDF、可视化与录制

目录 作用简述
geometry2 TF2:坐标变换库与消息工具链。
urdf URDF 解析与模型描述相关。
message_filters 基于时间同步的过滤器(常与 TF/感知配合)。
rviz RViz2 可视化(含 Ogre 等 vendor 子包)。
rosbag2 录制与回放(多种存储后端)。

2.6 src/ros/ — 与经典 ROS 生态衔接的通用库

子目录 作用简述
class_loader 多态类动态加载(插件体系基础之一)。
pluginlib 插件描述与加载框架。
urdfdom / urdfdom_headers URDF DOM 解析(C++)。
kdl_parser 从 URDF 构建 KDL 树。
robot_state_publisher 发布机器人关节状态对应的 TF。
resource_retriever 通过网络/文件解析 package:// 等资源 URL。
ros_environment 环境变量钩子(如 distro 名)。
ros_tutorials 经典教程包(ROS 2 适配)。

2.7 src/ros-visualization/ — Qt / rqt 工具链

rqt_*、qt_gui_corepython_qt_bindinginteractive_markers 等:基于 Qt 的桌面调试与可视化插件生态。

2.8 src/ros-planning/ — 规划相关消息

子目录 作用简述
navigation_msgs 导航栈常用消息(如 costmap、map meta 等)。

2.9 src/ros-perception/ — 感知通用包

子目录 作用简述
image_common 相机图像传输与 camera_info 等公共组件。
laser_geometry 激光扫描与 PointCloud 等几何转换。

2.10 src/ros-tooling/ — 工具类依赖

子目录 作用简述
keyboard_handler 键盘输入抽象(供 rviz 等使用)。
libstatistics_collector 统计信息采集(与 topic 统计等配合)。

2.11 src/gazebo-release/ — Gazebo 相关 CMake/Math vendor

子目录 作用简述
gz_cmake2_vendor / gz_math6_vendor 将 Gazebo 新版 CMake/Math 以 vendor 形式引入,供仿真相关栈构建。

2.12 src/osrf/ — OSRF 通用基础库

子目录 作用简述
osrf_pycommon launch 等 Python 组件共用小库。
osrf_testing_tools_cpp C++ 测试内存工具等。

2.13 src/ros2-rust/ — Rust 生成器(可选扩展)

子目录 作用简述
rosidl_rust rosidl_generator_rs:从 rosidl 生成 Rust 绑定(实验/扩展用途)。

3. 编译与依赖的粗粒度顺序(阅读源码时)

  1. ament / rcutils / rosidl 运行时与生成器 — 无 ROS 节点亦可独立测。
  2. rmw → rmw_implementation → 某一 rmw_*_cpp — 决定进程内实际 DDS。
  3. rcl → rclcpp / rclpy — 应用直接面对的 API。
  4. geometry2、urdf、rviz、rosbag2 — 在 RCL 之上叠功能。

具体包依赖以各包 package.xml 为准;colcon graph 可查看依赖图。


4. 与 ros2.repos 的关系

  • ros2.repos 声明了本工作区期望存在的仓库路径与版本;新增/删减仓库后需重新 vcs import 或手动 clone,并注意 URL 与 branch/tag 与 Humble 发行说明一致。
  • src/ros2/ 下列出的包名应与官方 ros2.repos 或发行版 manifest 对齐;若本地做过裁剪,以 ls src/ros2 实际结果为准。

5. 延伸阅读

文档 内容侧重
ros2_humble_src_源码详细解释.md src/ 下按包/按仓库 的逐项说明(与本文互补)。
ros2_humble_src_ros2_源码详解.md src/ros2/:仓库布局、分层、阅读顺序。
ros2_humble_代码架构说明.md 运行时分层、Mermaid 总览、推荐阅读顺序。
ros2_humble_软件模块源码设计解析.md rcl / rclcpp / rosidl / rcl_action 等内部设计与源码引用。
ubuntu2204_ros2_humble_环境搭建与文档生成.md Ubuntu 22.04 编译与文档生成步骤。
ROS2命名与机器人操作系统含义辨析.md ROS 2 命名与「机器人操作系统」概念。

本文档随 ros2_humble/src 实际目录生成;若你增删了 ros2.repos 中的仓库,请同步更新 §2 各表。

ROS 2 Humble 软件模块源码设计解析(ros2_humble)

ROS 2 Humble 软件模块源码设计解析(ros2_humble

本文在 ros2_humble_代码架构说明.md 的工作区拓扑与分层图之上,按模块说明设计意图、关键数据结构、调用链与扩展点。路径默认相对于工作区根目录 ros2_humble/


1. 设计总览:为何拆成这些层

ROS 2 把「语言绑定」「ROS 语义」「DDS 细节」拆开,便于多语言、多中间件实现并存:

层次 职责 典型依赖
rcutils C 侧分配器、日志宏、字符串、错误串、原子等,与 ROS 无关的底层工具 无 ROS 概念
rmw 纯头文件 API:node、pub/sub、wait、graph 等与实现无关的中间件抽象 rcutilsrosidl_runtime_c
rmw_implementation 在进程内加载某一个 rmw_* 共享库,并把 rmw_* 调用转发过去 rcpputils::SharedLibraryament_index
rcl 在 rmw 之上实现 context、命令行参数、重映射、命名解析、QoS 默认值、loan、图 guard 等 ROS 语义 rmwrcutils
rclcpp / rclpy 面向用户的对象模型、executor、类型安全封装 rcl
rosidl .msg/.srv/.action 生成类型与 typesupport,供 rmw 序列化 CMake 插件链

这样替换 DDS 时只需换 RMW 实现包,rcl 与上层 API 尽量保持稳定。


2. rcl:进程与节点生命周期

2.1 Context 与 rmw_context 的一对一关系

rcl_context_t 的私有实现里持有 rmw_context_t,表示「这一次 rcl_init 对应的中间件上下文」:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct rcl_context_impl_s
{
/// Allocator used during init and shutdown.
rcl_allocator_t allocator;
/// Copy of init options given during init.
rcl_init_options_t init_options;
/// Length of argv (may be `0`).
int64_t argc;
/// Copy of argv used during init (may be `NULL`).
char ** argv;
/// rmw context.
rmw_context_t rmw_context;
};

设计要点instance_iddomain_idlocalhost_onlyenclave、安全选项等先在 rcl 侧从环境变量与参数解析好,再填入 rmw_init_options,最后调用 rmw_init,保证 DDS 只看到已规范化的初始化选项。

2.2 rcl_init 中的关键顺序

rcl_init 在完成参数校验与 context->impl 分配后,会零初始化 rmw_context,再解析 argv、设置 instance_id、domain、localhost、enclave、security,最后进入中间件初始化:

1
2
3
4
// Initialize rmw_init.
rmw_ret_t rmw_ret = rmw_init(
&(context->impl->init_options.impl->rmw_init_options),
&(context->impl->rmw_context));

设计要点:失败路径用 goto fail 统一清理,避免 rmw/rcl 状态不一致;rcl_shutdownrcl_context_fini 的职责分割写在 context.c / init.h 注释中(先 shutdown 再 fini)。

2.3 Node:rcl 句柄 + rmw_node_t

节点的实现结构显式持有 rmw_node_t * 与图相关的 guard condition,其余命名空间校验、logger 名等围绕其展开:

1
2
3
4
5
6
7
8
struct rcl_node_impl_s
{
rcl_node_options_t options;
rmw_node_t * rmw_node_handle;
rcl_guard_condition_t * graph_guard_condition;
const char * logger_name;
const char * fq_name;
};

设计要点rcl_node_t 对用户是不透明句柄;rmw_node_t 才是 DDS participant 侧「节点」的抽象。上层只通过 rcl_* API 访问,便于测试 mock 与多 RMW。

2.4 Publisher:ROS 语义在前,rmw_create_publisher 在后

rcl_publisher_init 的典型顺序:校验 → 解析/重映射 topic → 分配 impl → 调 rmw 创建 → 取 actual QoS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Expand and remap the given topic name.
char * remapped_topic_name = NULL;
rcl_ret_t ret = rcl_node_resolve_name(
node,
topic_name,
*allocator,
false,
false,
&remapped_topic_name);
...
publisher->impl->rmw_handle = rmw_create_publisher(
rcl_node_get_rmw_handle(node),
type_support,
remapped_topic_name,
&(options->qos),
&(options->rmw_publisher_options));
RCL_CHECK_FOR_NULL_WITH_MSG(
publisher->impl->rmw_handle, rmw_get_error_string().str, goto fail);

设计要点:topic 字符串在进入 rmw 之前已定型,rmw 不负责 remap;rosidl_message_type_support_t * 把具体消息类型与 typesupport 绑定传给 rmw,实现多消息类型多模板实例化。

2.5 Wait set:rcl 索引 + rmw 等待原语

rcl_wait_setimpl 维护各类实体计数,并持有 rmw_wait_set_t *,与 rmw_subscriptions_t 等聚合类型对齐,便于最终调用 rmw_wait

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct rcl_wait_set_impl_s
{
// number of subscriptions that have been added to the wait set
size_t subscription_index;
rmw_subscriptions_t rmw_subscriptions;
...
rmw_wait_set_t * rmw_wait_set;
// number of timers that have been added to the wait set
size_t timer_index;
// context with which the wait set is associated
rcl_context_t * context;
// allocator used in the wait set
rcl_allocator_t allocator;
};

设计要点Timer 在 rcl 层维护,不直接进入所有 rmw 实现;Executor 通过 rcl_wait 把「有消息 / 有 guard / 定时器到期」统一成一次阻塞唤醒,这是 rclcpp 单线程与多线程 executor 的公共底座。


3. rclcpp:组合优于巨类

3.1 Node 的「接口拆分」

rclcpp::Node 通过 node_interfaces 把能力拆成多个接口类(topics、services、parameters、graph、clock、logging、waitables 等),每个接口有 *Interface 与具体实现类(如 NodeBase)。NodeBase 直接持有 rcl_node_t 相关资源与 Context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// Implementation of the NodeBase part of the Node API.
class NodeBase : public NodeBaseInterface, public std::enable_shared_from_this<NodeBase>
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBase)

RCLCPP_PUBLIC
NodeBase(
const std::string & node_name,
const std::string & namespace_,
rclcpp::Context::SharedPtr context,
const rcl_node_options_t & rcl_node_options,
bool use_intra_process_default,
bool enable_topic_statistics_default);

设计要点:便于单测替换某一接口;enable_shared_from_this 支持在回调里安全获取 Node 的 shared_ptr默认进程内通信、topic 统计等策略在构造期注入。

3.2 Executor:与通信图解耦的执行模型

基类 rclcpp::Executor 文档说明其职责是调度「可用工作」(订阅回调、定时器等),并明确与 rcl/wait 的关系:

1
2
3
4
5
6
7
8
9
10
11
/// Coordinate the order and timing of available communication tasks.
/**
* Executor provides spin functions (including spin_node_once and spin_some).
* It coordinates the nodes and callback groups by looking for available work and completing it,
* based on the threading or concurrency scheme provided by the subclass implementation.
* An example of available work is executing a subscription callback, or a timer callback.
* The executor structure allows for a decoupling of the communication graph and the execution
* model.
* See SingleThreadedExecutor and MultiThreadedExecutor for examples of execution paradigms.
*/
class Executor

设计要点CallbackGroup 控制可重入性与互斥;MultiThreadedExecutor 用线程池 spin,与 SingleThreadedExecutor 共享「建 wait set → wait → 分发」思路,差异在并发与锁。


4. rosidl:接口描述到运行时的流水线

4.1 CMake 聚合入口

rosidl_generate_interfaces 宏负责收集 .msg/.srv/.action,并驱动各 generator 的扩展点(注释即设计说明):

1
2
3
4
5
6
7
8
9
#
# Generate code for ROS IDL files using all available generators.
#
# Execute the extension point ``rosidl_generate_interfaces``.
...
# If the parent directory is 'action', it is assumed to be
# an action definition.
# If an action interface is passed then you must add a depend tag for
# 'action_msgs' to your package.xml, otherwise this macro will error.

设计要点action 通过目录约定与 action_msgs 依赖显式区分;非 .idl 会先走 rosidl_adapter 转成 .idl,兼容历史 .msg 工作流。

4.2 运行时 C 类型与支持结构

rosidl_runtime_c 提供 message_type_support_struct 等,与 rmw 的「发布某类型」签名衔接(见上文 rcl_publisher_inittype_support 参数)。序列化细节由 rosidl_typesupport_*(introspection、fastrtps、cpp 等)在编译期选链。


5. rcl_action:用已有原语组合 Action

Action 在实现上不增加新的 rmw 原语,而是在 rcl_client + rcl_subscription 上组合:例如 client 侧 impl 内含多个 client 与 subscription:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rcl_action_client_impl_t
_rcl_action_get_zero_initialized_client_impl(void)
{
rcl_client_t null_client = rcl_get_zero_initialized_client();
rcl_subscription_t null_subscription = rcl_get_zero_initialized_subscription();
rcl_action_client_impl_t null_action_client = {
null_client,
null_client,
null_client,
null_subscription,
null_subscription,
...
};
return null_action_client;
}

设计要点:goal / cancel / result 走 service 语义对应的 client;feedback、status 走 subscription;状态机goal_state_machine.c)在 rcl 层统一,降低 rmw 负担。


6. rmw_implementation 与多实现共存

运行时通过 RMW_IMPLEMENTATION 或 ament index 选择共享库,把符号解析到具体实现(详见 rmw_implementation/src/functions.cppload_library() 注释)。设计要点:二进制包可只装一种 RMW,源码工作区可同时编译多种,用环境变量切换,无需重编应用。


7. 其他模块(简析)

模块 源码位置(示例) 设计角色
rcl_lifecycle src/ros2/rcl/rcl_lifecycle/ 在节点之上叠加有限状态机与 transition 服务,与 rclcpp_lifecycle 配合
rcl_yaml_param_parser src/ros2/rcl/rcl_yaml_param_parser/ 将 YAML 参数文件解析为供 rcl/rclcpp 使用的结构
launch / launch_ros src/ros2/launch* 描述式启动:ComposableNode、参数、重映射以数据结构表达,可 Python/XML 执行
rosbag2 src/ros2/rosbag2/ 存储抽象(sqlite/mcap)+ 传输层复用,与 rclcpp 序列化路径对接
geometry2 / tf2 src/ros2/geometry2/ 坐标变换树,独立于 DDS 高频查询路径
sros2 src/ros2/sros2/ 安全策略与 keystore,与 DDS governance 配置衔接(如 policy/schemas

8. 源码阅读路径建议

  1. rmw/rmw/include/rmw/rmw.h:建立「中间件必须提供哪些原语」的心智模型。
  2. rcl/init.ccontext_impl.hnode.cpublisher.cwait.c:沿一条从进程启动到收发与等待的纵向切片。
  3. rclcpp/node_interfaces/ + executor.hpp:看 C++ 如何把 rcl 拆成可测试、可扩展的接口。
  4. rosidl_generate_interfaces.cmake + 任意消息包的 rosidl_generator_* 生成物:理解编译期代码生成。
  5. rcl_action/action_client.c:理解「组合模式」在 ROS 2 API 设计中的典型用法。

9. 文档说明

本文描述 Humble 分支在本工作区中的通用设计;具体函数行为以头文件注释与单元测试为准。若与 ros2_humble_代码架构说明.md 中的表格冲突,以 src/ 实际目录 为准。

src/ 下各包路径与职责逐项列表ros2_humble_src_源码详细解释.mdsrc/ros2/ 目录结构、分层与阅读顺序ros2_humble_src_ros2_源码详解.md

为什么叫 ROS 2?为什么说它是「机器人的操作系统」?

为什么叫 ROS 2?为什么说它是「机器人的操作系统」?

本文从命名由来比喻含义两方面说明:ROS 2 里的「2」指什么,以及「Robot Operating System」和常见意义上的操作系统(如 Linux)有何不同。阅读本仓库其它文档时,可把本文当作概念背景。


1. 为什么叫 ROS,又为什么有「ROS 2」

  • ROS 最初来自 Willow Garage 等社区项目,全称习惯写作 Robot Operating System(机器人操作系统)。它并不是从零写的一个内核,而是跑在通用操作系统之上的一套中间件、工具链与生态约定
  • ROS 2 是相对 ROS 1新一代设计与实现:更换了通信中间件抽象(如 DDS)、改进了实时性与安全、统一了多机器人与生命周期等模型。版本号上的「2」表示大代际升级,与发行版名(如 Humble)是不同维度:前者是产品线/架构代际,后者是长期支持(LTS)发行版代号。

简言之:ROS 2 = 在「机器人软件栈」这一角色上,承接并替代 ROS 1 的那套系统


2. 「机器人的操作系统」到底指什么

这里的 Operating System 更接近比喻,而不是计算机课本里「直接管理 CPU/内存/设备的内核」。

在机器人工程里,团队往往需要反复解决同类问题:

  • 多进程/多机之间的话题、服务、动作、参数如何通信;
  • 传感器与控制的**数据类型、时间戳、坐标系(TF)**如何统一;
  • 启动、调试、录包、可视化如何标准化;
  • 算法、驱动、仿真如何以包的形式复用

ROS / ROS 2 在这些层面上提供了类似操作系统给应用程序提供 API 那样的一层:约定 + 库 + 工具。所以社区会说它是「面向机器人的操作系统」——指的是机器人应用所依赖的那一层平台,而不是要替代 Linux 或 Windows。


3. 那 Linux、Windows、RTOS 算不算「机器人操作系统」

它们当然可以用来跑机器人,但通常不会用「Robot Operating System」这个专有名词来称呼它们,原因包括:

系统类型 主要解决的问题 与「ROS 式机器人 OS」的差别
通用操作系统(如 Ubuntu、Windows) 进程、文件、网络、设备驱动、用户界面 不提供 ROS 语义下的 Node/Topic/Service、标准消息生态、colcon/ament 工作流等;机器人团队仍要在其上自建或引入一层中间件。
实时操作系统 / 裸机(如 FreeRTOS、VxWorks、MCU 固件) 确定性时序、硬实时控制 底层控制回路;一般不承担整机多模块分布式图、高层导航与工具链的统一抽象。
ROS / ROS 2 在通用 OS(或 RTOS 配合)之上,统一机器人软件如何拆分、通信、集成与运维 定位是机器人应用的平台层,名称里的「Operating System」强调的是这一层角色,而非内核实现。

因此:不是「只有 ROS 才能做机器人」,而是 ROS 2 把自己定义成专门服务机器人软件开发的那类「平台型」系统;其它系统要么是更底层的真·操作系统,要么是不包含 ROS 语义的通用环境,所以不会用同一个专有名词来概括。


4. 小结

  1. ROS 2 表示相对 ROS 1 的新一代架构与实现;与 Humble 等发行版名称并存,含义不同。
  2. Robot Operating System行业习惯称呼,强调在通用 OS 之上为机器人应用提供的中间件与生态不是与 Linux 并列的另一种内核。
  3. Linux/Windows/RTOS 解决的是更底层或更通用的问题;它们可以承载 ROS 2,但不等同于 ROS 2 所特指的那一层「机器人软件操作系统」含义。

若你希望把本文与源码阅读串联,可继续阅读:ros2_humble_代码架构说明.mdros2_humble_软件模块源码设计解析.md

camera_calibration_parsers 源码详细分析

camera_calibration_parsers 源码详细分析

工作区路径:/home/cp/work2/ros2Learn/ros2_humble/src/ros-perception/image_common/camera_calibration_parsers
版本:3.1.12,许可证 BSD

camera_calibration_parsers 是 ROS 相机标定文件的 读写库:把磁盘上的 INI(Videre 遗留格式)YAML(OpenCV/camera_calibration 格式)sensor_msgs/msg/CameraInfo 互相转换。主要消费者是 camera_info_manager,相机驱动和 image_pipeline 通过它加载/保存内参。


1. 仓库结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
camera_calibration_parsers/
├── include/camera_calibration_parsers/
│ ├── parse.hpp # 统一入口 API
│ ├── parse_ini.hpp # INI 格式
│ ├── parse_yml.hpp # YAML 格式
│ ├── parse.h / parse_ini.h / parse_yml.h # 遗留 C 风格头(兼容)
│ └── visibility_control.hpp
├── src/
│ ├── parse.cpp # 按扩展名分发
│ ├── parse_ini.cpp # INI 解析/写入
│ ├── parse_yml.cpp # YAML 解析/写入(yaml-cpp)
│ ├── convert.cpp # CLI 格式转换工具
│ ├── parse_wrapper.cpp # Python Boost 绑定(已禁用)
│ └── camera_calibration_parsers/__init__.py # Python API(依赖已禁用的 wrapper)
├── test/
│ ├── test_parse_ini.cpp
│ ├── test_parse_yml.cpp
│ ├── calib5.ini / calib8.ini
│ └── make_calibs.hpp
├── CMakeLists.txt
└── package.xml

2. 在 image_common 栈中的位置

标定文件camera_calibration_parsersROS 2 消息消费者*.ini\nVidere 格式*.yml / *.yaml\nOpenCV 格式readCalibrationwriteCalibrationsensor_msgs/CameraInfo\nK, D, R, P, distortion_modelcamera_info_manager相机驱动\nusb_cam, v4l2...convert CLI
角色 说明
本包 文件 ↔ CameraInfo 序列化
camera_info_manager URL 解析、缓存、set_camera_info 服务
下游 图像 rectification、投影、立体视觉

3. 公共 API

3.1 统一入口(parse.hpp

函数 作用
readCalibration(file, camera_name, cam_info) 按扩展名读 .ini / .yml / .yaml
writeCalibration(file, camera_name, cam_info) 按扩展名写
parseCalibration(buffer, format, ...) 从内存字符串解析(仅 ini

目标类型统一为:

1
using CameraInfo = sensor_msgs::msg::CameraInfo;

3.2 格式分发(parse.cpp

1
2
3
4
5
6
7
8
9
10
bool writeCalibration(...)
{
if (p.extension() == ".ini")
return writeCalibrationIni(...);
else if (p.extension() == ".yml" || p.extension() == ".yaml")
return writeCalibrationYml(...);
else
RCLCPP_ERROR(..., "calibration must be '.ini', '.yml', or '.yaml'");
return false;
}

parseCalibration 的限制:

1
2
3
4
5
6
7
bool parseCalibration(const std::string & buffer, const std::string & format, ...)
{
if (format != "ini") {
return false;
}
return parseCalibrationIni(buffer, camera_name, cam_info);
}

内存解析不支持 YAML,只有 INI。


4. CameraInfo 字段映射

两种格式都填充 sensor_msgs/CameraInfo 的核心矩阵:

CameraInfo 字段 含义 尺寸
width, height 图像分辨率
k 相机内参矩阵 K 3×3
d 畸变系数 5 或 8
r 矫正矩阵 R 3×3
p 投影矩阵 P 3×4
distortion_model 畸变模型名 string

畸变模型(sensor_msgs/distortion_models.hpp):

模型 常量 D 系数个数
Plumb Bob plumb_bob 5
Rational Polynomial rational_polynomial 8

5. INI 格式(Videre 遗留)

5.1 文件结构

示例 test/calib5.ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[image]
width
640
height
480

[mono_left]
camera matrix
369.344588 0.000000 320.739078
...
distortion
0.189544 -0.018229 ...
rectification
1.000000 0.000000 0.000000
...
projection
262.927429 0.000000 ...

节(section)类型:

Section 作用
[image] width / height
[camera_name] 以节名作为相机名,含 K/D/R/P
[externals] translation/rotation(读取但不使用

5.2 解析流程(parse_ini.cpp

1
2
3
4
5
6
readCalibrationIni(stream)
→ split_lines() # 按行分割
→ split_sections() # 按 [section] 分组,跳过 # ; 注释
→ parse_image_section() # width/height
→ parse_camera_section() # K, D, R, P
→ parse_externals_section() # 可选,仅警告

矩阵解析:parse_matrix<rows, cols>() 从后续行按空格读浮点数。

5.3 畸变模型推断(INI 读)

1
2
3
4
5
6
7
8
auto d = parse_matrix<1, 8>(++distortion);
if (std::isnan(d[5])) {
cam_info.d = vector(d[0..4]);
cam_info.distortion_model = PLUMB_BOB;
} else {
cam_info.d = vector(d[0..7]);
cam_info.distortion_model = RATIONAL_POLYNOMIAL;
}

读 8 个系数,若第 6 个为 NaN 则截为 5 系数 plumb_bob。

5.4 INI 写限制

1
2
3
4
5
if (cam_info.distortion_model != PLUMB_BOB || cam_info.d.size() != 5)
{
RCLCPP_ERROR(..., "Videre INI format can only save plumb bob ... Use YAML");
return false;
}

INI 写出仅支持 plumb_bob + 5 系数;rational_polynomial 必须用 YAML。


6. YAML 格式(OpenCV / camera_calibration)

6.1 文件结构

测试用例格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
image_width: 640
image_height: 480
camera_name: mono_left
camera_matrix:
rows: 3
cols: 3
data: [1, 2, 3, 4, 5, 6, 7, 8, 9]
distortion_model: plumb_bob
distortion_coefficients:
rows: 1
cols: 5
data: [1, 2, 3, 4, 5]
rectification_matrix:
rows: 3
cols: 3
data: [1, 0, 0, 0, 1, 0, 0, 0, 1]
projection_matrix:
rows: 3
cols: 4
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

与 OpenCV FileStorage / camera_calibration 工具链兼容。

6.2 实现(parse_yml.cpp

  • 依赖 yaml-cpp(通过 yaml_cpp_vendor
  • 写:YAML::Emitter + 自定义 SimpleMatrix 序列化器(rows/cols/data 结构)
  • 读:YAML::Load() → 逐字段填充 CameraInfo
  • distortion_model 时默认 plumb_bob 并 WARN

YAML 读写均支持任意 D 长度和显式 distortion_model


7. 格式对比

特性 INI YAML
来源 Videre 工业相机遗留 OpenCV / camera_calibration
✅ plumb_bob / rational_polynomial ✅ 全模型
仅 plumb_bob (D=5) ✅ 全模型
解析库 手写 line/section yaml-cpp
distortion_model 读时推断,写时不存 显式字段
externals 有节但不使用

8. CLI 工具 convert

1
2
ros2 run camera_calibration_parsers convert input.yml output.ini
ros2 run camera_calibration_parsers convert input.ini output.yml

流程:readCalibrationwriteCalibration
注意:INI 输出时若源为 rational_polynomial 会失败。


9. camera_info_manager 集成

1
2
3
4
5
6
if (readCalibration(filename, cam_name, cam_info)) {
if (cname != cam_name) {
RCLCPP_WARN(..., "camera name mismatch");
}
cam_info_ = cam_info;
}

典型 URL:

1
2
file:///home/user/.ros/camera_info/my_camera.yaml
package://my_robot/config/camera_left.ini

保存标定(set_camera_info 服务回调)调用 writeCalibration()


10. 依赖关系

1
2
3
4
5
camera_calibration_parsers
├── sensor_msgs # CameraInfo, distortion_models
├── yaml_cpp_vendor # YAML 读写
├── rcpputils # 文件系统、路径扩展名
└── rclcpp # 日志(PRIVATE 链接 parse.cpp,PUBLIC 未导出)

构建产物:

  • libcamera_calibration_parsers.so
  • convert 可执行文件(安装到 lib/camera_calibration_parsers/

11. Python 支持状态

组件 状态
parse_wrapper.cpp 已注释禁用(仍用 ROS 1 boost::python + ros::serialization
setup.py 遗留 catkin 风格,未接入 ament CMakeLists
__init__.py 引用不存在的 camera_calibration_parsers_wrapper

ROS 2 Humble 中 Python API 不可用;应直接用 C++ API 或通过 camera_info_manager Python 绑定(若有)。


12. 测试覆盖

测试 内容
test_parse_ini 有效/无效 INI、5/8 系数、round-trip 读写
test_parse_yml plumb_bob / rational_polynomial YAML、round-trip
calib5.ini / calib8.ini 真实标定样例

make_calibs.hpp 提供标准 640×480 测试矩阵和 check_calib() 断言。


13. 设计特点与局限

特点 说明
双格式兼容 兼顾老 INI 与新 YAML 生态
流式 + 文件 API istream/ostream 与路径 overload
自动格式检测 扩展名驱动,无需手动指定
畸变模型感知 INI 读时推断,YAML 显式存储
局限 说明
INI 写能力弱 仅 plumb_bob
parseCalibration 无 YAML 内存 buffer 只支持 ini
externals 节无效 读但不写入 CameraInfo
Python 绑定废弃 ROS 2 未重建
日志依赖 rclcpp 纯库场景也需链接 rclcpp
遗留 .h 头文件 与 .hpp 并存,TODO 统一

14. 典型使用

C++

1
2
3
4
5
6
7
#include "camera_calibration_parsers/parse.hpp"

std::string camera_name;
sensor_msgs::msg::CameraInfo cam_info;
if (camera_calibration_parsers::readCalibration("left.yaml", camera_name, cam_info)) {
// 使用 cam_info.k, cam_info.d, ...
}

与 camera_calibration 工具链

1
2
# camera_calibration 保存的 YAML 可直接被 readCalibration 读取
ros2 run camera_info_manager caminfo_manager ...

15. 推荐阅读顺序

  1. parse.hpp — 三个公共函数
  2. parse.cpp — 扩展名分发逻辑
  3. parse_yml.cpp — 现代 YAML 路径(优先)
  4. parse_ini.cpp — Videre INI 解析细节
  5. test/calib5.ini + test_parse_yml.cpp — 格式样例
  6. camera_info_manager.cpploadCalibrationFile / saveCalibrationFile
  7. convert.cpp — 格式互转 CLI

16. 小结

camera_calibration_parsers 是 ROS 相机标定的 文件 I/O 适配层:INI 兼容 Videre 老格式,YAML 对接 OpenCV/camera_calibration 生态,统一输出 sensor_msgs/CameraInfocamera_info_manager 是其主要调用者;convert 提供格式转换。ROS 2 中 Python 绑定已移除,核心能力在 C++ 库中。

如果你希望,我可以把本文写入 ros2doc/ros-perception/camera_calibration_parsers 源码详细分析.md,或继续分析 camera_info_manager 的 URL 解析与 set_camera_info 服务流程

camera_info_manager 源码详细分析

camera_info_manager 源码详细分析

工作区路径:/home/cp/work2/ros2Learn/ros2_humble/src/ros-perception/image_common/camera_info_manager
版本:3.1.12,许可证 BSD

camera_info_manager 是 ROS 相机驱动的 标定数据管理库:负责从 URL 加载/保存 sensor_msgs/CameraInfo,提供 set_camera_info 服务供 camera_calibration 写入标定结果,并缓存当前内参。文件格式读写委托给 camera_calibration_parsers


1. 仓库结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
camera_info_manager/
├── include/camera_info_manager/
│ ├── camera_info_manager.hpp # 公共 API(主头文件)
│ ├── camera_info_manager.h # 遗留 C 风格头
│ └── visibility_control.h
├── src/
│ ├── camera_info_manager.cpp # 全部实现(~620 行)
│ └── split.hpp # 正则 split 工具(未使用)
├── tests/
│ ├── unit_test.cpp # ROS 1 风格测试(CMake 中已禁用)
│ ├── test_calibration.yaml # 测试标定样例
│ └── unit_test.test
├── CMakeLists.txt
└── package.xml

Python 对应包camera_info_manager_py(独立 ament 包,逻辑与 C++ 版平行)。


2. 在 image_common 栈中的位置

标定工具camera_info_managercamera_calibration_parsers相机驱动SetCameraInfocamera_calibrationloadCalibration\nURL 解析cam_info_ 缓存set_camera_info 服务saveCalibrationreadCalibration / writeCalibration发布 image + camera_info
组件 职责
camera_info_manager URL 管理、懒加载、服务、线程安全缓存
camera_calibration_parsers YAML/INI 文件序列化
camera_calibration 标定并调用 set_camera_info
image_pipeline 使用 CameraInfo 做 rectification

3. 类设计:CameraInfoManager

3.1 构造与成员

1
2
3
4
5
6
7
8
9
10
11
12
13
CameraInfoManager::CameraInfoManager(
rclcpp::Node * node,
const std::string & cname,
const std::string & url)
: logger_(node->get_logger()),
camera_name_(cname),
url_(url),
loaded_cam_info_(false)
{
info_service_ = node->create_service<SetCameraInfo>(
"set_camera_info",
std::bind(&CameraInfoManager::setCameraInfoService, this, ...));
}
成员 作用
camera_name_ 相机唯一标识(写入标定文件并校验)
url_ 标定文件 Uniform Resource Locator
cam_info_ 当前 CameraInfo 缓存
loaded_cam_info_ 是否已尝试加载(懒加载标志)
info_service_ set_camera_info 服务
mutex_ 保护上述可变状态

3.2 公共 API

方法 作用
getCameraInfo() 返回缓存;首次调用触发加载
isCalibrated() cam_info_.k[0] != 0 判断是否已标定
loadCameraInfo(url) 设置新 URL 并立即加载
setCameraName(cname) 改相机名,强制下次重新加载
setCameraInfo(info) 手动设置内参(不保存文件)
validateURL(url) 检查 URL 语法是否支持
resolveURL(url, cname) 展开 ${NAME} / ${ROS_HOME}

4. 懒加载机制

自 Fuerte 起,构造函数不加载文件,避免无效 URL 产生误导性错误日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CameraInfo CameraInfoManager::getCameraInfo(void)
{
while (rclcpp::ok()) {
std::lock_guard<std::mutex> lock(mutex_);
if (loaded_cam_info_) {
return cam_info_;
}
loaded_cam_info_ = true;
url = url_;
cname = camera_name_;
} // 释放锁
loadCalibration(url, cname); // I/O 在锁外
}
return CameraInfo();
}

要点:

  • 首次 getCameraInfo() / isCalibrated() 才触发 loadCalibration()
  • 即使加载失败,loaded_cam_info_ 也为 true,避免重复尝试
  • I/O 从不持锁,防止死锁与长时间阻塞

未标定时返回 全零 CameraInfo,image_pipeline 将其视为 uncalibrated。


5. URL 系统

5.1 支持的 URL 类型

1
2
3
4
if (iequals(url.substr(0, 8), "file:///"))   → URL_file
if (iequals(url.substr(0, 9), "flash:///")) → URL_flash (未实现)
if (iequals(url.substr(0, 10), "package://")) → URL_package
else → URL_invalid
类型 示例 行为
"" 使用默认 URL
file:// file:///home/user/cam.yaml 本地绝对路径(去掉 file:// 前缀 7 字符)
package:// package://my_pkg/config/cam.yaml ament_index 解析 share 路径
flash:// 警告,未实现

5.2 默认 URL

1
2
const std::string default_camera_info_url =
"file://${ROS_HOME}/camera_info/${NAME}.yaml";

空 URL 或无效 URL 保存时,回退到此默认路径(通常为 ~/.ros/camera_info/<camera_name>.yaml)。

5.3 变量替换(resolveURL

变量 替换为
${NAME} 当前 camera_name_
${ROS_HOME} 环境变量 ROS_HOME,否则 $HOME/.ros

单遍扫描,不支持递归替换。非法 ${...} 保留 $ 并 ERROR 日志。

示例:

1
2
3
4
5
package://my_robot/calibrations/${NAME}.yaml
→ package://my_robot/calibrations/left_camera.yaml

file://${ROS_HOME}/camera_info/${NAME}.yaml
→ file:///home/user/.ros/camera_info/left_camera.yaml

5.4 package:// 解析

1
2
3
std::string package = url.substr(prefix_len, rest - prefix_len);
std::string pkgPath = ament_index_cpp::get_package_share_directory(package);
return pkgPath + url.substr(rest);

6. 加载与保存流程

6.1 加载

1
2
3
4
5
6
7
loadCalibration(url, cname)
→ resolveURL(url, cname)
→ parseURL() 分派
→ loadCalibrationFile(filename, cname)
→ readCalibration() [camera_calibration_parsers]
→ 校验 camera_name(不匹配仅 WARN)
→ cam_info_ = cam_info

6.2 保存(set_camera_info 服务)

1
2
3
4
5
void setCameraInfoService(...)
{
cam_info_ = req->camera_info; // 总是更新内存
rsp->success = saveCalibration(req->camera_info, url_copy, cname);
}
1
2
3
4
5
saveCalibration(info, url, cname)
→ resolveURL + parseURL
→ saveCalibrationFile(filename, cname)
→ 创建父目录(rcpputils::fs::create_directories)
→ writeCalibration() [camera_calibration_parsers]

即使保存失败,内存中的 cam_info_ 也已更新


7. set_camera_info 服务

属性
服务名 set_camera_info(相对节点 namespace)
类型 sensor_msgs/srv/SetCameraInfo
调用方 camera_calibration 标定工具

典型驱动集成:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyCameraNode : public rclcpp::Node {
camera_info_manager::CameraInfoManager cinfo_;

MyCameraNode() : Node("camera"), cinfo_(this, "my_camera", camera_info_url) {}

void publishFrame() {
auto msg = std::make_unique<sensor_msgs::msg::CameraInfo>(
cinfo_.getCameraInfo());
msg->header.stamp = ...;
msg->header.frame_id = "camera_optical_frame";
pub_ci_->publish(std::move(msg));
}
};

驱动需提供 camera_info_url 参数(在驱动层处理,非本类内置)。


8. 相机名校验

1
2
3
4
5
6
7
8
9
bool setCameraName(const std::string & cname)
{
if (cname.empty()) return false;
for (char c : cname)
if (!isalnum(c) && c != '_') return false;
camera_name_ = cname;
loaded_cam_info_ = false; // 强制重新加载
return true;
}

合法字符:[a-zA-Z0-9_]。建议用设备序列号、型号等唯一标识。


9. 标定判定

1
return cam_info_.k[0] != 0.0;

K 矩阵第一个元素非零 作为“已标定”启发式判断,而非检查 distortion 或 P 矩阵。


10. 依赖关系

1
2
3
4
5
6
camera_info_manager
├── rclcpp # Node、Service、Logger
├── sensor_msgs # CameraInfo、SetCameraInfo
├── camera_calibration_parsers # 文件读写
├── ament_index_cpp # package:// URL
└── rcpputils # 文件系统、环境变量

11. 与 Python 版对比

特性 C++ camera_info_manager Python camera_info_manager_py
包名 本包 独立包
YAML 解析 camera_calibration_parsers 内置 yaml 模块
URL/服务逻辑 基本相同 基本相同
扩展 ZoomCameraInfoManager

Python 驱动应使用 camera_info_manager_py,而非 C++ 包。


12. 测试状态

文件 状态
tests/unit_test.cpp CMake 中注释禁用(仍用 ROS 1 ros::NodeHandle API)
tests/test_calibration.yaml 有效样例数据(640×480 plumb_bob)
lint cpplint / uncrustify 启用

ROS 2 端口后单元测试尚未完全迁移。


13. 遗留与未使用代码

说明
split.hpp 正则 split 工具,未被 camera_info_manager.cpp 引用
camera_info_manager.h 遗留头文件,新代码应用 .hpp
parse_wrapper 不在本包

14. 典型使用场景

场景 1:launch 指定标定文件

1
2
3
# 驱动参数
camera_info_url: "package://my_robot/config/left_camera.yaml"
camera_name: "left_camera"

场景 2:标定后自动保存

1
2
3
ros2 run camera_calibration cameracalibrator ...
# 标定完成后调用 /<namespace>/set_camera_info
# 默认保存到 ~/.ros/camera_info/<camera_name>.yaml

场景 3:多相机

1
2
3
camera_info_manager::CameraInfoManager left_ci(this, "left", left_url);
camera_info_manager::CameraInfoManager right_ci(this, "right", right_url);
// 或在子 namespace 下:left/camera, right/camera

15. 设计特点与局限

特点 说明
懒加载 构造时不读文件,减少启动噪声
URL 抽象 file/package + 变量替换,灵活配置
线程安全 短持锁 + I/O 锁外
服务集成 与 camera_calibration 工作流无缝对接
默认路径约定 ~/.ros/camera_info/ 社区惯例
局限 说明
flash:// 未实现 仅 WARN
package:// 写权限 保存到 package share 需可写(通常不推荐)
k[0] 标定判断 粗糙启发式
单元测试未启用 ROS 2 测试待迁移
Header 未填 getCameraInfo() 不设置 header,驱动必须填
resolveURL 公开 API 略暴露内部细节

16. 推荐阅读顺序

  1. camera_info_manager.hpp 文档注释 — URL/相机名/服务约定
  2. 构造函数 + getCameraInfo() — 懒加载模式
  3. loadCalibration / saveCalibration — URL 分派
  4. resolveURL / parseURL — 变量替换与语法
  5. setCameraInfoService — 标定写入路径
  6. camera_calibration_parsers 分析 — 文件格式细节
  7. camera_info_manager_py — Python 驱动参考

17. 小结

camera_info_manager 是 ROS 相机标定的 运行时管理器:通过 URL 定位标定文件,懒加载 CameraInfo,暴露 set_camera_info 供标定工具写入,并委托 camera_calibration_parsers 做持久化。它是连接 camera_calibration ↔ 相机驱动 ↔ image_pipeline 的关键中间层。

如果你希望,我可以把本文写入 ros2doc/ros-perception/image_common/camera_info_manager 源码详细分析.md,或继续分析 camera_calibration 如何调用 set_camera_info 的完整流程