ROS开发学习记录【一】

阶段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

  • builddevel 都是自动生成的

五、第一个 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

    cpp 复制代码
    nh.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

  • 传感器数据采集

  • 工控机真实项目结构

相关推荐
Tipriest_2 小时前
Linux(debian)包管理器aptitude介绍
linux·运维·debian·aptitude
冻伤小鱼干2 小时前
《自动驾驶与机器人中的slam技术:从理论到实践》笔记——ch7(3)
笔记·机器人·自动驾驶
码上宝藏2 小时前
从解耦到拓展:Clapper 0.10.0 插件化架构设计与 Lua 脚本集成
linux·开发语言·lua·视频播放器·clapper
WoY20202 小时前
conda修改镜像源遇到的问题:defaults(默认镜像源)清不干净导致创建环境失败
linux·python·conda
素素.陈2 小时前
调用大模型解析图片中的文字
linux·windows·microsoft
白书宇2 小时前
【STM32实战】从零开始写Linux 0.12内核 第2个实验 准备开发板
linux·stm32·嵌入式硬件
·present·2 小时前
射频网课学习第六章(功率增益圆)
学习
大连好光景2 小时前
Linux系统中那些重要的文件路径
linux·运维·服务器
·present·2 小时前
射频网课第三章学习(功率增益设计)
学习