专栏:VMware Ubuntu22.04 + ROS2 Humble 从入门实战教程
承接第五章【工作空间与功能包】
环境:VMware 虚拟机 Ubuntu22.04 + ROS2 Humble
文章目录
- 本章概述
- ROS2 节点是什么
- ROS2 节点常用命令行实操
- 案例:官方 Talker / Listener 节点演示
- 动手编写第一个 C++ 节点
- 节点核心 API 解析 & 常见编码坑
- 节点命名与命名空间
- VMware 环境踩坑汇总
- 课后练习
- 本章小结
1. 本章概述
上一章我们搭建好了 ROS2 的大本营:工作空间 ,并学会创建最小代码组织单元:功能包 。 在功能包内部,真正干活、独立运行的最小执行单元,就是节点 (Node)。
我们做一个形象类比:
- 工作空间:整个生物体
- 功能包:器官(视觉器官、运动控制器官)
- 节点:机器人的工作细胞
每个节点只负责单一任务,解耦设计。例如:
- 图像采集节点:负责读取摄像头画面
- 目标检测节点:识别画面中的障碍物
- 运动控制节点:下发底盘速度指令
单个节点崩溃不会影响其他节点,节点之间通过 ROS2 的通信机制传递数据,互不直接调用函数,这就是 ROS2 模块化设计思想。
2. ROS2 节点是什么
ROS2 节点本质是独立的可执行程序(进程)。 机器人软件系统由多个节点共同组成,每个节点只完成一件事情。
✅ 节点设计优势
- 模块化:功能拆分清晰,便于单独调试
- 高容错:某一个节点异常退出,其余节点继续运行
- 分布式:节点可以运行在同一台电脑,也可以分布在机器人主板和上位机,跨设备通信
核心:节点之间不直接交互,依靠话题、服务、动作等通信方式传递信息。
3. ROS2 节点常用命令行实操
前置:终端加载 ROS2 环境
# 加载ROS2系统环境
source /opt/ros/humble/setup.bash
# 如果需要使用自己工作空间编译的程序
source ~/ros2_ws/install/setup.bash
3.1 查看当前所有正在运行的节点
ros2 node list
输出的节点名称以 / 开头,例如 /talker。
3.2 查看节点详细信息
ros2 node info /节点名称
# 示例
ros2 node info /talker
可以查看该节点:发布的话题、订阅的话题、提供的服务、调用的服务等。
3.3 启动节点:ros2 run
语法:ros2 run 功能包名 可执行文件名称
ros2 run demo_nodes_cpp talker
3.4 节点重映射:运行时修改节点名称
同一时刻不能存在同名节点,启动时可以通过参数修改节点名,避免冲突:
ros2 run demo_nodes_cpp talker --ros-args -r __node:=talker_robot1
4. 案例:官方 Talker / Listener 节点演示
ROS2 自带示例包,talker(发布者)持续发送字符串消息,listener(订阅者)接收消息。
终端 1:启动 talker 节点
ros2 run demo_nodes_cpp talker
终端 2:启动 listener 节点
ros2 run demo_nodes_cpp listener
终端 3:查看节点列表
ros2 node list
可以看到 /talker 和 /listener 两个节点。 执行 ros2 node info /talker,查看该节点对外发布的话题信息。
现象:talker 不断打印消息,listener 终端收到对应的字符串。两个独立节点完成通信。
5. 动手编写第一个 C++ 节点
环境路径:
~/ros2_ws/src,先创建功能包(第五章已学)
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake my_node_pkg --dependencies rclcpp
cd my_node_pkg
mkdir src
5.1 新建代码文件 src/hello_node.cpp
#include "rclcpp/rclcpp.hpp"
// 创建节点类,继承 rclcpp::Node
class HelloNode : public rclcpp::Node
{
public:
// 构造函数:节点名称 hello_node
HelloNode() : Node("hello_node")
{
// ROS日志打印
RCLCPP_INFO(this->get_logger(), "Hello ROS2! 我是机器人的工作细胞");
}
};
int main(int argc, char * argv[])
{
// 初始化ROS2上下文
rclcpp::init(argc, argv);
// 创建节点实例
auto node = std::make_shared<HelloNode>();
// 启动节点事件循环
rclcpp::spin(node);
// 关闭ROS2
rclcpp::shutdown();
return 0;
}
5.2 修改 CMakeLists.txt
在文件中添加编译和安装配置:
add_executable(hello_node src/hello_node.cpp)
ament_target_dependencies(hello_node rclcpp)
install(TARGETS
hello_node
DESTINATION lib/${PROJECT_NAME}
)
5.3 修改 package.xml
确认依赖已经添加(创建包时已经自动添加)
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
5.4 编译 + 运行节点
cd ~/ros2_ws
# 只编译当前功能包
colcon build --packages-select my_node_pkg
# 刷新环境
source install/setup.bash
# 运行节点
ros2 run my_node_pkg hello_node
✅ 终端输出:[INFO] [xxx]: Hello ROS2! 我是机器人的工作细胞
6. 节点核心 API 解析 & 编码坑
rclcpp::init(argc, argv); // 初始化ROS2环境,必须最先执行
auto node = std::make_shared<HelloNode>(); // 实例化节点对象
rclcpp::spin(node); // 开启事件循环,监听回调,节点核心!
rclcpp::shutdown(); // 关闭ROS2,释放资源
⚠️ 新手头号坑:忘记写 rclcpp::spin (node) 如果没有 spin,程序运行瞬间直接退出,看不到日志输出。spin 会阻塞程序,等待回调事件。
7. 节点命名与命名空间
- 节点名称仅支持:小写字母、数字、下划线
_;不能带中文、空格 - 同一系统中不允许同名节点,后启动节点会报错
- 命名空间 namespace:用于多机器人分组
/robot1/talker:命名空间robot1,节点名talker/robot2/talker:命名空间robot2,节点名talker
多机器人场景下,使用命名空间可以复用同一套代码,不会出现节点重名冲突。
8. VMware Ubuntu22.04 环境踩坑汇总
-
ros2 run 找不到可执行文件
- 原因:编译后没有执行
source install/setup.bash - 解决:每次新开终端,进入工作空间后刷新环境变量
- 原因:编译后没有执行
-
节点启动报错:节点名称冲突
- 排查:
ros2 node list查看正在运行节点,关闭占用同名节点的终端
- 排查:
-
git clone 拉取古月居示例仓库报错 RPC failed curl GnuTLS
方案1:增大git缓存
git config --global http.postBuffer 524288000
方案2:浅克隆,不下载完整历史记录(推荐虚拟机)
git clone --depth=1 https://gitee.com/guyuehome/ros2_21_tutorials.git
-
虚拟机多机通信失败
- 虚拟机网卡切换为桥接模式,多台设备 ROS_DOMAIN_ID 保持一致。
9. 课后练习
- 启动 talker /listener 示例,使用
ros2 node list和ros2 node info观察节点信息。 - 修改上面 C++ 代码,更换节点名称,重新编译运行。
- 尝试启动两个 talker 节点,使用节点重映射参数,解决同名冲突。
10. 本章小结
节点 Node 是 ROS2 机器人软件中最小执行单元,是机器人的工作细胞。
- 工作空间:项目大本营
- 功能包:代码器官
- 节点:工作细胞
节点采用模块化设计,每个节点只负责单一任务,节点之间通过话题、服务等通信方式交换数据。