ROS2 框架下 C++ 与 Python 混合编程机制
1. ROS2 混合编程架构概述
ROS2(Robot Operating System 2)作为新一代机器人操作系统,在设计之初就充分考虑了多语言编程的需求。与 ROS1 相比,ROS2 在混合编程方面实现了更加灵活和高效的架构设计。
1.1 ROS2 多语言支持架构
ROS2 的多语言支持基于一个精心设计的分层架构。在这个架构中,所有的客户端库都构建在一个共同的核心 ROS 客户端库(RCL)之上。RCL 是用 C 语言实现的,提供了与语言无关的核心功能,包括节点管理、消息传递、服务调用等基础机制。这种设计使得不同语言的客户端库能够保持行为的一致性,同时又能发挥各自语言的优势。
具体而言,ROS2 官方提供了两种主要的客户端库:
-
rclcpp:C++ 客户端库,提供了 C++ 风格的接口,充分利用了 C++17 的特性,使得接口易于使用
-
rclpy:Python 客户端库,提供了 Python 风格的接口,使用原生的 Python 类型和模式,如列表和上下文对象
这种架构设计带来了几个重要优势。首先,它减少了代码重复,所有的核心功能都在 RCL 中实现,不同语言的客户端库只需要提供语言绑定即可(172)。其次,它保证了跨语言的行为一致性,无论使用哪种语言编写节点,其基本行为都是相同的。最后,这种设计使得添加新的语言支持变得更加简单,社区已经开发了多种其他语言的客户端库,包括 Java、.NET、Node.js、Rust 等。
1.2 C++ 与 Python 节点的运行时差异
C++ 和 Python 节点在 ROS2 运行时环境中表现出显著的差异,这些差异源于两种语言的本质特性。
C++ 节点的运行特点:
C++ 节点是编译型的,需要通过 CMake 进行编译生成可执行文件。在运行时,C++ 节点直接执行编译后的机器码,因此具有高效的性能和较低的内存占用(164)。C++ 节点通常通过继承rclcpp::Node类来创建,这种方式有助于在一个进程内组织多个节点,提高节点间的通信效率(164)。在资源管理方面,C++ 节点需要开发者手动管理内存,但这也提供了更精细的控制能力。
Python 节点的运行特点:
Python 节点是解释型的,不需要编译过程,可以直接运行。Python 节点通过rclpy库实现,该库在底层使用 CPython API 与 RCL 进行交互(154)。Python 节点的优势在于开发效率高、代码简洁、易于调试。然而,Python 节点在性能方面存在明显劣势,特别是在处理高频数据时,性能差异尤为明显。研究表明,Python 节点的 CPU 使用率通常比 C++ 节点高 2-3 倍(69)。
运行时架构差异:
在运行时架构方面,C++ 节点和 Python 节点都使用相同的执行器(Executor)机制。执行器负责管理节点的回调函数(包括订阅者、定时器、服务服务器等)的执行。ROS2 提供了三种类型的执行器:单线程执行器、多线程执行器和静态单线程执行器。无论是 C++ 还是 Python 节点,都可以使用这些执行器,但在具体实现上有所不同。
特别值得注意的是,Python 节点在处理某些系统资源时可能存在特殊问题。例如,在使用 Gazebo 仿真环境时,Python 节点可能会出现 CPU 使用率过高的问题,这主要是由于 Python 节点监听来自 Gazebo 的仿真时间消息导致的(128)。
1.3 混合编程的应用场景
ROS2 混合编程在实际应用中有多种典型场景,合理利用不同语言的优势可以显著提升开发效率和系统性能。
原型开发与快速迭代场景:
在项目的早期阶段,特别是原型开发期间,Python 是首选语言。Python 的动态类型特性、丰富的科学计算库(如 NumPy、SciPy)以及简洁的语法使得算法原型的开发和调试变得非常高效。开发者可以快速实现算法逻辑,进行实验验证,然后逐步优化。当算法稳定后,可以将关键部分用 C++ 重写以提升性能。
计算密集型任务场景:
对于需要大量计算的任务,如计算机视觉、物理仿真、路径规划等,C++ 是更好的选择。C++ 的编译特性使其能够充分利用现代硬件的性能优势,实现实时控制和高速通信(164)。例如,在处理激光雷达数据、图像识别、机器人运动控制等场景中,C++ 节点能够提供确定性的性能保证。
系统集成与脚本化场景:
Python 在系统集成和脚本化任务中表现出色。例如,在编写启动脚本、配置管理工具、数据记录和分析工具时,Python 的简洁性和丰富的标准库使其成为理想选择。此外,Python 还广泛用于与外部系统的接口,如数据库访问、Web 服务调用、传感器数据采集等。
多语言协作开发场景:
在大型项目中,开发团队可能由具有不同技术背景的成员组成。C++ 开发者和 Python 开发者可以并行工作,各自负责最适合的模块。通过 ROS2 的消息传递机制,不同语言编写的节点可以无缝协作,共同完成复杂的机器人任务。
2. C++ 节点的编译与加载机制
2.1 ament_cmake 构建系统详解
ROS2 使用 ament 构建系统来管理软件包的构建过程,其中ament_cmake是专门用于 C++ 包的构建类型。理解 ament_cmake 的工作机制对于成功构建 C++ 节点至关重要。
ament_cmake 的基本流程:
当使用ros2 pkg create命令创建一个 C++ 包时,可以指定--build-type ament_cmake选项来创建一个使用 ament_cmake 构建系统的包(85)。创建过程会生成基本的包结构,包括package.xml和CMakeLists.txt文件。
ament_cmake 的构建流程可以分为以下几个步骤:
-
初始化阶段:CMake 读取
CMakeLists.txt文件,解析项目配置和依赖关系。 -
依赖查找阶段:使用
find_package命令查找所需的依赖包,包括 ROS2 系统包(如 rclcpp)和其他自定义包。 -
目标构建阶段:使用
add_executable命令添加可执行文件,使用ament_target_dependencies命令添加目标依赖,使用target_link_libraries命令添加非 ROS2 库依赖。 -
安装配置阶段:使用
install命令配置可执行文件、库文件、头文件等的安装路径。 -
包生成阶段:最后调用
ament_package()宏来完成包的构建过程。
关键配置文件详解:
package.xml文件是包的元数据描述文件,其中与 C++ 编译相关的配置包括:
-
<buildtool_depend>ament_cmake</buildtool_depend>:声明使用 ament_cmake 作为构建工具 -
<depend>rclcpp</depend>:声明 rclcpp 作为运行时依赖 -
<build_depend>rclcpp</build_depend>:声明 rclcpp 作为构建依赖
CMakeLists.txt文件包含了具体的构建规则,一个典型的 C++ 节点构建配置如下:
cmake_minimum_required(VERSION 3.8)
project(my_cpp_node_pkg)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# 查找依赖
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
# 创建可执行文件
add_executable(my_cpp_node src/my_cpp_node.cpp)
# 添加ROS2依赖
ament_target_dependencies(my_cpp_node rclcpp)
# 安装可执行文件
install(TARGETS my_cpp_node
DESTINATION lib/\${PROJECT_NAME})
ament_package()
2.2 C++ 节点的编译流程与产物
C++ 节点的编译是一个由多个步骤组成的过程,理解这个过程有助于诊断编译问题和优化构建系统。
完整编译流程:
- 准备阶段:
-
确保工作空间的
src目录下包含所有需要编译的包 -
运行
rosdep install命令安装所有依赖 -
运行
colcon build命令开始构建过程
- 编译阶段:
-
CMake 生成 Makefile
-
Make 工具执行编译命令
-
C++ 源文件被编译成目标文件(.o)
-
目标文件链接成可执行文件
-
生成的可执行文件被安装到指定目录
-
安装阶段:
根据
CMakeLists.txt中的install命令配置,可执行文件被安装到以下路径:
install/\<package_name>/lib/\<package_name>/\<executable_name>
这个路径结构是 ROS2 的标准约定,确保了系统的一致性(96)。
编译产物分析:
C++ 节点编译后会生成以下主要产物:
-
可执行文件:
这是最主要的产物,包含了编译后的机器码。可执行文件的名称由
add_executable命令指定,默认安装在lib/${PROJECT_NAME}目录下。 -
目标文件:
编译过程中生成的中间文件(.o),存储在构建目录中,通常不会被安装。
-
库文件(可选):
如果在
CMakeLists.txt中使用了add_library命令,还会生成共享库或静态库。这在创建可组合节点(Component)时特别有用。 -
头文件:
如果项目包含公共头文件,需要在
CMakeLists.txt中配置安装规则,通常安装在include目录下。
编译选项配置:
在CMakeLists.txt中可以配置各种编译选项,以满足不同的需求:
- 警告选项:
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
- C++ 标准版本:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- 优化选项(发布版本):
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_options(-O3 -march=native)
endif()
2.3 动态加载机制(Component)
ROS2 引入了组件(Component)机制,允许将节点编译为共享库,并在运行时动态加载。这种机制为系统的灵活性和可扩展性提供了强大支持。
组件机制的优势:
-
运行时加载:组件可以在系统运行时动态加载和卸载,无需重启整个系统。
-
资源共享:多个组件可以在同一个进程中运行,共享内存和其他系统资源,提高了资源利用效率。
-
错误隔离:即使某个组件出现问题,也不会影响其他组件的运行。
-
热更新能力:可以在系统运行时更新组件,实现功能的动态升级。
组件的创建与注册:
创建一个组件需要遵循特定的规则。首先,组件类必须继承自rclcpp::Node,并且不能有main函数,因为组件是作为共享库加载的。其次,必须使用rclcpp_components包提供的宏来注册组件:
#include "rclcpp/rclcpp.hpp"
class MyComponent : public rclcpp::Node
{
public:
MyComponent() : Node("my_component") {}
};
// 注册组件
RCLCPP_COMPONENTS_REGISTER_NODE(MyComponent)
在CMakeLists.txt中,需要将组件构建为共享库而不是可执行文件:
add_library(my_component SHARED src/my_component.cpp)
ament_target_dependencies(my_component rclcpp rclcpp_components)
动态加载方式:
ROS2 提供了多种动态加载组件的方式:
-
使用 ROS 服务:
可以通过调用
composition_interfaces/srv/LoadNode服务来加载组件。首先启动一个组件容器(component_container),然后调用服务指定要加载的包名和库名。 -
使用命令行工具:
ROS2 提供了
ros2 component命令行工具,可以方便地加载和管理组件:
ros2 component load \<container_name> \<package_name> \<library_name>
-
使用 dlopen:
可以通过
dlopen函数直接加载共享库,这种方式更加底层,可以实现更灵活的加载策略。 -
使用启动文件:
在启动文件中可以使用
Component动作来自动加载组件,这是最常用的方式,特别适合在系统启动时加载多个组件。
组件容器的使用:
组件容器是一个特殊的节点,负责管理动态加载的组件。容器进程启动后,可以通过 ROS 服务或命令行工具向其发送加载 / 卸载组件的请求。容器还提供了组件列表查询、组件状态监控等功能。
使用组件机制时需要注意,组件容器必须能够找到所需的共享库。这要求在启动容器之前正确设置环境变量,通常通过source命令加载工作空间的setup.bash文件来实现。
3. Python 节点的动态加载机制
3.1 ament_python 构建系统
与 C++ 节点使用ament_cmake不同,纯 Python 包通常使用ament_python构建类型。这种构建系统专门针对 Python 代码进行了优化,提供了更加便捷的开发体验。
ament_python 的特点:
-
无需编译:Python 代码是解释型的,不需要编译过程,可以直接运行。
-
简化的构建流程:相比于 C++ 的复杂编译过程,Python 包的构建过程更加简单直接。
-
原生 Python 体验:保持了 Python 标准的开发和分发方式,包括
setup.py和setup.cfg文件。 -
与 ROS2 集成:虽然使用原生 Python 机制,但充分考虑了 ROS2 的特殊需求,如节点入口点配置。
创建 ament_python 包:
使用ros2 pkg create命令创建 Python 包时,可以指定--build-type ament_python选项:
ros2 pkg create --build-type ament_python my_python_pkg
创建过程会生成基本的包结构,包括:
-
package.xml:包的元数据文件 -
setup.py:Python 安装脚本 -
setup.cfg:Python 安装配置文件 -
my_python_pkg/目录:包含 Python 模块文件 -
scripts/目录(可选):包含可执行脚本
包结构详解:
一个典型的 Python 包结构如下:
my_python_pkg/
├── CMakeLists.txt
├── package.xml
├── setup.py
├── setup.cfg
└── my_python_pkg
├── __init__.py
├── my_module.py
└── my_node.py
其中:
-
__init__.py:使 Python 将该目录视为一个包 -
my_module.py:包含可导入的模块和函数 -
my_node.py:ROS2 节点实现文件
3.2 Python 节点的入口点配置
Python 节点的可执行性是通过setup.py文件中的entry_points配置实现的。这个机制允许ros2 run命令能够正确找到并执行 Python 节点。
entry_points 配置详解:
在setup.py文件中,entry_points部分用于定义命令行脚本的入口点:
from setuptools import setup, find_packages
setup(
name='my_python_pkg',
version='0.0.0',
packages=find_packages(exclude=\['test']),
entry_points={
'console_scripts': \[
'my_python_node = my_python_pkg.my_node:main',
],
},
)
这个配置的含义是:
-
my_python_node:这是节点的可执行名称,即运行时使用ros2 run命令时指定的名称 -
my_python_pkg.my_node:这是模块路径,指向包含节点代码的 Python 文件 -
main:这是模块中的入口函数名
入口点的工作原理:
当使用ros2 run命令运行 Python 节点时,系统会执行以下步骤:
-
查找包的安装目录
-
定位
entry_points配置的可执行文件 -
执行
load_entry_point函数来加载和执行指定的模块 -
调用模块中的
main函数来启动节点
具体的执行流程可以通过以下命令的输出来理解:
ros2 run my_python_pkg my_python_node
这个命令实际上执行了类似以下的 Python 代码:
from importlib.metadata import entry_points
ep = entry_points()\["console_scripts"]\["my_python_node"]
ep.load()()
多个入口点的配置:
一个 Python 包可以包含多个节点,每个节点都需要在entry_points中配置相应的入口点:
entry_points={
'console_scripts': \[
'talker = my_python_pkg.talker:main',
'listener = my_python_pkg.listener:main',
'service_server = my_python_pkg.service_server:main',
'service_client = my_python_pkg.service_client:main',
],
}
这样就可以通过ros2 run命令分别运行这四个节点。
入口点的最佳实践:
-
保持一致性:节点名称应与入口点名称保持一致,便于理解和维护。
-
避免重名:不同包中的节点应避免使用相同的名称,防止冲突。
-
清晰的命名:入口点名称应能够清晰地反映节点的功能。
-
模块化设计:将不同功能的节点放在不同的模块中,保持代码的清晰性。
3.3 运行时环境与执行流程
Python 节点的运行时环境和执行流程与 C++ 节点有显著差异,理解这些差异对于开发高效稳定的 Python 节点至关重要。
Python 节点的启动流程:
当执行ros2 run命令启动 Python 节点时,实际的执行流程如下:
- 环境准备:
-
首先需要
source工作空间的setup.bash文件,设置必要的环境变量 -
这些环境变量包括
ROS_DISTRO、ROS_PACKAGE_PATH、PYTHONPATH等 -
特别重要的是
PYTHONPATH,它确保 Python 能够找到 ROS2 库和自定义包
- 入口点解析:
-
ros2 run命令解析包名和节点名 -
根据
setup.py中的entry_points配置找到对应的模块和函数 -
使用
importlib动态导入指定的模块
- 节点初始化:
-
调用模块的
main函数 -
在
main函数中,首先调用rclpy.init()初始化 ROS2 Python 客户端库 -
创建节点对象,通常通过继承
rclpy.node.Node类实现 -
配置节点的各种功能,如订阅者、发布者、服务等
- 节点执行:
-
调用
rclpy.spin()或rclpy.spin_once()来启动节点的事件循环 -
事件循环处理各种回调函数(订阅回调、定时器回调等)
-
保持节点运行直到接收到终止信号
- 节点关闭:
-
接收到终止信号(如 Ctrl+C)后,调用
rclpy.shutdown() -
清理所有资源,包括销毁节点、关闭句柄等
Python 节点的执行模型:
Python 节点使用单线程执行模型,这与 C++ 节点可以使用多线程执行器有所不同。在 Python 中,由于 GIL(全局解释器锁)的存在,多线程并不能真正实现并行执行。因此,ROS2 的 Python 客户端库rclpy采用了以下策略:
-
单线程事件循环:所有的 ROS2 相关操作都在主线程中执行
-
异步回调处理:通过回调函数处理异步事件,避免阻塞主线程
-
定时器管理:使用
rclpy.Timer来实现定时任务 -
休眠机制:使用
rclpy.sleep()来实现非阻塞的等待
内存管理特点:
Python 的内存管理由垃圾回收器自动处理,这与 C++ 的手动内存管理形成对比。在 ROS2 Python 节点中,需要注意以下几点:
-
消息对象的生命周期:ROS2 消息对象在 Python 中是通过
__slots__定义的,以减少内存开销 -
避免循环引用:虽然有垃圾回收器,但循环引用仍可能导致内存泄漏
-
大对象的处理:对于大的消息(如图像、点云),需要注意内存使用
-
及时释放资源:不再使用的订阅者、发布者等应及时销毁
性能优化考虑:
由于 Python 的解释型特性,Python 节点在性能方面存在固有限制。以下是一些优化建议:
-
避免频繁的类型转换:Python 节点中的消息操作应尽量在 Python 层面完成,避免频繁的 C/Python 转换
-
批量处理数据:对于高频数据,应采用批量处理方式,减少回调次数
-
优化算法实现:将计算密集型代码用 C++ 实现,通过服务或话题与 Python 节点通信
-
使用合适的数据结构:选择高效的 Python 数据结构,如
array.array代替列表 -
限制日志输出:过多的日志输出会显著影响性能
4. 混合编程的实现方式
4.1 同一项目中混合 C++ 和 Python 节点
在 ROS2 中,在同一个项目中混合使用 C++ 和 Python 节点是完全可行的。这种方式结合了 C++ 的高性能和 Python 的开发效率,特别适合大型复杂项目。
混合项目的构建系统配置:
要创建一个包含 C++ 和 Python 代码的混合包,需要使用ament_cmake作为构建类型,并添加对 Python 的支持。具体步骤如下:
- 创建混合包:
ros2 pkg create --build-type ament_cmake my_mixed_pkg --dependencies rclcpp rclpy
-
配置 package.xml:
需要添加以下依赖项:
\<buildtool_depend>ament_cmake\</buildtool_depend>
\<buildtool_depend>ament_cmake_python\</buildtool_depend>
\<depend>rclcpp\</depend>
\<depend>rclpy\</depend>
-
配置 CMakeLists.txt:
在
CMakeLists.txt中,需要包含以下内容:
cmake_minimum_required(VERSION 3.5)
project(my_mixed_pkg)
# 查找依赖
find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclpy REQUIRED)
# C++可执行文件
add_executable(cpp_node src/cpp_node.cpp)
ament_target_dependencies(cpp_node rclcpp)
install(TARGETS cpp_node DESTINATION lib/\${PROJECT_NAME})
# Python模块安装
ament_python_install_package(\${PROJECT_NAME})
# Python可执行文件安装
install(PROGRAMS
scripts/python_node.py
DESTINATION lib/\${PROJECT_NAME})
ament_package()
混合项目的目录结构:
一个典型的混合包目录结构如下:
my_mixed_pkg/
├── CMakeLists.txt
├── package.xml
├── include/
│ └── my_mixed_pkg/
│ └── some_header.hpp
├── src/
│ ├── cpp_node.cpp
│ └── cpp_library.cpp
├── my_mixed_pkg/
│ ├── __init__.py
│ ├── python_module.py
│ └── utils.py
└── scripts/
└── python_node.py
C++ 和 Python 节点的协作方式:
在混合项目中,C++ 和 Python 节点可以通过 ROS2 的标准通信机制进行协作:
- 话题通信:
-
C++ 节点可以发布话题,Python 节点订阅
-
Python 节点可以发布话题,C++ 节点订阅
-
消息类型由接口定义文件(.msg)自动生成,保证了类型一致性
- 服务通信:
-
C++ 节点可以提供服务,Python 节点调用
-
Python 节点可以提供服务,C++ 节点调用
-
服务请求和响应的类型同样由接口文件定义
- 动作通信:
-
支持 C++ 动作服务器与 Python 动作客户端
-
支持 Python 动作服务器与 C++ 动作客户端
-
动作的目标、反馈和结果通过标准接口定义
混合编程的最佳实践:
- 职责划分:
-
C++ 负责:计算密集型任务、实时控制、硬件接口
-
Python 负责:系统集成、脚本化任务、原型开发、数据处理
- 接口设计:
-
使用清晰的接口定义文件(.msg、.srv、.action)
-
保持接口的稳定性,避免频繁修改
-
为接口添加清晰的注释文档
- 构建优化:
-
使用
ament_cmake_python来处理 Python 代码,避免使用setup.py -
合理配置编译选项,平衡性能和调试需求
-
使用
ament_lint工具进行代码规范检查
- 调试策略:
-
利用 ROS2 的调试工具,如
ros2 topic echo、ros2 service call -
在 Python 中使用
pdb进行调试 -
在 C++ 中使用 GDB 或 IDE 集成调试
4.2 同一节点内混合 C++ 和 Python 代码的技术可行性
关于在同一个节点内混合使用 C++ 和 Python 代码,这是一个技术复杂且存在争议的话题。经过深入分析,我们可以得出以下结论。
官方支持现状:
根据 ROS2 官方文档和社区讨论,ROS2 官方并不直接支持在同一个节点内混合使用 C++ 和 Python 代码(140)。这种限制主要源于以下技术原因:
-
运行时环境隔离:C++ 和 Python 有各自独立的运行时环境,它们的内存管理、对象模型、调用约定都不相同。
-
线程模型差异:C++ 节点可以使用多线程执行器,而 Python 节点受限于 GIL,只能在单线程中运行。
-
构建系统限制:ament 构建系统要求一个包只能有一种主要语言,无法在同一个编译单元中处理多种语言。
技术挑战分析:
即使尝试通过第三方工具实现同一节点内的混合编程,也会面临诸多挑战:
- 解释器嵌入问题:
-
在 C++ 中嵌入 Python 解释器需要处理 GIL 的获取和释放
-
需要管理 C++ 和 Python 之间的对象转换
-
可能导致性能下降和内存管理复杂性增加
- ABI 兼容性问题:
-
C++ 的名称修饰(name mangling)与 Python 的动态特性存在冲突
-
不同编译器和版本可能导致 ABI 不兼容
-
需要处理异常处理机制的差异
- 调试复杂性:
-
混合语言代码的调试需要同时支持 C++ 调试器和 Python 调试器
-
堆栈跟踪可能变得复杂,难以定位问题
-
内存泄漏的检测和修复更加困难
第三方解决方案评估:
虽然官方不支持,但社区探索了一些可能的解决方案:
-
使用 Cython:
Cython 可以将 Python 代码编译成 C 扩展,理论上可以与 C++ 代码混合。但这种方式需要重新编写部分代码,且仍面临与 ROS2 集成的挑战。
-
使用 SWIG 或 pybind11:
-
这些工具可以生成 C++ 到 Python 的绑定
-
但只能实现 C++ 代码的 Python 调用,无法在同一个节点中混合两种语言的执行逻辑
-
需要将 C++ 代码编译成共享库,通过 Python 导入使用
- 进程内通信:
-
可以在同一个进程中创建 C++ 和 Python 两个独立的执行环境
-
通过共享内存、管道或其他 IPC 机制进行通信
-
但这种方式实际上是将一个节点拆分成了两个部分,违背了 “同一节点” 的初衷
官方推荐的替代方案:
ROS2 官方推荐的做法是将 C++ 和 Python 代码分别放在不同的节点中,通过 ROS2 的标准通信机制进行交互(161)。这种方法具有以下优势:
-
架构清晰:每个节点有明确的语言边界,易于理解和维护
-
技术成熟:利用 ROS2 成熟的消息传递机制,保证了稳定性
-
调试方便:可以分别调试 C++ 和 Python 节点,问题定位清晰
-
性能可控:可以根据需要选择最适合的语言实现不同功能
特殊场景的变通方案:
在某些特殊场景下,可以考虑以下变通方案:
- C++ 库 + Python 包装器:
-
将核心功能用 C++ 实现为静态库
-
在 Python 包中包含这个静态库作为数据文件
-
通过 ctypes 或其他方式在 Python 中调用 C++ 库
-
但这种方式仍然是在 Python 节点中调用 C++ 代码,不是真正的混合编程
- 可组合节点 + Python 扩展:
-
将 C++ 代码实现为可组合节点(共享库)
-
使用 Python 的 C 扩展机制调用 C++ 组件
-
但这需要复杂的集成工作,且不被官方支持
4.3 跨语言通信机制
尽管不能在同一个节点内混合 C++ 和 Python 代码,但 ROS2 提供了完善的跨语言通信机制,使得不同语言编写的节点能够无缝协作。
统一的接口定义机制:
ROS2 的一个关键特性是使用接口定义文件(.msg、.srv、.action)来定义节点间的通信协议。这些接口定义文件使用一种与语言无关的语法,通过代码生成工具可以为不同语言生成相应的实现代码(160)。
接口定义文件的优势:
-
一次定义,多语言使用:只需要定义一次接口,就可以在所有支持的语言中使用
-
类型安全:生成的代码保证了类型的一致性,避免了类型转换错误
-
自动生成:通过
rosidl工具自动生成代码,减少了手动编写的工作量 -
向后兼容:支持接口的演进,保证了版本兼容性
消息传递机制详解:
在 ROS2 中,消息传递是通过话题(Topic)进行的。跨语言的消息传递过程如下:
- 消息定义:
-
使用.msg 文件定义消息结构
-
例如,定义一个包含 int32 类型数据的消息:
int32 data
- 代码生成:
-
rosidl工具为 C++ 生成相应的消息类 -
为 Python 生成相应的消息模块
-
生成的代码负责序列化和反序列化
- C++ 发布者示例:
#include "std_msgs/msg/int32.hpp"
auto publisher = node->create_publisher\<std_msgs::msg::Int32>("topic_name", 10);
std_msgs::msg::Int32 message;
message.data = 42;
publisher->publish(message);
- Python 订阅者示例:
from std_msgs.msg import Int32
def callback(msg):
print(f"Received: {msg.data}")
subscriber = node.create_subscription(Int32, "topic_name", callback, 10)
- 底层机制:
-
所有的消息操作在 Python 中都在 Python 版本的消息对象上进行
-
当需要传递给 RCL 层时,才转换为 C 版本的消息
-
这种转换是自动完成的,开发者无需关心细节(158)
服务通信机制:
服务(Service)提供了请求 - 响应式的通信方式,跨语言的服务通信同样基于接口定义:
- 服务定义:
-
使用.srv 文件定义服务接口
-
例如,定义一个加法服务:
int32 a
int32 b
\---
int32 sum
- C++ 服务服务器示例:
using AddTwoInts = example_interfaces::srv::AddTwoInts;
auto service = node->create_service\<AddTwoInts>(
"add_two_ints",
\[]\(const std::shared_ptr\<AddTwoInts::Request> request,
std::shared_ptr\<AddTwoInts::Response> response) {
response->sum = request->a + request->b;
});
- Python 服务客户端示例:
from example_interfaces.srv import AddTwoInts
client = node.create_client(AddTwoInts, "add_two_ints")
request = AddTwoInts.Request()
request.a = 41
request.b = 1
future = client.call_async(request)
rclpy.spin_until_future_complete(node, future)
response = future.result()
print(f"Sum: {response.sum}")
动作通信机制:
动作(Action)提供了更复杂的请求 - 响应机制,支持目标发送、进度反馈和结果返回:
- 动作定义:
-
使用.action 文件定义动作接口
-
包含目标(Goal)、反馈(Feedback)和结果(Result)三部分
- 跨语言支持:
-
C++ 动作服务器可以与 Python 动作客户端通信
-
Python 动作服务器可以与 C++ 动作客户端通信
-
动作的状态机管理由 ROS2 自动处理
- 实现注意事项:
-
动作通信涉及多个话题(/action_goal, /action_result, /action_feedback)
-
需要处理超时、取消等异常情况
-
建议使用异步接口以避免阻塞
性能考量与优化:
跨语言通信虽然方便,但也存在性能开销。以下是一些性能优化建议:
- 避免频繁的小消息:
-
频繁的消息传递会增加通信开销
-
可以考虑批量处理或提高消息发布频率
- 选择合适的 QoS 设置:
-
根据需求选择可靠或尽力而为的传输策略
-
合理设置队列大小,避免内存溢出
- 数据压缩:
-
对于大数据量(如图像、点云),可以考虑使用压缩格式
-
但需要权衡压缩和解压缩的计算开销
- 本地优化:
-
如果可能,将频繁通信的节点部署在同一台机器上
-
使用共享内存传输(Intra-Process Communication)来提高性能
5. 混合编程的最佳实践与性能优化
5.1 语言职责划分原则
在 ROS2 混合编程中,合理的语言职责划分是项目成功的关键。不同语言各有优势,正确使用它们可以显著提升系统性能和开发效率。
C++ 的适用场景:
- 实时控制任务:
-
机器人运动控制
-
传感器数据采集和预处理
-
任何对延迟敏感的任务
-
原因:C++ 的确定性执行和低延迟特性(164)
- 计算密集型算法:
-
计算机视觉算法(如 OpenCV)
-
物理仿真(如 ODE、Bullet)
-
路径规划算法
-
原因:C++ 的高效性能和低内存占用(164)
- 硬件接口开发:
-
底层驱动程序
-
通信协议实现(如 CAN、I2C、SPI)
-
实时操作系统集成
-
原因:需要直接访问硬件和精确的时序控制
- 资源受限环境:
-
嵌入式系统
-
移动机器人平台
-
任何内存或 CPU 资源有限的环境
-
原因:C++ 提供了更好的资源控制能力
Python 的适用场景:
- 系统集成与脚本化:
-
启动脚本和配置管理
-
数据记录和日志系统
-
与外部系统的接口(如数据库、Web 服务)
-
原因:Python 的简洁性和丰富的标准库
- 原型开发与算法验证:
-
新算法的快速实现和测试
-
机器学习模型的训练和推理
-
数据处理和分析
-
原因:开发效率高,易于迭代
- 用户界面和可视化:
-
简单的 GUI 界面
-
数据可视化(如 matplotlib)
-
调试工具和监控系统
-
原因:丰富的图形库和快速开发能力
- 非关键任务处理:
-
配置参数管理
-
日志分析
-
统计信息收集
-
原因:即使性能较低也不会影响系统关键功能
职责划分的最佳实践:
- 单一职责原则:
-
每个节点应该有明确的单一职责
-
避免在一个节点中混合多种功能
-
便于理解、测试和维护
- 高低层分离:
-
底层硬件接口和实时控制用 C++
-
高层逻辑和决策用 Python
-
中间层通过清晰的接口定义进行通信
- 性能优先原则:
-
对性能敏感的部分用 C++ 实现
-
非性能关键部分用 Python 实现
-
可以通过性能分析工具识别瓶颈
- 开发效率考虑:
-
快速原型阶段优先使用 Python
-
稳定后将关键部分用 C++ 重写
-
利用 Python 的动态特性进行快速迭代
- 团队技能匹配:
-
根据团队成员的技能分配任务
-
C++ 开发者负责核心算法和硬件接口
-
Python 开发者负责系统集成和工具开发
5.2 项目结构设计与依赖管理
良好的项目结构设计不仅有助于代码的组织和维护,也对混合编程的成功实施至关重要。
推荐的项目结构:
一个典型的 ROS2 混合编程项目应该采用以下结构(72):
my_robot_project/
├── src/
│ ├── my_robot_hw/ # C++硬件接口包
│ │ ├── CMakeLists.txt
│ │ ├── package.xml
│ │ ├── include/
│ │ └── src/
│ ├── my_robot_control/ # C++控制算法包
│ │ ├── CMakeLists.txt
│ │ ├── package.xml
│ │ └── src/
│ ├── my_robot_vision/ # C++视觉算法包
│ │ ├── CMakeLists.txt
│ │ ├── package.xml
│ │ └── src/
│ ├── my_robot_planning/ # Python路径规划包
│ │ ├── setup.py
│ │ ├── package.xml
│ │ └── my_robot_planning/
│ ├── my_robot_navigation/ # Python导航包
│ │ ├── setup.py
│ │ ├── package.xml
│ │ └── my_robot_navigation/
│ └── my_robot_bringup/ # 启动配置包
│ ├── CMakeLists.txt
│ ├── package.xml
│ └── launch/
├── launch/
├── config/
├── maps/
└── scripts/
包的组织原则:
- 功能模块化:
-
按照功能将代码组织到不同的包中
-
每个包应该有单一、清晰的目的
-
避免创建过大的综合包(73)
- 语言隔离:
-
C++ 包使用
ament_cmake构建类型 -
Python 包使用
ament_python构建类型 -
混合包使用
ament_cmake并添加 Python 支持
- 依赖最小化:
-
每个包只依赖它真正需要的其他包
-
使用
rosdep工具管理系统依赖 -
避免循环依赖
依赖管理策略:
- 声明依赖关系:
-
在
package.xml中声明所有依赖 -
区分构建依赖(build_depend)和执行依赖(depend)
-
对于混合包,需要同时声明 C++ 和 Python 依赖
- 版本控制:
-
使用语义化版本控制(Semantic Versioning)
-
在
package.xml中指定依赖的版本范围 -
使用
ament_lint工具检查依赖一致性
- 构建系统配置:
- C++ 包的
CMakeLists.txt配置:
find_package(rclcpp REQUIRED)
find_package(other_cpp_dep REQUIRED)
- Python 包的
setup.py配置:
install_requires=\[
'rclpy',
'other_python_dep',
]
- 工作空间管理:
-
使用独立的工作空间管理项目
-
通过
colcon build进行增量构建 -
使用
colcon test进行测试
构建系统优化:
- 并行构建:
-
使用
colcon build --parallel-workers N来指定并行构建的作业数 -
根据系统 CPU 核心数合理设置 N
-
加快构建速度
- 选择性构建:
-
使用
--packages-select选项只构建特定的包 -
使用
--packages-up-to选项构建指定包及其依赖 -
在开发阶段提高构建效率
- 缓存优化:
-
使用
colcon build --cmake-args -DCMAKE_CACHE_ARGS来优化 CMake 缓存 -
合理设置编译选项,避免重复编译
5.3 性能优化策略
混合编程的性能优化需要综合考虑 C++ 和 Python 的特性差异,以及它们之间的通信开销。
Python 节点性能优化:
Python 节点的性能问题是混合编程中最需要关注的。以下是一些关键的优化策略:
- 避免 Python 中的性能瓶颈:
-
减少对象创建:避免在循环中创建大量临时对象
-
使用高效数据结构:优先使用
array.array代替列表,使用deque代替列表进行队列操作 -
避免频繁的类型转换:保持数据类型的一致性,减少转换开销
- 优化 ROS2 相关操作:
-
批量发布消息:将多个小消息合并成一个大消息发布
-
合理设置 QoS:对于非关键数据,使用
RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT -
使用合适的回调策略:避免在回调函数中执行耗时操作
-
性能改进案例:
根据社区报告,ROS2 Galactic 版本修复了一个导致 Python 节点性能严重下降的问题。在 Foxy 版本中,发布大数据(如 10MB 点云)时,Python 比 C++ 慢 30-100 倍。这个问题在 Galactic 中得到了解决,但需要从源代码构建。
具体性能对比数据:
-
C++ 发布 10MB 点云:2.8ms
-
Python 发布 10MB 点云:92ms(Foxy 版本)
-
Python 发布 10MB 点云:约 3ms(Galactic 版本,修复后)
-
CPU 使用率优化:
研究表明,Python 节点的 CPU 使用率通常比 C++ 节点高 2-3 倍(69)。以下是一些降低 CPU 使用率的方法:
-
使用
rclpy.spin_once()配合适当的休眠时间,而不是rclpy.spin() -
减少不必要的定时器回调
-
优化循环频率,避免过度使用 CPU
跨语言通信优化:
- 减少通信频率:
-
分析数据需求,降低不必要的消息发布频率
-
使用数据压缩技术减少传输数据量
-
实现智能数据过滤,只传输变化的数据
- 选择合适的通信机制:
-
对于高频数据(如传感器数据),使用话题通信
-
对于请求 - 响应场景,使用服务通信
-
对于长时间运行的任务,使用动作通信
- 本地优化:
-
将频繁通信的节点部署在同一台机器上
-
使用共享内存传输(Intra-Process Communication)
-
配置
ROS_LOCALHOST_ONLY=1来限制网络通信
内存管理优化:
- 对象池技术:
-
在 C++ 中使用对象池来重用消息对象
-
避免频繁的内存分配和释放
-
对于 Python,可以使用
__slots__来减少内存占用
- 大对象管理:
-
对于大型数据(如图像),使用共享内存或内存映射文件
-
避免在不同语言间频繁复制大对象
-
使用零拷贝技术减少内存复制
- 内存泄漏检测:
-
使用 Valgrind 等工具检测 C++ 代码中的内存泄漏
-
使用 Python 的
tracemalloc模块监控内存使用 -
定期检查和清理不再使用的资源
算法优化策略:
- 算法选择:
-
在 Python 中优先使用经过优化的库(如 NumPy、SciPy)
-
将核心算法用 C++ 实现,通过服务调用
-
使用向量化操作代替循环
- 并行处理:
-
在 C++ 中充分利用多线程和 SIMD 指令
-
使用 OpenMP 或 Intel TBB 进行并行计算
-
对于 Python,考虑使用多进程代替多线程
- 预计算和缓存:
-
预计算常用的数值和变换
-
使用缓存技术存储频繁使用的结果
-
实现智能的缓存淘汰策略
性能监控与分析:
- 性能分析工具:
-
使用
ros2 topic hz监控话题频率 -
使用
ros2 node top查看节点资源使用情况 -
使用
rqt_gui的性能监控插件
- 代码级分析:
-
C++ 使用 gprof 或 perf 进行性能分析
-
Python 使用 cProfile 或 line_profiler 分析代码
-
结合分析结果进行针对性优化
- 系统级监控:
-
使用 htop 监控系统资源使用
-
使用 netstat 监控网络流量
-
使用 dstat 进行综合系统性能监控
6. 总结与展望
6.1 关键技术要点回顾
通过对 ROS2 混合编程机制的深入分析,我们可以总结出以下关键技术要点:
多语言架构的核心优势:
ROS2 的多语言支持架构基于统一的 RCL 核心库,实现了 C++ 和 Python 等语言的无缝集成。这种设计不仅保证了跨语言行为的一致性,还大大减少了代码重复,使得添加新的语言支持变得更加容易(172)。
C++ 节点的编译与加载机制:
C++ 节点通过ament_cmake构建系统进行编译,生成的可执行文件默认安装在lib/${PROJECT_NAME}目录下。除了传统的可执行节点,ROS2 还支持将 C++ 代码编译为可组合节点(Component),实现运行时的动态加载和卸载,为系统的灵活性提供了强大支持。
Python 节点的动态特性:
Python 节点使用ament_python构建系统,无需编译过程,通过setup.py中的entry_points配置实现可执行性。Python 节点的优势在于开发效率高、代码简洁,但在性能方面存在固有劣势,特别是在处理高频数据时,需要特别注意优化。
混合编程的实现方式:
在 ROS2 中,推荐的混合编程方式是将 C++ 和 Python 代码放在不同的节点中,通过 ROS2 的标准通信机制(话题、服务、动作)进行交互。官方不支持在同一个节点内混合使用 C++ 和 Python 代码,但提供了丰富的跨语言通信机制,确保不同语言节点能够无缝协作(140)。
性能考量与优化策略:
性能差异是混合编程必须考虑的重要因素。研究表明,Python 节点的性能通常比 C++ 节点低 30-100 倍(在未优化的情况下),CPU 使用率高 2-3 倍(69)。但通过合理的优化策略,如使用最新版本的 ROS2(Galactic 及以后)、优化通信机制、选择合适的数据结构等,可以显著改善性能。
6.2 未来发展趋势
随着机器人技术的不断发展和 ROS2 生态系统的日益成熟,混合编程技术也在不断演进。以下是一些值得关注的发展趋势:
语言支持的扩展:
ROS2 社区正在积极扩展对更多编程语言的支持。目前除了官方支持的 C++ 和 Python 外,社区已经开发了 Java、.NET、Node.js、Rust、Dart 等多种语言的客户端库。未来可能会有更多语言加入,特别是一些新兴的系统编程语言,这将为开发者提供更多选择。
性能优化的持续改进:
ROS2 开发团队一直在致力于性能优化,特别是针对 Python 客户端库的改进。随着版本的更新,Python 节点的性能问题正在逐步得到解决。例如,Galactic 版本修复了一个严重的性能问题,使 Python 节点的性能提升了 30 倍以上。未来,我们可以期待更多的性能优化措施。
新的编程范式:
ROS2 正在引入一些新的编程范式,如响应式编程、函数式编程等。这些新范式可能会改变我们对混合编程的理解和实践方式。例如,通过数据流编程模型,可以更清晰地定义不同语言模块之间的交互。
工具链的完善:
随着 ROS2 的成熟,相关的开发工具链也在不断完善。未来可能会出现更多专门针对混合编程的工具,如:
-
跨语言调试器,可以同时调试 C++ 和 Python 代码
-
性能分析工具,能够分析跨语言通信的开销
-
代码生成工具,可以自动生成跨语言接口代码
硬件加速支持:
随着 AI 硬件(如 GPU、NPU)的普及,ROS2 正在加强对硬件加速的支持。未来的混合编程可能会更多地涉及如何在不同语言间高效利用硬件加速资源,这可能会催生新的编程模式和最佳实践。
云原生集成:
随着机器人技术与云计算的结合越来越紧密,ROS2 正在开发对云原生技术的支持。这可能会带来新的混合编程场景,例如在边缘设备上运行 C++ 节点处理实时任务,在云端运行 Python 节点进行大规模数据处理和机器学习。
6.3 实践建议
基于以上分析,对于计划在 ROS2 项目中使用混合编程的开发者,我们提出以下实践建议:
项目规划阶段:
-
明确需求:在项目开始前,明确哪些部分需要高性能,哪些部分需要快速开发,据此制定语言选择策略。
-
架构设计:采用模块化设计,将不同语言的代码放在独立的节点中,通过清晰的接口进行通信。
-
团队准备:确保团队成员熟悉所选语言和 ROS2 的跨语言通信机制。
开发实施阶段:
- 遵循最佳实践:
-
保持节点职责单一,避免功能混杂
-
使用标准的接口定义文件(.msg、.srv、.action)
-
合理设置 QoS 策略,平衡可靠性和性能
- 性能优化:
-
优先使用 ROS2 的最新版本,以获得最佳性能
-
对关键性能部分使用 C++ 实现
-
优化 Python 代码,减少不必要的开销
- 测试验证:
-
对跨语言通信进行充分测试
-
使用性能分析工具识别瓶颈
-
建立完善的监控体系
维护改进阶段:
- 持续优化:
-
根据实际运行情况调整语言分工
-
关注 ROS2 新版本的性能改进
-
定期进行代码审查和重构
- 文档管理:
-
保持清晰的架构文档
-
记录跨语言接口的详细说明
-
维护性能基准测试结果
- 社区参与:
-
关注 ROS2 社区的最新发展
-
参与相关讨论,分享经验
-
贡献代码或文档,推动生态发展
结语:
ROS2 的混合编程机制为机器人开发者提供了极大的灵活性,使我们能够充分发挥不同编程语言的优势。虽然在同一节点内混合 C++ 和 Python 代码仍不被官方支持,但通过合理的架构设计和跨语言通信机制,我们完全可以实现高效的混合编程系统。
关键在于理解不同语言的特性,合理划分职责,遵循最佳实践,并持续进行性能优化。随着 ROS2 生态系统的不断完善,混合编程将变得更加简单高效,为机器人技术的发展提供强大支撑。无论是开发简单的原型系统,还是复杂的工业机器人应用,ROS2 的混合编程能力都能满足您的需求。
**参考资料 **
[1] Executors http://docs.ros.org/en/humble/Concepts/About-Executors.html
[2] arXiv:2505.21323v2 [cs.SE] 2 J(pdf) https://arxiv.org/pdf/2505.21323v2
[3] ROS2 Jazzy:执行器ROS2 中的执行管理由 执行器(Executor) 处理。执行器利用底层操作系统的一个或多 - 掘金 https://juejin.cn/post/7533503751005962240
[4] ROS2:节点 - sgqmax - 博客园 https://www.cnblogs.com/sgqmax/p/18521142
[5] ROS 2 节点介绍与实现(Python & C++)_ros2 python节点-CSDN博客 https://blog.csdn.net/small_jimmy/article/details/149592872
[6] 【ROS2】ROS2节点Node机制与常用命令行_ros2 node-CSDN博客 https://blog.csdn.net/maizousidemao/article/details/149864911
[7] Initialization, Shutdown, and Spinning https://docs.ros2.org/eloquent/api/rclpy/api/init_shutdown.html
[8] 如何在ROS 2中配置和实现使用Python与C语言混合编写的节点 - CSDN文库 https://wenku.csdn.net/answer/6pee8h6st8
[9] 【ROS2】高级:解锁 Fast DDS 中间件的潜力 [社区贡献]-CSDN博客 https://blog.csdn.net/cxyhjl/article/details/140483893
[10] Composing multiple nodes in a single process http://docs.ros.org/en/crystal/Tutorials/Composition.html
[11] ROS2机器人操作系统使用及简介-CSDN博客 https://blog.csdn.net/weixin_42554470/article/details/151680264
[12] ROS2节点通信机制 - 测评中心专版 - 电子工程世界-论坛 - 手机版 https://m.eeworld.com.cn/bbs_thread-1306981-1-1.html
[13] ROS2之节点_mob64ca14082604的技术博客_51CTO博客 https://blog.51cto.com/u_16213649/14202977
[14] ros2 tips_3线程_ros2 一个节点一个线程吗?-CSDN博客 https://blog.csdn.net/qq_41336087/article/details/133492283
[15] rclcpp_lifecycle::LifecycleNode::SharedPtr与rclcpp::node的区别_ROS2节点状态管理最佳实践_ - CSDN文库 https://wenku.csdn.net/answer/1jufhxpmm2
[16] Changes between ROS 1 and ROS 2 https://design.ros2.org/articles/changes
[17] 【ROS2】ROS2 C++版本 与 Python版本比较_ros2 python版本-CSDN博客 https://blog.csdn.net/maizousidemao/article/details/144160168
[18] How do you Architect your Robots? State of the Practice and Guidelines for ROS-based Systems(pdf) https://raw.githubusercontent.com/S2-group/icse-seip-2020-replication-package/master/ICSE_SEIP_2020.pdf
[19] 机器人操作系统:ROS二次开发_(4).ROS中的节点与话题.docx-原创力文档 https://m.book118.com/html/2025/0326/7113145154010052.shtm
[20] ROS2极简总结-新增概念_rclcpp::qos-CSDN博客 https://blog.csdn.net/ZhangRelay/article/details/119303578
[21] the time delay of message: c++pub-c++sub and python_pub-c++sub [closed] https://answers.ros.org/question/416239/the-time-delay-of-message-cpub-csub-and-python_pub-csub/
[22] The ROS API and Python https://nu-msr.github.io/ros_notes/ros2/ros_api.html
[23] TransformListener x10 higher CPU load in rclpy than rclpp https://answers.ros.org/question/381395/transformlistener-x10-higher-cpu-load-in-rclpy-than-rclpp/
[24] Difference between roscpp and rclcpp? https://answers.ros.org/question/352992/
[25] About ROS 2 client libraries http://docs.ros.org/en/foxy/Concepts/About-ROS-2-Client-Libraries.html
[26] Developing a ROS 2 package https://docs.ros.org/en/rolling/How-To-Guides/Developing-a-ROS-2-Package.html
[27] Install ROS2 HUMBLE https://docs.radxa.com/en/compute-module/cm5/radxa-os/app-dev/ros2_humble
[28] ROS 2中创建一个节点_ros2 创建节点-CSDN博客 https://blog.csdn.net/weixin_44318762/article/details/140949950
[29] ROS2 机器人从仿真到真机_ros2开发-CSDN博客 https://blog.csdn.net/weixin_41860904/article/details/150103823
[30] Creating Nodes - Messages https://husarion.com/tutorials/ros2-tutorials/2-creating-nodes-messages/
[31] ROS2基础使用(工作空间构建、编译和运行) - TDC|唐朝板栗 - 博客园 https://www.cnblogs.com/T-D-C/articles/18973156
[32] ament_cmake_python user documentation http://docs.ros.org/en/ros2_documentation/humble/How-To-Guides/Ament-CMake-Python-Documentation.html
[33] ROS2 工作空间中, CMakeLists.txt, setup.py和 package.xml的作用分别是?_ros2中setup.py的作用-CSDN博客 https://blog.csdn.net/a2213086589/article/details/148609915
[34] ROS 2 Packaging https://w3.cs.jmu.edu/spragunr/CS354/labs/ros_packages/packaging.shtml
[35] 5.3.2.7. Writing a simple service and client (Python) https://docs.vulcanexus.org/en/latest/ros2_documentation/source/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Service-And-Client.html
[36] ROS2 building with dependencies https://answers.ros.org/question/390865/ros2-building-with-dependencies/
[37] Create a ROS2 Python package https://roboticsbackend.com/create-a-ros2-python-package
[38] Ros2 Cartographer Setup(2)_custom serial communication node https://velog.io/@mseokq23/Ros2-Cartographer-Setup2custom-serial-communication-node
[39] ROS2 Nodes for Generative AI https://www.jetson-ai-lab.com/ros.html
[40] 如何在ROS 2中配置和实现使用Python与C语言混合编写的节点 - CSDN文库 https://wenku.csdn.net/answer/6pee8h6st8
[41] ROS2 for Android, iOS and Univ(pdf) https://roscon.ros.org/2018/presentations/ROSCon2018_ROS2%20for%20Android,%20iOS%20and%20Universal%20Windows%20Platform.pdf
[42] Introduction to ROS ROS: node example (C++)(pdf) http://wpage.unina.it/alberto.finzi/didattica/IROB/materiale/IR-Lezione9-ROS-intro.pdf
[43] ROS 2 composition and ZED ROS 2 Wrapper https://www.stereolabs.com/docs/ros2/ros2-composition
[44] From c++ code to python code for a ROS program https://answers.ros.org/question/203547/from-c-code-to-python-code-for-a-ros-program/
[45] ROS 2配置Python与C++混合节点实现指南 - CSDN文库 https://wenku.csdn.net/answer/4bv0g4xqmw
[46] Create a ROS2 package for Both Python and Cpp Nodes https://roboticsbackend.com/ros2-package-for-both-python-and-cpp-nodes/
[47] C++ and Python nodes in the same launch file? https://answers.ros.org/question/392115/
[48] ros2: C++ and Python in same package. Is it possible? https://answers.ros.org/question/298740/ros2-c-and-python-in-same-package-is-it-possible/
[49] Combined package for cpp and python in ROS2 foxy https://answers.ros.org/question/391193/combined-package-for-cpp-and-python-in-ros2-foxy/
[50] How to Add a Python ROS2 Node to a C++ ROS 2 Package https://automaticaddison.com/how-to-add-a-python-ros2-node-to-a-c-ros-2-package/
[51] 在python中使用C++类 https://wiki.ros.org/cn/ROS/Tutorials/Using%20a%20C++%20class%20in%20Python
[52] ROS 2配置Python与C++混合节点实现指南 - CSDN文库 https://wenku.csdn.net/answer/4bv0g4xqmw
[53] ros2: C++ and Python in same package. Is it possible? https://answers.ros.org/question/298740/ros2-c-and-python-in-same-package-is-it-possible/
[54] arXiv:2506.21628v1 [cs.RO] 24 (pdf) https://arxiv.org/pdf/2506.21628v1
[55] rclpy._rclpy_pybind11 - CSDN文库 https://wenku.csdn.net/answer/6056up6v10
[56] Build C++ Library and use in Python Package (Node) https://answers.ros.org/question/363051/
[57] Tutorial Creating a Custom Cpp Plugin - cyberbotics/webots_ros2 GitHub Wiki https://github-wiki-see.page/m/cyberbotics/webots_ros2/wiki/Tutorial-Creating-a-Custom-Cpp-Plugin
[58] ROS2与FastDDS混合架构中如何实现节点间高效数据传输?_编程语言-CSDN问答 https://ask.csdn.net/questions/8703378
[59] [Tips] development - lge-ros2/cloisim GitHub Wiki https://github-wiki-see.page/m/lge-ros2/cloisim/wiki/[Tips]-development
[60] ros2: C++ and Python in same package. Is it possible? https://answers.ros.org/question/298740/ros2-c-and-python-in-same-package-is-it-possible/
[61] Generated Python interfaces https://design.ros2.org/articles/generated_interfaces_python.html
[62] Development guidelines - bdaiinstitute/ros_utilities GitHub Wiki https://github-wiki-see.page/m/bdaiinstitute/ros_utilities/wiki/Development-guidelines
[63] PyStyleGuide https://wiki.ros.org/PyStyleGuide
[64] ROS C++ Style Guide https://wiki.ros.org/CppStyleGuide
[65] 【ROS2】ROS2 C++版本 与 Python版本比较_ros2 python版本-CSDN博客 https://blog.csdn.net/maizousidemao/article/details/144160168
[66] ROS2 Performance: rclpy is 30x-100x slower than rclcpp https://answers.ros.org/question/375827/ros2-performance-rclpy-is-30x-100x-slower-than-rclcpp/
[67] Publishing large data is 30x-100x slower than for rclcpp https://lightrun.com/answers/ros2-rclpy-publishing-large-data-is-30x-100x-slower-than-for-rclcpp
[68] High cpu load for simple python nodes https://discourse.ros.org/t/high-cpu-load-for-simple-python-nodes/28324?page=2
[69] Soft Realtime Performance of Rclpy https://www.barkhauseninstitut.org/research/lab-1/our-blog/posts/soft-realtime-performance-of-rclpy
[70] 如何在ROS 2中配置和实现使用Python与C语言混合编写的节点 - CSDN文库 https://wenku.csdn.net/answer/6pee8h6st8
[71] ros2: C++ and Python in same package. Is it possible? https://answers.ros.org/question/298740/ros2-c-and-python-in-same-package-is-it-possible/
[72] Organizing Files and Folders Inside a ROS 2 Package https://automaticaddison.com/organizing-files-and-folders-inside-a-ros-2-package/
[73] Naming and Organizing Packages in Large ROS 2 Projects https://automaticaddison.com/naming-and-organizing-packages-in-large-ros-2-projects/
[74] Home - org-arl/r2c2 GitHub Wiki https://github-wiki-see.page/m/org-arl/r2c2/wiki
[75] ROS JavaScript Style Guide https://wiki.ros.org/JavaScriptStyleGuide
[76] 2AILAS\nIntroduction to Orocos(pdf) https://atlas-itn.eu/wp-content/uploads/Presentations/NTA3/s4-orocos.pdf
[77] Packages https://wiki.ros.org/Packages
[78] Style Guide - acfr/ros2_template_pkg GitHub Wiki https://github-wiki-see.page/m/acfr/ros2_template_pkg/wiki/Style-Guide
[79] Title: Package Manifest Format Three Specification https://ros.org/reps/rep-0149.html
[80] Package and Test Your Driver https://wiki.ros.org/Drivers/Tutorials/PackageAndTestYourDriver
[81] Per-Package Documentation https://design.ros2.org/articles/per_package_documentation.html
[82] ros入门教程–4.ROS2功能包-CSDN博客 https://blog.csdn.net/qq_37631068/article/details/148589097
[83] Code style and language versions https://daobook.github.io/ros2-docs/galactic/Contributing/Code-Style-Language-Versions.html
[84] ROS2系列(3):第一个C++节点-CSDN博客 https://blog.csdn.net/weixin_51878399/article/details/154022894
[85] NMBU, INF205: Resource-efficient programming (spring 2024)(pdf) https://home.bawue.de/~horsch/teaching/inf205/lecture/4-3_concurrency_third-lecture.pdf
[86] NMBU, INF205: Resource-efficient programming (autumn 2022)(pdf) https://home.bawue.de/~horsch/teaching/inf205/lecture/inf205-u44-fl.pdf
[87] Compilation error when building ROS https://bbs.archlinux.org/viewtopic.php?pid=1851057
[88] ROS2基础使用(工作空间构建、编译和运行) - TDC|唐朝板栗 - 博客园 https://www.cnblogs.com/T-D-C/articles/18973156
[89] ROS 2机器人开发–如何注册编译第一个节点_ros2的编译-CSDN博客 https://blog.csdn.net/qq_45591302/article/details/145949343
[90] Creating C++ Nodes (for ament_cmake ) https://ros2-tutorial.readthedocs.io/en/latest/cpp/cpp_node.html
[91] ROS2 Error with colcon build and BUILD_TESTING arg https://answers.ros.org/question/364100/ros2-error-with-colcon-build-and-build_testing-arg/
[92] [Ros2] Package Binaries - ROS Answers: Open Source Q& A Forum https://answers.ros.org/question/331971/ros2-package-binaries/
[93] catkin
CMakeLists.txt https://wiki.ros.org/catkin/CMakeLists.txt
[94] ROSRobot Operating System\nAmi(pdf) https://staff.fnwi.uva.nl/a.visser/activities/robocup/ROS.pdf
[95] ROS2 + Clion https://discourse.ros.org/t/ros2-clion/2508
[96] ros中的install{TARGETS}和{DIRCTORY}用法和作用_ros 配置文件 在install-CSDN博客 https://blog.csdn.net/yan862659246/article/details/150205964
[97] Question about nodes https://answers.ros.org/question/219991/question-about-nodes/
[98] Why ros2 run executables are installed in “lib/{PROJECT_NAME}” https://answers.ros.org/question/361258/why-ros2-run-executables-are-installed-in-libproject_name/?sort=oldest
[99] [ERROR] [launch]: Caught exception in launch (see debug for traceback): package ‘odom_fusion’ found at ‘/home/hedongkai/ros2_ws/install/odom_fusion’, but libexec directory ‘/home/hedongkai/ros2_ws/install/odom_fusion/lib/odom_fusion’ does not exist - CSDN文库 https://wenku.csdn.net/answer/47bvdivdbg
[100] How to include external library (.so) into ROS2 environment https://answers.ros.org/question/380749/how-to-include-external-library-so-into-ros2-environment/
[101] Where to install ROS 2 node CMake executables with GNUInstallDirs https://answers.ros.org/question/416436/where-to-install-ros-2-node-cmake-executables-with-gnuinstalldirs/
[102] REP 122 – Filesystem Hierarchy Standard layout changes for ROS (ROS.org) https://www.ros.org/reps/rep-0122.html
[103] Introducing ROS 2 Wrapper for ZED https://www.stereolabs.com/blog/zed-wrapper-for-ros2
[104] Epson IMU ROS2 Driver Node https://wiki.ros.org/ess_imu_driver2
[105] Composing multiple nodes in a single process http://docs.ros.org/en/crystal/Tutorials/Composition.html
[106] C++ API http://docs.ros.org/en/ros2_packages/humble/api/class_loader/generated/index.html
[107] Robot Operating System——深度解析自动隐式加载动态库的运行模式_动态库隐试加载-CSDN博客 https://blog.csdn.net/breaksoftware/article/details/140880060
[108] A first look at ROS 2 applications written in asynchronous Rust(pdf) https://arxiv.org/pdf/2505.21323v1
[109] ament_cmake_python user documentation http://docs.ros.org/en/ros2_documentation/humble/How-To-Guides/Ament-CMake-Python-Documentation.html
[110] ROS 2 Packaging https://w3.cs.jmu.edu/spragunr/CS354/labs/ros_packages/packaging.shtml
[111] 5.4.2. Developing a ROS 2 package¶ https://docs.vulcanexus.org/en/latest/ros2_documentation/source/How-To-Guides/Developing-a-ROS-2-Package.html
[112] Robotics Operating System(pdf) https://opencourse.inf.ed.ac.uk/sites/default/files/https/opencourse.inf.ed.ac.uk/mob/2024/ros-intro-2024-2025-mob.pdf
[113] ROS Service Server (C++) ROS Service Server (Python)(pdf) https://www.ida.liu.se/~TDDE05/info/lectures/02_introduction_to_ros.pdf
[114] [ROS2 Q&A] 215 – How to Use ROS2 Python Launch Files https://www.theconstruct.ai/ros2-qa-215-how-to-use-ros2-python-launch-files/
[115] [ROS2]missing <buildtool_depend>ament_python</buildtool_depend> in package.xml https://answers.ros.org/question/358703/ros2missing-buildtool_dependament_pythonbuildtool_depend-in-packagexml/
[116] Writing a simple service and client (Python) http://docs.ros.org/en/rolling/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Service-And-Client.html
[117] Traceback (most recent call last): File “/home/konglingrui/learn/demo_python_pkg/install/demo_python_pkg/lib/demo_python_pkg/python_node”, line 33, in sys.exit(load_entry_point(‘demo-python-pkg==0.0.0’, ‘console_scripts’, ‘python_node’)()) File “/home/konglingrui/learn/demo_python_pkg/install/demo_python_pkg/lib/demo_python_pkg/python_node”, line 25, in importlib_load_entry_point return next(matches).load() File “/usr/lib/python3.10/importlib/metadata/init.py”, line 173, in load return functools.reduce(getattr, attrs, module) AttributeError: module ‘demo_python_pkg.python_node’ has no attribute ‘main’ [ros2run]: Process exited with failure 1 - CSDN文库 https://wenku.csdn.net/answer/2nncwz9bwq
[118] ROS2 building with dependencies https://answers.ros.org/question/390865/ros2-building-with-dependencies/
[119] Create a ROS2 Python package https://roboticsbackend.com/create-a-ros2-python-package
[120] rospy/Overview/Initialization and Shutdown - ROS Wiki https://wiki.ros.org/rospy/Overview/Initialization%20and%20Shutdown
[121] Writing a simple publisher and subscriber (Python) https://docs.ros.org/en/eloquent/Tutorials/Writing-A-Simple-Py-Publisher-And-Subscriber.html
[122] Ros2 Cartographer Setup(2)_custom serial communication node https://velog.io/@mseokq23/Ros2-Cartographer-Setup2custom-serial-communication-node
[123] Robot Operating System——深度解析手动加载动态库的运行模式_ros2中classloader类加载器的用法-CSDN博客 https://blog.csdn.net/breaksoftware/article/details/140880049
[124] class_loader https://docs.ros2.org/galactic/api/class_loader/
[125] ROS2 runtime launch of nodes https://answers.ros.org/question/339444/ros2-runtime-launch-of-nodes/
[126] Cannot run a ROS2 node containing my custom .py scripts https://answers.ros.org/question/408142/cannot-run-a-ros2-node-containing-my-custom-py-scripts/
[127] Launch wrapper for rclcpp::Node to make it a LifecycleNode https://discourse.ros.org/t/launch-wrapper-for-rclcpp-node-to-make-it-a-lifecyclenode/23106
[128] High cpu load for simple python nodes https://discourse.ros.org/t/high-cpu-load-for-simple-python-nodes/28324
[129] ROS2 多线程 与组件机制_ros2组件-CSDN博客 https://blog.csdn.net/ZPC8210/article/details/150111060
[130] ros2 python 包的 setup.cfg, setup.py 语法详细解释-CSDN博客 https://blog.csdn.net/wilsonwong/article/details/152664626
[131] ROS2 Launch not interleaving stdout? https://discourse.ros.org/t/ros2-launch-not-interleaving-stdout/2721/1
[132] ROS2: CMakeList, Command Line Publish, Metapackages [Revised Heading] https://discourse.ros.org/t/ros2-cmakelist-command-line-publish-metapackages-revised-heading/2640
[133] Unit4 - Question about entry_points in setup.py https://get-help.theconstruct.ai/t/unit4-question-about-entry-points-in-setup-py/22229
[134] ros2 run bash script from Python package https://answers.ros.org/question/411104/ros2-run-bash-script-from-python-package/
[135] ros2 launch not working after source my package https://answers.ros.org/question/350137/ros2-launch-not-working-after-source-my-package/
[136] ros2 run and ros2 node – Start and Introspect your ROS2 Nodes https://roboticsbackend.com/ros2-run-and-ros2-node-start-debug-ros2-nodes
[137] ros2 py文件调用cpp文件 - CSDN文库 https://wenku.csdn.net/answer/3z78n0quwn
[138] Create a ROS2 package for Both Python and Cpp Nodes https://roboticsbackend.com/ros2-package-for-both-python-and-cpp-nodes/
[139] ros2: C++ and Python in same package. Is it possible? https://answers.ros.org/question/298740/ros2-c-and-python-in-same-package-is-it-possible/
[140] Build C++ Library and use in Python Package (Node) https://answers.ros.org/question/363051/
[141] C++ and Python nodes in the same launch file? https://answers.ros.org/question/392115/
[142] Intro to ROS Part 6: Services, Requests, and Responses with C++ https://www.digikey.co.th/th/maker/tutorials/2025/intro-to-ros-part-6-services-requests-and-responses-with-c
[143] ROS2与C++入门教程-在C++包里增加python支持_ros2 c++ 调用python程序-CSDN博客 https://blog.csdn.net/ncnynl/article/details/125729671
[144] ROS2机器人操作系统使用及简介-CSDN博客 https://blog.csdn.net/weixin_42554470/article/details/151680264
[145] Supported programming languages https://groups.google.com/g/ros-sig-ng-ros/c/W7eSS-uacOk/m/KVXcpORnFQAJ
[146] 使用pybind11生成了so文件,如何将so文件导入到ros2的python项目中 - CSDN文库 https://wenku.csdn.net/answer/4sd2pr3uq6
[147] Build C++ Library and use in Python Package (Node) https://answers.ros.org/question/363051/build-c-library-and-use-in-python-package-node/
[148] Choose a language (or languages) https://roboticsknowledgebase.com/wiki/robotics-project-guide/choose-a-language/
[149] IntegratingPythonWithOtherLanguages https://wiki.python.org/moin/IntegratingPythonWithOtherLanguages
[150] ros2 py文件调用cpp文件 - CSDN文库 https://wenku.csdn.net/answer/3z78n0quwn
[151] Data Engineering for HPC with Python(pdf) https://arxiv.org/pdf/2010.06312
[152] ROS 2 Client Interfaces (Client Libraries) http://docs.ros2.org/dashing/rclcpp_cpp_client_library_overview.html
[153] es
ROS
LibreriasCliente https://wiki.ros.org/es/ROS/LibreriasCliente
[154] C++ bindings for python in ros 2 https://answers.ros.org/question/297466/c-bindings-for-python-in-ros-2/
[155] Plain C API https://discourse.ros.org/t/plain-c-api/11911
[156] 在python中使用C++类 https://wiki.ros.org/cn/ROS/Tutorials/Using%20a%20C++%20class%20in%20Python
[157] About ROS 2 client libraries http://docs.ros.org/en/foxy/Concepts/About-ROS-2-Client-Libraries.html
[158] Client libraries http://docs.ros.org/en/iron/Concepts/Basic/About-Client-Libraries.html
[159] Using a C++ class in Python https://wiki.ros.org/es/ROS/Tutoriales/Using%20a%20C++%20class%20in%20Python
[160] 【ROS2学习笔记】通信接口-CSDN博客 https://blog.csdn.net/YZYZYYNO_2/article/details/152513969
[161] ros2 py文件调用cpp文件 - CSDN文库 https://wenku.csdn.net/answer/3z78n0quwn
[162] Interface definition using .msg / .srv / .action files https://design.ros2.org/articles/legacy_interface_definition.html
[163] SOSS: a whole new approach to your ROS 1-ROS 2 bridge!外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
[164] 【ROS2】ROS2 C++版本 与 Python版本比较_ros2 python版本-CSDN博客 https://blog.csdn.net/maizousidemao/article/details/144160168
[165] the time delay of message: c++pub-c++sub and python_pub-c++sub https://answers.ros.org/question/416239/
[166] High cpu load for simple python nodes https://discourse.ros.org/t/high-cpu-load-for-simple-python-nodes/28324/18
[167] ROS2高级面试题汇总_ros2面试题-CSDN博客 https://blog.csdn.net/qq_57633442/article/details/142834946
[168] The ROS 2 C++ Executors https://discourse.ros.org/t/the-ros-2-c-executors/38296
[169] Reducing ROS 2 CPU overhead by simplifying the ROS 2 layers https://discourse.ros.org/t/reducing-ros-2-cpu-overhead-by-simplifying-the-ros-2-layers/13808
[170] ROS2 speed https://discourse.ros.org/t/ros2-speed/20162/19
[171] SingleThreadedExecutor creates a high CPU overhead in ROS 2 https://discourse.ros.org/t/singlethreadedexecutor-creates-a-high-cpu-overhead-in-ros-2/10077/26
[172] Message Flow Analysis with Complex Causal Links for Distributed ROS 2 Systems(pdf) https://arxiv.org/pdf/2204.10208v3
[173] ROS2 Performance: rclpy is 30x-100x slower than rclcpp https://answers.ros.org/question/375827/ros2-performance-rclpy-is-30x-100x-slower-than-rclcpp/
[174] ROS2 Jazzy:实现自定义的消息和服务接口(C++)目标 学习在ROS2中实现自定义接口的更多方法。 背景信息 在 - 掘金 https://juejin.cn/post/7497785507742498855
[175] ROS2 Jazzy:编写可组合节点(C++)ROS2 Jazzy:编写可组合节点(C++) 起始状态 假设你有一个常规 - 掘金 https://juejin.cn/post/7518931398339575818
[176] ROS2 Jazzy:使用C++创建并运行一个包含ROS参数的类(C++)目标 使用C++创建并运行一个包含ROS参数的 - 掘金 https://juejin.cn/post/7502001864394784783
[177] ROS2 Jazzy:用C++实现一个动作服务器和客户端ROS2 Jazzy:用C++实现一个动作服务器和客户端 目标 - 掘金 https://juejin.cn/post/7517841519253815348
[178] [ros2学习]-Client Libraries - 写一个简单的服务端和客户端(python)① 背景② 前提③ 任 - 掘金 https://juejin.cn/post/6966155023369633806
[179] [ros2学习]-进阶 - 同步与异步服务端和客户端本指南旨在警告用户与Python 同步服务客户端 call()API - 掘金 https://juejin.cn/post/6966155173232115726
[180] ROS2 Jazzy:编写一个简单的服务端和客户端(C++)目标 使用 C++ 创建并运行服务节点和客户端节点。 背景信 - 掘金 https://juejin.cn/post/7497183377654956086
[181] Guidelines on how to architect ROS-based systems https://discourse.ros.org/t/guidelines-on-how-to-architect-ros-based-systems/12641
[182] Attributes of High-Quality ROS2-Based Systems https://automaticaddison.com/attributes-of-high-quality-ros2-based-systems/
[183] How to Achieve Production- Grade Deployment with ROS 2 and RTI Connext(pdf) https://www.rti.com/hubfs/Collateral_2017/Whitepapers/rti-whitepaper-ros2-connext-dds.pdf
[184] Title: ROS 2 Hardware Acceleration Architecture and Conventions https://ros.org/reps/rep-2008.html
[185] Why ROS 2? https://design.ros2.org/articles/why_ros2.html
(注:文档部分内容可能由 AI 生成)
更多推荐


所有评论(0)