☰
ROS2从零入门:彻底搞懂节点+编写第一个自定义节点
2026/10/9 2:54:19 网站建设 项目流程

在上一篇博客中,我们掌握了 ROS2 环境配置、命令行启动程序、CMake 编译工具的使用,解决了如何运行ROS2程序的问题。而今天我们深入底层核心,讲解 ROS2 最基础、最重要的核心单元——节点(Node)。

所有 ROS2 机器人功能,无论是建图、导航、视觉识别、电机控制,本质上都是由一个个独立的节点协同完成。可以说:学会写节点,才算真正入门 ROS2 开发。

本文将从零讲解节点核心概念,搭配可直接复制运行的 C++ 源码,手把手教你完成「编写节点→配置编译规则→编译程序→运行调试」完整闭环,适配 Humble/Iron/Jazzy 全版本。

一、什么是 ROS2 节点?(通俗理解)

1. 节点的定义

在 ROS2 中,节点(Node)是执行单一特定功能的最小可执行单元,是编译后可以独立运行的程序。

我们可以把机器人系统类比成一个团队,每个节点就是一个独立的工作人员:

  • 雷达节点:专门负责采集环境雷达数据

  • 相机节点:专门负责采集图像画面

  • 导航节点:专门负责路径规划、点位导航

  • 电机控制节点:专门负责控制机器人运动

每个节点各司其职、独立运行,通过话题、服务等方式互相通信,最终实现机器人的完整功能。

2. 节点的核心优势

  • 模块化解耦:单个节点故障不会导致整个系统崩溃,稳定性更强

  • 可复用性高:写好的节点可直接复用在不同机器人项目中

  • 调试简单:可单独启动、单独调试某个功能模块

3. 节点、功能包、可执行文件的关系

很多新手容易混淆三者关系,这里做清晰梳理:

功能包(Package):存放源码、配置文件的文件夹,是项目管理单元

节点源码:我们编写的 .cpp 代码,是节点的原始程序

节点(可执行文件):源码经过 CMake 编译后生成的可运行程序,也就是我们用ros2 run启动的程序

二、自定义节点开发前置准备

默认你已经配置好 ROS2 环境、创建好了工作空间ros2_ws,我们先创建一个全新的自定义功能包,用于存放我们的第一个节点。

1. 创建自定义功能包

进入工作空间 src 目录,创建依赖 rclcpp(ROS2 C++ 核心库)的功能包:

cd ~/ros2_ws/src ros2 pkg create my_first_node --build-dependencies rclcpp

命令释义:创建名为my_first_node的功能包,默认依赖 C++ 节点核心库 rclcpp。

2. 创建源码文件夹

进入功能包,新建 src 文件夹(规范存放源码文件):

cd ~/ros2_ws/src/my_first_node mkdir src

三、手把手编写第一个 ROS2 C++ 节点

我们编写一个最简单的日志输出节点,实现节点启动后循环打印日志,验证节点正常运行。在src目录下新建文件hello_node.cpp,写入以下完整源码。

1. 完整节点源码(可直接复制)

// 引入ROS2 C++核心头文件 #include "rclcpp/rclcpp.hpp" // 主函数,程序入口 int main(int argc, char ** argv) { // 1. 初始化ROS2节点环境 rclcpp::init(argc, argv); // 2. 创建一个节点,命名为 hello_world_node auto node = std::make_shared<rclcpp::Node>("hello_world_node"); // 3. 循环输出日志(每秒打印一次) rclcpp::Rate loop_rate(1.0); // 设置频率1Hz while (rclcpp::ok()) // 节点正常运行时循环 { // 打印INFO级别日志 RCLCPP_INFO(node->get_logger(), "成功运行第一个ROS2节点!Hello ROS2!"); loop_rate.sleep(); // 休眠,控制循环频率 } // 4. 关闭节点环境 rclcpp::shutdown(); return 0; }

2. 代码逐行核心解析(新手必看)

  • #include "rclcpp/rclcpp.hpp":引入 ROS2 C++ 节点核心库,所有 C++ 节点必须包含该头文件

  • rclcpp::init(argc, argv):初始化 ROS2 通信环境,是节点运行的第一步

  • std::make_shared<rclcpp::Node>("hello_world_node"):创建节点实例,hello_world_node 是节点名称,全局唯一

  • rclcpp::Rate loop_rate(1.0):设置循环运行频率,1.0代表1秒执行一次

  • rclcpp::ok():判断节点是否处于正常运行状态,按下 Ctrl+C 后终止循环

  • RCLCPP_INFO:ROS2 标准日志打印函数,替代普通 printf,可输出日志级别、时间戳

  • rclcpp::shutdown():关闭节点,释放资源,程序结束

四、配置 CMakeLists.txt 编译规则(关键步骤)

写完源码后,必须配置编译规则,告诉 CMake 如何编译源码、生成可执行文件、安装运行文件。打开功能包根目录的CMakeLists.txt,替换为以下完整配置(衔接上一篇博客的CMake知识点)。

cmake_minimum_required(VERSION 3.8) project(my_first_node) # 查找依赖包 find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) # 编译可执行节点:源码文件 + 生成的节点名 add_executable(hello_node src/hello_node.cpp) # 绑定节点依赖 ament_target_dependencies(hello_node rclcpp) # 安装节点,让ros2 run可以识别 install(TARGETS hello_node DESTINATION lib/${PROJECT_NAME} ) ament_package()

核心重点:add_executable定义了最终的可执行文件名hello_node,后续启动节点需要使用该名称。

五、编译+运行节点完整流程

1. 编译功能包

返回工作空间根目录,执行编译命令:

cd ~/ros2_ws colcon build --packages-select my_first_node

2. 加载环境变量

编译完成后必须加载环境,否则无法识别新节点:

source install/setup.bash

3. 启动自定义节点

使用上一篇博客的ros2 run命令启动单个节点:

ros2 run my_first_node hello_node

4. 运行效果

终端会每秒循环打印日志,代表节点运行成功:

[INFO] 成功运行第一个ROS2节点!Hello ROS2!

按下Ctrl+C即可关闭节点。

六、验证节点状态(调试实操)

保持节点运行,新开终端加载环境,通过调试命令验证节点状态:

# 查看所有运行节点 ros2 node list # 查看节点详细信息 ros2 node info /hello_world_node

可以看到我们创建的hello_world_node节点,证明节点注册、运行完全正常。

七、新手开发常见报错避坑

  • 编译成功但无法启动节点:CMakeLists 未配置 install 安装规则,节点未部署到运行目录,重新配置并清理缓存编译

  • 提示节点不存在:编译后未执行 source 环境变量,或可执行文件名输入错误

  • 代码报错:rclcpp未定义:package.xml 和 CMakeLists 中未添加 rclcpp 依赖

  • 节点启动瞬间闪退:代码缺少循环逻辑,节点执行完毕后自动退出,需添加 while 循环常驻运行

八、总结与进阶方向

通过本文,我们彻底理解了 ROS2 节点的核心概念,同时完成了从0编写、配置、编译到运行的完整节点开发流程。这是所有 ROS2 进阶开发的基础,后续的话题通信、服务通信、参数配置、传感器开发,都是在节点的基础上延伸拓展。

简单复盘核心要点:

  1. 节点是ROS2最小可执行功能单元,模块化分工运行

  2. C++节点开发核心四步:建包→写源码→配CMake→编译运行

  3. 必须初始化、注册节点、循环常驻、最后关闭节点

下一篇我们可以基于该节点,讲解ROS2话题通信,实现节点之间的数据收发,真正实现多节点协同工作。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询