1. 项目概述为什么在 Ubuntu 20.04 上构建无人机软件开发环境不是“选修课”而是硬性入场券你手头有一块 Pixhawk 4 飞控刚买了树莓派 4B 准备做机载计算机或者正打算用 NVIDIA Jetson Nano 跑视觉算法——但你的主力开发机还是 Windows 11。你试过用 WSL2 跑 PX4 SITL结果 Gazebo 启动报错“GLX: failed to create context”ROS2 的 rviz2 界面卡成幻灯片你也尝试过 VMware 安装 Ubuntu却在加载 USB 设备时被dmesg | grep -i usb打出一串device descriptor read/64, error -110。这不是你技术不行而是你还没真正踩进无人机开发的底层逻辑所有主流开源飞控框架PX4、ArduPilot、所有工业级仿真工具链Gazebo ROS2、所有嵌入式 Linux 交叉编译流程其官方 CI/CD 流水线、文档验证环境、社区支持基线全部锚定在 Ubuntu 20.04 LTS 这个发行版上。它不是“随便一个 Linux 就行”而是经过 NASA JPL、ETH Zurich ASL 实验室、大疆创新早期开源团队、PX4 官方 CI 集群连续三年高强度验证的“黄金标尺”。我带过的 7 个校企联合无人机项目里有 5 个在初期因跳过这一步直接上 Ubuntu 22.04 或 CentOS导致 ROS2 Foxy 与 PX4 v1.13 的 C20 ABI 兼容性问题拖慢进度两个月。Ubuntu 20.04 的内核版本 5.4.0、GCC 9.3、CMake 3.16.3、Python 3.8.10 这套组合拳恰好卡在实时性、稳定性、生态兼容性的最佳平衡点上。它不新但足够稳它不炫但能跑通从电机 PWM 输出到 SLAM 建图的全栈链路。你不需要成为 Linux 内核专家但必须理解在这里敲下的每一行sudo apt install都在为后续的make px4_sitl_default gazebo、ros2 launch px4_ros_com sensor_combined_bridge.launch.py、甚至ssh pi192.168.1.100 cd ~/px4_ros_com colcon build奠定原子级可信基础。这不是折腾是给整个开发流水线打地基。2. 环境设计核心逻辑为什么拒绝“一键脚本”坚持手动分步构建很多人看到“Ubuntu 20.04 无人机开发环境”第一反应是搜“一键安装 PX4 ROS2 脚本”。我亲手删掉过 3 个 GitHub 上 star 过千的所谓“全自动部署脚本”原因很现实它们把apt update apt upgrade -y和pip3 install -r requirements.txt当成万能解药却无视了 Ubuntu 20.04 的三个致命陷阱。第一个是APT 源污染国内高校实验室常用清华、中科大镜像源但这些源对ros-foxy-*包的同步存在 2~7 天延迟而 PX4 官方 Dockerfile 明确要求http://archive.ubuntu.com/ubuntu focal main restricted universe multiverse这个原始源才能保证libignition-math6-dev与gazebo11的 ABI 一致性。第二个是Python 环境撕裂sudo apt install python3-colcon-common-extensions会强制安装python3.8-distutils但如果你之前用pyenv装过 Python 3.10colcon build时就会爆出ModuleNotFoundError: No module named distutils.util——因为pyenv的 Python 不带系统 distutils。第三个是NVIDIA 驱动与内核模块冲突网络热词里反复出现的 “nvidia 520” 驱动在 Ubuntu 20.04 内核 5.4.0-186-generic 下必须搭配nvidia-kernel-source-520特定版本否则modprobe nvidia-uvm直接失败Gazebo 渲染器连初始化都过不去。所以我的方案是“三段式隔离”系统层用apt装基础依赖确保内核模块纯净工具链层用curl | bash方式安装colcon、rosdep等 CLI 工具绕过 apt 的 Python 绑定工作区层用venv隔离 Python 包每个 ROS2 包单独pip install -e .。这样做的代价是多敲 20 行命令收益是当你在凌晨三点调试飞控固件上传失败时能精准定位到是dfu-util的 udev 规则没 reload而不是在 17 个 Python 环境中大海捞针。我见过太多人花三天时间重装系统就为了修复一个ImportError: libgazebo_common.so.11根源就是apt install ros-foxy-gazebo-ros-pkgs时顺手装了gazebo11却没意识到 PX4 SITL 需要的是gazebo11的 patched 版本必须从 OSRF 官方源拉取。手动分步不是复古是把控制权攥在自己手里。2.1 系统初始化从裸 ISO 到可信赖开发主机的 7 个不可跳过动作拿到 Ubuntu 20.04.6 LTS Desktop 版 ISO注意必须是 20.04.6不是 20.04.1后者内核缺少CONFIG_RT_GROUP_SCHEDy实时调度补丁刻录 USB 后首次启动别急着点“Install Ubuntu”。先按CtrlAltF2进入 TTY执行sudo nano /etc/default/grub把GRUB_CMDLINE_LINUX_DEFAULTquiet splash改成GRUB_CMDLINE_LINUX_DEFAULTquiet splash rcu_nocbs1 isolcpus2,3 nohz_full2,3 rcu_nocb_poll——这是为后续运行 RT-PREEMPT 内核打伏笔isolcpus把 CPU2、3 从内核调度器隔离出来专供飞控任务绑定。保存后sudo update-grub sudo reboot。重启后进入桌面立刻打开终端执行第一组命令# 动作1锁定内核版本防止自动升级破坏实时性 sudo apt-mark hold linux-image-5.4.0-186-generic linux-headers-5.4.0-186-generic # 动作2更换为官方源清华镜像虽快但这里必须用原厂 sudo sed -i s|http://.*archive.ubuntu.com|http://archive.ubuntu.com|g /etc/apt/sources.list sudo sed -i s|http://.*security.ubuntu.com|http://security.ubuntu.com|g /etc/apt/sources.list sudo apt update # 动作3安装基础编译工具链注意gcc-9而非gcc-11 sudo apt install -y build-essential gcc-9 g-9 cmake git wget curl gnupg2 lsb-release # 动作4配置 GCC 默认版本PX4 CMakeLists.txt 强制要求 GCC 9 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g g /usr/bin/g-9 # 动作5安装 USB 设备权限管理解决 Pixhawk 无法识别 echo SUBSYSTEMusb, MODE0666, GROUPplugdev | sudo tee /etc/udev/rules.d/99-pixhawk.rules sudo udevadm control --reload-rules sudo udevadm trigger # 动作6禁用 swap实时系统大忌 sudo swapoff -a sudo sed -i /swap/d /etc/fstab # 动作7启用 NTP 时间同步飞控日志时间戳精度要求 ±10ms sudo timedatectl set-ntp on这 7 个动作里第 1 条和第 6 条最常被忽略。我曾帮某研究所调试飞控数据不同步问题查到最后发现是systemd-timesyncd服务被禁用飞控板和地面站时间差达 1.2 秒导致 EKF2 位置估计发散。而第 4 条 GCC 版本锁定直接关系到 PX4 的math::constrain()函数汇编指令生成——GCC 11 会优化掉某些内存屏障导致多线程下姿态解算溢出。这些不是“高级技巧”是让环境能跑起来的底线操作。2.2 工具链分层安装为什么apt install ros-foxy-desktop是条死胡同ROS2 Foxy 的官方安装文档写着sudo apt install ros-foxy-desktop但这句话在无人机场景下是巨大误导。ros-foxy-desktop会安装rviz2、ros2cli、rosidl_generator_c等 127 个包其中ros-foxy-gazebo-ros-pkgs依赖gazebo11而 Ubuntu 20.04 官方源的gazebo11版本是11.3.0-1build1但 PX4 SITL 要求的是11.3.0-1ubuntu1~focal1这个后缀差异意味着 OSRF 官方打了 patch修复了gzserver在多线程下std::mutex死锁问题。如果你用apt installapt会优先选官方源的11.3.0-1build1结果make px4_sitl_default gazebo编译通过但./build/px4_sitl_default/bin/px4启动后 3 秒必崩日志里全是pthread_mutex_lock: Invalid argument。正确做法是分三层安装第一层ROS2 基础框架无 GUI# 添加 ROS2 官方源非 Ubuntu 源 sudo apt update sudo apt install -y curl gnupg2 lsb-release curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - echo deb [arch$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main | sudo tee /etc/apt/sources.list.d/ros2-latest.list sudo apt update # 只装核心不装 desktop sudo apt install -y ros-foxy-ros-base python3-argcomplete第二层Gazebo 专用版本OSRF 源# 添加 OSRF 源专供 Gazebo sudo sh -c echo deb http://packages.osrfoundation.org/gazebo/ubuntu-stable lsb_release -cs main /etc/apt/sources.list.d/gazebo-stable.list wget https://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add - sudo apt update # 强制指定版本 sudo apt install -y gazebo1111.3.0-1ubuntu1~focal1 libgazebo11-dev11.3.0-1ubuntu1~focal1 # 锁定版本防升级 sudo apt-mark hold gazebo11 libgazebo11-dev第三层PX4 工具链GitHub 源# Colcon 安装不用 apt避免 Python 冲突 pip3 install -U colcon-common-extensions # ROSdep 初始化关键 sudo apt install -y python3-rosdep sudo rosdep init rosdep update # PX4 依赖注意不是 apt是 pip pip3 install pyserial packaging future这个分层逻辑的本质是ROS2 是通信中间件Gazebo 是仿真引擎PX4 是飞控固件——三者由不同团队维护更新节奏完全不同。强行用 apt 统一安装等于把三个异步时钟强行耦合必然在某个时间点失步。我在珠海航展现场调试某型垂直起降无人机地面站时就遇到ros2 topic list能看到/fmu/out/vehicle_status但ros2 topic echo /fmu/out/vehicle_status却收不到数据最后发现是ros-foxy-rmw-cyclonedds-cpp的 DDS QoS 配置与 PX4 的uORB发布频率不匹配而这个包在ros-foxy-desktop里是默认启用的必须手动sudo apt remove ros-foxy-rmw-cyclonedds-cpp改用rmw-fastrtps-cpp。分层安装让你随时能切换单个组件这是工程化开发的生命线。3. 核心环境搭建实操从零构建 PX4 ROS2 Gazebo 闭环开发流现在进入真正的硬核环节构建一个能编译固件、运行仿真、订阅传感器数据、发送控制指令的完整闭环。不要幻想“下载源码make就完事”PX4 的构建系统是 CMake NuttX POSIX 的三重嵌套任何一个环节出错都会让你卡在ninja: build stopped: subcommand failed.。我们按真实工作流拆解3.1 PX4 固件编译为什么make px4_fmu-v5_default必须在特定目录结构下执行PX4 的构建系统要求工作区必须是Firmware/目录且该目录下必须有boards/、src/、Tools/等子目录。很多人把克隆的仓库放在~/projects/px4/然后cd ~/projects/px4 make px4_fmu-v5_default结果报错CMake Error at CMakeLists.txt:123 (find_package): By not providing Findcatkin.cmake in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by catkin, but CMake did not find one.。这不是缺 catkin而是 PX4 构建系统在cmake/px4_functions.cmake里硬编码了set(ENV{PX4_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})当你的当前路径不是Firmware/时CMAKE_CURRENT_SOURCE_DIR指向错误位置。正确姿势是# 创建标准工作区 mkdir -p ~/px4_ros_com/src cd ~/px4_ros_com/src # 克隆 PX4 固件注意是 Firmware不是 PX4-Autopilot git clone https://github.com/PX4/Firmware.git cd Firmware # 检出稳定版本v1.13.4 是目前最稳的 LTS git checkout v1.13.4 # 初始化子模块关键 git submodule update --init --recursive # 编译前检查PX4 自带的健康检查 make px4_fmu-v5_default check # 执行编译注意这里必须用 make不是 ninja make px4_fmu-v5_defaultmake px4_fmu-v5_default check这步不能跳。它会检查arm-none-eabi-gcc是否在 PATH、python3是否可用、nuttx子模块是否完整。我见过最离谱的案例是某学生git submodule update时网络中断nuttx目录下只有.git文件夹make却不报错直到烧录固件时dfu-util传过去一堆乱码。check命令会扫描nuttx/nuttx/Makefile是否存在缺失则直接退出。编译成功后固件在Firmware/build/px4_fmu-v5_default/px4_fmu-v5_default.px4大小约 1.2MB用file Firmware/build/px4_fmu-v5_default/px4_fmu-v5_default.px4应显示ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]...。如果显示data说明链接失败大概率是arm-none-eabi-gcc版本不对必须是 9-2020-q2-update。3.2 Gazebo SITL 仿真如何让make px4_sitl_default gazebo真正跑起来SITLSoftware In The Loop是无人机开发的“数字孪生”但make px4_sitl_default gazebo默认启动的是iris机型它没有激光雷达、没有 GPS 噪声模型、没有风扰动——这和真实飞行差距太大。我们必须定制自己的sdf模型。以最常见的iris_rplidar为例带 RPLIDAR A2 激光雷达# 进入 Gazebo 模型目录 cd ~/px4_ros_com/src/Firmware/Tools/sitl_gazebo # 创建自定义模型 mkdir -p models/iris_rplidar # 编写 iris_rplidar.sdf核心是添加 plugin 标签 cat models/iris_rplidar/iris_rplidar.sdf EOF ?xml version1.0 ? sdf version1.6 model nameiris_rplidar include urimodel://iris/uri /include include urimodel://rplidar_a2/uri /include joint namerplidar_joint typefixed parentiris::base_link/parent childrplidar_a2::link/child pose0 0 0.1 0 0 0/pose /joint /model /sdf EOF # 启动仿真指定模型和世界 make px4_sitl_default gazebo __verbose1 PX4_SIM_MODELiris_rplidar PX4_SIM_WORLDempty关键参数__verbose1会输出详细日志PX4_SIM_MODEL指定模型名PX4_SIM_WORLD指定 Gazebo 世界文件empty.world在~/.gazebo/worlds/。此时gzclient窗口会弹出但你可能看不到无人机——因为默认视角在(0,0,0)而iris起飞高度是 10 米。按CtrlT打开终端输入ros2 topic pub /fmu/in/vehicle_command px4_msgs/msg/VehicleCommand {command: 176, param1: 3, param2: 0, param3: 0, param4: 0, param5: 0, param6: 0, param7: 0}176 是VEHICLE_CMD_DO_SET_MODE3 是PX4_CUSTOM_MAIN_MODE_AUTO再发ros2 topic pub /fmu/in/vehicle_command px4_msgs/msg/VehicleCommand {command: 22, param1: 1, param2: 0, param3: 0, param4: 0, param5: 0, param6: 0, param7: 0}22 是VEHICLE_CMD_COMPONENT_ARM_DISARM1 是 arm。这时你会看到gzclient里无人机螺旋桨开始旋转悬停在 10 米高度。如果没反应tail -f ~/px4_ros_com/src/Firmware/build/px4_sitl_default/log/latest/px4.log查看INFO [commander] Armed by user是否出现。这个过程不是魔法是 PX4 的commander模块在监听/fmu/in/vehicle_command解析VehicleCommand消息调用arming_state_machine切换状态。理解这个数据流比记住 100 个命令更重要。3.3 ROS2 桥接为什么px4_ros_com是比mavros更优的选择ROS2 生态里mavros是老牌桥梁但它基于 ROS1 的mavlink协议栈对 ROS2 的rclcpp生命周期管理支持薄弱。PX4 官方推荐的px4_ros_com是纯 ROS2 实现用rclcpp::Node封装uORB订阅/发布性能提升 40%。但它的坑在于必须用colcon build编译且CMakeLists.txt里find_package(ament_cmake REQUIRED)必须在find_package(px4_msgs REQUIRED)之前。否则colcon build会报Could not find a package configuration file provided by px4_msgs。实操步骤# 创建 ROS2 工作区 mkdir -p ~/px4_ros_com/src cd ~/px4_ros_com/src # 克隆官方桥接包注意分支 git clone -b foxy https://github.com/PX4/px4_ros_com.git git clone -b foxy https://github.com/PX4/px4_msgs.git # 返回工作区根目录 cd ~/px4_ros_com # 源 ROS2 环境 source /opt/ros/foxy/setup.bash # 编译关键必须用 --symlink-install colcon build --symlink-install --packages-select px4_ros_com px4_msgs # 源工作区 source install/setup.bash # 启动桥接在另一个终端 ros2 launch px4_ros_com sensor_combined_bridge.launch.py--symlink-install参数至关重要。它让colcon不复制文件而是创建符号链接这样你修改px4_ros_com/src/sensor_combined_bridge.cpp后只需colcon build --packages-select px4_ros_com无需重新链接。sensor_combined_bridge.launch.py会启动SensorCombinedBridge节点它订阅 PX4 的sensor_combineduORB 主题转换为 ROS2 的sensor_msgs/msg/Imu消息发布到/sensor_combined。验证ros2 topic echo /sensor_combined应持续输出加速度、角速度、磁场数据。如果卡住ros2 node list看sensor_combined_bridge是否在运行ros2 node info /sensor_combined_bridge查看其订阅/发布关系。这个桥接不是黑盒它是px4_ros_com/src/sensor_combined_bridge.cpp里 200 行 C 代码orb_subscribe(ORB_ID(sensor_combined))获取 uORB 句柄orb_copy()拷贝数据publisher_-publish(ros2_msg)发布。读懂这 200 行你就掌握了 PX4 与 ROS2 交互的全部密码。4. 关键问题排查与避坑指南那些让工程师彻夜难眠的真实故障在无人机开发环境里90% 的问题不是代码 bug而是环境配置的“幽灵错误”。我整理了 5 个高频、高杀伤力问题附带真实日志和秒级定位法4.1 问题Gazebo启动黑屏或崩溃dmesg显示NVRM: API mismatch现象make px4_sitl_default gazebo启动后gzclient窗口全黑终端刷屏Segmentation fault (core dumped)dmesg | grep -i nvidia输出NVRM: API mismatch: the client has the version 520.61.05, but the kernel module has the version 520.56.06。根因NVIDIA 驱动版本与内核模块版本不一致。nvidia-smi显示的驱动版本是用户态/proc/driver/nvidia/version显示的是内核态二者必须完全相同。秒级定位# 查看用户态驱动版本 nvidia-smi --query-gpudriver_version --formatcsv,noheader,nounits # 查看内核态驱动版本 cat /proc/driver/nvidia/version | grep Kernel Module # 如果不一致卸载并重装注意版本号 sudo apt-get purge *nvidia* sudo apt-get autoremove sudo apt-get install nvidia-driver-520 sudo reboot避坑心得不要用ubuntu-drivers autoinstall它会装最新版而 Ubuntu 20.04 内核 5.4.0-186 只认证nvidia-driver-520。我曾因nvidia-driver-535导致 Gazebo 渲染器libGL加载失败耗时 18 小时才定位到。4.2 问题ros2 topic list看不到/fmu/out/vehicle_status但px4进程在运行现象SITL 正常启动ps aux | grep px4显示进程存在ros2 topic list却空空如也ros2 node list也看不到任何节点。根因px4_ros_com的sensor_combined_bridge节点未启动或启动时找不到px4_msgs。秒级定位# 检查工作区是否源正确 echo $AMENT_PREFIX_PATH # 应包含 ~/px4_ros_com/install # 检查 px4_msgs 是否编译成功 ls ~/px4_ros_com/install/share/px4_msgs/cmake/ # 应有 px4_msgsConfig.cmake # 如果没有重新编译 px4_msgs cd ~/px4_ros_com colcon build --packages-select px4_msgs # 启动桥接时加 --debug ros2 launch --debug px4_ros_com sensor_combined_bridge.launch.py避坑心得colcon build后必须source install/setup.bash否则ros2 launch找不到包。很多新手colcon build后直接ros2 launch以为编译完就自动生效这是 ROS2 和 ROS1 的根本区别。4.3 问题make px4_fmu-v5_default报错fatal error: nuttx/config.h: No such file or directory现象编译固件时在src/modules/uORB/uORBManager.cpp报错提示找不到nuttx/config.h。根因nuttx子模块未初始化或损坏。PX4 的nuttx不是独立仓库是Firmware/NuttX/nuttx/的软链接指向Firmware/NuttX目录。秒级定位# 检查 nuttx 目录是否存在 ls -la ~/px4_ros_com/src/Firmware/NuttX/ # 如果是空目录或 broken link重新初始化 cd ~/px4_ros_com/src/Firmware git submodule update --init --recursive # 强制重置 nuttx cd NuttX git reset --hard cd ..避坑心得git submodule update必须在Firmware/目录下执行且网络要稳定。建议在国内用git config --global url.https://ghproxy.com/https://github.com/.insteadOf https://github.com/配置代理注意此处仅为 GitHub 加速非其他用途。4.4 问题ros2 topic echo /sensor_combined数据静止px4日志显示WARN [logger] Logger disabled现象桥接节点运行但传感器数据不更新px4控制台不断打印WARN [logger] Logger disabled。根因PX4 的 logger 模块未启用导致uORB主题不发布。SITL 默认关闭 logger 以节省资源。秒级定位# 在 SITL 终端不是 ROS2 终端输入 pxh logger start -t # 或在启动时加参数 make px4_sitl_default gazebo PX4_LOGGER1避坑心得logger start -t中的-t表示按时间戳记录不加则按循环缓冲区记录数据会覆盖。这是 PX4 的隐藏开关文档里藏得很深。4.5 问题dfu-util -l能看到 Pixhawk但make upload提示No DFU capable USB device available现象USB 线连接飞控lsusb显示Future Technology Devices International, Ltd FT232 Serial (UART) IC但make upload失败。根因Pixhawk 进入 DFU 模式需要硬件复位不是插上线就行。秒级定位# 步骤1断开 USB # 步骤2按住 Pixhawk 的 RESET 按钮小孔 # 步骤3插入 USB 线此时电脑应识别为 STM32 BOOTLOADER # 步骤4松开 RESET 按钮 # 步骤5执行 make upload避坑心得RESET 按钮必须在插 USB 前按住顺序错一点都不行。我用过 7 种 Pixhawk 变体只有 CubeOrange 支持“一键 DFU”其他都必须手动复位。把这个流程贴在工位上比背 100 行代码有用。5. 工程化延伸从开发环境到真实部署的 3 个关键跃迁搭建好 Ubuntu 20.04 环境只是起点真正的工程价值在于如何把开发成果落地。我总结了三个必须跨越的鸿沟5.1 从仿真到真机如何安全地把iris_rplidar模型参数迁移到实物无人机SITL 里iris_rplidar的 PID 参数调得再完美搬到真机上也会失效。因为仿真里gazebo的物理引擎用的是 ODE而真实电机响应有电感、反电动势、机械摩擦。我的迁移方法是“三步缩放”第一步惯量缩放。SITL 中iris的转动惯量Ixx0.0048实物四旋翼用mpu6000测得Ixx0.0032缩放系数k_i 0.0032/0.0048 0.667。第二步电机响应缩放。SITL 中电机从 0 到满油门响应时间 0.02s实测电调电机为 0.08s缩放系数k_t 0.08/0.02 4。第三步PID 参数缩放。将 SITL 中调好的MC_ROLL_P 6.5按公式K_real K_sim * k_i * k_t 6.5 * 0.667 * 4 17.3。实测这个值会让实物无人机剧烈振荡再乘以 0.7 的安全系数最终MC_ROLL_P 12.1。这个过程不是玄学是经典控制论的τ J/β时间常数 转动惯量 / 阻尼系数的工程实践。我带的某农业植保无人机项目就是靠这套缩放法把仿真 3 天调好的参数真机首飞 1 小时就完成悬停。5.2 从单机到集群如何用px4_ros_com构建多机协同通信骨架px4_ros_com默认只支持单机但集群需要uORB主题的跨机路由。PX4 官方方案是mavlink-router但它的 UDP 广播在复杂电磁环境下丢包率超 30%。我的替代方案是ROS2 DDS 自定义 QoS// 在 px4_ros_com/src/vehicle_command_bridge.cpp 中修改 rclcpp::QoS qos_profile(10); qos_profile.reliability(RMW_QOS_POLICY_RELIABILITY_RELIABLE); qos_profile.durability(RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL); qos_profile.history(RMW_QOS_POLICY_HISTORY_KEEP_LAST); // 发布时指定 publisher_ this-create_publisherpx4_msgs::msg::VehicleCommand( /fmu/in/vehicle_command, qos_profile);TRANSIENT_LOCAL确保新加入的无人机能收到历史命令RELIABLE强制重传。配合cyclonedds.xml配置文件把dds.domain.id设为10集群 IDdds.domain.general.allow_multicast设为false强制走单播。这样 5 台无人机在 2.4GHz WiFi 干扰下命令到达率仍保持 99.2%。这个方案比mavlink-router少 2 层协议栈延迟降低 40ms。5.3 从开发到交付如何制作可离线部署的Ubuntu 20.04 PX4定制 ISO客户现场往往没有外网你不能指望他们apt update。我的做法是制作定制 ISO# 用 Cubic 工具Custom Ubuntu ISO Creator sudo apt install cubic cubic # 在 Cubic 界面中 # 1. 选择 ubuntu-20.04.6-desktop-amd64.iso # 2.