
先说个背景最近我手上有个小项目要在 Gazebo 仿真里做无人机自主避障底层方案选了 ROS2 和 PX4 对接。做之前我以为难点在规划算法真正动手才发现光是让两边通信稳定、数据能对上就已经能写一篇万字踩坑记了。标题里说的四个 ROS2 发行版我全都实际用过一轮PX4 从 v1.13 到 v1.14.3 也测过一遍。这篇文章就把整个流程捋清楚版本怎么选、通信机制是什么、环境怎么搭、数据怎么调通最后把那些让人抓狂的坑集中列出来。适合看这篇的人大概分三类刚入门 ROS2 想接 PX4 的学生、正在做无人机/机器人项目但被版本问题卡住的开发者、以及想从 MAVROS 迁移到 ROS2 原生方案的工程师。文章里会涉及 Ubuntu、Docker、PX4 源码编译、micro-ROS Agent 这些基础概念但我会尽量讲得直白命令可以直接抄。1. 先解决版本选型Humble、Iron、Jazzy、Rolling 到底选哪个我刚接触这题的时候第一反应是「不就是装个 ROS2 吗」结果打开官网一看四五个发行版摆在那儿每个对应的 Ubuntu 版本还不一样直接懵了。所以先把这个最基础的问题解决掉。1.1 四个版本的定位区别ROS2 的发行版命名是有规律的Humble Hawksbill、Iron Irwini、Jazzy Jalisco、Rolling Ridley名字结尾字母是按 A、B、C 这样往下排的。但真正的区别在于发布周期和支持期限。发行版发布时间推荐 Ubuntu支持周期类型Humble Hawksbill2022.0522.04至 2027.05LTSIron Irwini2023.0522.04至 2024.11非 LTSJazzy Jalisco2024.0524.04至 2029.05LTSRolling Ridley滚动更新最新无固定期限滚动版LTS 的意思是长期支持版ROS2 的 LTS 一般是 5 年维护周期适合做产品和项目。非 LTS 版本只维护 1 年多适合尝鲜和给开发者测试新特性用。Rolling 则是永远在滚动的开发版今天装完明天可能就有大更新不太适合做正经项目。1.2 版本选型的实际逻辑我的建议很简单做项目优先 Humble其次是 JazzyIron 和 Rolling 除非你有特殊需求否则不要碰。为什么优先 Humble因为目前 ROS2 生态里教程最多、社区问答最丰富、第三方包兼容性最好的就是 Humble。你随便搜一个问题十有八九是在 Humble 环境下解决的照着抄就行。PX4 官方文档和示例在 Humble 下跑得也最顺畅。我自己在 Humble 上配 PX4 v1.14.3基本没有遇到因为发行版差异导致的兼容问题。Jazzy 是 2024 年 5 月出的新 LTS对应 Ubuntu 24.04支持周期到 2029 年。如果你是全新项目、又不介意一些旧工具链还没跟上的话直接上 Jazzy 也挺好毕竟 PX4 的新版本对 Jazzy 的支持也在逐步完善。但要注意一点很多老教程里的命令在 Jazzy 上可能会有差异排查问题时要多留个心眼。Iron 这个版本比较尴尬非 LTS 周期已经结束了你搜到的好多答案在 Iron 上可能已经过时唯一的价值就是测试一些 Humble 没有的新特性。Rolling 就更不用说了除非你想当小白鼠否则别在生产环境里用。这里还要顺带说一个新手特别容易搞混的点ROS2 的发行版和 PX4 的固件版本不是一一对应的关系。ROS2 选 HumblePX4 可以用 v1.13、v1.14、v1.15反过来ROS2 用 JazzyPX4 也能跑。真正约束你的是通信中间件的版本和接口定义方式后面细说。2. PX4 和 ROS2 的对接机制为什么现在都用 uXRCE-DDS搞清楚版本之后下一个核心问题是PX4 和 ROS2 到底是怎么通信的这里涉及到 PX4 内部的软件架构和 ROS2 底层的 DDS 机制不理解这个后面出问题你根本不知道从哪里排查。2.1 从微内核到分布式PX4 的消息总线 uORBPX4 自动驾驶仪的架构是微内核式的内部有很多独立运行的小模块姿态估计、位置控制、航向控制、传感器驱动等。这些模块之间不直接调用函数而是通过一个叫 uORB 的轻量级消息总线来交换数据。比如 GPS 驱动把位置数据发布到vehicle_gps_position话题上位置控制器订阅这个话题来获取当前位置。这个设计非常像 ROS 的话题通信但它是纯内部机制外部程序不能直接读到。早期的方案是 MAVROS 通过 MAVLink 协议和 PX4 通信MAVLink 主要传输的是飞行状态、指令、遥测数据带宽有限而且消息格式是预先定义好的不够灵活。后来 PX4 引入了 RTPS/DDS 通信能力v1.13 及之前叫 micro-ROS / Fast DDSv1.14 开始改成了 uXRCE-DDS。这套机制的核心思路是把 PX4 内部的 uORB 话题通过一个「桥梁」暴露给外部 DDS 网络这样 ROS2 就能用标准的 DDS 协议直接订阅和发布。2.2 uXRCE-DDS 是怎么工作的uXRCE-DDS 这个名字看起来复杂拆开就很简单。uXRCE 是 Micro XRCE-DDS 的缩写专门为资源受限的嵌入式设备设计的 DDS 实现。PX4 作为 XRCE 客户端micro-ROS Agent 作为服务端两者通过 UDP 或串口通信。数据流向是这样的PX4 内部的传感器数据先发布到 uORB 话题然后 uXRCE 客户端把数据序列化通过 UDP 发送给 AgentAgent 收到后再以标准 DDS 消息的身份发布到 ROS2 网络。反过来ROS2 节点往话题里发消息Agent 接收后序列化传输给 PX4PX4 再把数据写进 uORB 话题。我打个比方Agent 就像是一个翻译官PX4 说的是自己的方言 uORBROS2 说的是普通话 DDS翻译官把两边的话互相翻译两边都觉得自己在跟对方直接对话。这里有个关键点ROS2 侧的节点看到的不是 PX4 本体而是 Agent 这个节点。所以你在ros2 topic list里看到的话题名类似/fmu/out/vehicle_attitude意思是「FMU 输出的姿态话题通过 uXRCE 转发」。2.3 和 MAVROS 的差异对比很多人会问MAVROS 用了这么多年为什么还要折腾这套我整理了一个对比一目了然。对比项MAVROS MAVLinkuXRCE-DDS ROS2消息类型固定 MAVLink 消息PX4 uORB 消息可自定义传输方式串口/ UDP文本二进制混合DDS严格二进制序列化带宽利用率较低有协议开销较高二进制紧凑延迟几十毫秒级毫秒级灵活性需要解析 MAVLink 字段直接使用 ROS2 标准接口学习成本MAVLink 协议要专门学熟悉 ROS2 即可实际体验下来uXRCE-DDS 在传输高频数据IMU 200Hz、姿态 250Hz时明显更顺畅。还有一个好处是你可以直接用 ROS2 的原生工具链比如ros2 topic echo、rqt_graph不用额外引插件。所以结论是新项目直接用 uXRCE-DDS别走 MAVROS 的老路了。MAVROS 目前仍有价值的地方在于地面站相关的串口通信场景但纯粹做 ROS2 对接DDS 是更现代的选择。3. 环境配置全流程从 Ubuntu 到 PX4 工具链版本和机制都清楚了下面开始实际操作。这一节我把从零到能跑通通信的完整步骤走一遍默认你的电脑是 x86_64 架构系统是 Ubuntu 22.04ROS2 选 HumblePX4 选 v1.14.3。3.1 ROS2 Humble 安装与初始化ROS2 官方推荐用 apt 安装。先把软件源加上然后把 ROS2 的 GPG 密钥导进来这里要注意官方源在国内访问速度一般建议直接把源换成国内镜像站具体操作不展开大家根据自己的网络情况选关键是确保能正常apt update。sudo apt update sudo apt install curl gnupg lsb-release 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 $(lsb_release -cs) main | sudo tee /etc/apt/sources.list.d/ros2.list /dev/null sudo apt update然后安装 ROS2 Humbo 桌面版包含 rviz、demo、tutorials 这些常用工具sudo apt install ros-humble-desktop python3-argcomplete装完之后记得把环境变量加进~/.bashrc不然每次开终端都要手动 source 一遍。这个问题新手常常遇到我在后面问题排查部分会细讲。echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc最后安装一些开发工具ROS2 的生态用的是 colcon 构建工具sudo apt install python3-colcon-common-extensions python3-rosdep3.2 PX4 源码与仿真环境PX4 的代码托管在 GitHub 上v1.14.3 是很多教程默认的稳定版本。clone 的时候一定要带--recursive因为 PX4 有很多子模块少了会编译不过。git clone --recursive -j8 https://github.com/PX4/PX4-Autopilot.git --branch v1.14.3 cd PX4-AutopilotPX4 官方提供了一个自动化脚本自动安装所有依赖一步到位bash ./Tools/setup/ubuntu.sh这个脚本会装很多工具链包括 gazebo 仿真、交叉编译工具、Python 依赖等耗时比较长建议找个网络好的时候跑。装完之后就可以编译仿真固件了v1.14 里推荐用 Gazebo 的 Harmonic 版本make px4_sitl gz_x500这条命令会编译 SITLSoftware In The Loop仿真固件然后启动 x500 四旋翼模型。第一次编译大概要十分钟左右之后就快了。编译过程中如果提示缺少依赖看一下是会报具体包名还是编译错误。前者用 apt 装就行后者基本都是子模块没更新完全重新git submodule update --init --recursive再编译。3.3 micro-ROS Agent 的两种部署方式PX4 侧的 uXRCE 客户端是内置在固件里的但 ROS2 侧的 Agent 需要单独跑。有两种方式Docker 一键启动和源码编译我两个都试过简单对比一下。Docker 方式最省事拉镜像直接跑docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --nethost microros/micro-ros-agent:humble udp4 --port 8888 -v6注意这里镜像标签humble要和你的 ROS2 版本匹配如果你用的是 Jazzy就拉jazzy标签。源码编译方式稍微麻烦一点但好处是不依赖 Docker也不会遇到镜像拉不下来的问题git clone -b humble https://github.com/micro-ROS/micro-ROS-Agent.git cd micro-ROS-Agent rosdep install --from-paths src --ignore-src -r -y colcon build source install/local_setup.bash编译完成之后启动 Agent 的命令是ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888 -v6udp4表示用 IPv4 UDP 传输--port 8888是 PX4 默认连接的端口-v6是日志等级调到最高方便排错。3.4 编译 px4_ros_com 接口包Agent 启动之后ROS2 侧还需要一个接口描述包px4_ros_com它负责把 PX4 的 uORB 消息定义转换成 ROS2 的 msg 格式这样 ROS2 才知道/fmu/out/vehicle_attitude里每个字段是什么意思。git clone https://github.com/PX4/px4_ros_com.git cd px4_ros_com colcon build source install/local_setup.bash这个过程会生成一堆px4_msgs消息定义包括VehicleAttitude.msg、VehicleLocalPosition.msg、OffboardControlMode.msg等。编译成功后你可以直接在install/px4_msgs/share/px4_msgs/msg/目录下看到这些文件。我建议把source install/local_setup.bash也写进.bashrc不然每次新终端都要手动 source。注意顺序先 source ROS2 的 setup再 source px4_ros_com 的 setup顺序反了可能会出问题。4. 数据通信实战让 ROS2 和 PX4 真正对上话环境都搭好了现在开始最激动人心的部分——让数据流动起来。我按「启动顺序 - 验证话题 - 订阅发布 - Offboard 控制 - 自定义消息」这个路线走。4.1 启动顺序与连接检查启动顺序很重要基本原则是先启动 Agent再启动 PX4。因为 PX4 启动的时候会主动去寻找 Agent如果你还没开 AgentPX4 会一直重试虽然开了之后也能连上但日志会多一堆报错容易干扰判断。第一步打开终端 A启动 Agentros2 run micro_ros_agent micro_ros_agent udp4 --port 8888 -v6第二步打开终端 B进入 PX4 目录启动 SITLcd PX4-Autopilot make px4_sitl gz_x500启动后如果是默认配置PX4 会自动作为 uXRCE 客户端连接本机的 8888 端口。如果不放心可以在 QGroundControl 的 MAVLink Console 里执行这条命令手动启动客户端uxrce_dds_client start udp -p 8888看到 Agent 那边打印出类似Client connected的日志就说明 PX4 已经连上 Agent 了。这一步是整个对接的命门很多人卡在这里后面我会列具体排查点。4.2 用 ros2 topic 验证消息流连上之后开一个终端 Csource 环境然后ros2 topic list正常情况下你会看到一堆/fmu/out/开头的话题比如/fmu/out/vehicle_attitude飞行器姿态四元数/fmu/out/vehicle_local_position机体坐标系下的位置和速度/fmu/out/vehicle_odometry里程计融合输出/fmu/out/sensor_combinedIMU 加速度和角速度原始数据/fmu/out/battery_status电池电压和电流如果你想看某个话题的内容用 echoros2 topic echo /fmu/out/vehicle_attitude然后手动在 Gazebo 里拖动一下无人机或者用键盘控制它前后左右移动你会发现话题里的四元数在变化。这就是数据通信的最佳证明。这里要提一个细节PX4 很多高频话题的数据量很大直接在终端里 echo 会有几百行刷屏建议加上过滤条件ros2 topic echo /fmu/out/vehicle_attitude --field attitude只打印 attitude 字段输出的内容是四元数w x y z这样更容易观察。4.3 Offboard 控制从订阅到发布光有数据还不够真正的控制需要 ROS2 侧发布指令给 PX4。PX4 的 Offboard 模式就是专门给外部控制器用的ROS2 节点通过话题给它发期望姿态/位置/速度。需要用到两个重要话题/fmu/in/offboard_control_mode告诉 PX4 你现在要控制什么位置、速度、姿态/fmu/in/vehicle_command发送模式切换指令比如切换到 Offboard 模式px4_ros_com 仓库里自带了一个 offboard 控制的示例节点直接用ros2 run px4_ros_com offboard_control这个节点会以 50Hz 的频率发布 Offboard 控制指令让飞机先起飞到一个设定点然后悬停。实际项目中你可以在自己的节点里订阅里程计数据然后根据规划算法计算出目标位置再发布给 PX4。这里我想重点讲一下ROS2 CallbackGroup 的概念。你可能觉得 Offboard 控制就是简单发消息但等到你真正写自己的控制节点时会发现一个隐藏问题ROS2 的订阅回调默认是在单线程执行器里串行执行的。比如你订阅了/fmu/out/vehicle_odometry同时又要发布控制指令如果回调里处理耗时任务比如跑路径规划发布就会卡住控制频率上不去。解决办法就是用rclcpp::CallbackGroup把订阅回调放到独立线程里。我在实际项目里就是这么做的里程计订阅走 multithread executor控制发布走另一个 callback group保证指令发送不被阻塞。这是从「Demo 能跑」迈向「真机能飞」的关键一步。4.4 自定义话题与消息扩展PX4 内置的话题在 px4_msgs 里都有定义但有些时候你想传输自定义数据比如视觉识别出的目标坐标、自定义控制指令。这时候需要用 PX4 的自定义 uORB 消息机制。操作步骤是在PX4-Autopilot/msg/目录下新建一个.msg文件比如MyTargetPosition.msg然后重新编译。注意光编译固件不够还要重新编译 px4_ros_com 让新消息生成到 ROS2 接口里。这个流程有两个坑每次修改 PX4 的 msg 文件后必须把 PX4-Autopilot 和 px4_ros_com 一起重新编译顺序不能反如果只是改了自定义消息内容可以只编译单独模块比如make px4_sitl gz_x500会自动触发 msg 生成用这个机制你可以把视觉、激光雷达的数据以 PX4 原生消息的形式融合进控制回路这也是后来做无人机八叉树地图导航、自主避障时最常用的路径。ROS2 侧把 octomap 地图数据通过自定义话题传给规划器再把规划结果发回 PX4。5. 常见问题与排障实录这一节的价值我个人觉得比前面加起来都重要。这些坑我全都踩过或者帮别人排查过写出来能给大家省下大量时间。5.1 镜像拉取失败与编译替代方案很多人在 Docker 方式启动 micro-ROS Agent 的时候会遇到这样的报错Unable to find image microros/micro-ros-agent:humble locally这表示本地没有这个镜像而 Docker 去远程仓库拉取失败了。常见原因有网络问题、镜像标签问题、Docker 服务没起来等。我一般直接放弃 Docker 方式改用源码编译只要把 ROS2 环境装好源码编译基本一次过。如果你确实想用 Docker可以检查一下 Docker 是否能正常拉取其他公共镜像如果都不能先解决 Docker 的网络问题再重试。5.2 命令找不到与环境变量装完 ROS2 之后终端里输入ros2提示ros2: command not found这个问题九成是环境变量没生效。检查两件事第一/opt/ros/humble/setup.bash这个文件是否存在第二~/.bashrc里是否写了 source 命令。如果写了但还是不行可能是改完没 sourcesource ~/.bashrc还有一种情况是你在~/.bashrc里先后 source 了多个版本的 ROS2顺序写反了导致后面把前面覆盖了。保持只 source 一个发行版不会错。5.3 话题出不来与 QoS 不匹配这是最让人抓狂的问题Agent 连上了但ros2 topic list里一个/fmu/话题都看不到。我分享一个排查思路按顺序来检查 Agent 的日志看有没有持续的Heartbeat或者Client connected输出。如果没有说明 PX4 和 Agent 还没建立连接查端口、查防火墙。检查 PX4 的uxrce_dds_client start是否真的成功了可以在 MAVLink Console 里执行uxrce_dds_client status看状态。检查ROS_DOMAIN_ID是否一致。ROS2 的 discovery 靠 domain ID默认都是 0但如果你的环境变量里设置了不同的值两边就互相看不见。检查是否设置了ROS_LOCALHOST_ONLY1如果设置了跨机器通信会被限制单机仿真一般不需要开。另外一个隐蔽的坑是QoS 不匹配。PX4 的很多话题发布用的是 SensorDataQoS也就是 BestEffort、深度较大的队列。你在写订阅者的时候如果用了默认的 Reliable QoS会一直收不到数据而且不报错。所以订阅 PX4 高频传感器话题时QoS 要设置为SensorDataQoS我在写节点时总是这样设置。反之低频指令话题比如 OffboardControlMode用默认 QoS 通常没问题。5.4 版本兼容性集锦最后整理一个版本相关的问答都是群友常问的。Humble 和 Foxy 到底差在哪Foxy 是 2020 年的发行版对应 Ubuntu 20.04目前已经过了支持周期。Humble 比 Foxy 新两年Python 版本更高CMake 版本也更新API 层面基本兼容但 Foxy 的老包不一定能在 Humble 上直接编译过。PX4 v1.13 和 v1.14 在通信上有什么区别v1.13 及之前用 Fast DDS 的 micro-ROS 集成方式v1.14 换成 uXRCE-DDS配置更简洁默认端口都是 8888。如果你看老教程让你设置RTPS_CONFIG参数那是 v1.13 时代的写法在 v1.14 里不适用了。能不能在 Ubuntu 20.04 上用 Jazzy不行Jazzy 只官方支持 Ubuntu 24.04。如果你暂时不想换系统就老老实实待在 Humble。好在 Humble 目前完全够用PX4 和绝大多数生态包都支持。px4_ros_com 编译时提示找不到某个依赖怎么办先rosdep update再rosdep install --from-paths src --ignore-src -r -y一般能解决。如果还不行把报错信息贴到群里基本是缺了某个系统的lib。5.5 我认为最值得提前养成的两个习惯第一个所有终端环境统一。启动 Agent、启动 PX4、跑自己的节点保持同一个.bashrc、同一个ROS_DOMAIN_ID不要一个终端 source 了这个、另一个 source 了那个后面排查问题会崩溃。第二个日志永远开高。Agent 启动时用-v6自己的节点里尽量用rclcpp的RCLCPP_INFO输出关键信息。通信问题不像编译错误会直接告诉你哪一行出问题只能靠日志逐步缩小范围。说到 PX4 的估计器很多人对接完还想深入了解姿态和位置是怎么算出来的这就绕不开 PX4 的卡尔曼滤波。PX4 用的是扩展卡尔曼滤波核心是ekf2模块它把 IMU、GPS、气压计、磁力计的数据融合出位姿估计。我刚开始看卡尔曼滤波推导的时候也是一头雾水后来回过味来对接数据通信阶段其实不需要把推导完全抠懂先理解输入输出ekf2吃传感器数据吐vehicle_attitude、vehicle_local_position这些话题你订阅这些话题就能拿到融合后的位姿。等你对整个数据流有了体感再回头啃推导会轻松很多。最后再分享一个我自己用得很顺的调试小技巧在rqt_graph里看节点拓扑。跑通了基础通信之后打开rqt_graph你能清晰地看到 Agent 节点和你的 ROS2 节点之间的话题连线。如果发现某个话题有两个 publisher 或者没有 subscriber一眼就能看出哪里不对劲。这个工具比反复看日志直观得多强烈推荐养成习惯。