本文是独立成篇的 ROS2 笔记,涵盖从命令行到仿真的全链路。建议配合 Ubuntu 22.04 + Humble 食用。
1. 什么是 ROS2?为什么要用它?
ROS 全称 Robot Operating System,它不是传统意义的操作系统(像 Linux/Windows),而是一套运行在 Linux 上的机器人软件框架:
硬件抽象:屏蔽雷达、摄像头、IMU、电机驱动的底层差异
中间件:提供标准化的节点间通信(类似你之前学的 MQTT,但更强大)
工具链:调试、可视化(RViz2)、仿真(Gazebo)、录包(bag)
算法库:导航 Nav2、建图 SLAM、MoveIt2 机械臂规划,开箱即用
不用 ROS2 的痛点:
假设机器人有 3个模块:激光雷达、摄像头、底盘控制,由3个团队开发。
没 ROS2:雷达团队写个 socket 发数据,摄像头团队写个串口,底盘团队写个 CAN,接口对不上,联调地狱。
有 ROS2:大家都说Topic普通话,雷达发
/scan,导航订阅/scan,底盘订阅/cmd_vel,即插即用。
2. ROS1 vs ROS2:一次颠覆性的重构
| 特性 | ROS1 (Noetic) | ROS2 (Humble/Iron) |
|---|---|---|
| 核心架构 | 中心化,必须有一个roscore / Master节点,Master挂了全挂 | 去中心化,无Master,基于 DDS 自动发现,无单点故障 |
| 通信中间件 | 自定义 TCPROS/UDPROS | DDS 标准(工业级,航空/国防在用) |
| 实时性 | 弱,TCP延迟不可控 | 强,DDS 可配置 QoS 实时策略 |
| 跨平台 | 主要 Linux | Linux/Windows/macOS/RTOS |
| 构建系统 | catkin | ament + colcon |
| Python | Python2 | Python3 |
| 节点生命周期 | 无,节点启动即运行 | 有,可配置 unconfigured/inactive/active/shutdown,适合产品 |
| 安全性 | 无加密 | SROS2支持认证加密 |
一句话总结:ROS1 是实验室玩具,ROS2 是能上产线的商业系统。
3. ROS2 架构:五层分层模型
从底到顶:
DDS层 (Data Distribution Service):厂商实现,Fast DDS(默认)、CycloneDDS、Connext。负责真正的网络传输,UDP多播/单播、共享内存。
RMW层 (ROS Middleware Interface):抽象层,把不同厂商 DDS API 统一成一套标准接口
rmw_*。好处:今天用 Fast DDS,明天切 CycloneDDS,代码一行不改。RCL层 (ROS Client Library):C语言实现的
rcl,封装节点、话题、服务等核心概念。客户端库层:
rclcpp(C++)、rclpy(Python)、rcljava(Java) 等,面向开发者。应用层:你的节点、Nav2、MoveIt2。
所以 ROS2 删除 Master 后怎么发现彼此?
靠 DDS 的SPDP + SEDP自动发现:
新节点上线,DDS 向
239.255.0.1多播发广播:我来了,我有/scan发布器。其他节点收到,回复我是谁我有什么订阅。
两边 QoS 兼容,则建立 P2P 直连,后续不经过任何中心。
4. 五大核心通信机制(嵌入式类比秒懂)
对于 STM32 开发者,用 FreeRTOS 类比:
| ROS2组件 | FreeRTOS类比 | 核心功能 | 通信模式 | 典型场景 |
|---|---|---|---|---|
| 节点 Node | 任务 Task | 最小功能单元 | - | 激光驱动、电机控制、路径规划各一个节点 |
| 话题 Topic | 消息队列 + 串口广播 | 连续数据流 | 异步、多对多 | 雷达发/scan,相机发/image_raw,底盘发/odom |
| 消息 Message | struct 结构体 | 数据格式定义 | - | geometry_msgs/Twist速度,sensor_msgs/LaserScan雷达 |
| 服务 Service | 函数调用 + 问答 | 一次性远程调用 | 同步、一对一 | 拍照、查询电量、重置里程计 |
| 动作 Action | 状态机 + 带反馈任务 | 长时间可取消任务 | 异步 + 反馈 | 导航到目标点NavigateToPose,可中途取消,看进度 |
| 参数 Parameter | Flash配置 + 全局变量 | 节点动态配置 | - | PID增益、最大速度,不重启即可修改 |
4.1 话题 Topic(最常用,80%场景)
publisher_node -- /scan (sensor_msgs/LaserScan) --> subscriber_node(s)
特点:解耦,发布者不知道谁在听,订阅者不知道谁发的。
4.2 服务 Service
客户端发 Request,等待服务端 Response。同步阻塞,但 ROS2 中是异步回调,不会卡死。
/client 请求 "计算路径" -> /planner 服务端 -> 返回路径
4.3 动作 Action(服务+话题的合体)
处理3秒以上的长任务:导航、机械臂抓取。
包含3部分:Goal目标 + Feedback周期反馈 + Result最终结果,且可取消。底层由3个话题+2个服务实现,但对你透明。
4.4 参数 + QoS
参数:
ros2 param set /turtlesim background_r 128动态改背景颜色,无需重启。QoS:可靠性 RELIABLE / BEST_EFFORT,历史 KEEP_LAST,持久性 TRANSIENT_LOCAL 等,可针对雷达/图像/控制指令精细配置。
4.5 ROS2命令行操作
ROS2 90%的调试都靠命令行,掌握它就掌握了机器人的控制台。
| 命令族 | 常用命令 | 作用 |
|---|---|---|
ros2 node | list,info /turtlesim,kill | 查看/杀死节点 |
ros2 topic | list -t,echo /scan,hz /scan,bw,pub /cmd_vel ... | 调试连续数据流,最常用 |
ros2 service | list -t,call /spawn ...,type,find | 调用一次性服务 |
ros2 action | list,info /navigate_to_pose,send_goal | 调试导航等长任务 |
ros2 param | list,get /node param,set,dump/load | 动态改参,运行时调PID |
ros2 interface | show geometry_msgs/msg/Twist,list,proto | 查看消息结构 |
ros2 bag | record -a,play,info | 录包回放,复现偶发Bug |
ros2 run | run turtlesim turtlesim_node | 运行单个节点 |
ros2 launch | launch nav2_bringup bringup_launch.py | 一键启动多节点 |
colcon | colcon build --symlink-install,--packages-select | 编译工作空间 |
实战口诀:
# 不知道有什么? ros2 topic list -t # 看话题 ros2 node list # 看节点 ros2 service list # 看服务 # 不知道数据格式? ros2 interface show sensor_msgs/msg/LaserScan # 看数据流是否正常? ros2 topic echo /scan --no-arr # 不打超长数组 ros2 topic hz /scan # 看雷达频率是不是10Hz
5. ROS2开发环境配置
推荐组合:Ubuntu 22.04 + ROS2 Humble Hawksbill,LTS到2027年,最稳。
5.1 一键安装
sudo apt update && sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 sudo apt install software-properties-common -y sudo add-apt-repository universe sudo apt install curl gnupg lsb-release -y sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null sudo apt update sudo apt install ros-humble-desktop -y # 桌面完整版,含RViz2+Gazebo+示例 sudo apt install python3-colcon-common-extensions python3-rosdep ros-dev-tools -y # 环境变量 echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc source ~/.bashrc # 初始化 rosdep sudo rosdep init || true rosdep update
5.2 多机隔离与工具
# 多机器人同WiFi防串台 export ROS_DOMAIN_ID=10 # 0~101,同一ID才能互通 # VSCode插件:ROS, URDF, 记得装 # Docker版(Windows/Mac用户) docker pull osrf/ros:humble-desktop验证:
ros2 run demo_nodes_cpp talker & ros2 run demo_nodes_py listener # 看到 hello world 互通即成功
6. 工作空间与功能包:开发过程的大本营
工作空间 Workspace是项目的物理边界。官方推荐~/ros2_ws。
四个子目录:
src:放所有功能包源码,git clone都在里build:colcon 编译中间文件,不用管install:编译产物,setup.bash在这log:编译日志
功能包 Package是最小复用单元。包含package.xml(依赖声明)+CMakeLists.txt(C++) 或setup.py(Python) + 代码。
mkdir -p ~/ros2_ws/src && cd ~/ros2_ws/src # 创建C++包 ros2 pkg create my_cpp_pkg --build-type ament_cmake --dependencies rclcpp std_msgs # 创建Python包 ros2 pkg create my_py_pkg --build-type ament_python --dependencies rclpy std_msgs # 创建带消息定义的包 ros2 pkg create my_interfaces --build-type ament_cmake --dependencies rosidl_default_generators cd ~/ros2_ws rosdep install -i --from-path src --rosdistro humble -y colcon build --symlink-install source install/setup.bash
--symlink-install对Python极其重要,改.py不用重编,直接运行。
7. 节点:机器人的工作细胞
节点 Node 是 ROS2 最小执行单元,一个独立进程,只做一件事。
import rclpy from rclpy.node import Node class MyNode(Node): def __init__(self): super().__init__('my_first_node') # 节点名唯一 self.get_logger().info('Hello, 我是工作细胞!') self.timer = self.create_timer(1.0, self.tick) def tick(self): self.get_logger().info('心跳...') def main(): rclpy.init() rclpy.spin(MyNode()) # 阻塞,处理回调 rclpy.shutdown()节点生命周期(ROS2 独有,产品级必用):unconfigured -> inactive -> active -> finalized,可通过生命周期管理器lifecycle_manager统一配置,机器人启动时先加载参数,再激活。
8. 话题:节点间传递数据的桥梁
话题 Topic 是异步、多对多广播,最常用。
/demonstration Publisher ---(/cmd_vel, geometry_msgs/Twist)---> Subscriber(s)
Python 发布者:
self.pub = self.create_publisher(Twist, '/cmd_vel', 10) msg = Twist() msg.linear.x = 0.2 self.pub.publish(msg)
订阅者:
self.sub = self.create_subscription(LaserScan, '/scan', self.scan_callback, 10) def scan_callback(self, msg): print(f'最前面障碍物距离: {msg.ranges[0]}')命令行调试:
ros2 topic list -t ros2 topic echo /turtle1/pose ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.5}}" -1QoS 可选RELIABLE/BEST_EFFORT,雷达用 BEST_EFFORT 少延迟,控制指令用 RELIABLE 保到达。
9. 服务:节点间的你问我答
服务 Service 是同步一对一请求响应,类似函数调用。
Client ---(Request: 拍照请求)---> Server Client <---(Response: 照片结果)--- Server
turtlesim 典型服务:
ros2 service list ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: 'turtle2'}"代码:
from turtlesim.srv import Spawn self.client = self.create_client(Spawn, '/spawn') req = Spawn.Request(x=2.0, y=2.0, name='t2') future = self.client.call_async(req) rclpy.spin_until_future_complete(self, future)
适用:重置里程计、保存地图、触发拍照等只需执行一次的任务。
10. 通信接口:数据传递的标准结构
所有话题/服务/动作的数据类型都有标准定义,放在msg/srv/action文件中。
Message (.msg):话题载体
# Twist.msg Vector3 linear Vector3 angularService (.srv):请求---响应
# AddTwoInts.srv int64 a int64 b --- int64 sumAction (.action):目标---结果---反馈
# Fibonacci.action int32 order # Goal --- int32[] sequence # Result --- int32[] partial_sequence # Feedback
自定义接口:
# my_interfaces/msg/Student.msg string name int32 age # CMakeLists.txt rosidl_generate_interfaces(${PROJECT_NAME} "msg/Student.msg" "srv/AddTwoInts.srv" )
ros2 interface show就能看到。
11. 动作:完整行为的流程管理
Action = Service(可取消) + Topic(周期反馈)。处理长时间任务:导航、机械臂执行。
Client --Goal--> Server (开始去(2,2)) <--Feedback-- (已走30%) <--Feedback-- (已走80%) --Cancel--> (用户中途取消) <--Result-- (成功/失败/取消)
命令行:
ros2 action list ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose "{pose: {pose: {position: {x: 2, y: 2}}}}"Nav2 导航就是一个 Action Server,RViz2 点目标点就是 Client。
12. 参数:机器人系统的全局字典
参数 Parameter 是节点的可动态配置变量,无需重启。
self.declare_parameter('kp', 1.0) kp = self.get_parameter('kp').value # 支持回调,参数一改,控制立刻生效 self.add_on_set_parameters_callback(self.param_callback)命令行:
ros2 param list ros2 param get /turtlesim background_r ros2 param set /turtlesim background_r 200 ros2 param dump /turtlesim > params.yaml ros2 param load /turtlesim params.yaml
应用:现场调小车最大速度、PID增益、相机曝光,直接param set,不用重新编译烧录。
13. 分布式通信:多计算平台的任务分配
ROS2 原生支持分布式:
机器人端:Jetson Orin 跑激光+相机驱动
PC端:高性能主机跑建图、Nav2导航
只要同一局域网,同一
ROS_DOMAIN_ID,同一WiFi,节点自动发现,话题互通。
# 机器人端(192.168.1.10) export ROS_DOMAIN_ID=42 ros2 run rplidar_ros rplidar_composition # PC端(192.168.1.20) export ROS_DOMAIN_ID=42 ros2 topic echo /scan # 就能收到机器人雷达 rviz2 # 就能可视化
比 ROS1 需要ROS_MASTER_URI配置简单太多。
进阶:DDS支持跨广域网、SROS2加密,适合车队。
14. DDS:机器人的神经网络
DDS 是 ROS2 的底座,工业级标准。
Domain:逻辑隔离域,
ROS_DOMAIN_ID就是 DDS Domain ID。Participant:每个进程一个 Participant。
Topic + DataWriter/DataReader:底层真正收发。
QoS策略:
Reliability: RELIABLE/BEST_EFFORT
Durability: VOLATILE/TRANSIENT_LOCAL(新订阅者能否收到历史)
History: KEEP_LAST depth
RMW:ROS中间件接口层,抽象不同厂商 DDS。切换实现:
# 默认 Fast DDS export RMW_IMPLEMENTATION=rmw_fastrtps_cpp # 换 CycloneDDS,更轻量 sudo apt install ros-humble-rmw-cyclonedds-cpp export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
理解 DDS,调透 QoS,是解决图像卡顿、控制丢包的关键。
15. Launch:多节点启动与配置脚本
机器人启动要启动 10+ 节点:雷达、IMU、底盘、TF、RViz...一个个ros2 run会累死,Launch 一键搞定。
ROS2 Launch 是 Python 脚本,比 ROS1 XML 强大百倍,支持 if 判断、变量。
# my_robot/launch/robot.launch.py from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node(package='rplidar_ros', executable='rplidar_composition', parameters=[{'serial_port': '/dev/ttyUSB0', 'frame_id': 'laser'}]), Node(package='my_robot', executable='base_driver', output='screen'), Node(package='tf2_ros', executable='static_transform_publisher', arguments=['0','0','0.2','0','0','0','base_link','laser']), Node(package='rviz2', executable='rviz2', arguments=['-d', 'my.rviz']) ])运行:ros2 launch my_robot robot.launch.py带参:ros2 launch my_robot robot.launch.py use_sim_time:=true
16. TF:机器人坐标系管理器
机器人有无数坐标系:map地图、odom里程计、base_link底盘、laser雷达、camera_link。TF就是管理它们关系的时变树。
TF 是话题
/tf和/tf_static每个变换都是
父坐标 -> 子坐标 + 时间戳tf2可查询任意时刻任意两坐标系的关系。
ros2 run tf2_ros static_transform_publisher 0 0 0.2 0 0 0 base_link laser ros2 run tf2_tools view_frames # 生成PDF的TF树 rviz2 -> Add -> TF 看坐标轴
代码监听:
from tf2_ros import Buffer, TransformListener self.tf_buffer = Buffer() self.tf_listener = TransformListener(self.tf_buffer, self) trans = self.tf_buffer.lookup_transform('map', 'base_link', rclpy.time.Time())没有 TF,导航、建图全崩。必须保证TF树连通无环。
17. URDF:ROS机器人建模方法
URDF (Unified Robot Description Format) 用 XML 描述机器人连杆 Link + 关节 Joint。
<robot name="my_car"> <link name="base_link"> <visual><geometry><cylinder length="0.1" radius="0.2"/></geometry></visual> </link> <link name="left_wheel"/> <joint name="left_wheel_joint" type="continuous"> <parent link="base_link"/><child link="left_wheel"/> <origin xyz="0 0.2 0"/><axis xyz="0 1 0"/> </joint> </robot>
link:外观visual、碰撞collision、惯性inertialjoint:fixed固定、continuous连续旋转轮子、revolute有限转角舵机、prismatic滑轨Xacro:URDF 宏,支持变量、计算,复杂机器人必用。
sudo apt install ros-humble-joint-state-publisher-gui ros2 launch urdf_tutorial display.launch.py model:=my_car.urdf # 在RViz里拖动滑杆,看关节运动
URDF + TF = 机器人完整数字孪生。
18. Gazebo:三维物理仿真平台
Gazebo 是独立的物理引擎,支持重力、摩擦、碰撞、光照、传感器仿真(雷达噪声、相机畸变)。
Gazebo 负责让机器人动起来,有物理
Rviz 负责把数据画出来,无物理
经典流程:
# 安装 sudo apt install ros-humble-gazebo-ros-pkgs ros-humble-gazebo-ros2-control # 启动仿真 ros2 launch my_robot gazebo.launch.py # 话题桥接:Gazebo的 /clock, /scan 会自动转 ROS2 话题
在URDF里加<gazebo>标签和插件,如libgazebo_ros_diff_drive.so差速驱动,Gazebo就开始仿真轮子转。
价值:无需真机,在仿真中测试 Nav2 算法,撞烂了也不心疼。
19. Rviz:三维可视化显示平台
Rviz2 不模拟,只订阅话题并可视化。
常用 Display:
RobotModel:显示URDF模型LaserScan:雷达点云PointCloud2:3D点云Map:占据栅格地图Path:导航路径TF:坐标系Image:相机图像
rviz2 # Add -> By topic -> 勾选 /scan # 配置文件保存 .rviz,下次一键加载
配合 Nav2,Rviz里可点2D Pose Estimate初始位姿,2D Goal Pose导航目标。
20. RQT:模块化可视化工具
RQT 是基于 Qt 的插件容器,集成几十个小工具:
rqt # 打开插件选择器 rqt_graph # 节点图,最常用,看话题连接(上一章用过) rqt_plot # 画曲线,/odom速度波形 rqt_console # 日志过滤 rqt_reconfigure # 动态调参图形化前端 rqt_bag # 播放 bag 包
安装:sudo apt install ~nros-humble-rqt*
调试三件套:rqt_graph+ros2 topic echo+rviz2。
21. ROS2应用与进阶攻略
到此,你已学完 ROS2 核心。下一步:
应用层
导航 Nav2:
sudo apt install ros-humble-navigation2,SLAM建图slam_toolbox,定位amcl,一键导航。机械臂 MoveIt2:抓取规划。
ros2_control:统一硬件接口,你的 STM32 底盘写一个
hardware_interface,就能被 Nav2 调度。micro-ROS:在 STM32F4/H7 上直接跑 ROS2 节点,不再经串口转发,订阅
/cmd_vel成为真·ROS2节点。
进阶路线图
动手造小车:差速底盘 + RPLIDAR A1 + IMU,跑通
URDF -> Gazebo -> Nav2全流程。视觉:
v4l2_camera+OpenCV+YOLO,话题/image_raw→ 目标检测。多机协同:两台机器人同
ROS_DOMAIN_ID,Nav2支持多机编队。云边端:ROS2 + MQTT桥,机器人数据上阿里云,参考你之前 MQTT 篇。
最终建议:
先把turtlesim + 话题服务玩熟
再用URDF + Rviz搭自己模型
再进Gazebo 仿真 + Nav2 导航
最后接真车
总结
本篇严格目录,独立介绍了 ROS2 的命令行、环境、工程、五大通信、DDS、Launch、TF、URDF、Gazebo、Rviz、RQT。
工具包:Humble官方文档 + 鱼香ROS《ROS2机器人开发从入门到实践》 + 古月居教程