无人机开发选ROS1还是ROS2?一线开发者深度对比与迁移实践
1. 无人机软件架构选型的十字路口搞无人机软件开发的人这两年几乎都绕不开一个话题新项目到底该上 ROS1 还是 ROS2。我自己从 2018 年前后开始用 ROS1 做飞控外围和视觉感知模块到 2021 年逐步把几个在研项目迁移到 ROS2中间踩过的坑、熬过的夜、推翻重来的架构设计攒了不少真实体会。这篇文章不打算写成官方文档的复述而是想以一个一线开发者的视角把“为什么我更推崇 ROS2”这件事讲透顺带把迁移过程中那些文档里不会写的细节摊开来说。先说清楚这篇文章适合谁看。如果你正在做无人机相关的软件开发涉及飞控通信、视觉感知、路径规划、集群协同这些方向并且正在纠结技术栈选型那这篇内容应该能帮你省下不少试错时间。如果你刚接触 ROS还在看 ros2 菜鸟教程、ros2 入门教程这类材料也可以先了解一下两个版本的本质差异避免一开始就走上一条后期要推倒重来的路。文章会涉及 ROS1、ROS2、DDS、micro-ROS 这些核心概念也会聊到实际项目中的通信机制、实时性、部署方式等工程问题。我推崇 ROS2 不是因为它“新”而是因为它在无人机这个特定场景下解决了一批 ROS1 时代靠打补丁才能勉强应付的问题。下面我从架构设计、核心机制、实操落地、问题排查几个维度把这件事掰开揉碎讲清楚。2. 为什么无人机项目对通信架构如此敏感2.1 无人机软件系统的真实构成一架稍微像样的无人机软件层面从来不是“一个程序跑到底”。它至少包含这几块飞控固件跑在 STM32 这类 MCU 上、机载计算单元树莓派、Jetson、RK3588 等、地面站软件、以及可能存在的云端调度服务。机载计算单元上又要同时跑视觉感知、路径规划、状态估计、任务调度等多个模块。这些模块之间需要频繁交换数据IMU 姿态、GNSS 定位、图像帧、点云、控制指令、航点信息。问题就出在这里。ROS1 时代节点间通信走的是自定义的 TCPROS/UDPROS 协议底层依赖一个叫 roscore 的中心节点。所有节点启动时都要先向 master 注册通信时先问 master 要对方的地址然后再建立连接。这个设计在实验室里跑 demo 没问题但放到无人机上麻烦就来了。我印象很深的一次是做一个多机协同的编队项目。地面站和几架无人机之间需要同步状态结果 roscore 一挂整个系统全瘫。更头疼的是WiFi 链路抖动的时候TCPROS 的重连逻辑会让某些话题的延迟突然飙到几百毫秒对于需要实时响应的控制回路来说这是致命的。2.2 ROS1 架构在无人机场景下的三个硬伤第一个硬伤是单点故障。roscore 是全局唯一的它一旦崩溃或者网络分区所有节点之间的通信都会中断。无人机在天上飞你不可能说“等我重启一下 master”。虽然可以用多 master 方案或者一些第三方工具来缓解但本质上都是在跟架构设计对抗。第二个硬伤是实时性无法保证。ROS1 的通信层没有 QoS 概念所有消息都是“尽力而为”或者“可靠传输”二选一没法针对不同话题做差异化配置。但无人机上不同数据的实时性要求天差地别IMU 数据要求高频低延迟丢几帧无所谓而控制指令丢了可能直接导致炸机。ROS1 没法在通信层面区分这些需求。第三个硬伤是对嵌入式端支持差。无人机上大量使用 STM32、ESP32 这类 MCUROS1 基本没法直接跑上去只能通过串口桥接写一堆自定义协议。这不仅增加开发量还让整个系统的可维护性变差。热词里出现的 stm32 micro-ros、esp32 无人机 开源这些方向其实都是在解决这个问题而这些方案几乎都是围绕 ROS2 生态展开的。2.3 ROS2 带来的架构性改变ROS2 最根本的变化是去掉了中心化的 master改用 DDS 作为通信中间件。DDS 本身就是为分布式实时系统设计的自带服务发现、QoS 策略、多播通信这些能力。节点之间直接通过 DDS 发现彼此不需要一个“中间人”。这意味着任何一个节点挂掉都不会影响其他节点之间的通信。这个改变对无人机来说意义重大。你可以把视觉节点、规划节点、控制节点分别部署在不同的计算单元上它们通过 DDS 自动发现并建立通信整个系统没有单点。而且 DDS 的 QoS 机制允许你针对每个话题单独配置可靠性、持久性、 deadline、延迟预算等参数真正做到“重要数据可靠传高频数据快速传”。3. ROS1 与 ROS2 核心机制对比拆解3.1 通信模型从 TCPROS 到 DDSROS1 的通信模型可以类比成“打电话先查黄页”。你要给某个节点发消息得先去 master 那里查它的地址然后建立连接。这个过程中 master 是必经之路而且连接建立后是点对点的 TCP 或 UDP。ROS2 的 DDS 模型更像“对讲机群聊”。每个节点加入一个 domain通过多播或者单播的方式自动发现同一 domain 内的其他节点。发现之后数据的传输是节点之间直接进行的不经过任何中心。DDS 还支持多种传输方式包括共享内存、UDP、TCP可以根据场景自动选择。这里要特别提一下Fast DDS这是 ROS2 默认的 DDS 实现之一也是目前用得最广的。它的特点是性能好、配置灵活支持零拷贝传输。对于无人机上的图像和点云这类大数据量话题零拷贝能显著降低 CPU 占用和延迟。热词里 fast dds 详解 被频繁搜索说明大家确实在关注这块的底层机制。3.2 QoS 策略无人机场景下的关键差异QoS 是 ROS2 相比 ROS1 最实用的改进之一。我拿几个无人机上的典型话题来说明。话题类型数据特征ROS1 处理方式ROS2 QoS 建议配置IMU 姿态高频、可丢帧默认可靠传输易堆积Best EffortKeep Last 1控制指令低频、不可丢可靠传输但无优先级ReliableKeep Last 1Deadline 监控图像帧高频、大流量容易阻塞其他话题Best EffortKeep Last 1限制带宽航点信息低频、需持久无持久化机制ReliableTransient Local状态告警事件型、需可靠可靠传输ReliableKeep All这张表是我在实际项目中反复调整后总结出来的。ROS1 时代你没法针对话题做这种差异化配置只能全局调参数结果就是要么牺牲实时性要么牺牲可靠性。ROS2 的 QoS 让你可以“因材施教”这是架构层面的进步。3.3 实时性与确定性控制回路的关键无人机的控制回路对实时性要求极高。从传感器采样到控制输出整个链路的延迟必须稳定且可预测。ROS1 的通信层没有 deadline 概念你没法知道一条消息是否在预期时间内到达。ROS2 的 DDS 支持Deadline和Latency Budget等 QoS 策略可以监控通信是否满足实时性要求超时还能触发回调。另外ROS2 支持实时内核和实时执行器配合 PREEMPT_RT 补丁可以把控制回路的抖动控制在微秒级。这对于做高精度姿态控制或者高速避障的团队来说是 ROS1 完全给不了的能力。3.4 嵌入式端支持micro-ROS 的价值micro-ROS 是 ROS2 生态里专门为 MCU 设计的轻量级实现。它让 STM32、ESP32 这类资源受限的芯片可以直接作为 ROS2 节点参与通信而不需要额外的桥接程序。热词里 stm32h7 结合 dmamux 双缓冲与 dds 技术实现高精度波生成、stm32 micro-ros、esp32 无人机 开源 这些内容反映的正是这个趋势。我自己的一个项目里用 STM32H7 跑 micro-ROS直接发布 IMU 数据和接收控制指令省掉了一颗专门做协议转换的芯片。整个系统的节点数量减少了故障点也少了。micro-ROS 底层同样走 DDS所以它和机载 Linux 上的 ROS2 节点是无缝通信的不需要任何自定义协议。4. 无人机项目迁移到 ROS2 的实操路径4.1 环境搭建从零到可运行先说安装。ROS2 的安装比 ROS1 友好很多官方提供了一键脚本和二进制包。以 Ubuntu 22.04 为例安装 ROS2 Humble 的步骤大致如下# 设置 locale sudo apt update sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 # 添加 ROS2 软件源 sudo apt install software-properties-common sudo add-apt-repository universe sudo apt update sudo apt install curl -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 # 安装 ROS2 Humble sudo apt update sudo apt install ros-humble-desktop sudo apt install ros-dev-tools # 配置环境变量 echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc装完之后可以用ros2 run demo_nodes_cpp talker和ros2 run demo_nodes_cpp listener验证通信是否正常。如果能看到消息收发说明 DDS 层工作正常。注意如果你之前装过 ROS1环境变量可能会冲突。建议在 .bashrc 里用条件判断区分或者干脆用 Docker 隔离两个环境。我见过太多人因为 source 顺序问题导致 ros2 command not found排查半天才发现是 ROS1 的环境变量覆盖了。4.2 飞控通信接口的重新设计ROS1 时代和飞控通信通常用 mavros 或者自己写串口驱动。ROS2 下 mavros 也有对应版本但更推荐的做法是用 micro-ROS 直接让飞控作为 ROS2 节点或者用 DDS 桥接。以 PX4 为例ROS2 下可以用px4_ros_com和micro-ROS-agent配合让 PX4 跑 micro-ROS 客户端直接发布 uORB 消息到 ROS2 话题。这样飞控和机载计算机之间的通信就走 DDS不需要额外的 mavlink 转换层。配置 micro-ROS-agent 的典型命令# 启动 micro-ROS agent监听串口 ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 -b 921600飞控端需要集成 micro-ROS 客户端库配置好 topic 映射和 QoS。这里有个经验串口波特率尽量拉高921600 是起步能上 2M 更好。因为 IMU 数据频率高波特率不够会导致消息堆积。4.3 视觉感知模块的迁移要点无人机视觉感知通常涉及图像采集、目标检测、跟踪、深度估计等模块。ROS1 下常用 usb_cam、cv_bridge、image_transport 这些包。ROS2 下都有对应版本但 API 有变化。迁移时最容易踩的坑是cv_bridge 的编码格式。ROS1 和 ROS2 在图像消息的 encoding 字段处理上有差异直接移植代码可能出现颜色通道错乱。建议在转换时显式指定编码from cv_bridge import CvBridge bridge CvBridge() # ROS2 下建议显式指定 desired_encoding cv_image bridge.imgmsg_to_cv2(msg, desired_encodingbgr8)另一个坑是图像话题的 QoS。默认的 QoS 是 Reliable对于高帧率图像来说会导致发送端阻塞。一定要改成 Best Effortfrom rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy qos QoSProfile( reliabilityReliabilityPolicy.BEST_EFFORT, historyHistoryPolicy.KEEP_LAST, depth1 ) self.create_subscription(Image, /camera/image_raw, self.callback, qos)4.4 路径规划与导航栈的适配ROS1 的 navigation 栈在 ROS2 下对应的是 Nav2。八叉树地图导航在 ROS2 下用 octomap_server2 或者直接集成到 Nav2 的 costmap 插件里。热词里 ros2 八叉树地图导航 被搜索说明这是很多人的实际需求。Nav2 的配置比 ROS1 的 move_base 复杂但灵活性更高。核心配置文件包括nav2_params.yaml全局和局部代价地图、规划器、控制器参数behavior_trees行为树定义控制导航流程map_server地图加载我建议先用默认配置跑通再逐步调参。特别是无人机的三维导航需要把 costmap 配置成 3D 的或者用 octomap 做障碍物表示。5. 实操中的典型问题与排查实录5.1 DDS 发现失败节点互相看不见这是 ROS2 新手最常见的问题。两个节点明明在同一台机器上就是发现不了对方。排查思路如下现象可能原因解决方法同机节点发现不了ROS_DOMAIN_ID 不一致统一 export ROS_DOMAIN_ID42跨机发现不了多播被禁用配置单播发现或检查防火墙部分节点可见网卡选择错误设置 ROS_LOCALHOST_ONLY 或指定网卡发现延迟大DDS 配置问题调整发现协议参数或换 DDS 实现我遇到过一次是因为开发机上装了 DockerDDS 默认绑到了 docker0 网卡上导致和外部节点发现不了。解决办法是设置ROS_LOCALHOST_ONLY1或者显式指定网卡。5.2 消息延迟抖动QoS 配置不当有次做视觉伺服发现图像话题的延迟忽高忽低控制回路跟着抖。查了半天发现是图像话题用了默认的 Reliable QoS发送端在等接收端确认接收端处理不过来就堆积。改成 Best Effort 之后延迟立刻稳定了。经验高频传感器数据一律用 Best Effort控制指令和状态告警用 Reliable。这个原则能解决 80% 的延迟问题。5.3 micro-ROS 连接不稳定micro-ROS 跑在 MCU 上资源有限连接不稳定是常见问题。排查要点串口波特率是否足够建议 921600 以上MCU 端的内存池是否够用默认配置可能偏小micro-ROS-agent 的版本是否和客户端库匹配是否有其他程序占用了串口我自己的项目里把 STM32 的 micro-ROS 内存池从默认的 4KB 调到 16KB 之后连接稳定性明显提升。5.4 编译与依赖问题ROS2 用 colcon 替代了 catkin编译命令变成colcon build。常见问题包括ros2 command not found环境变量没 source或者 ROS1 和 ROS2 冲突包找不到检查AMENT_PREFIX_PATH和COLCON_PREFIX_PATHPython 版本问题ROS2 Humble 默认用 Python 3.10虚拟环境里要注意建议用--symlink-install参数编译方便调试colcon build --symlink-install --packages-select your_package6. 工具链与生态的长期考量6.1 仿真环境ROS2 下 Gazebo 的集成比 ROS1 更紧密Ignition Gazebo现在叫 Gazebo Sim原生支持 ROS2。无人机仿真可以用gz配合ros_gz_bridge把仿真中的传感器数据桥接到 ROS2 话题。相比 ROS1 时代的 gazebo_ros_pkgs配置更清晰性能也更好。6.2 可视化工具RViz2 是 ROS2 的可视化工具功能上比 RViz 更现代支持更多插件。安装和使用sudo apt install ros-humble-rviz2 ros2 run rviz2 rviz2对于无人机常用的可视化包括TF 树、点云、图像、路径、marker 等。RViz2 的配置可以保存为 .rviz 文件方便团队共享。6.3 集群通信无人机集群是 ROS2 的强项。DDS 天然支持多节点发现和通信配合 ROS_DOMAIN_ID 可以隔离不同集群。对于大规模集群可以用 DDS 的 partition 功能做进一步隔离。我做过一个 5 机编队的项目每架无人机跑一个 ROS2 节点通过 DDS 自动发现地面站作为监控节点加入同一 domain。整个系统没有中心节点任何一架失联都不影响其他无人机。6.4 长期维护与社区趋势ROS1 的 Noetic 是最后一个版本2025 年 5 月已经停止维护。ROS2 的 Humble 是 LTS 版本支持到 2027 年后续还有 Iron、Jazzy 等版本。从社区活跃度看新功能、新工具几乎都只在 ROS2 上开发。现在入局无人机软件开发选 ROS2 是顺势而为。7. 我个人的迁移体会与建议如果你手头有 ROS1 的老项目不建议一次性全量迁移。我的做法是新模块直接用 ROS2 写老模块通过 ros1_bridge 逐步替换。ros1_bridge 可以让 ROS1 和 ROS2 节点互相通信给迁移留出缓冲期。对于新项目直接上 ROS2别犹豫。学习曲线确实比 ROS1 陡一点主要是 DDS 和 QoS 的概念需要时间消化但一旦理解你会发现很多在 ROS1 里需要绕弯解决的问题在 ROS2 里是原生支持的。最后分享一个我踩过的坑别在无人机上跑默认的 DDS 配置。默认配置是为通用场景设计的资源占用和发现行为不一定适合无人机。花时间调一下 DDS 的发现协议、线程池、内存池参数对系统稳定性提升很大。Fast DDS 的 XML 配置文件可以精细控制这些行为值得深入研究。至于 micro-ROS如果你的飞控是 STM32H7 或者 ESP32强烈建议试试。它能让你的飞控直接成为 ROS2 网络的一部分省掉一层协议转换整个系统的架构会清爽很多。