ROS 2 基础入门:用 C++ 编写第一个节点
学习范围:《ROS 2 机器人开发:从入门到实践》第 2 章 2.1.2 C++ 示例
当前目标:用 C++ 写一个最小 ROS 2 节点,对比 Python 节点的结构。
本节要掌握什么
学完这一小节,要能做到:
- 能写出一个最小 C++ 节点。
- 能用
colcon build编译 C++ 功能包。 - 能运行 C++ 节点,并用
ros2 node list查看。 - 能理解 C++ 节点和 Python 节点在结构上的共同点。
为什么还要学 C++ 节点
ROS 2 同时支持 Python 和 C++。实际项目中:
- 快速原型、测试脚本、高层逻辑常用 Python。
- 对性能要求高的底层模块(传感器驱动、导航算法、实时控制)常用 C++。
两种语言的 ROS 2 节点生命周期是一样的:初始化 → 创建节点 → 运行 → 关闭。区别只在语法和构建方式。
用 STM32 的经验理解 C++ 节点
以前用 STM32 写 C 代码,对 C++ 的语法不会陌生。做一个类比:
| STM32 / C 开发 | ROS 2 C++ 开发 |
|---|---|
main() 函数入口 |
main() 函数入口 |
| HAL 初始化 | rclcpp::init() |
while(1) 主循环 |
rclcpp::spin() |
printf 调试 |
RCLCPP_INFO 日志 |
| Makefile / Keil 工程 | CMakeLists.txt + colcon |
头文件 #include |
头文件 #include "rclcpp/rclcpp.hpp" |
STM32 的 while(1) 让程序不停运行;ROS 2 的 rclcpp::spin() 让节点持续等待回调和事件。思路一样,只是粒度不同。
C++ 节点和 Python 节点的对比
| 对比项 | Python 节点 | C++ 节点 |
|---|---|---|
| 初始化 | rclpy.init() |
rclcpp::init() |
| 创建节点 | Node("name") |
std::make_shared<rclcpp::Node>("name") |
| 日志输出 | node.get_logger().info() |
RCLCPP_INFO(node->get_logger(), ...) |
| 保持运行 | rclpy.spin(node) |
rclcpp::spin(node) |
| 关闭 | rclpy.shutdown() |
rclcpp::shutdown() |
| 构建方式 | 直接 python3 xxx.py |
colcon build → 运行可执行文件 |
| 依赖管理 | package.xml(ament_python) |
package.xml + CMakeLists.txt(ament_cmake) |
核心生命周期完全一致,只是语言表达不同。
创建 C++ 功能包
ROS 2 的 C++ 代码不能像 Python 那样直接运行一个 .py 文件,需要先创建功能包并编译。
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake cpp_node_pkg --dependencies rclcpp
这条命令会生成一个功能包目录,包含:
CMakeLists.txt:CMake 构建配置。package.xml:功能包元数据和依赖声明。src/:源码目录。include/:头文件目录。
--dependencies rclcpp 会自动在 package.xml 和 CMakeLists.txt 中添加对 rclcpp 的依赖。
编写 C++ 节点代码
在功能包的 src/ 目录下创建 cpp_node.cpp:
cd ~/ros2_ws/src/cpp_node_pkg/src
code cpp_node.cpp
写入代码:
#include "rclcpp/rclcpp.hpp"
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<rclcpp::Node>("cpp_node");
RCLCPP_INFO(node->get_logger(), "你好,ROS 2 C++ 节点!");
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
配置 CMakeLists.txt
打开 CMakeLists.txt,找到自动生成的可执行文件部分,添加:
add_executable(cpp_node src/cpp_node.cpp)
ament_target_dependencies(cpp_node rclcpp)
install(TARGETS
cpp_node
DESTINATION lib/${PROJECT_NAME})
说明:
add_executable:告诉 CMake 要编译哪个源文件生成哪个可执行文件。ament_target_dependencies:链接 ROS 2 依赖库。install:把编译好的可执行文件安装到正确位置,这样ros2 run才能找到它。
编译
回到工作空间根目录,使用 colcon 编译:
cd ~/ros2_ws
colcon build
编译成功后会看到类似输出:
Starting >>> cpp_node_pkg
Finished <<< cpp_node_pkg [X.XXs]
编译产物在 install/ 目录下。如果只想编译这一个包:
colcon build --packages-select cpp_node_pkg
运行节点
先加载安装目录的环境:
source install/setup.bash
然后运行:
ros2 run cpp_node_pkg cpp_node
说明:
cpp_node_pkg:功能包名。cpp_node:CMakeLists.txt 中add_executable定义的可执行文件名。
正常输出:
[INFO] [时间戳] [cpp_node]: 你好,ROS 2 C++ 节点!
验证节点
保持第一个终端运行,新开终端:
source ~/ros2_ws/install/setup.bash
ros2 node list
应该看到 /cpp_node。查看节点信息:
ros2 node info /cpp_node
按 Ctrl+C 结束节点。
常见问题
问题 1:colcon build 报错找不到 rclcpp
确认已安装 ROS 2 C++ 库:
sudo apt install ros-humble-rclcpp
(把 humble 换成你的 ROS 2 版本。)
问题 2:ros2 run 找不到可执行文件
检查两点:
- 是否执行了
source install/setup.bash。 CMakeLists.txt中的install(TARGETS ...)是否正确配置。
问题 3:编译成功但运行时找不到节点名
检查 add_executable 和 ros2 run 用的可执行文件名是否一致。
本节小结
本节完成了第一个 ROS 2 C++ 节点。和 Python 节点对比后可以看到:
初始化 ROS 2 -> 创建节点 -> 让节点运行 -> 关闭 ROS 2
这个生命周期是 ROS 2 所有程序的基础,不管用 Python 还是 C++ 都一样。C++ 多了编译这一步,但也带来了更好的性能和类型安全。后续学习话题、服务等内容时,两种语言的结构都是相通的。
课后练习
- 把节点名改成
my_cpp_node,重新编译运行,用ros2 node list验证。 - 在节点中多加几行
RCLCPP_INFO,输出不同的日志信息。 - 试试
RCLCPP_WARN和RCLCPP_ERROR,观察日志级别有什么不同。 - 对比 Python 和 C++ 节点代码,用自己的话说说两者结构上的共同点。
下一节建议继续学习:2.2 Python 功能包组织。目标是学会用标准的 ROS 2 功能包结构来组织 Python 代码。
更多推荐


所有评论(0)