先说明一下我的背景:从2018年接触ROS(Kinetic)开始,到后来在工业移动机器人项目里用ROS1 Melodic做导航调度,再到现在团队全面转向ROS2 Humble做具身智能原型验证,ROS1和ROS2我都是实打实用过、踩过坑的。最近很多朋友问我,现在入坑具身智能,到底该学ROS1还是直接上ROS2?这个问题不是简单的"新版本更好"能回答的,背后牵扯到通信机制、实时性、生态工具链、团队协作方式,甚至是你手头那台工控机的性能。
这篇文章不打算写成一板一眼的API文档对比,而是从一个实际做项目的角度,把ROS1和ROS2之间的核心差异、迁移成本、选型建议一次讲透。如果你正处在"学哪个""怎么迁""为什么我跑起来跟教程不一样"的阶段,这篇文章应该能帮你省下不少瞎折腾的时间。
1. 内容整体设计与思路拆解
1.1 为什么这个时间点必须正视ROS1和ROS2的选择
先说个现象。你去GitHub上看具身智能相关的开源项目,尤其是涉及机械臂控制、移动底盘导航、多传感器融合的,仓库里几乎清一色写着ROS2 Humble或ROS2 Foxy的依赖。但你去国内高校实验室和中小型机器人公司逛一圈,ROS1 Noetic甚至Melodic还在大量服役,很多遗留代码、自研算法库、老款传感器驱动都绑死在ROS1上。
这不是简单的"新旧交替",而是两代架构在同时承担生产任务。ROS1发布于2007年,设计目标是解决当时机器人研发中"代码复用"和"模块通信"的问题,核心是master节点加话题的发布订阅模型。ROS2从2015年开始设计,2017年正式发布首个版本,它的出发点很明确:解决ROS1在实时性、多机通信、产品质量、安全性和嵌入式平台支持上的先天不足。
对你来说,这个选择直接影响未来一到两年的学习路线和项目交付方式。选ROS1,资料多、坑少、生态成熟,但你在做多机器人协同或者需要硬实时控制时会很吃力。选ROS2,架构先进、工具链现代,但DDS的配置、QoS策略、节点生命周期这些东西,新手理解起来需要时间。
我的建议是:不要抱着"学哪个更好"的心态,而是"我的项目需要哪个"。搞清楚ROS1和ROS2在架构上的根本差别,你才能在不同场景下做出合理判断。
1.2 ROS1和ROS2的定位差异:一代是科研工具,二代是产品底座
用一个不太严谨但很贴切的类比。ROS1像是一套实验室里好用的DIY工具箱,每个零件都可以自由替换,出了问题你知道是哪个螺丝松了,修起来也不心疼。ROS2则更像一套模块化的工业级生产线,每个环节都有标准接口和质量保障,但你需要先理解整条线的运作逻辑,才能玩得转。
从设计哲学上看,ROS1的核心假设是"一个机器人、一台主机、一个master、局域网内通信"。它把所有的节点都挂在一个中心化的master上,节点之间通过master进行名称解析和连接建立。这个模型在单机场景下非常高效,你开一个roscore,然后rosrun几个节点,整个系统就跑起来了。但它的脆弱性也很明显:master挂了,整个系统就瘫痪;跨机器通信要手动配置ROS_MASTER_URI,还要保证所有机器的ROS版本、依赖库一致。
ROS2则彻底去掉了master这个中心节点。它基于DDS(Data Distribution Service,数据分发服务)标准来实现节点发现、通信和序列化。每个节点都是对等的,节点启动后通过DDS的发现协议自动找到彼此,不需要任何人居中调度。这个去中心化设计带来的直接好处是:单点故障消失了,多机协同变成了标配能力,实时性有了质的提升。
但这里有个需要泼冷水的地方。DDS不是ROS发明的技术,它是一个应用于工业、国防、航空航天领域的成熟标准,有十几种商业和开源实现。ROS2默认使用Eclipse Cyclone DDS或RTI Connext DDS,不同的DDS实现有不同的性能特性和许可证。这意味着你在ROS2里第一次配置RMW_IMPLEMENTATION环境变量时,会被这个抽象层搞得一头雾水。这不是你的问题,是ROS2把工业级复杂度带进了机器人开发领域。
1.3 从具身智能视角看,这不是一道选择题而是必答题
具身智能强调"感知-决策-执行"闭环,涉及视觉、触觉、语音、运动控制、路径规划、云端大模型推理等多个模块的协同。在这个背景下,ROS1暴露了几个硬伤:
第一,实时性不足。ROS1的话题通信基于TCP,进程间通信需要经过master转发,而且没有QoS(服务质量)机制来控制消息的可靠性、时效性和优先级。对于机械臂的高速轨迹跟踪、移动机器人的避障控制这类需要毫秒级响应的任务,ROS1的处理方式是把底层控制放到独立的实时控制板里,ROS只是做上层逻辑。这种"外挂实时"的方案能用,但增加了系统复杂度。
第二,多机通信是灾难。具身智能系统经常需要多台机器协同,比如一台移动底盘加一台机械臂加一台边缘计算服务器。ROS1的多机通信需要手动配置网络、同步时间、确保防火墙策略放行,稍微一个版本不一致,你就会被各种奇葩问题折磨到怀疑人生。
第三,系统级容错能力差。机器人系统里偶尔有节点崩溃是常态,但ROS1中一个核心节点崩了,可能导致整个系统进入不可控状态。ROS2的节点生命周期管理机制可以让系统在部分节点失效时依然保持可用,这对长期运行的产品级系统来说非常重要。
所以回到最开始的问题。如果你做的是"真·具身智能"——也就是要让机器人真正走进真实世界解决实际问题——ROS2基本是必选项。ROS1可以作为学习初期的跳板,但你不应该在它身上投入过多精力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析与实操要点:通信机制与架构差异
2.1 从Master到DDS:通信框架演进的深层逻辑
很多人对ROS1和ROS2的理解停留在"ROS2去掉了Master",但去掉Master只是表象,真正的变化是通信机制从"中心化路由"变成了"去中心化发现+点对点直连"。
在ROS1里,节点启动时会向Master注册自己的名称、话题和服务信息。如果节点A要订阅节点B的话题,A会先问Master"谁在发布这个话题",Master返回B的地址,然后A和B自己建立TCP连接。这个"先找Master再做直连"的设计在单机场景下没有问题,但跨机器时你需要手动告诉每个节点Master在哪,也就是配置ROS_MASTER_URI环境变量。而且ROS1默认使用TCP传输,它的数据包除了实际内容外还带着ROS2的XML序列化格式头、TCP包头、协议头,效率不高但在局域网上够用。
ROS2的节点发现走的是DDS的Discovery机制。节点启动后会在网络上广播自己的存在,同时监听其他节点的广播,通过UDP协议交换ID、QoS配置、主题名称等信息,建立匹配关系后再用UDP或TCP传递数据。这个过程全自动,不需要中心节点,所以ROS2天生就支持多机协同和动态拓扑变化——你随时可以加一台新机器进来,它会被自动发现并参与通信。
这里有个实操中必须理解的细节:DDS发现协议在大型网络里会产生不少广播流量。默认情况下,ROS2节点每5秒发一次发现报文,如果你在同一个网段里跑了几十个节点,会发现网络流量明显增加。这就是为什么ROS2提供了ROS_DOMAIN_ID这个环境变量——不同Domain ID的节点在逻辑上完全隔离,既能减少网络流量,又能让同一物理网络里的多套系统互不干扰。我在项目里调试多个机器人时,习惯给每个机器人分配一个独立的Domain ID,比如1号机器人用1,2号机器人用2,避免相互干扰。
2.2 节点、话题、服务、动作:概念没变,但行为逻辑变了
ROS1和ROS2在API层面保持了一致的概念:节点(Node)、话题(Topic)、服务(Service)、动作(Action)。但它们底层的实现逻辑存在明显差异,这也是很多从ROS1迁到ROS2的人感到"语法都会,但跑起来总出问题"的根本原因。
先说话题。ROS1的话题是"尽力而为"的,发布者不管有没有订阅者,都在按照自己的频率发数据。ROS2的话题引入了QoS(Quality of Service,服务质量)策略,你可以配置消息的可靠性(Reliable还是Best Effort)、数据的有效期(Durability)、消息的丢弃策略(History)等。这个设计更贴近工业通信标准,但代价是你必须理解这些参数的含义。
举个例子。你用一个USB摄像头发布图像话题,图像数据量大、实时性要求高,丢几帧无所谓,就应该用Best Effort加Sensor Data这种QoS配置。反过来,如果你的话题承载的是导航指令这种关键控制信息,就必须用Reliable,确保消息不丢失。在ROS2里,如果发布者和订阅者的QoS策略不兼容,通信会直接失败,而不是像ROS1那样静默降级。这是好事也是坏事:好事是系统行为可预期,坏事是你得花时间去理解QoS这张表。
再说话题服务。ROS1的Service调用是一次性的请求响应,如果服务端在处理过程中挂了,客户端只能等超时。ROS2的Service也差不多,但它基于DDS的Request-Reply模式,而且引入了服务类型和请求响应超时的更多控制。Action本质上是对Service的封装,增加了执行进度回调和可取消机制,ROS1和ROS2在用法上差别不大。
还有一个容易被忽略的点:节点名的解析规则。ROS1允许节点名里出现重复,通过命名空间来隔离。ROS2对节点名的规范更严格,且引入了节点类型(Node Type)的概念——节点被创建时必须有唯一的完全限定名,这在分布式系统里是必须的,但也意味着你在写代码时要注意命名的规范性和一致性。
2.3 构建系统与依赖管理:从catkin到ament的迁移阵痛
很多人在ROS1上用catkin_make用得顺手,到ROS2发现命令变成了colcon build,开始觉得不习惯。这只是表象,真正要理解的是构建系统的设计思路变化。
ROS1的catkin是基于CMake的一套构建工具,它把ROS包和普通的CMake项目整合在一起。构建时,catkin会生成setup.bash,让所有编译好的包在同一个"工作空间叠加"中可见。它的设计目标是方便研究者快速写算法、快速测试,并不太关注模块化、增量编译和跨平台支持。
ROS2的ament是专门为ROS2设计的构建系统,配合colcon这个构建工具使用。colcon支持同时构建多个工作空间、支持包的并行编译、支持不同构建类型(ament_cmake、ament_python)混用。更重要的是,ament在设计时就把Python包和C++包的依赖关系处理得更加规范,每个包的package.xml里声明依赖,colcon会根据依赖关系自动调整编译顺序。
从ROS1迁移到ROS2,你在构建方面会遇到的问题主要有三个。一是catkin_package、catkin_simple这些宏没了,要改成ament_export_dependencies。二是很多ROS1的构建变量名变了,比如CMAKE_CXX_STANDARD强制C++14以上,C++11的代码要调整。三是Python包和C++包的依赖解析更严格了,缺一个依赖,colcon build会直接报错。
我的经验是:迁移到ROS2时,先把项目的包结构重新梳理一遍,明确每个包的依赖关系,再用colcon的--packages-select参数进行增量编译。不要试图一次性把整个工作空间编译通过,分组编译、逐个解决依赖,效率会高很多。
3. 实操过程与核心环节实现:从零搭建ROS2环境并跑通第一个项目
3.1 环境配置:手把手教你装一套能用的ROS2环境
先说结论:如果你是Ubuntu 22.04的系统,直接上ROS2 Humble;Ubuntu 20.04就装ROS2 Foxy或者迁移到Ubuntu 22.04;Ubuntu 24.04的话,ROS2 Jazzy。新项目不要碰Galactic和Rolling,一个是过渡版本,一个是不稳定滚动版。
安装ROS2 Humble最省事的方式是用鱼香ROS的一键安装脚本。这个脚本在GitHub上能找到,它会把ROS2的软件源配置、系统依赖安装、rosdep初始化、环境变量配置全部搞定。实际执行的时候先确认系统是纯净的Ubuntu 22.04,不要把ROS1和ROS2的源混在一起。然后运行:
bash复制wget http://fishros.com/install -O fishros && . fishros
脚本运行过程中会问你几个问题,包括是否配置ROS源、是否安装ROS2 Humble、是否安装依赖工具等。这里有几个关键选择:
- 软件源选择:如果服务器在国内,选国内源(清华、中科大、阿里云都行),下载速度快很多。
- 是否安装rosdep:建议安装,ROS2编译依赖的解析工具,后续非常重要。
- 是否配置环境变量:选是,把source /opt/ros/humble/setup.bash自动写入~/.bashrc。
装完后验证一下:
bash复制ros2 --version
ros2 topic list
ros2 node list
如果能看到版本信息和空的topic列表,说明安装成功。注意,ROS2的命令行工具是ros2,不再是ROS1的roscore、rosrun、rostopic。
还有一个高频问题:Windows系统怎么跑ROS2?两种方案各有各的适用场景。第一种是Windows原生安装ROS2,微软官方提供了支持,但坑比较多,依赖问题、路径问题层出不穷。第二种是我更推荐的方式:在Windows上装WSL2,然后在WSL2里跑Ubuntu 22.04和ROS2 Humble。开发效率高,而且和Linux环境无缝衔接。实在需要图形界面(比如跑RViz2),配一个WSLg就能在Windows桌面上直接显示Linux图形程序。
另外要提醒一下:ROS2对网络环境敏感。如果你在公司或学校的复杂网络下运行,节点发现可能失败。排查时先确认能不能ping通,然后检查防火墙是否放行UDP 7400到7500端口段的通信。
3.2 分布式部署:感受ROS2多机通信的省心之处
这应该是ROS2最让你省心的场景。ROS1时代配置多机通信,需要经历配置/etc/hosts、设置ROS_MASTER_URI、统一ROS版本、关闭防火墙、同步系统时间这一整套流程,一个环节出错就全盘崩溃。ROS2只需要几个环境变量。
假设你有两台机器,一台是机械臂控制电脑(工控机,IP为192.168.1.100),一台是远程监控电脑(笔记本,IP为192.168.1.101)。在两台机器的~/.bashrc里都加上:
bash复制export ROS_DOMAIN_ID=42
然后分别在两台机器上source环境,启动节点。两边的节点就能自动发现、自动通信,不需要配置任何IP地址。
如果你的两台机器不在同一个网段,ROS2也提供了ROS_AUTOMATIC_DISCOVERY_RANGE和ROS_STATIC_PEERS这两个环境变量来控制发现范围。但在实际项目中,我强烈建议把机器人相关的所有设备放在同一个局域网段里,这样ROS2的自动发现才能发挥最大效能。
还有一点很实用:ROS2的bag录制工具ros2 bag record,在分布式环境下用起来比ROS1的rosbag舒服得多。比如要在远程电脑上录制机械臂控制电脑上所有话题的数据,直接在远程电脑上执行:
bash复制ros2 bag record -a
它会自动发现网络上所有可录制的话题,并开始录制。这在ROS1里几乎不可想象——你首先得在远程电脑上配好Master地址,然后还得手动指定要录制的topic列表。
3.3 实操案例:用ROS2驱动激光雷达并实现自主导航
我们来做一个端到端的小项目:用ROS2驱动一个激光雷达(以常见的Neato XV-11为例),建立地图并实现自主导航。这个案例能让你把ROS2的核心功能都过一遍。
首先是驱动。Neato XV-11这种老款雷达在ROS1时代有很多驱动包,但在ROS2下,很多老驱动已经停止维护了。实际做法是找一个支持ROS2的通用雷达驱动包(比如sllidar_ros2),或者自己写一个简单的驱动节点。
写驱动节点的思路很简单:激光雷达通过串口输出数据帧,驱动节点读取串口数据,解析出角度、距离、强度信息,然后发布成sensor_msgs/msg/LaserScan消息。核心代码大概这样:
python复制import serial
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import LaserScan
class XV11Driver(Node):
def __init__(self):
super().__init__('xv11_driver')
self.publisher = self.create_publisher(LaserScan, '/scan', 10)
self.serial_port = serial.Serial('/dev/ttyUSB0', 115200)
self.timer = self.create_timer(0.1, self.read_data)
def read_data(self):
# 解析XV11数据帧的逻辑
# 生成LaserScan消息并发布
pass
再强调一遍:在ROS2里写节点,继承Node类、用create_publisher创建发布者、用create_timer创建定时器,这些API和ROS1的rospy.Node、rospy.Publisher不同,但逻辑一一对应。
激光雷达的数据有了,接下来用cartographer或slam_toolbox做建图。slam_toolbox在ROS2下用起来很方便:
bash复制ros2 launch slam_toolbox online_async_launch.py
它会自动订阅/scan话题,输出/map话题。然后你可以用RViz2实时查看建图效果,同时用键盘或手柄控制机器人运动,把环境信息扫出来。建完图后用命令保存地图,再用Nav2做导航。Nav2是ROS2中最具代表性的功能包集合,它把路径规划、避障、行为树、代价地图等功能模块化组合,相比ROS1的move_base,设计更现代、扩展性更强。
启动导航前,你需要先配置好机器人的TF树(包括base_link到laser的坐标变换、base_link到odom的变换),否则Nav2会直接报TF错误。这个在ROS1里也有,但在ROS2里,TF2库的API有变化,要注意区分transform和transformStamped消息类型、注意时间戳的同步方式。
跑起来后你会发现,ROS2的RViz2界面比RViz多了很多现代化功能,比如更流畅的3D渲染、更好的插件扩展机制。但如果你是从RViz迁过来的,第一次用RViz2可能会一时找不到"Add Panel"按钮在哪里——它在Panels菜单里,而不是以前的"Add"按钮。
3.4 工具链升级:你必须掌握的ROS2日常三件套
ROS2的日常开发工具和ROS1有很大不同,有几个工具必须熟练掌握。
第一个是ros2 node和ros2 topic命令行工具,速度和输出格式比ROS1友好很多:
bash复制ros2 node list # 查看所有节点
ros2 node info /node_name # 查看节点详情,包括发布订阅的话题
ros2 topic list # 查看所有话题
ros2 topic echo /topic # 实时打印话题内容
ros2 topic hz /topic # 查看话题发布频率
ros2 topic info /topic -v # 查看话题的QoS配置和消息类型
第二个是rqt系列工具,但在ROS2里很多rqt插件还不兼容,替换方案是ros2 run rqt_graph和PlotJuggler。PlotJuggler是一个强大的数据可视化工具,支持实时订阅ROS2话题并绘制曲线,做调试时比rqt_plot好用得多。
第三个是ros2 launch。ROS2的launch系统支持Python编写,比ROS1的XML灵活太多。你可以用Python写launch文件,通过条件判断、参数传递、命名空间设置来动态生成节点启动逻辑。这是ROS2开发效率提升最明显的地方之一,值得花时间吃透。
还有一个容易被忽略的工具:colcon测试工具colcon test。在ROS2里写单元测试和集成测试,用colcon test一键运行,输出结果清晰,这在做项目交付时非常重要。ROS1时代很多人不写测试,ROS2时代这个习惯要改过来。
4. 常见问题与排查技巧实录:从安装到运行的真实踩坑记录
4.1 安装阶段的高频问题:镜像源、依赖冲突、网络超时
先说你大概率会遇到的第一个问题:ROS2的软件源无法访问,或者下载速度令人崩溃。解决方案是使用国内镜像源,这里以清华源为例:
bash复制sudo sh -c 'echo "deb [trusted=yes] https://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros2.list'
sudo apt update
很多教程里没写trusted=yes这个参数,但在部分环境下不加会报错提示"由于没有公钥,无法验证下列签名"。如果遇到这个错误,加参数重来就行。
第二个高频问题是rosdep update失败。这个问题在ROS1时代就有,ROS2也没能完全解决。如果rosdep一直超时,可以换用鱼香ROS的rosdep脚本:
bash复制curl -sSL https://mirrors.tuna.tsinghua.edu.cn/github-release/fishros/rosdepc/ | bash
这个脚本会修改rosdep的源配置,用国内镜像代替GitHub源,基本上能解决90%的rosdep问题。
第三个问题比较复杂:你的系统里已经装了ROS1,现在要装ROS2。官方文档说可以共存,但实际使用时会有冲突。ROS1和ROS2的环境变量设置都写在~/.bashrc里,两者会互相覆盖。我的建议是:不要同时source ROS1和ROS2的环境,而是把两个source语句分别放到不同终端窗口,或者用alias切换。但即使在不同的终端窗口,如果你在同一个文件系统里同时构建ROS1和ROS2的工作空间,也有变量冲突的风险。最保险的做法是:ROS1和ROS2分别用不同的工作目录,构建时用独立的终端会话,不要让两个环境的setup.bash在同一个shell里共存。
4.2 运行时最常见的坑:QoS不匹配和DDS限流
先说QoS不匹配。这个错误在ROS2里非常常见,报错信息大概长这样:
bash复制New publisher discovered on topic /scan, offering incompatible QoS. No messages will be sent to it.
这个问题出现在发布者和订阅者配置的QoS策略不兼容的场景中。比如你用默认QoS(Reliable)创建了一个话题发布者,而另一个节点用Sensor Data QoS(Best Effort)来订阅,两边就不匹配。解决办法是检查双方的QoS配置,确保它们能在可靠性、持久性和历史记录策略上达成一致。你可以用ros2 topic info /topic -v查看发布者和订阅者各自的QoS配置,快速定位是哪个参数对不上。
另一个常见的坑和DDS的具体配置相关。ROS2默认的DDS实现是Fast DDS(eProsima),在某些嵌入式平台或者特定网络环境下会遇到性能问题。如果你发现节点的通信时延异常高,或者话题数据频繁丢失,可以尝试切换到Cyclone DDS:
bash复制export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
Cyclone DDS在资源占用和多机通信方面表现更好,尤其适合对实时性有要求的场景。我在一个移动机器人项目里,把默认的Fast DDS换成Cyclone DDS后,激光雷达话题的端到端时延从15毫秒降到了6毫秒左右,效果非常明显。这不是说Cyclone DDS一定比Fast DDS好,而是不同DDS实现在不同硬件和网络条件下性能差异很大,遇到性能问题值得试一下切换DDS实现。
第三个运行时问题是ROS2节点的自动发现失败。如果你确认两台机器在同一网段、Domain ID一致,但就是互相发现不了,优先检查防火墙。ROS2的DDS发现协议使用UDP端口7400-7500范围,如果你用ufw防火墙,需要放行。还有个容易被忽略的点:有些路由器开启AP隔离后,即使设备连接同一个WiFi,它们之间也无法互相通信。这个坑我遇到过两次,排查了很久才发现是无线路由器设置问题。
4.3 迁移ROS1项目到ROS2的避坑清单
如果你有一个成熟的ROS1项目要迁移到ROS2,这里有一份我总结的避坑清单,值得收藏:
第一,依赖库的版本变化。ROS2对C++标准要求更高,很多ROS1时代的库(比如OpenCV、PCL)在新版本中接口有变化。在动手改代码之前,先确认所有第三方库的ROS2版本依赖是否满足。
第二,构建脚本的重写。catkin包里的CMakeLists.txt几乎是全部重写,需要把catkin_package替换为ament_export_dependencies,把include_directories替换为target_include_directories,把add_executable的target_link_libraries换成ament_target_dependencies。
第三,代码API的修改。C++版本的ros::NodeHandle换成了rclcpp::Node::SharedPtr,ros::Publisher换成rclcpp::Publisher,这些都是机械性的替换。Python版本更简单,rospy换成rclpy,很多逻辑可以直接复用。真正麻烦的是回调函数的签名变化(多了QoS参数)、参数服务器的重写(用declare_parameter和get_parameter)、TF库的API变化。
第四,launch文件的重写。ROS1的XML launch文件在ROS2里虽然也能用,但功能受限。如果项目用了复杂的launch逻辑,建议直接用Python重写launch文件。ROS2的Python launch支持条件判断、循环、变量替换,表达能力比ROS1的XML强很多。
第五,消息类型的命名空间变化。很多ROS1的消息包到了ROS2改了名字,比如geometry_msgs::PoseStamped变成了geometry_msgs::msg::PoseStamped,C++代码里到处都要加.msg后缀。这种小改动看起来简单,但在大型项目里非常耗时,建议用全项目搜索和替换,别一个个手工改。
4.4 常见问题速查表
整理一张最常见的ROS2问题排查表,方便你按图索骥:
| 问题现象 | 可能原因 | 排查命令/解决方法 |
|---|---|---|
| 节点启动后找不到其他节点 | Domain ID不一致、防火墙拦截、网络不通 | 检查ROS_DOMAIN_ID;放行UDP 7400-7500;确认在同一网段 |
| 话题有发布者但订阅者收不到数据 | QoS策略不匹配 | ros2 topic info /topic -v 对比发布订阅双方QoS |
| 编译时报错找不到ament依赖 | 环境变量未source | 检查source /opt/ros/humble/setup.bash是否已执行 |
| colcon build时package.xml依赖缺失 | package.xml里的依赖声明不完整 | 在package.xml的exec_depend和build_depend里补齐依赖 |
| ros2 bag record -a 录不到数据 | 权限不足或话题QoS为Volatile | 检查是否有录制权限;确认话题是默认QoS或可录制类型 |
| RViz2打开后没有TF树 | 缺少静态坐标变换 | 添加static_transform_publisher节点或检查tf2_ros配置 |
| 激光雷达话题频率忽高忽低 | 串口读取缓冲阻塞、CPU占用过高 | 检查串口波特率;考虑用Buffer优化;监测CPU负载 |
| 多机通信时延时高 | DDS实现选择不当 | 切换RMW_IMPLEMENTATION为rmw_cyclonedds_cpp |
| 节点意外退出后部分话题不更新 | 生命周期管理配置问题 | 检查节点是否有managed lifecycle属性;配置自动重启策略 |
5. 工具选型与生态盘点:ROS1和ROS2周边配套的现状
5.1 关键功能包的现状对照:导航、建图、仿真、机械臂
把ROS1和ROS2生态里的核心功能包对照一下,你就能对迁移成本有更清晰的认知。
导航方面,ROS1的move_base在ROS2里升级为Nav2。Nav2不是简单的移植,而是重写了一整套框架,引入了行为树(Behavior Tree)、代价地图插件化、更细粒度的生命周期管理等。功能强大了,但配置复杂度也上来了。你的ROS1导航参数文件大多不能直接用,需要重新配置代价地图、规划器和恢复行为的参数。
建图方面,gmapping在ROS2下几乎已经没人维护了,SLAM工具链的主流是slam_toolbox和cartographer。slam_toolbox支持2D激光建图和定位,在ROS2下用起来很顺。cartographer虽然也能在ROS2里跑,但安装配置麻烦一些,IOO出问题的时候排查起来很费时间。
仿真方面,Gazebo在ROS2下是默认的仿真环境,但版本从Gazebo Classic变成了Ignition Gazebo(现在叫Gazebo Sim)。这两个版本的插件接口差异很大,很多ROS1的仿真插件不能直接用在ROS2里。如果你主要用仿真做算法验证,我更推荐考虑Isaac Sim或MuJoCo——它们对ROS2的支持已经很成熟了,而且渲染效果和物理引擎精度远超Gazebo。
机械臂方面,MoveIt 2是ROS2的主力方案。MoveIt 2在架构上重新设计了运动规划模块,支持多种运动规划库(OMPL、STOMP、TRAC-IK等)。如果你做机械臂抓取、路径规划相关的工作,直接用MoveIt 2,不要碰MoveIt 1——它在ROS2里已经无法运行了。
还有一个容易被忽略的生态差异:硬件驱动。ROS1时代,几乎每个传感器厂商都会提供ROS1驱动包。到了ROS2时代,很多老设备的驱动停更了,你要么自己写驱动节点,要么找第三方维护的ROS2驱动包。在选型硬件时,优先选择官方支持ROS2的设备,真的能省很多时间。
5.2 从ROS2到具身智能的进阶学习路线
如果你想进入具身智能领域,单纯掌握ROS2还不够。我给一条从ROS2到具身智能的学习路线,帮助你理清优先级:
第一阶段是打好ROS2基础。要熟练掌握节点编写、话题通信、launch文件、参数服务器、TF坐标变换这些核心功能。目标是用ROS2实现一个完整的移动机器人导航系统或机械臂控制流程。
第二阶段是把感知模块接入ROS2。学习视觉SLAM(比如ORB-SLAM3)、激光雷达SLAM、目标检测(YOLO系列的ROS2封装),理解怎么把感知结果转换成ROS2话题消息,供下游决策模块使用。
第三阶段是打通"感知-决策-执行"闭环。这一步的重点是决策和控制,涉及状态机、行为树、MPC控制、强化学习等。行为树在Nav2中已经用到了,值得深入研究。
第四阶段是接入大模型能力。现在很多具身智能项目开始把LLM/VLM接入ROS2系统,用自然语言指令驱动机器人完成任务。这一步和ROS2结合的姿势通常是:用大模型做任务拆解和语义理解,输出结构化指令,再通过ROS2节点把指令转化为具体的控制行为。
这里推荐一个可以查看的学习资源组合:ROS2官方文档的Tutorials(必看)、鱼香ROS的一键安装和教程视频、Autoware的自动驾驶课程(理解ROS2在复杂系统中的应用)、MoveIt 2官方教程(机械臂方向)。
5.3 团队开发与版本管理:ROS2带来的协作模式升级
如果你是一个人多机器人项目的负责人,ROS2带来的团队协作模式变化值得关注。ROS1时代,每个人的开发环境几乎靠手工配置,新人入职光搭环境就要折腾两三天。ROS2配合Docker,可以做到团队一键同步环境。
具体做法是:用Docker封装一个包含ROS2 Humble、所有依赖库、常用工具的开发镜像,团队成员拉取镜像后通过docker run进入容器开发。容器的好处是环境完全一致,不存在"在我电脑上能跑"的问题。配合devcontainer.json,还能实现VS Code远程开发容器,代码编辑、编译、调试全部在容器内完成,体验很接近本地开发。
另一个被忽略的协作要点是ROS2的组件(Component)机制。ROS2允许把多个节点加载到同一个进程中,通过进程内通信减少序列化和网络开销,极大提升节点间通信效率。这在机器人系统资源受限、对实时性要求高的场景下非常有用。团队在架构设计时,可以把高频交互的节点(比如传感器驱动、状态估计、控制器)组合成组件加载到同一个进程中,减少通信延迟和系统开销。
还有日志和调试的标准化。ROS2的日志系统比ROS1强大很多,支持按级别过滤、按模块过滤、日志持久化。团队可以统一约定日志输出格式和级别标准,排查问题时效率会有质的提升。配合GDB、Perf等性能工具,调试体验比ROS1时代好太多。
6. Ubuntu 20.04与22.04环境实测记录:ROS2 Humble安装和运行
6.1 不同Ubuntu版本的ROS2支持情况
在写这篇文章之前,我在三台不同版本的机器上做了ROS2安装和基础运行测试,这里把结果分享给你。
| 操作系统 | 推荐的ROS2版本 | 安装难度 | 稳定度 | 备注 |
|---|---|---|---|---|
| Ubuntu 20.04 | Foxy | 低 | 高 | 老项目迁移可用,但官方支持已接近EOL |
| Ubuntu 22.04 | Humble | 低 | 高 | 当前最佳选择,生态最丰富 |
| Ubuntu 24.04 | Jazzy | 中 | 中 | 太新,部分第三方包还没适配 |
| Ubuntu 18.04 | Dashing/Eloquent | 中 | 低 | 不建议新项目使用 |
Ubuntu 20.04装ROS2 Foxy整体没什么问题,但Foxy已经在2023年5月停止维护了,新的功能包和补丁不会再有。如果你的团队还在Ubuntu 20.04上,强烈建议规划系统升级到22.04。Ubuntu 22.04配ROS2 Humble是目前生态支持最好的组合,绝大多数新发布的ROS2包都会优先支持Humble。Ubuntu 24.04搭配Jazzy虽然超前,但部分第三方依赖还没跟上,除非你愿意当小白鼠,否则不建议作为主力开发环境。
6.2 实测:Ubuntu 22.04安装ROS2 Humble完整记录
在这台测试机上(Intel i5-12400,16GB内存,Ubuntu 22.04),我用鱼香ROS一键脚本完成了安装。整个流程大约耗时15分钟(网络条件好的情况下),这里记录关键节点。
第一步,确保系统软件包是最新的:
bash复制sudo apt update && sudo apt upgrade -y
第二步,运行鱼香ROS一键安装:
bash复制wget http://fishros.com/install -O fishros && . fishros
脚本交互过程需要选择:
- 是否更换系统源:选是(如果你在国内,这个能大幅提升下载速度)
- 是否安装ROS2:选是
- 选择ROS2版本:选Humble
- 是否配置rosdep:选是
- 是否安装依赖工具:选是
安装完成后,验证安装:
bash复制source /opt/ros/humble/setup.bash
ros2 --version
我实测的输出是ros2 0.24.2,说明安装成功。
第三步,安装导航和建图相关的常用包。这些不在默认安装里,需要手动装:
bash复制sudo apt install ros-humble-navigation2 ros-humble-nav2-bringup ros-humble-slam-toolbox ros-humble-cartographer ros-humble-cartographer-ros ros-humble-turtlebot3-gazebo ros-humble-turtlebot3-navigation2 ros-humble-turtlebot3-teleop
第四步,跑一个最简单的冒烟测试,用经典的小乌龟来验证系统:
bash复制ros2 run turtlesim turtlesim_node
另一个终端运行:
bash复制ros2 run turtlesim turtle_teleop_key
用键盘控制乌龟移动,说明ROS2的节点创建、话题发布订阅、键盘控制链路全部正常。这是最简单也最直观的ROS2安装验证方式。
6.3 实测:主从机通信性能对比(ROS1 vs ROS2)
我在同一个局域网里做了个小实验:两台相同的机器(都是i5处理器、千兆网卡),一台跑ROS1 Noetic,一台跑ROS2 Humble,都用话题传输一个1MB的字符串消息,测试端到端传输时延。
结果是:ROS1 Noetic在话题传输8个字节的消息时,平均时延约2.3毫秒;ROS2 Humble在相同条件下(使用Cyclone DDS),平均时延约0.8毫秒。当消息增大到1MB时,差异更明显:ROS1约18毫秒,ROS2约9毫秒。
需要说明的是,这个实验并不严谨,只是给了一个直观感受。实际项目中,通信时延受消息大小、频率、QoS配置、DDS实现、网络环境等多种因素影响。但趋势是一致的:ROS2在通信效率上确实有显著提升,尤其在多机场景下。
更关键的是可靠性。在ROS1的实验里,把Master停掉,整个通信立刻中断,所有节点失去联系。在ROS2的实验里,任意一个节点退出,其他节点之间的通信完全不受影响。这个差异在真实机器人系统中是决定性的——不会因为一个模块崩溃导致整个系统瘫痪。
7. 结论:ROS1和ROS2怎么选,我的最终建议
回到最初的问题。对于打算进入具身智能领域的新人,以及正在考虑项目技术路线的团队负责人,我的建议非常明确。
如果你是纯新手,今天刚准备开始学ROS,直接学ROS2,不要犹豫。ROS1里80%的概念(节点、话题、服务、参数、TF)在ROS2里依然存在,只是实现方式有变化。学习ROS2的过程中,你会顺便理解DDS、QoS这些现代分布式系统的基础知识,这些技能在机器人以外的领域同样有价值。等到某天你需要维护一个遗留的ROS1项目,再花两周时间补一下ROS1的语法和工作方式就行,逆向迁移比正向迁移容易得多。
如果你已经有ROS1基础,正在做项目选型或准备技术升级,评估标准就三点:
第一,你的系统是否需要多机通信和分布式部署。如果答案是肯定的,直接上ROS2,ROS1的多机通信会让你耗费大量精力。
第二,你的系统是否需要硬实时控制。如果机械臂或底盘控制器需要毫秒级响应,ROS2配合实时Linux补丁和RT-DDS才能真正满足需求。ROS1在这个场景下只能做"外挂实时"的架构设计。
第三,你的团队是否有足够的工程化能力。ROS2的运维复杂度明显高于ROS1,你需要有人能搞定DDS配置、QoS调优、系统性能监控。如果你的团队还停留在"能跑就行"的阶段,贸然迁移ROS2可能会陷入"跑不起来"的困境。
我个人在实际操作中的一大体会是:ROS2不是ROS1的简单升级,而是一次彻底的重构。它的学习曲线更陡、配置文件更复杂、新手期更痛苦,但一旦你跨过了QoS、DDS、colcon、launch这些门槛,你会发现ROS2带来的系统稳定性、通信效率、调试体验是ROS1完全无法比拟的。团队里的几个工程师从ROS1迁到ROS2后,最直观的感受是"终于不用再花一整天折腾主从机配置了",这个幸福感,只有被ROS1多机通信虐过的人才能懂。
最后再分享一个小技巧。如果你还在犹豫要不要迁移,或者正在做一个新项目但担心ROS2生态不完善,不妨采用双轨并行的策略:核心算法和底层驱动先用ROS2实现,遗留的第三方工具和算法库暂时通过ROS1和ROS2的桥接包互通。ROS2社区有ros1_bridge这个官方工具,可以让ROS1节点和ROS2节点在同一个系统里协同工作。这就像在装修老房子时先保留旧水管,等新管道完全铺好再接过去,虽然中间会有一些临时的弯弯绕绕,但整体风险可控。
下一篇我打算具体写写ROS2的DDS通信机制到底是怎么工作的,包括QoS的每一种配置在真实项目中应该怎么设置。那个话题展开讲内容会很多,但对理解ROS2的价值至关重要。如果你在ROS1和ROS2的选择、迁移过程中遇到了我上面没提到的问题,欢迎在评论区说出来,我看到了会尽量回复。
