news 2026/10/1 7:27:21

WSL2 + ROS 2 无人机多机协同与AI视觉仿真环境搭建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WSL2 + ROS 2 无人机多机协同与AI视觉仿真环境搭建

前阵子导师丢给我一台 Windows 11 笔记本,要求把“无人机多机协同 + AI 视觉”的整套仿真环境跑起来。我第一反应是装双系统 Ubuntu,但折腾一晚上就放弃了——不是因为装不上,而是因为开发过程中要频繁在 Windows 和 Linux 之间切换查资料、传文件、截图,双系统这条路在项目早期实在太费人了。后来我改用 Windows 11 + WSL2,把 PX4、Gazebo、ROS 2、QGroundControl、Android 端全部串起来,最终在笔记本上跑通了多机协同仿真和基于视觉的 offboard 控制。

这篇文章就是我那台机器从零到多机协同的完整过程记录,包括环境选型逻辑、WSL2 的落地细节、PX4 与 Gazebo 的版本泥潭、ROS 2 和 PX4 的通信链路、QGroundControl 的 Windows/Android 双端连接,以及最后 AI 视觉如何接入控制闭环。目标读者很明确:想在自己的 Windows 电脑上搭一套无人机开发环境、又不想为了仿真去装双系统的同学。只要按顺序走,基本可以一次跑通,少走我踩过的那几坑。

1. 这套组合凭什么成立:WSL2、PX4、ROS 2 的取舍逻辑

1.1 为什么最终放弃双系统和传统虚拟机

很多人一想到 Linux 开发环境,第一反应就是“装个双系统”,或者“开个 VMware”。这两种方案我都认真用过,最后都换掉了,原因很直接。

双系统的问题是“切换成本”太高。PX4 源码编译、Gazebo 仿真、ROS 2 节点调试,这些任务分散在一整天的开发流程里,你不可能一直待在 Ubuntu 里。遇到编译报错要查资料、要截图发给同学、要改文档,你就得重启进 Windows;查完再重启回来。一天来回三四次,心态很容易崩。更别说双系统引导损坏、Windows 更新覆盖 GRUB 这类经典事故。

VMware 这类传统虚拟机的问题更致命——性能损耗和 3D 加速。Gazebo 是 OpenGL 渲染的仿真环境,VMware 里经常出现画面闪烁、模型加载缓慢的问题。不少同学搜过“vmware 打开 gazebo 屏幕闪烁怎么办”,我也经历过。那本质上是显卡 3D 加速没有正确透传,折腾 VMware Tools 和加速选项的时间,够重新装两遍系统了。

WSL2 和这两者都不一样。它底层是一个轻量级虚拟机,跑的是真正的 Linux 内核,而不是翻译层模拟。这意味着 PX4 的 CMake 编译、ROS 2 的原生二进制包、Eigen 这些依赖库,都能以接近原生 Linux 的方式工作。与此同时,WSL2 和 Windows 共享文件系统、网络端口、GPU 资源,你可以在 Windows 侧用熟悉的工具看代码、截图、跑 QGroundControl,Linux 侧负责编译和仿真。两边不用重启互相切换,这才是“开发环境”应有的样子。

还有一个容易被忽略的点:Docker Desktop 在 Windows 上的后端就是 WSL2。也就是说,如果你以后想把仿真环境容器化、或者要跑团队统一的 ROS 镜像,这套 WSL2 底子是现成的,不用重新学一套虚拟化方案。

1.2 版本选型是成败的一半:Ubuntu 22.04 与 ROS 2 Humble 的匹配关系

WSL2 只是底座,真正的版本组合才是这套环境能不能稳的命门。我直接给出经过验证的推荐矩阵:

组件推荐版本原因
WindowsWindows 11 21H2 及以上原生支持 WSLg 图形界面,不用装第三方 X Server
WSL2 内核自动更新到最新修复了多个 DDS 组播转发和 localhost 转发问题
Ubuntu22.04 LTS与 ROS 2 Humble 官方支持版本严格对应
ROS 2Humble HawksbillUbuntu 22.04 对应版本,社区文档最全
PX4v1.14 或 main 分支SITL 仿真成熟,uXRCE-DDS 桥接开箱即用
GazeboGazebo Classic 11PX4 官方 SITL 默认模拟器,兼容性最好
QGroundControl最新稳定版Windows 和 Android 都支持,协议兼容 PX4

这里有个很容易被热搜词带偏的点:很多人搜“gazebo 安装 ignition gazebo fortress”,以为 Gazebo 的新版本就是 Fortress。实际上 Gazebo 生态已经分裂了——原本的 Gazebo(经典版)现在叫 Gazebo Classic,新的那套基于 Ignition 架构,软件名改成了 Gazebo Sim,版本号是 Fortress、Garden 这些代号。ROS 2 Humble 里集成的 gazebo_ros_pkg 默认对接的还是 Gazebo Classic 11。而 PX4 官方 SITL 默认模拟器目前也用 Gazebo Classic。所以对这套环境来说,老老实实用 Gazebo Classic 11 最稳,Fortress 留给别的项目去折腾。

ROS 2 用 Humble 而不是 Rolling 或其他版本,理由也很简单:Ubuntu 22.04 的 apt 源里原生提供 Humble 的二进制包,apt install ros-humble-desktop一条命令就装齐。如果你用 Ubuntu 24.04 或 20.04,版本对应关系又不一样,网上大量教程会失效。环境的稳定性优先于尝鲜。

2. Windows 11 上 WSL2 的落地细节:从安装、迁移到图形界面

2.1 安装前置检查与常见报错

WSL2 的安装流程在 Windows 11 上已经简化到近乎无脑,但有几个前置条件不检查的话,会卡在奇怪的地方。

首先确认 BIOS 里的虚拟化已开启。Windows 11 的任务管理器 -> 性能 -> CPU,右下角能看到“虚拟化”是否为“已启用”。如果没启用,需要进 BIOS 打开 Intel VT-x 或 AMD SVM,否则 WSL2 的内核起不来,报错一般是“请启用虚拟机平台 Windows 功能并确保在 BIOS 中启用了虚拟化”。

接着在管理员 PowerShell 里执行:

wsl --install -d Ubuntu-22.04

这条命令会自动做三件事:启用“适用于 Linux 的 Windows 子系统”功能、启用“虚拟机平台”功能、下载安装 WSL2 内核,然后安装 Ubuntu 22.04。第一次执行完,按要求重启系统。

重启后进入 Ubuntu 终端,设置用户名和密码。这里建议记住你设置的用户名,后面 WSL 迁移、Docker 共享、文件权限都会用到。

如果你和我一样,公司电脑可能禁止从商店安装软件,或者网络环境受限,那就走离线安装路线。先到官网下载 WSL2 内核安装包(msi 文件)和 Ubuntu 22.04 的 appx 包,然后:

# 安装内核 wsl_update_x64.msi # 注册系统组件 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart # 安装发行版 Add-AppxPackage .\Ubuntu2204-220630.5-x64.appx

离线安装时要注意 WSL 版本默认可能是 1,务必备份后执行:

wsl --set-default-version 2

装完后确认版本:

wsl -l -v

如果 NAME 旁边显示 VERSION 是 2,就对了。如果是 1,执行wsl --set-version Ubuntu-22.04 2升级。

2.2 把 WSL2 迁移到 D 盘的正确姿势

WSL2 的虚拟磁盘文件默认存储在 C 盘用户目录下的 AppData\Local\Packages 里。这个东西加 Ubuntu 系统、然后随着 PX4 源码、Gazebo 模型、ROS 2 环境、编译中间文件一起长大,很快就能吃到 30-40GB。C 盘是系统盘,空间本来就紧张,所以大概率需要迁移。

迁移的步骤有官方支持的导出/导入法,比直接拷贝 vhdx 安全得多。先把 WSL 关掉:

wsl --shutdown

然后导出到 D 盘:

wsl --export Ubuntu-22.04 D:\wsl-backup\ubuntu2204.tar

然后注销原来的发行版:

wsl --unregister Ubuntu-22.04

注意,unregister会删除原发行版的所有数据,所以导出一定要成功再执行。最后导入到新位置:

wsl --import Ubuntu-22.04 D:\WSL\Ubuntu2204 D:\wsl-backup\ubuntu2204.tar --version 2

导入完成后,WSL 会默认以 root 用户登录,桌面图标可能也丢失,需要执行一次:

ubuntu2204.exe config --default-user yourname

把yourname换成第一步创建的用户名。顺便在 Windows 的开始菜单里把 Ubuntu 图标固定,免得每次都要敲命令进子系统。

2.3 WSLg 与网络模式:为什么 Windows 11 不用装 X Server

老教程里通常会让你在 Windows 上装 VcXsrv 或 X410,再配置 DISPLAY 环境变量才能弹 Linux 图形界面。Windows 11 自带 WSLg,已经把这件事做完了。我在 WSL2 里启动 Gazebo,窗口能直接显示在 Windows 桌面上,像是原生应用一样,不需要任何额外的 X Server。

验证 WSLg 是否正常工作:

echo $DISPLAY

输出:0就说明 WSLg 在工作。如果输出为空,检查 Windows 版本和 WSL 版本,老版本内核不支持 WSLg,wsl --update一下。

网络模式是我这次搭建里遇到的另一个关键点。WSL2 默认的网络模式是 NAT,WSL 内部有一个独立 IP,Windows 和 WSL 之间通过虚拟网卡互通。这在日常使用中问题不大,但 ROS 2 的 DDS 发现机制依赖组播,QGroundControl 连接 SITL 也依赖 UDP 端口转发,NAT 模式下经常出现“Windows 里的 QGC 收不到 WSL 里 PX4 的 MAVLink 数据”这种玄学问题。

解决办法是启用 WSL 的 mirrored 网络模式。在 Windows 用户目录下创建.wslconfig文件:

[wsl2] networkingMode=mirrored

然后wsl --shutdown再启动。mirrored 模式下,WSL2 共享 Windows 的网络栈,IP 地址和 Windows 一样,localhost 直接互通。这样 QGC 连127.0.0.1:14550就能连上 WSL 里的 SITL,ROS 2 节点之间的 DDS 发现也更加顺畅,不用设置ROS_LOCALHOST_ONLY也基本能正常工作。

2.4 英伟达驱动在 WSL2 里的工作方式

后续要跑 AI 视觉,GPU 是绕不开的。很多人的疑问是“WSL2 里英伟达驱动生效吗”——答案是生效,但方式和传统 Linux 不一样。

WSL2 的 GPU 方案是:驱动装在 Windows 侧,WSL2 通过 GPU 半虚拟化(dxgkrnl)直接调用 Windows 的显卡驱动,Linux 侧不需要安装 NVIDIA Linux 驱动。你只需要在 Windows 侧安装最新的 NVIDIA 驱动(包含 WSL2 支持的版本),然后进 WSL2:

nvidia-smi

如果能看到显卡信息,说明 CUDA 调用链路是通的。接着装 CUDA Toolkit 的 WSL-Ubuntu 版本,或者直接用pip install torch跑 PyTorch,都能正常调用 GPU。我在 WSL2 里跑 YOLO 推理,速度基本和原生 Linux 一致,这一点 WSL2 做得比传统虚拟机好太多。

需要参看的一点:WSL2 里共享 GPU 显存并不完全等同于物理机,显存和 Windows 侧是共享的。如果你要在 Windows 上同时开很多图形应用,再在 WSL 里跑大模型推理,显存会有竞争。开发调试阶段完全够用,大规模训练我建议还是留给专门的 Linux 服务器。

3. PX4 与 Gazebo 的仿真环境:版本泥潭与冷启动坑

3.1 从源码跑起 PX4 SITL 的完整过程

PX4 的 SITL(Software In The Loop)仿真,本质是把整套飞控逻辑编译成可执行文件,跑在你的电脑上,通过 Gazebo 模拟真实的物理世界。飞控的每个模块(姿态估计、气压计、GPS、EKF)在 SITL 里都有对应的仿真数据源,所以你可以像操作真机一样,通过 QGC 给它解锁、起飞、切换模式。

依赖安装建议直接用 PX4 官方脚本:

cd ~ git clone --recursive https://github.com/PX4/PX4-Autopilot.git cd PX4-Autopilot bash ./Tools/setup/ubuntu.sh

这个脚本很长,会自动装一系列编译工具链和 Gazebo。如果你的网络比较差,--recursive克隆子模块可能会失败,多点几次或者用代理的方式单独拉取子模块目录都行。

编译并启动仿真:

make px4_sitl gazebo-classic

第一次编译会下载依赖、编译整个 PX4 固件,我试过大约要 15-25 分钟,取决于 CPU。编译完成自动弹出一个 Gazebo 窗口,里面有一架默认的 iris 四旋翼,终端里是 px4 控制台,不断滚动输出消息。到这步 SITL 就活了。

一个细节:Ubuntu 22.04 上,PX4 官方文档在 1.14 之后推荐写gazebo-classic而不是gazebo,因为 PX4 在跟进新版的 Gazebo Sim 支持。如果你用老命令make px4_sitl gazebo,在某些分支会提示需要指定模拟器类型。以官方文档为准,用gazebo-classic最稳。

3.2 首次启动 Gazebo 黑屏:模型下载超时的处理

第一次跑make px4_sitl gazebo-classic,十有八九会遇到 Gazebo 窗口弹出来但世界是灰的,终端里一直在waiting for model...,过好几分钟才出现飞机。这个现象的根本原因不是 PX4 坏了,而是 Gazebo 第一次要去下载飞机模型和传感器模型,这些模型托管在开源服务器上,网络稍差就超时。

验证 + 解决方案如下。首先确认模型是否存在本地缓存:

ls ~/.gazebo/models

如果该目录是空的或者缺 iris,可以手工把 PX4 的模型仓库克隆下来,然后指定资源路径:

git clone https://github.com/PX4/PX4-gazebo-models.git export GZ_SIM_RESOURCE_PATH=$PWD/PX4-gazebo-models

注意 PX4 1.15 之后的模型仓库路径有调整,还能顺便把Tools/simulation/gazebo-classic/sitl_gazebo-classic/models目录显式加进GAZEBO_MODEL_PATH。命令行设置完毕后重新启动仿真,模型加载就从本地读取,黑屏问题基本消失。

此外,如果你的 Gazebo 窗口出现飞机爆炸、乱飞、直接掉落的动画,通常不是仿真的 bug,而是编译时和运行时使用了不同版本的 Gazebo 插件。稳妥起见,PX4 的ubuntu.sh脚本装的是 Gazebo Classic 11,不要手动去把 Gazebo 升级到更高版本,除非你知道自己在干什么。

3.3 多机仿真如何在同一个 Gazebo 世界里跑起来

单机仿真跑通后,多机协同才是标题里的重头戏。PX4 官方提供了一套多机 SITL 脚本,能直接在一个 Gazebo 世界里生成多架飞机:

cd ~/PX4-Autopilot/Tools/simulation/gazebo-classic ./sitl_multiple_run.sh

这个脚本默认启动 3 架 iris,每架飞控一个独立进程,端口递增,Gazebo 世界里能看到三架飞机。如果你想手动控制飞机数量,脚本里有参数,也可以在已有的仿真基础上再启动新实例:

# 先启动第 0 号实例 make px4_sitl gazebo-classic # 新开终端,启动第 1 号实例 PX4_SIM_MODEL=iris ./build/px4_sitl_default/bin/px4 -i 1 # 再开终端,启动第 2 号实例 PX4_SIM_MODEL=iris ./build/px4_sitl_default/bin/px4 -i 2

每个实例自动分配不同的系统 ID 和 MAVLink 端口,QGC 默认会自动发现所有在广播的无人机。这就搭起了多机协同的下层基础——多套飞控、共享一个仿真物理世界,彼此物理上可见、会碰撞,控制上又是独立的。

一个经验之谈:多机仿真对电脑性能的要求是线性增长的。3 架 iris 在 i7 + 16G 内存的笔记本上还能流畅跑,5 架以上就要关掉 Gazebo 的实时渲染或者降低图形质量,再往上最好用无 GUI 的 headless 模式跑。

4. ROS 2 与 PX4 的通信链路:从 uORB 到 DDS 的桥怎么搭

4.1 PX4 内部的 uORB 机制和它在 ROS 2 通信中的角色

PX4 的核心是一个叫 uORB 的发布/订阅消息总线。飞控内部的传感器数据、姿态估计、位置控制状态,全都通过 uORB topic 在模块之间流动。比如vehicle_attitude是姿态四元数,vehicle_odometry是里程计,offboard_control_mode是 offboard 模式切换指令,trajectory_setpoint是期望轨迹点。

问题是 uORB 是 PX4 自己的一套机制,ROS 2 看不懂,反之亦然。两者之间需要一座“桥”。老办法是 Fast-RTPS 桥,新版本 PX4 已经用 uXRCE-DDS(micro eProsima XRCE-DDS)取代了它。

uXRCE-DDS 的思路是在 PX4 内部跑一个 XRCE 客户端(client),在飞控外部跑一个 XRCE 代理(agent),两者之间用轻量的 XRCE 协议通信,agent 再把数据转换成完整的 DDS 消息进入 ROS 2 的世界。整个过程可以概括成四层:

Gazebo 物理仿真 -> PX4 SITL(uORB) -> XRCE Client -> UDP -> DDS Agent | v 用户程序(rclpy / MAVSDK) <- ROS 2 topics <- DDS 域

这个架构的好处是职责清晰:PX4 只负责飞控逻辑,ROS 2 只负责应用层决策和 AI,两者通过标准消息接口解耦。多机场景下,每架 PX4 实例就是一个独立的 XRCE 客户端,可以分别连到不同的 agent 端口,在 ROS 2 侧用命名空间区分。

4.2 uXRCE-DDS 桥接的配置与启动顺序

先从源码安装 agent:

git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git cd Micro-XRCE-DDS-Agent mkdir build && cd build cmake .. make sudo make install

然后先启动 agent,监听 UDP 8888 端口:

MicroXRCEAgent udp4 -p 8888

接着再启动 PX4 SITL:

cd ~/PX4-Autopilot make px4_sitl gazebo-classic

PX4 SITL 默认会启动 uXRCE-DDS 客户端去连127.0.0.1:8888,这和 agent 正好对上。如果在 QGC 里想改配置,参数名是UXRCE_DDS_CFG,默认配置就是 UDP 8888,不用额外设。

启动顺序建议是:agent 先起来,PX4 SITL 后起来。如果顺序反了,PX4 客户端连接失败会反复重试,虽然最终也能连上,但会浪费时间且日志刷屏。

4.3 验证通信:ros2 topic 看到飞机状态的完整命令与预期输出

通信是否打通,最直观的验证就是 ROS 2 能看到 PX4 的 topic。新开一个终端,先加载 ROS 2 环境:

source /opt/ros/humble/setup.bash

然后列出话题:

ros2 topic list

如果桥接成功,你会看到类似这样的输出:

/fmu/out/vehicle_attitude /fmu/out/vehicle_odometry /fmu/out/vehicle_status /fmu/in/offboard_control_mode /fmu/in/trajectory_setpoint

注意/fmu/out/前缀是 PX4 向外部发布的主题,/fmu/in/是接收外部指令的主题。查看具体的姿态:

ros2 topic echo /fmu/out/vehicle_attitude

能看到四元数在实时刷新,说明 PX4 内部的状态已经走进了 ROS 2 数据域里。至此,ROS 2 能读状态、能发指令,整个通信链路就算打通了。

一个常见的坑:如果你在 WSL2 里跑 ROS 2 和 agent,又在 Windows 上的某个容器或另外一台机器跑 ROS 2 节点,两边的 DDS discovery 可能因为网络安全策略互相看不到对方。优先保证所有 ROS 2 节点都在同一个 WSL2 发行版内,等单机调试通了,再考虑跨机器组网。

5. QGroundControl 与 Android 端:多机的地面控制与移动调试

5.1 QGC 连接 SITL 的参数与网络配置

QGroundControl 是 PX4 的官方地面站,Windows 原生版本直接去官网下载安装即可。SITL 模式下,PX4 默认在 UDP 14550 端口上广播 MAVLink 数据。大多数情况下,打开 QGC 会自动连接上 WSL2 里的 SITL,因为 QGC 默认监听 UDP 14550。

如果自动连接没生效,手动添加连接方式:

  • 点击左上角“通信链路”设置 -> 添加 -> UDP
  • 端口填写14550,目标地址留空或填127.0.0.1
  • 保存,QGC 应该立刻显示无人机状态、姿态、电池图标

WSL2 早期 NAT 模式下 QGC 偶尔收不到数据,我提过的.wslconfigmirrored 网络模式可以根治这个问题。确保你改完配置后用wsl --shutdown重启过一次 WSL。

QGC 在工作流里承担的角色不只是“看飞机状态”,它还负责参数设置和校准。PX4 的很多关键参数,比如UXRCE_DDS_CFG、飞控 ID、机架类型,都可以在 QGC 的参数面板里改,改完直接写入 SITL 实例,比命令行改方便太多。

5.2 Android 版 QGC:手机连飞机的三种网络路径

Android 版 QGC 是同一套软件,手机端的价值在于现场调试和演示——不需要背着笔记本,拿手机就能看飞机状态、切换模式、触发返航。

手机要连上 WSL2 里的 SITL,有三种路径,按推荐程度排序:

第一种,最省事:如果 WSL2 开了 mirrored 网络模式,WSL 里的服务和 Windows 共享网络栈。手机和电脑连同一个 Wi-Fi 时,直接在手机 QGC 里添加 UDP 连接,目标地址填电脑的局域网 IP,端口填 14550,就能收到 SITL 的数据。

第二种,老版本 WSL2 NAT 模式:手机无法直接访问 WSL 的虚拟网卡 IP,需要在 Windows 上做一个 UDP 端口转发。以管理员身份运行 PowerShell,把 Windows 的 14550 端口转发到 WSL 的 IP:

netsh interface portproxy add v4tov4 listenport=14550 listenaddress=0.0.0.0 connectport=14550 connectaddress=<WSL2_IP>

其中<WSL2_IP>需要先通过wsl hostname -I查出来。注意 WSL2 重启后 IP 可能变化,需要重新执行。

第三种,彻底绕开 WSL 网络:在 WSL2 里启动一个 MAVLink 路由器,把 SITL 的消息转发到局域网 IP,手机再直连。这种方案适合后续要组多机、UDP 端口冲突的场景,复杂度也更高。

实际开发中我最常用的是第一种。手机 QGC 界面和桌面版基本一致,飞行轨迹、姿态仪表、参数面板都有。

5.3 多机协同中 QGC 的职责边界:MAVLink 转发与日志回放

多机协同场景下,QGC 不只是监控界面,还承担了很重要的调试职能。3 架飞机同时在 Gazebo 里飞,QGC 会自动发现多个连接,每个连接对应一架飞机。在通信链路面板里,你可以给每个链接命名,比如 drone0、drone1、drone2,切换查看每架飞机的状态。

调试编队算法时,经常需要知道“某一时刻每架飞机收到的指令是什么”,QGC 的 MAVLink 日志回放功能非常有用。我习惯在跑多机协同实验时全程开启日志记录,跑完在 QGC 里回放,能看到每架飞机的飞行姿态和指令人机接口的完整时间线,定位算法问题比盯着实时终端高效得多。

QGC 不负责编队算法本身,它只提供监控和调试。真正的协同逻辑写在 ROS 2 节点里。边界要清楚:QGC 是地面站,不是机载大脑。

6. 从仿真到 AI 多机协同:最后一公里的控制闭环

6.1 多机协同的核心难点分布:发现、通信、决策、避碰

当 ROS 2 和 PX4 通信跑通、多架飞机能同时升空之后,多机协同真正的难点才开始浮现。以我的实践观察,难点集中在四个方面:

第一是“发现”。多机场景里,每架飞机要有唯一标识,ROS 2 侧要用命名空间或 topic 前缀区分不同飞机。我习惯的做法是每架飞机配一个独立 agent 端口,然后在 ROS 2 里为每个飞机的节点组设置命名空间drone0、drone1。这样/drone0/offboard_control_mode就不会和/drone1/offboard_control_mode互相干扰。

第二是“通信”。PX4 内部消息是 uORB,ROS 2 决策节点的消息是 DDS,跨飞机交互如果依赖 DDS discovery,多机和单机的 QoS 策略差异会立刻暴露。相比 TCP,DDS 的默认可靠传输在仿真高负载时会有明显延迟抖动。实际调试中,控制类的 topic 我尽量用 best-effort QoS,状态监控类用 reliable QoS,混用两种策略才能既保证实时性又不丢关键状态。

第三是“决策”。编队控制、任务分配、目标跟踪,这些算法跑在 ROS 2 层。我用的是经典的 leader-follower 思路:一架 leader 按预设轨迹飞行,几架 follower 订阅 leader 的位姿,结合自身位姿计算期望偏移,再生成各自的 offboard setpoint。这个模式实现简单,适合从零起步的多机项目。

第四是“避碰”。这是多机系统里最容易出事故的环节。仿真里飞机碰撞虽然不会导致炸机损失,但会让后续逻辑全乱。起步阶段我建议先在任务层避免冲突——给每架飞机分配不同的高度层或不同的任务区域,别指望 PX4 自带编队避碰功能,它在很多版本里压根不提供。

6.2 把 YOLO 检测接入 offboard 控制的完整链路

AI 视觉接入多机协同,本质就是让决策节点能“看到”世界,然后输出 setpoint 指令。我在 WSL2 里用 PyTorch 和 YOLO 做目标检测,跑在 Gazebo 的机载相机图像上,再接进 ROS 2 控制环。

节点结构大致是三层:

第一层,图像源。Gazebo 里的相机模型会把图像发布为 ROS 2 的sensor_msgs/Image,或者你直接在仿真环境里配置机载相机的话题。我是在 iris 模型上挂了一个模拟 RGB 相机,topic 名/drone0/camera/image_raw。

第二层,视觉检测。用 rclpy 写一个订阅节点,收到图像后交给 YOLO 模型推理,输出目标类别和检测框。检测结果发布为自定义消息,比如包含目标中心坐标和帧中心偏移量。

第三层,控制节点。订阅检测结果,把“目标在画面中心偏左多少像素”转换成“向左移动多少速度”,然后通过 PX4 提供的 offboard 控制 topic 发送速度指令。核心伪代码逻辑如下:

import rclpy from rclpy.node import Node from geometry_msgs.msg import TwistStamped from px4_msgs.msg import OffboardControlMode, TrajectorySetpoint class VisionController(Node): def __init__(self): super().__init__('vision_controller') # 订阅检测结果 self.detection_sub = self.create_subscription(Detection, '/detection', self.on_detection, 10) # 发布 offboard 控制模式 self.offboard_pub = self.create_publisher(OffboardControlMode, '/fmu/in/offboard_control_mode', 10) self.traj_pub = self.create_publisher(TrajectorySetpoint, '/fmu/in/trajectory_setpoint', 10) def on_detection(self, msg): # 计算像素偏差 -> 期望速度 vx = self.kp * msg.x_error vy = self.kp * msg.y_error # 发布 offboard 模式和期望轨迹点 self.publish_offboard(vx, vy, 1.0) # 稳定高度 1m

实际跑的时候有两个关键细节。第一,offboard 模式的进入需要在 QGC 或代码里先解锁,然后切换模式,等待 PX4 确认进入后再持续发送 setpoint;如果 setpoint 发送频率低于 2 Hz,PX4 会自动退出 offboard 模式。第二,在仿真里你的视觉控制环是有延迟的,Gazebo 渲染图像、YOLO 推理、指令回传给飞控,整个过程可能有几百毫秒。要在控制增益上留足裕度,否则飞机会出现类似“醉汉”的震荡航迹。

6.3 关于这套环境,我拆过不少坑之后想说的几点

最后分享几条实操体会,都是这次搭建过程中反复折腾换来的。

项目源码和 workspace 一定要放在 WSL2 的 Linux 文件系统里(比如~/PX4-Autopilot),不要放到/mnt/c/下。WSL2 访问 Windows 文件系统存在明显的 I/O 性能损耗,PX4 这种包含几万个头文件的 C++ 工程,在/mnt/c/下编译时间能翻倍。我第一次不知道,放在 C 盘项目目录里编译,每次改代码都要等很久才发现根因。

组件之间要一件一件验证。WSL2 装好了先验证网络和图形界面,PX4 单机仿真跑通了再上 ROS 2 桥,桥通了再接 QGC,最后才做多机和 AI。每一步的验证时间也许只要几分钟,但跳步的排查成本是按小时算的。有一次我以为 ROS 2 和 PX4 的桥没问题,直接上多机,结果发现 topic 全是单机的,排查半天才知道是 agent 端口配置不对,每架飞机各自连了同一个 agent。

.wslconfig这个文件值得反复调。mirrored 网络模式、内存上限、CPU 核数,都能在这里配置。我现在的配置是内存限制 12GB、8 核,跑 3 架 iris + YOLO 推理仍然流畅。如果 Gazebo 频繁崩溃或者 WSL 整体卡顿,先调这里,而不是重装。

这套环境最大的价值在于:它把“多机协同 + AI 视觉”烧钱且危险的开发过程,搬进了一个完全可复现、可回放、可试错的仿真环境。当你在仿真里把 offboard 控制、视觉检测、编队逻辑全部调顺之后,真机开发只是在同样的控制架构上换掉数据来源而已——飞控逻辑、通信链路、决策节点都不变。对于刚开始做无人机方向的同学,这条从 Windows 桌面到多机 AI 仿真的路径,省下来的不只是时间,更是很多次真机调参的提心吊胆。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 7:26:41

智能体平台Dify的可观测性与MCP:把调用链日志接到TaoToken统一通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 7:26:38

2026香港公司注册代理怎么选?

一、代理机构的核心作用是什么 2026年香港公司注册的政策环境已发生多项调整&#xff0c;包括公司秘书合规审查趋严、银行开户尽调标准提高&#xff0c;以及注册地址证明文件要求升级。这些变化意味着&#xff0c;仅靠一纸注册证书已无法满足实际经营需求。代理机构的核心价值在…

作者头像 李华
网站建设 2026/10/1 7:24:23

偶发bug排查实战:串口、蓝牙、烧录三类问题三板斧

过去这一个月&#xff0c;我被三个偶发 bug 磨掉了半层皮&#xff1a;串口打印偶尔顿住、蓝牙连着连着就断、还有一批板子在烧录时随机失败。三个问题看起来毫无关联&#xff0c;但真查下来&#xff0c;用的都是同一套思路——先别急着改代码&#xff0c;先把“偶发”变成“必现…

作者头像 李华
网站建设 2026/10/1 7:23:33

拼多多省钱月卡拆解:付费会员如何用沉没成本锁住下沉用户

简介&#xff1a;这份PDF以拼多多省钱月卡为核心案例&#xff0c;系统拆解付费会员的层级模型与运营思路&#xff0c;面向电商运营、会员体系设计及增长策略相关从业者&#xff0c;帮助读者理解年卡制与月卡制的差异、权益分层逻辑与用户留存方法。资源包共1个PDF文件&#xff…

作者头像 李华