返回
机器人基础教程 第八课:机器人操作系统与软件架构
这一课把“机器人软件怎么搭起来、怎么跑起来、怎么和硬件连起来”讲清楚。你可以把它当作:从“会写算法”走向“能做完整机器人系统”的分水岭。
8.1 机器人操作系统(ROS)概述
8.1.1 ROS 是什么?为什么它是现代机器人开发的核心?
ROS(Robot Operating System)更像是机器人软件中间件 + 工具链 + 生态,它解决的不是“某一个算法”,而是“把很多算法、硬件、工程流程拼成一个可用系统”。
ROS 帮你解决这些真实痛点:
模块化协作:感知、定位、规划、控制、UI 各写各的,靠统一通信机制拼起来
复用与生态:SLAM、导航、机械臂规划、相机驱动……大量现成包直接用
工程化工具:录包回放、可视化、调参、日志、仿真、发布部署
跨硬件:同一套上层算法能跑在不同底盘、不同雷达/相机上(只要驱动和话题对上)
补充一个重要现实:ROS 1(Noetic)已在 2025-05-31 达到 EOL,新项目更建议以 ROS 2 为主。
8.1.2 ROS 的结构与组件:节点、话题、消息(再加上你必须知道的 4 个概念)
ROS 2 把系统拆成很多“进程/组件”,每个组件做一件事:
(1) Node 节点
一个节点负责一个清晰功能:例如“读取雷达”“发布里程计”“做 SLAM”“做路径规划”。官方教程也强调节点应当职责单一、模块化。
(2) Topic 话题(发布/订阅)
最常用通信方式:A 节点发布数据到某个 topic,B 节点订阅它。ROS 2 官方把 topic 形容为“节点交换消息的总线”。
(3) Message 消息
topic 里传的数据结构(强类型),例如 sensor_msgs/LaserScan、geometry_msgs/Twist。
(4) Service 服务(请求/响应)
像函数调用:请求一次,返回一次。适合“设置模式、触发一次动作”。
(5) Action 动作(可反馈、可取消的长任务)
例如“导航到目标点”:过程中会反馈进度,也可以取消。
(6) Parameter 参数
节点运行参数:PID 增益、滤波系数、地图分辨率、控制频率等。
再加一个你后面绕不过去的:TF 坐标变换
机器人一切感知与控制都离不开坐标系:map / odom / base_link / camera_link / laser,TF2 用来维护这些变换关系。很多“导航跑不起来”的问题,本质是 TF 错了或时间戳不对。
8.2 ROS 开发环境的搭建
8.2.1 选 ROS 1 还是 ROS 2?选哪个版本?
新项目:优先 ROS 2(生态和维护趋势都在 ROS 2)
ROS 2 的一个常用选择是 Jazzy Jalisco。官方安装文档显示:Jazzy 的 Ubuntu deb 包面向 Ubuntu 24.04 (Noble)。
ROS 1 Noetic:已 EOL(上面已引用),除非维护存量项目否则不建议新上。
8.2.2 在 Ubuntu 上安装与配置(以 ROS 2 Jazzy 为例)
下面给你一个“新手最少踩坑”安装路径(思路:官方 deb + colcon 工作空间):
A. 系统准备
Ubuntu 24.04
保持系统更新、时间同步(机器人分布式通信很怕时间飘)
B. 按官方文档走 deb 安装
官方写明 Jazzy 的 deb 包适配 Ubuntu 24.04。
安装完成后,重点是这两件事:
source 环境(让 shell 认识 ros2 命令、包路径)
建立自己的 colcon workspace
典型工作空间结构:
~/ros2_ws/src:放你自己的包
~/ros2_ws/build / install / log:编译生成
8.2.3 ROS 开发常用工具与模拟器(你会频繁用)
命令行工具(必须熟)
ros2 node list / info
ros2 topic list / echo / hz / bw
ros2 service list / call
ros2 action list / send_goal
ros2 param list / get / set
ros2 bag record / play(录包回放,复现问题神器)
可视化 / 调试
RViz2:看激光点云、地图、TF、路径、代价地图
rqt 系列:rqt_graph 看通信拓扑、rqt_plot 看曲线
仿真
Gazebo:注意“Gazebo Classic 已在 2025-01 EOL”,建议迁移到新 Gazebo(Gazebo Sim)。
这点很关键:很多老教程用 Gazebo 11(Classic),你照着装可能会越走越偏。
8.3 机器人算法与控制模块
这里不只讲“算法名字”,而是讲它们在系统里怎么串起来。
8.3.1 基本运动控制:PID 控制(举 3 个常见例子)
PID 在机器人里无处不在:轮速、角速度、姿态、关节位置、末端力控都能用。
例 1:差速底盘轮速控制
输入:目标轮速 v_ref
测量:编码器反馈 v_meas
输出:电机 PWM / 电流给定
难点:编码器噪声、死区、低速爬行、负载变化
常见工程做法:
速度环 PID + 前馈(加速度前馈能明显改善跟随)
输出限幅、防积分饱和
低速段做摩擦补偿(或者设定最小驱动)
例 2:云台/小机械臂关节位置控制
输入:目标角度
测量:编码器角度
输出:驱动器位置/速度指令
工程上常见是“位置环 + 速度环 + 电流环”(电流环多在驱动器内部)。
例 3:沿墙/循线控制
输入:期望距离/轨迹
测量:侧向雷达距离/视觉偏差
输出:角速度 w
这类 PID 的关键不是公式,而是测量信号滤波与控制频率。
8.3.2 路径规划(把它拆成“全局 + 局部 + 控制”)
以移动机器人为例,一个成熟框架通常分三层:
全局规划:从 A 到 B,在地图上找一条总体可行路径(A*、Dijkstra 等)
局部规划/避障:考虑动态障碍、代价地图、机器人运动学约束(DWB、TEB 思路等)
轨迹跟踪控制:把局部轨迹变成底盘速度指令(Pure Pursuit、MPC、PID 等)
一个非常典型的 ROS 2 组合是:SLAM/定位 + Nav2(导航) + ros2_control(控制)
你可以把它理解为“软件架构模板”。
8.3.3 高级算法:SLAM、视觉识别、物体抓取(讲清楚系统链路)
A. SLAM(同步定位与建图)
SLAM 的输入通常来自:
LiDAR(2D/3D)
里程计(轮编码器)
IMU
输出通常是:
机器人位姿(pose)
地图(栅格/点云)
TF:map -> odom -> base_link
例:仓储 AMR 的常见 SLAM 链
雷达 scan + 里程计 odom + IMU imu
→ SLAM 节点
→ 输出 map 与 pose
→ Nav2 做导航
→ 控制器输出 cmd_vel
→ 底盘驱动执行
踩坑点(非常常见):
里程计时间戳不准、TF 断链
雷达安装角度导致数据畸变
IMU 未做重力方向校准,融合漂移
B. 视觉识别(检测/分割/定位)
视觉链路通常是:
相机驱动 → 图像话题 → 预处理(畸变校正/同步) → 模型推理(检测/分割) → 位姿估计(PnP/深度) → 发布目标位姿
例:产线抓取的“视觉 + 坐标标定”
相机识别出工件在图像坐标中的位置
通过相机标定 + 手眼标定,转换到 base_link 或机械臂基座坐标
MoveIt2 做规划,生成轨迹
执行器执行抓取
C. 物体抓取(MoveIt2 + 控制 + 传感)
抓取不是“规划一次就完事”,实际项目更像:
视觉给粗定位
机械臂接近
力/触觉做最后的对接与插入(比如插接件、装配)
8.4 开发与调试工具
8.4.1 ROS 中调试与测试的“实战套路”
遇到“机器人不动/乱动/偶发问题”,建议按这个顺序排:
第一步:拓扑是否对?
rqt_graph 看节点之间是否连上
有没有发 cmd_vel?有没有订阅它的底盘节点?
第二步:数据是否在跑?频率对不对?
ros2 topic echo 看值是否合理
ros2 topic hz 看频率是否稳定(控制回路很怕抖)
第三步:坐标系是否对?
RViz2 看 TF 树是否完整
典型:map -> odom -> base_link -> laser
第四步:录包复现
ros2 bag record 把关键话题录下来
线下回放定位问题:是感知错、规划错、还是控制错
第五步:QoS 与网络
ROS 2 在不同网络、不同 QoS 下表现差异很大。多机通信时尤其要注意 QoS 不匹配会“看得到话题但收不到数据”。
8.4.2 模拟环境:如何使用 Gazebo 做机器人模拟(你该怎么选)
旧教程常见 Gazebo Classic(Gazebo 11),但它已在 2025 年后进入 EOL 状态,官方也强调迁移到新 Gazebo(Gazebo Sim)。
仿真里你通常会做三件事:
放入机器人模型(URDF/SDF)
接上传感器插件(雷达/相机/IMU)
接上控制接口(差速、四轮、机械臂关节)
强烈建议新手的训练路径
先只仿真底盘:cmd_vel → 机器人移动
再加雷达:能在 RViz2 看到 scan
再跑 SLAM:能出地图
最后上 Nav2:能点目标导航
每一步都能闭环验证,不要一口气全装上。
8.5 机器人硬件与 ROS 的集成
8.5.1 把硬件连上 ROS:常见架构(最清晰的分层)
建议你按“分层”设计,后期维护会轻松很多:
硬件层:电机、驱动器、编码器、IMU、雷达、相机
驱动层(ROS Driver):把硬件数据变成 ROS 消息/话题
中间层:滤波、融合(EKF)、TF、状态机
能力层:SLAM、定位、规划、抓取
应用层:任务逻辑、调度、人机交互、云端
这样做的好处:换硬件时通常只改“驱动层 + 少量参数”。
8.5.2 实际操作:控制机器人运动与任务执行(给你两个可落地例子)
例 1:移动底盘从“能跑”到“能导航”
目标:你在 RViz2 里点一个目标点,机器人自己走过去。
你需要把链路打通:
底盘驱动节点:订阅 cmd_vel,发布 odom
传感器驱动:发布 scan、imu
TF:odom -> base_link(来自里程计),base_link -> laser(静态标定)
融合:用 EKF 融合 odom + imu(让姿态更稳)
SLAM/定位:出 map 与 map->odom
Nav2:接收目标点,输出 cmd_vel
常见问题与快速定位:
不动:先看 cmd_vel 是否有、底盘是否订阅到
原地打转:TF 方向错(雷达/底盘坐标轴反了非常常见)
地图漂:里程计/IMU 时间戳、参数、安装角度问题
例 2:机械臂执行“识别-抓取-放置”
目标:相机识别工件,机械臂抓起来放到指定区域。
链路如下:
相机驱动发布图像
视觉节点输出目标位姿(在相机坐标系)
标定节点提供 camera -> base 的变换
MoveIt2 规划:从当前姿态到抓取姿态,再到放置姿态
控制执行:ros2_control 下发关节轨迹到驱动器
夹爪控制:service/action 控制开合
可选:力矩传感器做接触检测(插装/压装更可靠)
如果你希望“更像能直接上手的课”,我也可以把这一课补成一个“完整小项目模板”版本:
目录结构(src 放哪些包)
每个包负责什么
关键话题/TF/参数清单
最小可运行 demo(先仿真、再真机)