【具身智能-90】这个系列走到第90篇,按理说该聊点算法或者传感器融合这类花活,但我偏要聊一个看起来技术含量不高、实际上最磨人的问题:ROS1和ROS2到底怎么选。做机器人软件这些年,我被问得最多的不是路径规划怎么调参,而是“我现在该装哪个版本”“我照着老教程写的功能包为什么在ROS2里跑不起来”“主从机怎么配都连不上”。搜索平台上一堆“ubuntu20.04装ros”“一键安装ros”“ros小车自主导航仿真”这类热词,说明这个领域一直在进新人,而新人进门的第一道坎,不是SLAM,不是IMU标定,而是ROS这套系统的版本和架构本身。
这篇文章我会从架构原理、通信机制、安装部署、实操迁移几个层面,把ROS1和ROS2的差异讲透,也把社区里高频出现的“一键安装脚本”“Docker跑ROS”“多机配置”“SLAM导航仿真”“激光雷达驱动”这些场景都拉进来一起说。看完之后,你应该能自己回答一个问题:你手上的项目,到底该留在ROS1,还是现在就切到ROS2。
1. 项目概述与现实困惑:为什么现在还在纠结ROS1还是ROS2
1.1 具身智能的软件栈需求,正在倒逼大家从ROS1挪到ROS2
具身智能这个概念火起来之后,机器人不再只是实验室里的验证平台了。机械臂要抓取、移动底盘要自主导航、双足要动态平衡,更重要的是这些模块之间要高频、低延迟地交换数据,往往还牵涉到多台机器、多个传感器同步。这种需求下,ROS1那套2007年设计出来的架构就有点力不从心了。
我在实际项目里感受最深的一次,是给一台AGV同时接激光雷达、双摄像头、底层运动控制板,还要跟另一台工控机共享地图和路径信息。ROS1下要实现这种多机协同,先得折腾Master的IP配置,再小心翼翼地规划话题名,稍不注意网络抖动,整个系统就开始丢数据,排查起来极其痛苦。而ROS2的DDS机制天生就是为这种分布式、多参与的通信场景设计的,自动发现、QoS策略这些特性,让多机协同的复杂度明显下降。
很多新手看到网上的教程,一上来就是ROS1的Kinetic或者Noetic,照着做完发现跟ROS2的命令行完全不一样,于是开始怀疑是不是自己装错了。这不是你装错了,是这两代系统的设计哲学本来就不同。ROS1解决的是“让机器人研究能跑起来”,ROS2解决的是“让机器人系统能稳定地跑在真实产品里”。
1.2 ROS不是操作系统,是一套“机器人软件的粘合剂”
先明确一个基本常识:ROS不是真正的操作系统,它是一套运行在Linux上的通信框架和工具集,负责把传感器驱动、算法模块、运动控制这些节点(Node)用话题(Topic)和服务(Service)串起来。ROS1的节点之间通信要经过一个叫Master的中央节点做“牵线搭桥”,而ROS2把这个角色干掉了,节点之间通过DDS直接发现对方、直接通信。
这套架构上的变化,导致了一个很现实的结果:ROS1时代积累的教程、代码、驱动,很多不能直接拿到ROS2里用。比如ROS1里最经典的gmapping建图包,在ROS2里要么用slam_toolbox替代,要么找社区移植版。传感器驱动更是重灾区,很多老型号的激光雷达、工业相机的官方驱动只写了ROS1版本。
所以我不建议再用“ROS1更成熟所以选它”这种惯性思维去选型。你真正要考虑的是:你的项目要跑多久、要部署到几台机器上、有没有实时性要求、硬件驱动有没有ROS2支持。想清楚这几个问题,版本选择就不会纠结。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 架构与通信原理解读:从Master到DDS的底层变迁
2.1 ROS1的中心化架构:为什么Master挂了系统就瘫痪
ROS1的通信模型用一个词概括就是“先报到,再通信”。所有节点启动后,先到Master那里登记自己的名字、话题、服务列表。A节点想发数据给B节点,流程是A向Master打听“B在哪”,Master把B的地址告诉A,然后A和B之间建立点对点连接,之后的数据传输就完全不经过Master了。
听起来好像Master只干了一次“中介”的活,但实际上它一旦挂了,新节点就再也加入不了这个系统,已有的连接虽然还能撑一会,但任何需要重新握手、重新发现的操作都会失败。我在实验室维护一台老机器人的时候,最怕的就是好不容易把多台设备都跑起来了,结果Master所在的电脑蓝屏,整套系统直接瘫痪,重启之后所有节点的连接状态全乱套。
另外ROS1的多机通信配置也是一言难尽。两台电脑要想配合,得保证一是时间同步(比如装chrony或ntp),二是主机上设置ROS_MASTER_URI指向Master那台机器的IP,三是从机上设置ROS_IP指向自己的实际网卡地址。这三步里任何一步漏了,大概率就是“话题列表能看到节点,但数据就是收不到”。而且ROS1的底层传输以TCP为主,也支持UDPROS,但后者用的人少,配置起来更麻烦,很多开发者根本不知道还有这个选项。
2.2 ROS2的DDS去中心化:自动发现、QoS与实时性从哪来
ROS2把通信层整个换成了DDS(Data Distribution Service,数据分发服务),这是一个工业界早已广泛使用的分布式通信标准。在这个模型里,节点启动后会通过UDP组播自动发现彼此,不再需要任何中央节点。你只要让所有节点处于同一个域(Domain ID),它们就能自动找到对方。
这就引出一个经常被问的问题:“ROS2的分发协议是UDP吗?”严格来说,DDS的底层传输默认用的是UDP,但也支持TCP甚至共享内存(Shared Memory),具体用哪种取决于RMW(ROS Middleware Interface)实现和QoS配置。比如在同一台机器上的两个节点,选择共享内存传输可以极大提升通信吞吐量,这在ROS1里是做不到的。
DDS真正厉害的地方是QoS(Quality of Service,服务质量)策略。你可以为每个话题单独配置可靠性(Reliability)、数据留存策略(Durability)、历史深度(History)等。举个例子:激光雷达数据量大,丢了零散的几帧问题不大,可以把Reliability设成BEST_EFFORT,这样通信更轻快;而控制指令一帧都不能丢,就要设成RELIABLE,确保可靠到达。ROS1里根本没有这种细粒度的通信质量控制,所有数据都是“尽力发送”,一旦网络拥塞,丢包只能靠上层自己处理。
实时性方面,ROS2引入了可配置的Executor执行模型,把回调按优先级和时间约束来调度。虽然离硬实时还有距离,但配合PREEMPT_RT内核,已经能满足不少运动控制的需求。再加上SROS2提供的加密和访问控制,ROS2在安全性和产品化方向上的潜力,是ROS1完全不具备的。对于嵌入式MCU,还有micro-ROS这种专门为单片机裁剪的实现,ROS1从来没有过这种扩展路径。
2.3 一张核心差异对照表
我把两代系统最关键的差异整理成一张表,方便你随时回顾:
| 对比维度 | ROS1(以Noetic为代表) | ROS2(以Humble/Jazzy为代表) |
|---|---|---|
| 核心架构 | 中心化,依赖Master节点 | 去中心化,DDS自动发现 |
| 默认通信协议 | TCP为主(TCPROS),有UDPROS | UDP为主(DDS),可配置TCP/共享内存 |
| 实时性支持 | 基本没有,非实时设计 | 支持Executor调度,配合RT内核更佳 |
| 多机通信 | 需手动配置ROS_MASTER_URI、ROS_IP | 同一Domain ID自动发现,相对简单 |
| 通信QoS | 不支持 | 支持可靠性、持久性、历史深度等策略 |
| 构建工具 | catkin(catkin_make / catkin build) | ament + colcon |
| 生命周期管理 | 无标准机制 | 引入Lifecycle Node,节点状态可管理 |
| 安全性 | 无内建安全机制 | SROS2加密、权限控制 |
| 嵌入式支持 | 无官方方案 | micro-ROS支持MCU |
| 官方EOL状态 | Noetic已于2025年结束维护 | Humble支持至2027年,Jazzy支持至2029年 |
这张表不是告诉你ROS2“全面碾压”般好,而是告诉你一个事实:新一代系统在设计上补了很多ROS1的短板,但这也意味着迁移成本是真实存在的,后面我会专门讲迁移时踩到的坑。
3. 安装部署与操作系统选型:Ubuntu版本和ROS版本怎么配
3.1 发行版与Ubuntu版本对应关系,以及EOL时间线
安装ROS踩坑,一半是版本不匹配造成的。很多人拿着Ubuntu 22.04的机器,照着网上的老教程敲“sudo apt install ros-noetic-desktop-full”,结果发现根本装不上,然后开始怀疑人生。其实ROS1的Noetic只支持Ubuntu 20.04,你拿22.04去装,软件源里根本没有这个包。
下面是主流发行版的对应关系和生命周期:
| 系统版本 | 支持Ubuntu版本 | 生命周期状态 |
|---|---|---|
| ROS1 Kinetic | Ubuntu 16.04 | 已停止维护(2021年EOL) |
| ROS1 Melodic | Ubuntu 18.04 | 已停止维护(2023年EOL) |
| ROS1 Noetic | Ubuntu 20.04 | 2025年停止维护,存量项目仍在跑 |
| ROS2 Foxy | Ubuntu 20.04 | 已停止维护(2023年EOL) |
| ROS2 Galactic | Ubuntu 20.04 | 已停止维护(2022年EOL) |
| ROS2 Humble | Ubuntu 22.04 | 官方支持至2027年,当前主力 |
| ROS2 Iron | Ubuntu 22.04 | 已停止维护(2024年EOL) |
| ROS2 Jazzy | Ubuntu 24.04 | 官方支持至2029年,新项目推荐 |
从这张表可以看得很清楚:如果是新装机,Ubuntu 20.04已经是个过渡版本,ROS1和ROS2都能装,但两边都已不是最前沿;Ubuntu 22.04只能装ROS2(Humble/Iron);Ubuntu 24.04只能装ROS2(Jazzy)。所以只要你的机器是这两年的新电脑,答案基本就是“老老实实用ROS2”。
3.2 鱼香ROS一键安装与手动安装的取舍
社区里流传很广的一键安装脚本是“鱼香ROS”,执行命令就一行:
bash复制wget http://fishros.com/install -O fishros && . fishros
这个脚本的好处是交互式引导,可以把ROS、依赖、常用工具、系统源、Docker环境等一堆东西一次性配好,对新手来说确实省了不少事。我自己在虚拟机里测试过,脚本会自动检测Ubuntu版本,然后给出对应的ROS版本选项,还会顺手帮你把rosdep update的问题一起处理掉,这点非常友好。
但我也要提醒一句:任何一键脚本都属于“别人帮你做了决定”,建议运行之前先大体看一下脚本内容(用cat命令查看),确认它做的事是你需要的。另外,鱼香ROS脚本默认会把软件源切换成国内镜像,这对国内网络环境是巨大优化,但如果你后续要装一些依赖特定源的第三方包,需要能自己改回官方源,这个操作要会。
如果你倾向手动安装,关键步骤其实也不复杂,以Ubuntu 22.04 + ROS2 Humble为例:
bash复制sudo apt update && sudo apt install curl
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu jammy main" | sudo tee /etc/apt/sources.list.d/ros2.list
sudo apt update
sudo apt install ros-humble-desktop python3-colcon-common-extensions
注意把源里的“jammy”换成你对应Ubuntu版本的代号(20.04是focal,24.04是noble)。国内服务器可以换成清华或中科大的镜像源,速度会快很多。手动安装能让你对整个系统的构成有清晰认识,排查问题时更容易定位,所以我个人建议至少手动装一次,熟练之后再用脚本。
3.3 Docker跑ROS:Windows环境下的曲线救国方案
很多人的主力电脑是Windows,但ROS在Windows原生的支持一直不理想。社区里最成熟的方案就是用Docker在Windows里跑一个Linux容器,然后在里面装ROS。热词里的“Windows安装docker运行ROS”指的就是这个。
官方镜像地址是Docker Hub上的osrf/ros,拉取命令很简单:
bash复制docker pull osrf/ros:humble-desktop
跑起来之后要解决两个问题。第一个是图形界面,Gazebo、RViz这些工具需要X11转发,在Windows下建议用WSLg直接支持GUI应用,或者在Docker Desktop设置里打开WSL集成。启动容器时加上这几行参数:
bash复制docker run -it --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix osrf/ros:humble-desktop bash
第二个是设备透传,如果要用激光雷达、摄像头这类USB设备,得把设备映射进容器:
bash复制docker run -it --privileged -v /dev:/dev --net=host osrf/ros:humble-desktop bash
Docker方案的优点是环境干净,镜像删了重来,再怎么折腾都不影响宿主机。缺点是每次都要手动挂载目录和设备,跑Gazebo仿真时性能会有轻微损耗。我的经验是:做仿真和算法验证,Docker完全够用;接真实传感器跑硬件,还是装双系统或者直接用Linux更省心。
4. 实操环节:用TurtleBot3从ROS1迁移到ROS2跑通SLAM导航
4.1 环境准备:TurtleBot3仿真包的差异
为了让对比更直观,我选了一个在ROS1和ROS2里都有完整支持的平台:TurtleBot3。它同时提供了Gazebo仿真和真实硬件支持,是学习ROS迁移的最佳参照物。
安装依赖包:
bash复制sudo apt install ros-humble-turtlebot3-simulations ros-humble-nav2-bringup
启动仿真环境时,两个版本的命令风格差异非常明显。ROS1是这样:
bash复制export TURTLEBOT3_MODEL=burger
roslaunch turtlebot3_gazebo turtlebot3_world.launch
ROS2改成了Python编写的launch文件,命令也变成了“ros2 launch”:
bash复制export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
这里的关键区别不只是命令多了一个“2”,而是launch文件的组织方式完全不同。ROS1的launch是XML格式,ROS2虽然也支持XML,但官方推荐用Python写launch,好处是可以在launch阶段加入复杂的条件判断、参数计算和回调逻辑。对一个简单项目来说这感觉不到差距,但对复杂系统来说,Python launch的可维护性高了一大截。
4.2 SLAM建图:从gmapping到slam_toolbox
建图是探索机器人最经典的需求。ROS1里最常用的建图算法是gmapping,基于粒子滤波,配置简单,效果稳定。在ROS1环境下去掉已经写好的gmapping包,跑起来的命令是:
bash复制roslaunch turtlebot3_slam turtlebot3_slam.launch
ROS2里官方推荐的默认替代是slam_toolbox,它实现了基于图优化的SLAM,在回环检测和长时间建图方面的表现比gmapping更好,参数也能在运行时动态调整。跑起来:
bash复制ros2 launch turtlebot3_slam slam_toolbox.launch.py
这里有一个新手很容易坑的地方:slam_toolbox里有很多参数,比如“minimum_travel_distance”“minimum_travel_heading”,这些参数控制的是“机器人移动多少距离或者转多少角度之后才触发新的扫描匹配”。如果你把这两个参数设得太小,地图会出现大量冗余计算,CPU占用飙升;设得太大,建图精度会下降。我通常把距离阈值设在0.2米、角度阈值在0.1弧度,这是一个在精度和算力之间比较平衡的起始值。
另外,用键盘控制TurtleBot3移动建图的时候,千万别忽快忽慢。SLAM算法对“运动速度与传感器频率”的匹配很敏感,你推着机器人快速转圈,激光帧之间的位移太大,匹配会失败,地图就会糊。这也是为什么很多新手照着教程跑,地图却歪七扭八——不是算法不行,是手推得太猛。
4.3 自主导航:Nav2与move_base的差异
ROS1的自主导航核心是move_base,一个相对“一体化”的导航栈,配置主要由costmap参数和planner参数组成。ROS2里的替代品是Nav2,它把导航系统拆成了很多独立模块:服务器端的行为树(Behavior Tree)、代价地图、规划器、控制器(DWB)、AMCL定位等等。Nav2还引入了生命周期节点管理,每个模块都有明确的启动、活动、停止状态,整个系统更接近工业软件的架构。
启动导航在ROS1下是:
bash复制roslaunch turtlebot3_navigation turtlebot3_navigation.launch
ROS2下是:
bash复制ros2 launch turtlebot3_navigation2 navigation2.launch.py
Nav2的配置复杂度确实比move_base高。你需要关注的核心参数包括:机器人模型的半径(robot_radius)、代价地图分辨率(resolution)、控制周期(controller_frequency)、以及AMCL的粒子数量(max_beams,min_particles)。如果你跑仿真发现机器人原地转圈不走,我会优先检查“robot_base_frame”是否指向正确——在TurtleBot3里这个值应该是“base_footprint”,而不是“base_link”,搞错了就会导致坐标变换找不到,导航直接宕掉。
另一个高发问题是Nav2的BT导航器默认会先执行“计算路径”的行为树节点,如果你给的初始位姿离目标点太近,行为树会直接判定“已到达”,压根不会启动控制器。这种“目标点设得比机器人半径还近”的坑,在实际调车时特别容易踩。
4.4 激光雷达驱动的现实问题:neato xv-11的冷暖自知
仿真跑得再顺,终归要接真实传感器。热词里有一个非常经典的老型号传感器:neato xv-11激光雷达。这是一个由扫地机器人拆机改造而来的低成本激光雷达,在ROS1时代有非常成熟的开源驱动,社区里很多人靠它入门SLAM,一百多块钱就能体验一把激光建图。
但到了ROS2时代,这个传感器的处境就尴尬了:厂商没有提供ROS2驱动,社区移植也不积极,官方驱动包的维护早已停止。我在ROS2环境里尝试用第三方驱动包,发现要么编译报错,要么扫描频率和数据格式都对不上。最后还是靠ros1_bridge把ROS1节点接入ROS2系统,才让这颗老雷达继续发光发热。
这个案例非常典型地说明了ROS2生态的现状:新系统在架构上很强,但老硬件驱动的迁移速度远远跟不上。你手上如果有类似的传感器,在做选型之前,第一件事应该是搜索“你的设备型号 + ROS2”,看看有没有可用的驱动。没有的话,要么继续用ROS1并桥接,要么换硬件。
5. 代码迁移要点与常见问题速查表
5.1 从ROS1代码迁移到ROS2必须知道的5个变化
如果你决定拥抱ROS2,最痛苦的阶段就是把旧代码从ROS1平移到ROS2。我列一下最常见、最影响编译的几个改动点。
第一,构建系统从catkin换成了ament + colcon。原来用catkin_make编译的工程,现在要用colcon build。对应的CMakeLists.txt里很多函数变了,比如“catkin_package()”要改成“ament_target_dependencies()”,包内依赖声明也有新写法。package.xml的格式也变了,需要添加一些新的依赖标签,否则构建时很容易提示找不到依赖。
第二,C++头文件路径变了。比如ROS1里的“#include <ros/ros.h>”在ROS2里要改成“#include <rclcpp/rclcpp.hpp>”,原来的“std_msgs/String.h”变成“std_msgs/msg/string.hpp”。Python方面,原来“import rospy”变成“import rclpy”。
第三,回调机制变了。ROS1里你需要手动调用“ros::spin()”或“spinOnce()”来处理回调,ROS2这个职责交给了Executor。如果你的代码里多线程用得比较多,一定要搞清楚SingleThreadedExecutor和MultiThreadedExecutor的调度差异,不然回调不触发或者乱序会让你排查到崩溃。
第四,坐标变换库只剩tf2了。ROS1里还有老版的tf包,ROS2直接没了,只有tf2。API也变了,比如“tf::TransformListener”在ROS2里是“tf2_ros::TransformListener”,消息类型是“tf2_msgs/msg/TFMessage”。这意味着所有涉及坐标变换的代码都要重写。
第五,参数系统大改。ROS1的参数服务器是全局的一个键值对存储,ROS2是每个节点独立维护参数,启动时通过param文件加载。原来用“rosparam get”拿到全局参数的方式不再适用,你需要把参数定义在节点的声明里,然后通过launch文件或命令行传入。
5.2 实操高频问题排查:我踩过的坑和解决办法
最后把高频问题整理成速查表,这每一个都是我在项目里真实遇到过的。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| ROS1主从机之间能看到节点,但收不到数据 | ROS_IP没设成实际网卡地址、时间不同步 | 从机设置export ROS_IP=本机IP,两端统一用chrony同步时间 |
| ROS2多机之间发现不了对方 | Domain ID不一致、路由器禁了组播 | 两端export ROS_DOMAIN_ID=同一个数字,检查防火墙UDP组播 |
| 订阅话题后回调不触发 | QoS策略不匹配 | 检查发布端和订阅端的Reliability是否一致,传感器话题通常都用BEST_EFFORT |
| ROS2 rqt_graph里看不到节点 | 环境变量没有source完整 | source /opt/ros/humble/setup.bash后再启动rqt |
| Gazebo启动后黑屏/崩溃 | 显卡驱动或OpenGL版本问题,Docker下尤其常见 | 本地装好GPU驱动,容器里挂载/dev/dri设备,或加LIBGL_ALWAYS_SOFTWARE=1兜底 |
| colcon build时编译报“Could not find a package” | package.xml里的依赖项不全 | 把源代码里include的头文件对应依赖补到package.xml和CMakeLists.txt |
| 运行节点报“ROS_DOMAIN_ID”相关警告 | 环境变量未统一 | 所有机器export相同的ROS_DOMAIN_ID,避免不同项目互相干扰 |
| 导入传感器驱动启动后无数据 | 驱动只支持ROS1或USB权限不足 | 用ros1_bridge桥接,或检查/dev/ttyUSB*权限,把登录用户加入dialout组 |
这里想特别强调“ROS_DOMAIN_ID”这个环境变量,它是ROS2多机协同的关键。ROS1里靠ROS_MASTER_URI区分网络域,ROS2则靠Domain ID。同一网段里,只有DOMAIN_ID相同的节点才能互相发现。如果你在一个办公室里有好几组人都在跑ROS2,不统一设置DOMAIN_ID,就会出现“你的机器人收到了我的速度指令”这种诡异现象。我一般会在~/.bashrc里固定写死一个数字,比如export ROS_DOMAIN_ID=24,避免每次开新终端都忘了设置。
在实际操作中,ROS2的多机通信还有一个底层依赖:DDS默认用UDP组播做发现,某些企业路由器会禁掉组播包,导致节点就是互相看不见。遇到这种情况,可以切换到CycloneDDS并配置共享内存或TCP模式,效果立竿见影。具体做法是装ros-humble-rmw-cyclonedds-cpp,然后export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp,再用CycloneDDS的xml配置文件指定通信方式。
还有一个更隐蔽的坑:ROS2节点之间的通信数据默认走UDP,而UDP包如果超过MTU(通常1500字节)会触发分片。大消息(比如高分辨率点云、图像)在高负载下容易因为分片丢失导致接收异常。解决办法是把所属网卡的MTU调大,或者在上层把大消息拆小。ROS1时代大家很少考虑这些问题,因为TCP协议栈帮你处理了可靠性和分片,但TCP的代价就是延迟和头部开销,DDS选择UDP作为默认传输,本质上是把“性能”和“调优责任”一起交到了你手上。
关于“MobaXterm配置开发环境”以及“树莓派装ROS Kinetic”这类老教程,我的建议是一致的:MobaXterm这类远程终端工具适合做轻量开发,但跑Gazebo仿真或者高负载SLAM,还是要本地执行或者用带GPU的远端机器。树莓派这种低功耗板子,跑ROS1的Kinetic也就勉强能用,跑ROS2的话资源会很紧张,建议直接用Docker镜像里的ROS2版本,比在新版系统上编译要省心得多。
至于“机械臂开发”和“MoveIt”的选型,也是同样的逻辑。ROS1下有MoveIt 1.0,ROS2下有MoveIt 2,功能覆盖已经基本对齐。如果你是从零开始学习,直接学MoveIt 2 + ROS2反而是捷径,因为不会有几个月后又要迁移的痛苦。类似的还有“宇树Go2机器狗”这类新硬件,官方给的统一是ROS2接口,这已经是新机器人产品的默认配置了。
我个人现在的做法是:核心系统、新项目、新硬件一律用ROS2;仓库里那些老传感器、老算法包,通过ros1_bridge桥接到ROS2里继续用,而不是逼自己在老版本的泥潭里硬撑着。ROS1已经完成了它的历史使命——大量科研成果、开源代码、社区教程都是基于它沉淀下来的,但这不代表你要用下一个十年继续给它“养老”。反过来,ROS2在架构上的优势是实打实的,哪怕现在的迁移过程让人挠头,至少新写的每一行代码,未来五年都不会因为系统退市而被废弃。
最后分享一个小技巧,算是送给即将入坑ROS2的同学。装好ROS2之后,第一件事不是急着写代码,而是先想清楚你要用哪套RMW实现。Fast DDS是默认的,功能全但偶尔有性能抖动;CycloneDDS在某些场景下延迟更低;如果机器之间通过共享内存通信,zenoh也可以作为备选。选好之后把RMW_IMPLEMENTATION写进~/.bashrc,一切问题都会少一半。我在这个问题上吃过亏,默认Fast DDS跑多机SLAM时偶尔卡顿,换成CycloneDDS后流畅很多。选型这种事情,越早做决定,后面越省心。
