阶段1:从 0 到工程级 ROS 基础能力
嵌入式 Linux / 工控机环境
ROS Noetic(无 GUI版本)
C++(roscpp)
一、为什么要写这篇总结?
在学习 ROS 的过程中,我逐渐意识到一件事:
真正学会 ROS 的标志,不是"跑通示例",
而是"能在嵌入式 Linux / 工控机上独立搭建、调试 ROS 系统"。
因此,我决定在 阶段 1 完成后,对整个学习过程做一次系统总结,并整理成博客,一方面加深理解,另一方面也希望能给后来者一些参考。
二、阶段 1 的学习目标
阶段 1 的目标非常明确,不追求"功能炫酷",而是夯实基础:
-
理解 ROS 的运行模型
-
掌握 ROS 节点与通信机制
-
能在 无 GUI 的嵌入式 Linux / 工控机环境 下调试 ROS
-
具备工程级 ROS 入门能力
三、ROS 的运行模型(核心认知)
1. ROS 不是一个程序
ROS 的本质是一个分布式通信系统,由三部分构成:
cpp
roscore + 多个节点(Node) + 通信机制(Topic / Service)
-
roscore
-
提供 Master(注册中心)
-
参数服务器
-
日志系统
-
-
Node
-
本质是 Linux 进程
-
每个节点都是一个独立程序
-
-
Topic
-
发布 / 订阅模型
-
异步、解耦通信
-
四、catkin 工作空间结构
在 ROS Noetic 中,常用的构建系统是 catkin。
1. 工作空间目录结构
catkin_ws/
├── src/ # 源码目录(开发只在这里进行)
│ └── myros_demo/
├── build/ # 编译中间文件
├── devel/ # 运行环境(可执行文件)
└── install/ # 安装目录(可选)
实际开发中:
-
只需要关心
src -
build和devel都是自动生成的
五、第一个 ROS 包:myros_demo
1. 创建 ROS 包
cpp
catkin_create_pkg myros_demo roscpp std_msgs
这一步完成了:
-
创建标准 ROS 包结构
-
声明依赖:
-
roscpp:C++ ROS API -
std_msgs:标准消息类型
-
2. 包结构说明
myros_demo/
├── CMakeLists.txt # 编译规则(最关键)
├── package.xml # 包信息与依赖声明
└── src/
├── talker.cpp # 发布者节点
└── listener.cpp # 订阅者节点
六、核心节点代码解析
1. talker.cpp ------ 发布者节点
功能说明
周期性向指定 topic 发布字符串消息
发布频率和 topic 名可通过参数配置
关键代码解析
cpp
ros::init(argc, argv, "talker");
-
初始化 ROS
-
注册节点名
talker
cpp
ros::NodeHandle nh("~");
-
使用私有命名空间
-
所有参数和 topic 都挂在
/talker下cppnh.param<std::string>("topic", topic_name, "chatter"); nh.param<int>("rate", rate_hz, 1); -
从 参数服务器 读取参数
-
实现"代码不变,行为可配置"
cpp
ros::Publisher pub =
nh.advertise<std_msgs::String>(topic_name, 10);
-
创建发布者
-
10表示发送队列长度(缓冲)
cpp
ros::Rate rate(rate_hz);
-
控制发布频率
-
是 ROS 中调度与实时性的基础
2. listener.cpp ------ 订阅者节点
功能说明
订阅 topic,并在回调函数中处理数据
cpp
ros::Subscriber sub =
nh.subscribe("chatter", 10, callback);
-
创建订阅者
-
注册回调函数
cpp
ros::spin();
-
进入 ROS 事件循环
-
没有 spin,回调函数不会执行
七、CMakeLists.txt(最容易踩坑的部分)
1. CMakeLists.txt 的核心作用
决定你的 ROS 节点能否"正确链接 ROS 库"。
2. 关键配置说明
cpp
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)
-
声明 ROS 依赖
-
决定
ros::init等符号是否可用
cpp
include_directories(${catkin_INCLUDE_DIRS})
指定头文件搜索路径
cpp
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
-
编译可执行文件
-
链接 ROS 核心库(非常关键)
八、无 GUI 环境下的 ROS 调试方法
在嵌入式 Linux / 工控机环境中,通常没有图形界面,此时命令行调试尤为重要。
1. rostopic 常用命令
cpp
rostopic list # 查看所有 topic
rostopic echo /xxx # 查看 topic 数据
rostopic hz /xxx # 查看 topic 频率
2. rostopic info ------ rqt_graph 的替代方案
cpp
rostopic info /chatter
可以清楚看到:
-
发布者
-
订阅者
在无 GUI 场景下:
rostopic info 就是文字版 rqt_graph
九、命名空间(阶段 1 的隐藏重点)
使用:
cpp
ros::NodeHandle nh("~");
并结合参数:
cpp
rosrun myros_demo talker _topic:=fast_chatter
最终 topic 实际为:
cpp
/talker/fast_chatter
这是 ROS 中:
-
多节点实例
-
工程部署
-
命名隔离
的核心设计。
十、参数服务器(阶段 1 的核心成果)
通过参数服务器,可以做到:
cpp
rosrun myros_demo talker _rate:=5 _topic:=fast_chatter
实现:
-
修改发布频率
-
修改 topic 名
-
无需重新编译
这是 ROS 工程化能力的关键体现。
十一、阶段 1 总结与收获
✅ 阶段 1 完成后:
-
理解 ROS 的运行模型
-
独立创建 ROS 包
-
编写并调试 C++ ROS 节点
-
在无 GUI 的嵌入式 Linux 上调试 ROS
-
使用参数服务器进行工程级配置
十二、下一步计划(阶段 2)
阶段 2 将进入真实硬件世界:
-
ROS ↔ 串口(UART)
-
ROS ↔ MCU
-
传感器数据采集
-
工控机真实项目结构