简介面向无人机仿真入门用户的ROS2、PX4与Gazebo环境搭建配套源码包重点解决Ubuntu系统下从零安装ROS2 Humble、编译PX4固件并配置Gazebo Classic仿真环境的流程难题。压缩包体积仅8KB内含3个文件HTML格式的说明页面便于在浏览器中查阅操作指引.inscode配置文件可联动在线开发环境.gitignore则规范版本管理整体轻量而聚焦核心。已有97人学习下载适合希望快速搭建无人机开发与仿真环境的初学者。配合详细教程使用可对照完成环境配置减少踩坑成本并为后续创建ROS2工作空间、安装DDS通信中间件打下基础。资源提供可运行源码适合边学边练帮助读者在真实动手前理顺环境依赖关系提升搭建成功率。1. ROS2PX4Gazebo理清版本匹配拿到就能跑的环境包很多人把 ROS2 PX4 Gazebo 环境搭建理解成“装三个软件”真正动手才发现它是一场版本与依赖的排列组合PX4 固件、ROS2 消息、Gazebo 插件任何一环版本错位仿真器都会在你面前翻车。我之前带项目时在这个环境上耗掉两周最后整理出一套可复现的构建流程才把这个坎迈过去。这个可运行源码包要解决的正是这一件事按包内脚本的顺序执行你能得到一个从头到尾都能复现的仿真环境——Gazebo 里有带传感器模型的无人机ROS2 里能看到 PX4 发布的姿态与控制话题QGroundControl 也能接入控制。适合想做无人机、地面机器人仿真验证又不想把时间耗在编译报错上的从业者和新手先跑通再改代码。2. 拆解源码包目录结构、三套依赖与版本对应关系2.1 三个软件为什么必须“抱团”版本对应关系先把三者之间的关系捋清楚。PX4 和 Gazebo 之间走的是 MAVLink over UDP飞控模型把姿态、推力数据发出去Gazebo 的物理引擎算完反馈机身状态。ROS2 要拿到这些数据走的是 uXRCE-DDS 通道把 PX4 内部的 uORB 话题翻译成 ROS2 话题。ROS2 要想操作 Gazebo 里的模型靠的是 gazebo_ros_pkgs 提供的插件与消息接口。这三条链路不是同一时间建立的所以源码包里的构建顺序全都在刻意照顾“先飞控、后通信、再仿真”。Ubuntu 22.04 ROS2 Humble Gazebo Classic 11 PX4 1.14.x SITL这个组合是目前资料最多、最稳的一组。Humble 自带的 gazebo_ros_pkgs 是编译好的二进制包直接对接 Gazebo ClassicPX4 1.14 的 SITL 启动器里也内置了 gazebo-classic 目标。如果你换到 Rolling 版本 ROS2 或者 Gazebo Ignition依赖名全变源码包里的脚本就得重写。所以拿到包第一件事是确认 README 里写的这三行版本号别急着跑脚本。你可能会问为什么不直接用 Gazebo Garden因为 PX4 官方对 Gazebo Classic 的适配最成熟ROS2 Humble 的 gazebo_ros 插件的默认实现也是 Classic。用新版反而要把桥接层重新编译这部分坑比环境搭建本身还多。我见过不少人卡在“ros-ign-gazebo”这套包装不上最后退回 Classic 问题立刻消失。这不是玄学是生态里大家都走过的路。2.2 源码包的文件布局你一眼要认出的关键文件拿到包先不要运行任何命令先看目录结构省得后面连“该在哪个目录下执行”都找不着。px4_sim_ws/ ├── scripts/ │ ├── 01_install_deps.sh │ ├── 02_build_px4.sh │ ├── 03_setup_env.sh │ └── 04_run_sim.sh ├── src/ │ ├── PX4-Autopilot/ │ ├── px4_msgs/ │ └── px4_ros_com/ ├── config/ │ ├── models/ │ └── worlds/ ├── launch/ └── README.mdscripts 目录是整套环境的操作入口01 到 04 的顺序是经过验证的依赖顺序。01 安装系统依赖02 编译 PX403 配置环境变量04 启动仿真。src 下除了 PX4-Autopilot 固件本体还有 px4_msgs 和 px4_ros_com这两个是官方为 ROS2 准备的消息定义和桥接工具缺一个 ROS2 都拿不到 /fmu 开头的自定义话题。config 目录里放的是 Gazebo 模型和 world 文件如果后面你发现机身不在场地中央问题基本都出在这个目录的路径配置上。我把文件的用途总结成一张表方便你对照路径作用什么时候动它scripts/01_install_deps.sh安装编译工具、依赖库、仿真器只在首次搭建时执行scripts/03_setup_env.sh导出 GAZEBO_MODEL_PATH 等环境变量每个新终端都要 sourcesrc/PX4-AutopilotPX4 固件源码改飞控逻辑时编译src/px4_ros_comRXCE-DDS 桥接与 ROS2 通信异常时检查config/worlds自定义仿真场景想换场地模型时替换launch/ROS2 启动文件想把仿真一键拉起来时使用2.3 环境变量二十分钟后你就明白 source 在解决什么很多新手报的错误本质上是环境变量没传过去。ROS2 的终端环境、Gazebo 的模型路径、PX4 的固件目录这三者互相独立但又必须在一个终端里同时生效。源码包的 03 脚本本质上是在帮你把下面这些变量预置好# 设置 PX4 工程根目录后面很多脚本依赖这个变量 export PX4_ROOT$HOME/px4_sim_ws/src/PX4-Autopilot # 告诉 Gazebo 去哪里找无人机模型和 world 文件 export GAZEBO_MODEL_PATH$HOME/px4_sim_ws/config/models:${GAZEBO_MODEL_PATH} # 设置 ROS2 通信域同一台机器上多套环境时必须错开 export ROS_DOMAIN_ID0 # 引入 ROS2 的安装环境 source /opt/ros/humble/setup.bash # 引入当前工作区的编译产物 source $HOME/px4_sim_ws/install/setup.bashGAZEBO_MODEL_PATH 是最容易踩坑的一个。Gazebo 在启动时会按这个路径去加载模型库路径里没有你的无人机模型它就只给你一片灰蒙蒙的世界。ROS_DOMAIN_ID 则是多机、多环境间串话的根源两台设备都用默认值 0 时它们会在同一个局域网里看到彼此的节点。我一般建议同一台机器只跑一套仿真但 ROS_DOMAIN_ID 也要固定下来不然重启后终端之间消息对不上。注意不要在前面加 sudo 执行 source 或 export。source 的是 shell 当前会话加 sudo 反而会把环境变量隔离到另一个进程里等于没设。3. 从零开始在 Ubuntu 上把 ROS2 和 Gazebo 装到位3.1 选系统先看处理器架构再动手拿到源码包先确认你的系统能否承载这套仿真。我推荐 Ubuntu 22.04其次是 20.04。PX4 官方对 22.04 的依赖脚本支持完整Gazebo Classic 11 在 Ubuntu 软件源里直接可以装ROS2 Humble 也是长期维护版本。如果你用的是 Ubuntu 24.04依赖源会变得不全很多包要手工编译工作量翻倍。处理器架构也要先确认Intel 和 AMD 的 x86_64 架构最省事所有二进制包都有现成的。如果你用的是 ARM 架构的开发板比如 RK3588 这类板子我建议把编译任务放到 x86 机器上完成再把整个 install 目录同步过去。为什么因为 gazebo_ros_pkgs 在 ARM 上经常需要从源码编译而且编译过程中还会因为内存不足报 OOM。先看内存仿真器的内存占用一般在 4GB 上下加上编译时的临时开销建议至少 8GB 内存磁盘预留 30GB 以上。# 检查架构、内存和磁盘空间 uname -m free -h df -h /home这三个命令的结果决定你要不要升级机器。我见过有人在 4GB 内存的虚拟机上硬跑 Gazebo结果编译器被杀Gazebo 打开后黑屏查到最后是 swap 都不够用。还有一个容易忽略的点Gazebo 的渲染依赖 GPU 驱动。如果是一台没有显卡的云主机Gazebo 会退回软件渲染画面卡顿明显仿真还能跑但帧率极低。这种情况建议不要装 gazebo直接用 headless 模式跑 SITL只做通信测试。3.2 ROS2 Humble 安装与软件源ROS2 安装没有太多花活但有几个细节值得较真。第一是软件源官方源在国内下载速度不稳定我一般会在安装前先确认网络能连上 packages.ros.org如果总是超时就把 apt 源切到国内镜像具体操作是在 /etc/apt/sources.list.d/ros2.list 里替换镜像地址这种事没必要硬等。# 添加 ROS2 官方源的 GPG 密钥 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 # 更新并安装桌面版 ROS2ros-dev-tools 里带了调试工具 sudo apt update sudo apt install -y ros-humble-desktop ros-dev-toolsros-humble-desktop 已经包含 rviz2、常见传感器驱动和仿真接口。如果你只是为了跑 PX4 仿真其实不用装 ros-humble-ros-base但 desktop 版能省掉后面单独寻找消息包的麻烦。接下来把 ROS2 环境写进 bashrc并且安装 colcon 编译工具不然你没法构建 ROS2 工作区。echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc # colcon 是 ROS2 的编译工具对应 ROS1 里的 catkin sudo apt install -y python3-colcon-common-extensions提示安装完后重新打开一个终端执行 ros2 --help 确认命令可用。如果提示找不到命令说明 /opt/ros/humble/setup.bash 没有写入当前 shell回到 bashrc 检查 source 有没有生效。colcon 的常见参数是colcon build --symlink-installsymlink-install 会把 Python 脚本和 launch 文件以软链接形式安装到 install 目录改代码后不用重新编译。后面我们编译工作区时会用到。3.3 Gazebo ClassicROS2 需要的是 gazebo_ros_pkgsGazebo 部分最容易把版本搞混。ROS2 Humble 官方对接的是 Gazebo Classic到 2024 年之后 Gazebo 官方把版本命名改成了 Ionic、Harmonic但 PX4 的 SITL 目标仍然叫 gazebo-classic。你在 Humble 里装apt install gazebo默认就是 Classic 11。装完 gazebo 本体还不够必须装 ros-humble-gazebo-ros-pkgs它提供 gazebo_ros 插件和 launch 文件。# 安装 Gazebo Classic 11 本体及开发库 sudo apt install -y gazebo-11 libgazebo11-dev # 安装 ROS2 到 Gazebo 的桥接包 sudo apt install -y ros-humble-gazebo-ros-pkgs # 验证版本确保 gazebo --version 显示 11.x gazebo --version # 查看 gazebo_ros 包是否被 ROS2 正确识别 ros2 pkg prefix gazebo_rosros2 pkg prefix gazebo_ros会打印 gazebo_ros 包所在的安装前缀如果能输出/opt/ros/humble说明包已被 ROS2 环境索引到。如果输出为空多半是软件源安装不完整或当前 shell 没有 source ROS2。还有一个细节libgazebo11-dev 是编译自定义插件时必备的库只装 gazebo-11 本体在编译某些功能包时会报找不到头文件。为了少走一次弯路开发库建议一次装齐。装完这些ros2 和 gazebo 之间能不能通信可以用一个最小测试验证启动一个空世界然后看 ros2 topic list 是否出现 /gazebo 开头的消息。但通常这个验证会在后面 PX4 一起做因为直接空跑 gazebo 只涉及模型加载不涉及 MAVLink 链路。4. 编译 PX4 并跑通 SITL先让机身模型动起来4.1 用源码包里的脚本把 PX4 固件编译出来这套环境的关键在 PX4 固件本身。PX4 SITL 的意思是把本来跑在真实飞控上的固件编译成 Linux 可执行程序直接跑在电脑上与 Gazebo 里的仿真模型通信。这样你没有硬件也能测试飞行逻辑。第一次编译前先执行源码包里的依赖安装脚本它会补齐 PX4 编译用的交叉工具和 Python 依赖。之后千万不要用 sudo 编译PX4 的 CMake 脚本在不同用户权限下会写出不同的配置缓存我用 root 编译过一次第二次用普通用户重编时报出一堆诡异错误最后清空 build 目录重来。cd ~/px4_sim_ws/PX4-Autopilot ls正确姿势是直接进入 PX4-Autopilot 目录运行固件的 make 命令。源码包 02 脚本做的事情和下面这条命令等价cd ~/px4_sim_ws/src/PX4-Autopilot make px4_sitl gazebo-classicmake 目标 px4_sitl 表示编译为仿真固件gazebo-classic 表示启动时选择 Gazebo Classic 作为仿真器。第一次运行会拉取子模块这里必须保证网络稳定否则会卡在某个 git submodule update 上。编译时间跟机器性能有关一般 20 到 40 分钟。编译完成后它会自动启动 Gazebo你会看到一架飞机的模型出现在世界里。如果没出来多半是模型路径没配好见下一章排查。# 编译时可以这样提前设置 Make 并行数避免内存不足 # 8GB 内存建议 -j416GB 以上可以 -j8 make px4_sitl gazebo-classic -j4-j4 参数控制并行编译任务数这个值不要超过 CPU 核心数。我自己的经验是8GB 内存的机器用 -j8 经常爆内存Gazebo 模型加载到一半进程被杀用 -j4 就稳定了。4.2 启动后马上验证的四件事SITL 启动不是启动完就完事至少要做四个验证点否则后续 ROS2 通信出问题你根本不知道是哪一环断的。第一Gazebo 窗口里应能看到无人机模型并且模型不在世界坐标原点时会显示在场地中央附近。第二PX4 shell 终端里应能看到 SITL 输出包括 MAVLink 端口信息默认是 UDP 14540。第三打开新终端输入 ros2 node list应能看到 /gazebo 相关节点。第四如果 px4_ros_com 已经编译ros2 topic list 里应能看到 /fmu 开头的话题。# 在新终端里检查当前 ROS2 节点 ros2 node list # 查看是否出现 pose、odometry 等话题 ros2 topic list | grep fmu第一次进入 ros2 topic list 时如果只有 /rosout 属于正常因为此时 PX4 固件还没有通过 uXRCE-DDS 把 uORB 话题桥接到 ROS2。别急着排查环境先进入下一节建立桥接。4.3 让 uXRCE-DDS 链接建立ROS2 才算真正拿到飞控数据PX4 与 ROS2 的通信并不是自动连上的。PX4 固件内部使用的是 uORB 消息机制ROS2 内部使用的是 DDS两套协议中间需要一层桥。PX4 这边的桥是 uXRCE-DDS clientROS2 这边的桥是 Micro XRCE-DDS Agent。只有两边的 agent 和 client 都运行ROS2 才能看到 PX4 的真实话题。常见做法是先在 PX4 SITL 的终端里启用 uXRCE-DDS client然后在第二个终端启动 MicroXRCEAgent指定 UDP 端口和本机 IP。PX4 的 SITL 默认会监听 UDP 8888Host 地址是 127.0.0.1。# 终端 A 中在 PX4 SITL 终端里输入并回车 uxrce_dds_client start# 终端 B 中启动 micro-ROS agent MicroXRCEAgent udp4 -p 8888第二条命令中的udp4指定传输协议为 UDP/IPv4-p 8888是 PX4 固件默认启用的端口。如果固件参数里修改了端口这里也要同步。Agent 启动后你会看到类似Client connected的日志此时再回终端输入ros2 topic list | grep fmu应能看到/fmu/out/vehicle_attitude、/fmu/out/vehicle_status等话题。注意如果 Agent 报端口被占用优先检查是否已经有一个 Agent 在后台跑着。多开 agent 会导致连接不停闪断现象是 ros2 topic list 里话题出现又消失。PX4 1.14 之后还有一条更省事的路直接在 launch 时指定环境变量让固件在启动时自动连 Agent。源码包的脚本里可能没有预置你可以手动加export PX4_UXRCE_DDS_AGENT_PORT8888 make px4_sitl gazebo-classic这样固件启动时就会自动尝试连接 127.0.0.1:8888。前提是 Agent 要比固件先启动否则固件启动后连不上就放弃了。5. 避坑指南版本冲突、环境变量与仿真卡死的常见问题5.1 现象Gazebo 启动后只有空场地看不到无人机模型我遇到最多次的就是这个。Gazebo 正常启动但场地里什么都没有或者只有一个残缺的模型骨架。原因基本是GAZEBO_MODEL_PATH没有包含无人机模型的路径。Gazebo 加载 SITL 时PX4 会引用模型名和 world 文件而模型名对应的目录必须在 Gazebo 的模型搜索路径里。roslaunch 启动时不会自动 export 这个变量需要自行配置。解决方法是把源码包 config/models 目录加入环境变量必要时还要加入 PX4-Autopilot 内置的模型目录。我一般会在 .bashrc 里追加下面两行然后再重启终端export GAZEBO_MODEL_PATH$HOME/px4_sim_ws/config/models:$HOME/px4_sim_ws/src/PX4-Autopilot/Tools/sitl_gazebo/models:${GAZEBO_MODEL_PATH} export GAZEBO_RESOURCE_PATH$HOME/px4_sim_ws/src/PX4-Autopilot/Tools/sitl_gazebo:${GAZEBO_RESOURCE_PATH}配置后重新启动 Gazebo。注意 Gazebo 在启动时会读取模型路径环境变量如果变量加晚了需要把 Gazebo 进程完全杀掉再重新启动光 reload 是不生效的。5.2 现象make px4_sitl gazebo-classic 报错找不到 world 文件报错信息通常是Error: Unable to load world file [empty.world]或类似路径。问题出在 PX4 的启动脚本默认从当前工作目录相对路径读取 world你没有在 PX4-Autopilot 目录下运行命令或者 world 文件不在预期的 Tools/sitl_gazebo/worlds 目录里。解决也很简单回到固件源码根目录执行构建不推荐为了省事直接用绝对路径。因为我发现 PX4 的启动配置里有大量相对路径只有当前目录在固件根目录时才能全部命中。如果你是从源码包根目录直接调用脚本脚本内部已经做了 cd那没问题但手工执行 make 时务必先 cd。5.3 现象ros2 topic list 看不到任何 /fmu 话题这个现象在第一次搭建时几乎必现。你按照第 4 节操作后Agent 和 client 都起来了但 ROS2 的话题列表里始终只有 /rosout 和 /parameter_events。原因有三层。第一层Agent 没起来或者端口号与固件不一致第二层固件里的 uXRCE 参数没有配置比如SYS_UXRCE_CFG被置为 -1第三层ROS_DOMAIN_ID 不一致两个终端虽然在同一台机器上但 shell 启动时来源的环境不同。排查顺序很重要我建议按以下命令逐层定位# 当前 ROS_DOMAIN_ID 是否一致 echo $ROS_DOMAIN_ID # Agent 是否真的在监听听口 ss -ulpn | grep 8888 # 查看 PX4 SITL 终端里 client 是否连接成功 uxrce_dds_client status如果uxrce_dds_client status显示已连接但话题仍然不出再看固件的 uORB 发布速率。某些仿真模型在未解锁时不发布 attitude 话题这时可以先给一个解锁指令或者直接看/fmu/out/vehicle_status这类常驻话题。最后考虑 ROS2 的 QoS 配置不匹配但这是熟手才会遇到的问题建议先排除前三个。5.4 现象colcon build 报找不到 gazebo_ros 头文件编译自定义 Gazebo 插件或消息包时报fatal error: gazebo_ros/...: No such file or directory。原因非常明确系统里没有安装 gazebo_ros_pkgs或者 ROS2 软件源里的版本没被当前 shell 识别。装了这个包后头文件在安装目录的 include/gazebo_ros 下CMake 里通常用find_package(gazebo_ros REQUIRED)寻找。解决方法是先补装再重新 sourcesudo apt install -y ros-humble-gazebo-ros-pkgs source /opt/ros/humble/setup.bash如果已经装过但仍报错检查 CMakeLists.txt 里有没有显式包含/opt/ros/humble/include。某些 ROS2 包需要设置CMAKE_PREFIX_PATH当它为空时 find_package 找不到依赖。我遇到过这类问题最终把 bashrc 里的source /opt/ros/humble/setup.bash移到 colcon 编译命令前并重新开启终端就消停了。5.5 现象QGroundControl 打开后无法连接仿真飞控QGroundControl 能连真实 USB 飞控但连不上 SITL 仿真这是端口没对上。PX4 SITL 默认把 MAVLink 发送到本机 UDP 14540QGroundControl 的地面链接配置需要手动添加这个 UDP 端口。解决方法是打开 QGroundControl左上角齿轮进入应用设置找到“通信连接”删除已有的默认 USB 连接新建一个 UDP 连接目标端口填 14540。时间一长 QGroundControl 会自己发现 SITL 广播但手动配置最稳妥。还有一个隐蔽问题如果 QGroundControl 安装方式是 AppImage首次运行时可能会因为没有获取网络端口权限而卡白屏。我一般在命令行用./QGroundControl.AppImage启动如果缺权限运行sudo chmod x后再执行不要用 sudo 直接运行避免图形界面拉起在 root 会话。6. 进阶技巧用 launch 文件把仿真、DDS 和监控一键拉齐到这一步你已经能手动把 ROS2、PX4、Gazebo 全部跑通。但手动流程有个麻烦每次开新终端都要重新 source 环境然后再手动启动 Agent再启动 SITL顺序一乱就翻车。我后来会写一个 ROS2 launch 文件把 Gazebo、PX4 SITL 启动、uXRCE-DDS Agent 全部编排在一条命令内。下面这个 launch 文件是简化版放在源码包 launch 目录下命名为 sim.launch.pyfrom launch import LaunchDescription from launch.actions import ExecuteProcess import os def generate_launch_description(): px4_dir os.path.expanduser(~/px4_sim_ws/src/PX4-Autopilot) return LaunchDescription([ ExecuteProcess( cmd[make, px4_sitl, gazebo-classic], cwdpx4_dir, outputscreen ), ExecuteProcess( cmd[MicroXRCEAgent, udp4, -p, 8888], outputscreen ) ])cwd 参数是关键它会让你不用每次手动 cd 到固件目录。output 设为 screen可以把 PX4 SITL 的日志实时打印在当前终端方便看 MAVLink 端口是否正常。实际使用时我在这个文件里还会加一个 Node 动作用于持续转发静态坐标系变换否则 rviz2 里看到的无人机模型会缺失 frame。把 launch 文件组装成 ROS2 包后构建并运行cd ~/px4_sim_ws colcon build --symlink-install source install/setup.bash ros2 launch launch sim.launch.py.bashrc里的环境变量最好也收敛到 launch 内不要在脚本里再 export 一次避免多个终端环境变量打架。运行起来后验证消息链路是否正常最直接的办法是用 timeout 限制监听时长避免 CtrlC 忘收timeout 20 ros2 topic echo /fmu/out/vehicle_attitude --once如果能在 20 秒内打印一帧 attitude 四元数说明 PX4 → uXRCE-DDS → ROS2 的全链路是通的。从那以后我每次搭新的无人机仿真环境都强制走一遍这个流程先核对版本组合再跑依赖脚本最后用 launch 文件做一次全链路验证。这三个步骤做完环境基本不会出幺蛾子。希望帮到你。本文还有配套的精品资源点击获取 SEO 优化官网定制响应式建站教育培训建站