1. 无人机软件开发的中间件选型为什么这个决定比选飞控还关键搞无人机软件开发的同行大概都有过这种经历飞控硬件选好了机架装完了电机电调也调通了结果一到软件架构层面就卡住了——到底用ROS1还是ROS2这个问题在2019年之前几乎不是问题因为那时候ROS2还没成熟到能上天的程度。但到了2024年如果你还在新项目里用ROS1我真心觉得你是在给自己挖坑。我自己从2017年开始用ROS1做无人机地面站和机载计算模块2021年全面转向ROS2中间踩过的坑、熬过的夜、炸过的机好在都是小四轴损失可控让我对这个话题有太多想说的。这篇文章不是官方文档的复读机也不是简单的版本对比表而是我从实际项目里总结出来的经验——为什么在无人机这个特定领域ROS2的优势是压倒性的以及如果你正准备从ROS1迁移或者新项目直接上ROS2有哪些关键细节你必须提前知道。先给不太熟悉背景的读者快速对齐一下认知ROSRobot Operating System不是传统意义上的操作系统而是一套分布式通信中间件加工具链加软件包生态。ROS1的核心是TCPROS/UDPROS协议加上一个中心化的Master节点ROS2则彻底重写底层换成了DDSData Distribution Service去掉了Master支持实时性和多机通信。对于无人机来说这意味着什么意味着你的飞控计算机、机载视觉计算机、地面站之间的通信可靠性、延迟确定性、系统容错能力全部都会因为这一个选择而产生代际差异。这篇文章适合谁看如果你正在做无人机软件开发无论是做飞控算法验证、视觉感知、集群编队还是地面站开发只要你需要决定通信架构这篇文章就是写给你的。如果你还在用ROS1但项目周期还有一年以上我也建议你认真考虑迁移路径。如果你刚入门正在搜“ros2菜鸟教程”或者“ros2入门教程”那更好直接从ROS2开始学省得以后还要转。2. ROS1在无人机项目里的真实体验那些年我们忍过的痛2.1 单点故障Master挂了全机队都瞎了ROS1的架构核心是一个Master节点所有节点启动时都要向Master注册通信时先问Master要对方的地址。这个设计在实验室里跑跑小乌龟没问题但在无人机上就是灾难。我亲身经历过一次三架无人机做编队飞行地面站跑着roscore结果地面站电脑因为散热问题自动降频roscore响应变慢三架飞机同时失去彼此的位置信息虽然飞控本身的底层稳定控制还在但编队逻辑直接崩了最后靠手动接管才没出大事。ROS1的Master是单点故障源这在无人机集群场景下是致命的。你可能会说“我可以写个脚本监控roscore然后自动重启”但重启期间所有节点都要重新注册通信中断至少几秒钟对于空中飞行的无人机来说几秒钟的通信中断可能就意味着碰撞。2.2 通信延迟不确定你的控制环路经不起抖动ROS1的TCPROS默认使用TCP协议TCP的重传机制在丢包时会引入不确定的延迟。对于无人机来说姿态控制环路通常要求1kHz以上的更新率位置控制也要100Hz以上。你用ROS1的topic传IMU数据偶尔来一次TCP重传延迟从2ms跳到50ms你的PID控制器就会输出一个错误的修正量。我做过实测在同样的硬件上ROS1的topic通信在稳定网络下延迟约1-3ms但一旦网络出现轻微拥塞延迟会飙升到20-100ms而且抖动很大。ROS2的DDS默认使用UDP并且支持可配置的QoS策略你可以选择Best Effort模式不重传适合高频传感器数据或者Reliable模式重传适合关键指令延迟可以稳定控制在1ms以内抖动在微秒级。2.3 多机通信每个项目都要重新造轮子ROS1的多机通信需要手动配置ROS_MASTER_URI和ROS_IP每台机器都要设置环境变量而且Master只能有一个。如果你想让两架无人机互相通信要么把其中一架的Master作为中心要么搞一个地面站当Master。这在集群场景下非常别扭。我见过一个项目为了做五架无人机的协同团队花了两周时间写了一个Master选举和同步的中间层结果还是经常出现节点注册失败的问题。ROS2原生支持多机通信DDS的域IDDomain ID机制让同一网络下的不同机器人可以自动发现不需要任何中心节点。你只需要确保所有机器人在同一个DDS域里它们就能自动找到彼此。2.4 实时性支持ROS1基本没有ROS2有希望无人机的底层控制对实时性有要求虽然硬实时通常由飞控单片机比如STM32H7保证但机载计算机上的任务调度也需要一定的实时性。ROS1的节点调度完全依赖Linux的CFS调度器没有优先级继承没有实时锁一个低优先级的日志写入线程可能阻塞高优先级的控制线程。ROS2从设计之初就考虑了实时性支持实时内核如PREEMPT_RTDDS层可以配置线程优先级和CPU亲和性。虽然ROS2本身还不是硬实时系统但至少它提供了向实时方向优化的路径。我在STM32H7上跑micro-ROSROS2的微控制器版本做电机控制配合DMA双缓冲和DDS技术实现高精度波生成整个链路的确定性比ROS1时代好太多。3. ROS2在无人机领域的核心优势不只是“新版本”那么简单3.1 DDS带来的通信革命去中心化与QoSROS2最根本的变化是底层通信从TCPROS换成了DDS。DDS是一个成熟的工业级发布-订阅中间件标准广泛应用于航空、国防、工业自动化领域。它有几个关键特性对无人机特别友好第一去中心化。没有Master每个节点都是对等的通过DDS的发现协议自动找到彼此。这意味着任何一架无人机掉线不会影响其他无人机的通信。我在做无人机集群时用ROS2的DDS域隔离不同编队每个编队内部自动发现编队之间通过桥接节点通信架构非常清晰。第二QoS策略。DDS允许你为每个topic配置服务质量策略包括可靠性Reliable/Best Effort、持久性Transient Local/Volatile、历史记录Keep Last/Keep All、截止时间Deadline、活跃度Liveliness等。对于无人机你可以这样配置IMU数据Best EffortKeep Last 1低延迟优先控制指令ReliableKeep Last 10确保不丢包地图数据ReliableTransient Local新加入的节点能收到最后一份地图心跳信号ReliableDeadline 100ms超时触发告警这种细粒度的控制是ROS1完全做不到的。ROS1只有TCP和UDP两种选择而且不能按topic配置。第三Fast DDS详解。ROS2默认使用Fast DDS以前叫Fast RTPS作为DDS实现但你可以替换成Cyclone DDS、RTI Connext等。Fast DDS在无人机场景下表现不错资源占用适中支持共享内存传输同一台机器上的节点通信可以走共享内存延迟降到微秒级。我在Ubuntu 22.04上跑ROS2 Humble用Fast DDS的共享内存模式机载计算机内部节点通信延迟稳定在50微秒以内。3.2 micro-ROS让STM32也能融入ROS2生态ROS1时代单片机要接入ROS生态非常麻烦通常需要写一个串口桥接节点把自定义的二进制协议转换成ROS消息。micro-ROS的出现彻底改变了这个局面。micro-ROS是ROS2的微控制器版本可以在STM32、ESP32等资源受限的MCU上运行直接支持ROS2的topic、service、parameter等概念。我最近的一个项目用STM32H7做飞控通过micro-ROS和机载计算机上的ROS2节点通信。STM32H7负责IMU读取、电机控制、DMA双缓冲DDS波生成然后通过micro-ROS把姿态数据发布到ROS2网络。机载计算机上的视觉节点订阅这些数据做视觉感知和路径规划再把控制指令发回STM32。整个链路没有自定义协议全部是标准ROS2消息调试起来非常方便。如果你在搜“ros 2 humble micro-ros esp32”或者“stm32 micro-ros”我建议直接从micro-ROS的官方示例开始。ESP32的话用PlatformIO加Docker环境docker microros ros2 humble vscode platformio esp32可以快速搭建开发环境。STM32的话用STM32CubeMX配置UART或者CAN然后集成micro-ROS的静态库。注意micro-ROS对内存要求比较高STM32H7系列比如H743比较合适F4系列可能会比较吃力。3.3 工具链与生态rviz2、ros2 bag、launch系统的进化ROS2的工具链比ROS1成熟太多。rviz2的可视化能力更强支持更多的显示类型而且启动速度更快。ros2 bag可以录制和回放topic数据格式比ROS1的bag更高效支持压缩和分片。launch系统用Python重写比ROS1的XML灵活得多可以写条件判断、循环、参数传递。对于无人机开发我特别推荐几个工具ros2 topic hz查看topic发布频率调试传感器数据流ros2 topic delay测量端到端延迟评估通信质量ros2 param动态调整节点参数不用重启ros2 run rqt_graph rqt_graph可视化节点拓扑ros2 launch管理多节点启动支持组合式启动还有一个很重要的点ROS2的构建系统从catkin换成了colcon。colcon支持并行构建、隔离构建、混合构建同时构建ROS1和ROS2包对于迁移项目非常友好。你可以先用colcon在ROS2环境下构建ROS1的包逐步迁移。3.4 生命周期管理与节点组合ROS2引入了节点生命周期Lifecycle Node的概念节点可以处于Unconfigured、Inactive、Active、Finalized等状态。对于无人机来说这意味着你可以精确控制每个节点的启动顺序和状态转换。比如视觉感知节点必须先进入Active状态路径规划节点才能开始工作如果视觉节点崩溃路径规划节点可以自动进入Inactive状态触发安全降落。节点组合Composition是另一个利器。ROS2允许把多个节点组合到一个进程中减少进程间通信开销。对于机载计算机资源有限的情况你可以把IMU处理、姿态估计、控制律计算组合成一个进程共享内存通信延迟更低CPU占用更少。4. 从ROS1迁移到ROS2实操路径与避坑指南4.1 迁移策略渐进式还是重写如果你有一个成熟的ROS1无人机项目是渐进式迁移还是直接重写我的建议是如果项目还在活跃开发用渐进式迁移如果项目已经稳定运行且没有新功能需求可以先不动但新项目一定用ROS2。渐进式迁移的具体做法是用ros1_bridge包在ROS1和ROS2之间建立桥接把部分节点先迁移到ROS2通过桥接和剩余的ROS1节点通信。ros1_bridge支持双向通信可以桥接topic、service、action。你可以在同一台机器上同时运行ROS1和ROS2用bridge连接。我做过一个项目把视觉感知节点先迁移到ROS2因为视觉算法依赖的OpenCV和深度学习框架在ROS2下更好用。飞控接口节点暂时留在ROS1通过bridge和视觉节点通信。等视觉节点稳定后再迁移路径规划节点最后迁移飞控接口。整个过程花了三个月没有中断项目进度。4.2 安装与环境配置Ubuntu 20.04/22.04的选择ROS1 Noetic官方支持Ubuntu 20.04ROS2 Humble官方支持Ubuntu 22.04。如果你要同时用ROS1和ROS2建议用Ubuntu 20.04装ROS1 Noetic然后从源码编译ROS2 Humble或者用Docker容器隔离。如果只用ROS2直接上Ubuntu 22.04加ROS2 Humble这是目前最稳定的组合。安装ROS2 Humble的步骤Ubuntu 22.04# 设置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 export LANGen_US.UTF-8 # 添加ROS2 apt源 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一键安装步骤”那个脚本确实方便但我建议至少手动装一次理解每一步在做什么。安装完成后跑一下ros2 run demo_nodes_cpp talker和ros2 run demo_nodes_py listener确认通信正常。如果遇到“ros2 command not found”检查环境变量是否source了。4.3 消息定义与接口迁移ROS1的msg和srv文件在ROS2中基本兼容但有一些变化。ROS2的msg文件支持默认值srv文件格式略有不同。迁移时把ROS1的msg文件复制到ROS2包的msg目录下然后在package.xml和CMakeLists.txt中声明。注意ROS2的CMakeLists.txt写法变化很大需要重新组织。对于自定义消息我建议在ROS2中重新设计利用ROS2的新特性。比如可以用bounded sequences替代unbounded提高内存安全性可以用constants定义枚举提高可读性。另外ROS2的IDLInterface Definition Language支持更丰富的数据类型比如多维数组、嵌套结构。4.4 通信模式迁移从topic到QoS配置ROS1的topic迁移到ROS2时默认的QoS是Reliable Volatile Keep Last 10。对于传感器数据这个配置可能不合适。你需要根据数据特性调整QoS。比如数据类型ROS1配置ROS2推荐QoS理由IMU原始数据TCP默认Best Effort, Keep Last 1高频丢一两帧无所谓低延迟优先姿态估计TCP默认Reliable, Keep Last 5关键数据不能丢但可以容忍少量延迟控制指令TCP默认Reliable, Keep Last 10, Deadline 50ms必须可靠且要有超时检测地图/点云TCP默认Reliable, Transient Local, Keep Last 1新节点加入需要最新地图心跳/状态TCP默认Best Effort, Deadline 200ms周期性超时告警配置QoS的代码示例Cauto qos rclcpp::QoS(rclcpp::KeepLast(1)).best_effort().durability_volatile(); auto sub create_subscriptionsensor_msgs::msg::Imu(imu, qos, callback);4.5 实操案例用ROS2 Humble micro-ROS搭建无人机视觉感知链路我拿一个实际项目片段来说明。项目目标无人机通过机载摄像头做视觉感知识别地面目标发布目标位置。硬件机载计算机Ubuntu 22.04 ROS2 HumbleSTM32H7飞控micro-ROSUSB摄像头。软件架构STM32H7读取IMU运行姿态控制通过micro-ROS发布/imu/data和/attitude订阅/cmd_vel机载计算机运行视觉节点订阅/camera/image_raw发布/detected_objects地面站运行rviz2订阅所有topic做可视化关键步骤STM32H7端用STM32CubeMX配置UART波特率921600和DMA集成micro-ROS静态库。初始化micro-ROS创建node、publisher、subscriber。注意micro-ROS的内存池要配置足够大否则会分配失败。机载计算机端安装ROS2 Humble和micro-ROS agent。micro-ROS agent负责和STM32通信把micro-ROS消息转换成标准ROS2消息。启动agentros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 -b 921600视觉节点用OpenCV读取摄像头用YOLO做目标检测把检测结果封装成自定义消息发布到/detected_objects。注意视觉节点的QoS要配置成Best Effort避免图像数据阻塞其他通信。调试用ros2 topic hz /imu/data检查IMU频率用ros2 topic delay /detected_objects检查视觉延迟用rviz2可视化所有数据。这个架构跑下来IMU数据延迟稳定在2ms以内视觉检测延迟约50ms取决于模型大小控制指令延迟1ms以内。整个系统没有自定义协议所有通信都是标准ROS2消息调试和扩展非常方便。5. 常见问题与排查技巧实录5.1 ROS2节点发现失败DDS域和网络配置ROS2节点发现依赖DDS的发现协议默认使用多播。如果多播被网络设备禁用节点就找不到彼此。常见现象ros2 node list为空或者只能看到本机节点。排查步骤检查ROS_DOMAIN_ID是否一致。不同域ID的节点不能通信。默认是0建议不同项目用不同域ID。检查多播是否可用。用ros2 multicast send和ros2 multicast receive测试。如果多播不可用配置DDS使用单播发现。在Fast DDS的XML配置文件中设置初始对等节点列表。检查防火墙是否阻止了DDS端口。DDS默认使用7400-7500端口范围。我踩过的坑在某个项目中交换机默认开启了IGMP snooping但没有querier导致多播发现不稳定。解决方案是配置静态多播或者改用单播发现。5.2 micro-ROS连接不稳定串口参数与内存配置micro-ROS通过串口和agent通信常见问题是连接断开、消息丢失。排查要点串口波特率建议921600或更高115200可能不够。检查STM32的UART时钟配置确保波特率误差小于2%。内存池micro-ROS需要预分配内存池如果池太小创建publisher/subscriber会失败。建议至少分配10KB给节点每个publisher/subscriber额外2KB。看门狗STM32的看门狗可能复位micro-ROS任务导致连接断开。确保micro-ROS任务定期喂狗。电源噪声USB供电的STM32可能因为电源噪声导致串口误码。建议用独立电源或者加滤波电容。5.3 实时性不达标CPU亲和性与优先级配置ROS2节点默认使用Linux CFS调度实时性有限。如果控制环路要求高实时性需要配置使用PREEMPT_RT内核设置节点线程的调度策略为SCHED_FIFO优先级99设置CPU亲和性把控制节点绑定到独立CPU核心配置DDS线程优先级在ROS2中可以通过rclcpp::NodeOptions设置rclcpp::NodeOptions options; options.use_intra_process_comms(true); auto node std::make_sharedrclcpp::Node(control, options);然后在线程启动后用pthread_setschedparam设置优先级。5.4 常见问题速查表问题现象可能原因解决方法ros2 command not found环境未sourcesource /opt/ros/humble/setup.bash节点列表为空域ID不一致或多播问题统一ROS_DOMAIN_ID检查多播topic通信延迟大QoS配置不当传感器数据用Best Effortmicro-ROS连接断开串口误码或内存不足提高波特率增大内存池rviz2启动崩溃显卡驱动问题更新驱动用软件渲染colcon build失败依赖缺失rosdep install --from-paths src节点CPU占用高进程间通信开销大使用节点组合共享内存消息类型不匹配ROS1/ROS2消息定义差异检查msg文件重新编译5.5 独家避坑技巧第一不要在生产环境用ROS2的默认QoS。默认QoS是Reliable对于高频传感器数据会导致缓冲区膨胀和延迟增加。一定要按topic配置。第二micro-ROS的agent要放在机载计算机上不要放在地面站。串口线越短越好避免电磁干扰。第三用ros2 bag录制数据时注意磁盘空间。图像数据很占空间建议只录制关键topic或者用压缩格式。第四迁移ROS1代码时注意ROS2的API变化很大。比如ros::init变成了rclcpp::initros::NodeHandle变成了rclcpp::Node消息头从std_msgs::Header变成了std_msgs::msg::Header。建议用ros1_bridge先桥接逐步替换。第五如果要用ROS2做无人机集群建议用Cyclone DDS替代Fast DDS。Cyclone DDS在多机场景下发现更快资源占用更低。配置方法是在环境变量中设置RMW_IMPLEMENTATIONrmw_cyclonedds_cpp。6. 无人机路径规划与视觉感知在ROS2下的实践扩展6.1 八叉树地图导航从ROS1到ROS2的迁移八叉树地图OctoMap是无人机室内导航常用的环境表示方法。ROS1有octomap_server包ROS2也有对应的octomap_server2。迁移时注意ROS2的octomap_server2订阅的topic类型是sensor_msgs::msg::PointCloud2和ROS1一致参数配置从ROS1的XML launch文件改成ROS2的Python launch文件坐标系变换用tf2ROS2的tf2和ROS1的tf基本兼容但API有变化我在一个室内无人机项目中用ROS2 Humble octomap_server2 Nav2做路径规划。Nav2是ROS2的导航框架比ROS1的move_base更灵活支持行为树Behavior Tree配置。对于无人机需要把Nav2的2D规划器替换成3D规划器比如用octomap做碰撞检测用A或RRT做路径搜索。6.2 视觉感知AMD数据集与施工现场无人机数据如果你在做无人机视觉感知特别是农田语义检测或施工现场监控数据集是个大问题。AMDAgricultural Machine Dataset是一个农田场景的语义分割数据集包含无人机拍摄的农田图像和标注。下载渠道建议通过学术论文的官方链接或者Kaggle镜像。施工现场无人机数据集相对较少可以关注一些开源项目比如用无人机拍摄的建筑工地图像做目标检测。在ROS2下做视觉感知建议用image_transport做图像传输用cv_bridge做OpenCV和ROS消息的转换。注意ROS2的cv_bridge和ROS1的API略有不同主要是命名空间从cv_bridge变成了cv_bridge::消息类型从sensor_msgs::Image变成了sensor_msgs::msg::Image。6.3 无人机集群DDS域隔离与通信优化无人机集群是ROS2最能发挥优势的场景。我的做法是每架无人机一个DDS域域ID从1到N每架无人机内部节点在同一域内通信集群协同节点通过一个桥接节点跨域通信地面站用一个独立域通过桥接节点订阅所有无人机的状态这样做的优点是单架无人机的通信故障不会影响其他无人机集群协同的通信量可控地面站可以灵活选择订阅哪些无人机的数据。通信优化方面集群协同建议用Best Effort Keep Last 1因为集群状态更新频率高丢一两帧不影响整体行为。关键指令比如起飞、降落、返航用Reliable Keep Last 10确保不丢。6.4 无人机电机选型与ROS2的关联电机选型看似和ROS2无关但实际上ROS2的通信频率会影响电机控制指令的更新率。如果你用ROS2做电机控制控制指令的发布频率至少要和电调PWM频率匹配。比如电调支持400Hz PWM那ROS2的控制指令发布频率至少400Hz。如果ROS2通信延迟抖动大电机响应就会不平滑。我的经验是电机控制指令用micro-ROS直接从STM32发布不经过机载计算机的ROS2网络。这样延迟最低确定性最好。机载计算机只负责高级决策比如路径规划、目标识别把期望的姿态或速度指令发给STM32STM32再转换成电机PWM。7. 我的最终建议新项目直接上ROS2老项目规划迁移如果你正在启动一个新的无人机软件项目不要犹豫直接用ROS2 Humble。ROS2的DDS通信、micro-ROS支持、QoS策略、生命周期管理、工具链成熟度在无人机场景下全面优于ROS1。ROS1 Noetic虽然还在维护但官方已经停止新功能开发社区也在逐步迁移。如果你有一个ROS1的老项目先评估如果项目稳定且没有新功能需求可以暂时不动如果有新功能需求或者维护成本高建议用ros1_bridge做渐进式迁移。迁移过程中优先迁移视觉感知、路径规划等计算密集型节点飞控接口节点可以最后迁移。最后分享一个小技巧在Ubuntu 22.04上同时用ROS1和ROS2可以用Docker容器隔离。ROS1 Noetic跑在一个容器里ROS2 Humble跑在另一个容器里用ros1_bridge连接。这样环境干净不会互相干扰。Docker的配置可以参考ros1_bridge的官方示例注意网络模式用host否则DDS发现会有问题。我在实际项目中的体会是ROS2的学习曲线确实比ROS1陡一些主要是DDS概念和QoS配置需要时间理解。但一旦上手你会发现ROS2的架构更清晰调试更方便扩展性更好。特别是micro-ROS的出现让STM32这种单片机也能无缝融入ROS2生态这在ROS1时代是不可想象的。如果你还在犹豫我的建议是花一周时间把ROS2 Humble装好跑通小乌龟和micro-ROS示例然后你就再也不想回ROS1了。