ROS2系列(3):第一个C++节点
ROS2系列(3):第一个C++节点
作为ROS2开发的核心语言之一,C++以其高性能特性成为机器人节点开发的首选。本文将从代码编写、编译配置、工具链调试到节点运行分析,完整拆解第一个ROS2 C++节点的开发全流程,并补充资深开发者的实践细节。
一、编写C++节点代码:ros2_cpp_node.cpp
创建核心代码文件ros2_cpp_node.cpp,实现节点初始化、日志输出等基础功能:
#include "rclcpp/rclcpp.hpp"int main(int argc, char **argv)
{// 初始化ROS2运行时rclcpp::init(argc, argv);// 创建节点,命名为"cpp_node"auto node = std::make_shared<rclcpp::Node>("cpp_node");// 输出INFO级日志RCLCPP_INFO(node->get_logger(), "你好 C++ 节点!");// 保持节点循环运行(处理回调、话题等)rclcpp::spin(node);// 关闭ROS2运行时rclcpp::shutdown();return 0;
}
代码解析:
- rclcpp::init(argc, argv):初始化ROS2系统,支持节点重映射、参数配置等命令行参数。
- std::make_shared<rclcpp::Node>("cpp_node"):创建共享指针管理的节点对象,- cpp_node为节点默认名称。
- RCLCPP_INFO(...):通过节点日志器输出信息,是ROS2调试的核心手段。
- rclcpp::spin(node):启动节点“事件循环”,持续处理话题、服务、定时器等事件。
二、CMake配置:从编译错误到正确配置
ROS2 C++节点需通过CMake编译,以下是完整配置流程。
2.1 初始错误配置与编译失败
先编写基础但存在依赖缺失的CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
project(ros2_cpp)
add_executable(ros2_cpp_node ros2_cpp_node.cpp)
执行编译命令:
cmake .
make
会触发头文件缺失错误:
fatal error: rclcpp/rclcpp.hpp: 没有那个文件或目录
原因:未配置rclcpp库的头文件和库文件路径,CMake无法找到ROS2核心依赖。
2.2 正确的CMakeLists.txt配置
补充rclcpp依赖的查找与链接:
cmake_minimum_required(VERSION 3.8)
project(ros2_cpp)# 查找rclcpp包(依赖缺失则编译失败)
find_package(rclcpp REQUIRED)add_executable(ros2_cpp_node ros2_cpp_node.cpp)# 包含rclcpp头文件目录
target_include_directories(ros2_cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS})
# 链接rclcpp库文件
target_link_libraries(ros2_cpp_node ${rclcpp_LIBRARIES})
配置解析:
- find_package(rclcpp REQUIRED):自动获取- rclcpp的头文件目录(- rclcpp_INCLUDE_DIRS)和库文件(- rclcpp_LIBRARIES)。
- target_include_directories:确保编译器能找到- rclcpp的头文件。
- target_link_libraries:确保可执行文件能链接到- rclcpp的动态库。
2.3 编译与运行
重新编译并运行:
cmake .
make
./ros2_cpp_node
输出日志:
[INFO] [1698472590.755824396] [cpp_node]: 你好 C++ 节点!
三、VSCode配置:实现C++代码提示
为了在VSCode中获得rclcpp的代码提示,需配置头文件搜索路径。
3.1 安装C/C++扩展
在VSCode扩展商店安装 C/C++ Extension Pack(提供代码提示、语法检查等功能)。
3.2 配置includePath
打开VSCode设置(Ctrl+,),搜索C_Cpp: Include Path,添加以下路径:
${workspaceFolder}/**
/opt/ros/${ROS_DISTRO}/include/**
- ${workspaceFolder}/**:包含工作空间内自定义头文件。
- /opt/ros/${ROS_DISTRO}/include/**:包含ROS2系统级头文件(如- rclcpp)。
3.3 效果验证
配置后,在代码中输入node.时,VSCode会自动提示get_logger()等方法,鼠标悬停可查看函数说明:
// 输入node.后,会自动提示get_logger()
node->get_logger().info("日志信息");
四、节点调试:命令行参数与节点信息
4.1 命令行参数(argc/argv)处理
ROS2节点支持命令行参数,以下是自定义参数处理示例:
#include <iostream>
#include "rclcpp/rclcpp.hpp"int main(int argc, char **argv)
{rclcpp::init(argc, argv);auto node = std::make_shared<rclcpp::Node>("arg_node");// 打印参数数量和程序名std::cout << "参数数量: " << argc << std::endl;std::cout << "程序名字: " << argv[0] << std::endl;// 处理自定义参数(如--help)if (argc > 1 && std::string(argv[1]) == "--help") {RCLCPP_INFO(node->get_logger(), "这里是节点帮助信息");}rclcpp::spin(node);rclcpp::shutdown();return 0;
}
编译运行并传入参数:
./ros2_arg_node --help
输出:
参数数量: 2
程序名字: ./ros2_arg_node
[INFO] [1732905678.123456] [arg_node]: 这里是节点帮助信息
4.2 查看节点信息(ros2 node工具链)
步骤1:列出运行中的节点
ros2 node list
输出:
/cpp_node
步骤2:查看节点详细信息
ros2 node info /cpp_node
输出解析:
/cpp_nodeSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEvent  # 订阅参数变更事件Publishers:/parameter_events: rcl_interfaces/msg/ParameterEvent  # 发布参数变更事件/rosout: rcl_interfaces/msg/Log                      # 发布全局日志话题
- /parameter_events:ROS2内建话题,用于节点间参数变化的通知。
- /rosout:全局日志话题,可通过- ros2 topic echo /rosout查看所有节点日志。
五、C++节点开发的其他细节
5.1 rclcpp依赖的底层逻辑
rclcpp是ROS2 C++生态的核心库,通过find_package(rclcpp REQUIRED)可自动关联rcutils、rmw等底层依赖,无需手动处理多级依赖关系。
5.2 rclcpp::spin的核心作用
rclcpp::spin(node)是节点的“事件循环”,负责处理:
- 话题的发布/订阅回调;
- 服务的请求/响应;
- 定时器(rclcpp::Timer)触发;
- 参数变更通知(/parameter_events)。
缺少spin,节点会在输出日志后立即退出,无法持续运行。
5.3 日志级别与调试技巧
ROS2日志分为DEBUG、INFO、WARN、ERROR、FATAL五级。调试时可通过环境变量调整输出级别:
export RCUTILS_LOGGING_MINIMUM_SEVERITY=DEBUG
./ros2_cpp_node
也可在代码中指定日志器级别:
node->get_logger().set_level(rclcpp::Logger::Level::Debug);
5.4 节点名称冲突解决方案
若多个节点重名,ROS2会默认让后启动的节点覆盖前一个。建议:
- 开发时用ros2 node list确认节点名称;
- 生产环境通过命名空间(__ns)或唯一标识区分,例如:./ros2_cpp_node --ros-args --remap __node:=robot1_cpp_node --remap __ns:=/robot1
总结
本文从代码编写、编译配置、工具链调试到运行时分析,完整覆盖了第一个ROS2 C++节点的开发流程。掌握rclcpp基础API、CMake依赖配置、VSCode代码提示及ros2 node工具链,是入门ROS2 C++开发的关键。后续可进一步学习话题、服务、参数等进阶内容,逐步构建复杂机器人应用。
