DUDuuu.studio

Back

简介#

PX4 作为目前全世界广泛流行的开源飞控,在无人机设计和控制方面为开发人员带来便利。ROS 作为机器人操作系统,其提供的分布式通信架构简化了无人机编队仿真流程,通过 Gazebo 物理仿真引擎,可以提供真实的仿真环境。

ROS 目前已经更新到了 ROS2,相较于 ROS1,其应用性和可维护性会更加强大。目前已有的 ROS2+PX4 的仿真案例并不多,且伴随二者的不断更新,有很多环境配置的问题。笔者在这里提供一种个人的开发流程。

ROS2+PX4 仿真系统架构示意
图 1:ROS2+PX4 仿真系统架构示意

Ubuntu 系统的安装#

本环境基于 Ubuntu 22.04 系统进行搭建。大家可以安装虚拟机或者在 Windows 系统中安装双系统。在这里,笔者给出一个在 Windows11 下安装 Ubuntu 22.04 双系统的视频教程链接:

现在开始进行环境开发流程,这里给出一个博主的环境开发流程,与我们的环境搭建较为相似,简洁明了。如果只有单机仿真需求,也可以参考这篇资料进行环境搭建:

注意:在开始下列步骤之前,建议首先保证能够科学上网,且网速流畅,否则后续从 Github 克隆仓库时会中途闪退。

PX4 源码下载及编译#

首先从 Github 上克隆 PX4 源码,并且更新子模块:

git clone https://github.com/PX4/PX4-Autopilot.git --recursive
bash

由于后续环境配置会装很多东西,有可能难以完全清干净,建议在这一步完成后运行以下命令,备份 ~/PX4-Autopilot,以免后续环境配错需要重新克隆代码:

zip -r PX4-Autopilot.zip PX4-Autopilot/
bash

接着安装相关依赖:

bash ./PX4-Autopilot/Tools/setup/ubuntu.sh
bash

此时 PX4 的源码已经下载好并且安装好相关依赖了,我们可以试着运行以下命令进行编译及启动仿真:

cd ~/PX4-Autopilot/
make px4_sitl         # 先编译 SITL 固件(必须!)
make px4_sitl jmavsim # 编译完成后启动 jmavsim 仿真
bash

常见错误:如果直接运行 make px4_sitl jmavsim 出现 ninja: error: unknown target 'jmavsim',说明 PX4 的 CMake/Ninja 构建系统尚未生成 jmavsim 目标。必须先执行 make px4_sitl 完成首次编译,再运行 make px4_sitl jmavsim 启动仿真,之后便可直接使用后者。

我们会发现,开始编译 PX4 的源码,并且开始启动 jmavsim 物理仿真引擎,这是因为在我们安装依赖时就已经为我们装好了 jmavsim 和 Gazebo-classic。如果发现终端中出现了绿色的 ready for takeoff,且 jmavsim 出现,则说明编译成功。如果这一步失败,请检查自己的科学上网工具。

现在我们在终端中回车,在 pxh> 后面输入 PX4 的指令:

commander takeoff/land/shutdown
plaintext

则可以控制无人机的起飞、降落以及关闭仿真。此时可以在 jmavsim 的 UI 中看到无人机的起降。到此步,PX4 的源代码下载和编译全部完成。

出现绿色的 ready for takeoff 后回车输入起飞命令
图 2:出现绿色的 "ready for takeoff" 后回车输入起飞命令
在 jmavsim UI 中看到无人机起飞
图 3:在 jmavsim UI 中看到无人机起飞

ROS2 及其相关依赖的安装#

我们使用 ROS2 Humble 进行开发,ROS2 及其依赖的安装和环境配置有些繁琐,在此我强烈建议各位使用”鱼香 ROS”的一键安装功能,在这里感谢其为 ROS 开发提供的便利。直接在 Ubuntu 的系统终端输入以下命令并按终端返回的指令安装即可:

wget http://fishros.com/install -O fishros && . fishros
bash

其一键安装工具中还有 Docker 等工具的一键安装选项,大家可以按需使用,再次感谢。另外,使用 ROS2 Foxy 版本进行开发的朋友也可以使用该工具进行安装和环境配置。

Gazebo Sim 8.9.0 的安装#

根据 PX4 的官方文档,之前的 Gazebo Ignition 更名为 Gazebo,以前的 Gazebo 现在叫 Gazebo-classic。Ubuntu 22.04 支持 Gazebo (Ignition) 系列。在之前安装 PX4 依赖时,ubuntu.sh 会自动安装 jmavsim 和 Gazebo-classic,而我们多机仿真需要使用的是 Gazebo Harmonic(v8.x,即 Gazebo Sim 8.9.0)。

重要:Gazebo 的版本与 ROS2 桥接包必须一致,混装多个版本是环境崩溃的首要原因。Gazebo Garden (v7)、Harmonic (v8)、Ionic (v9) 不能共存

首先添加 OSRF 源并安装 Gazebo Harmonic:

cd ~/PX4-Autopilot
sudo apt install wget
sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
sudo apt update
sudo apt-get install gz-harmonic
bash

然后安装对应版本的 Gazebo-ROS2 通信桥(Harmonic 对应 gzharmonic):

sudo apt install ros-humble-ros-gzharmonic
bash

安装完成后验证版本唯一性(只应出现一个版本号):

gz sim --versions   # 应只显示 8.9.0
bash

常见错误:不要安装 gz-gardenros-humble-ros-gzgarden,那是 Gazebo Garden (v7),与 PX4 当前的 gz-sim8 编译目标不兼容。

在 Ubuntu 系统中出现 Gazebo sim8 图标即可
图 4:在 Ubuntu 系统中出现 Gazebo sim8 图标即可

MicroXRCE-DDS Agent 的安装#

根据官方文档说明,在 ROS2 中 PX4 使用 uXRCE-DDS 中间件来允许在配套计算机上发布和订阅 uORB 消息,而不再使用 MAVROS,我们按照官方案例进行下载、编译及安装。

通信图示
图 5:通信图示

下载源码:

git clone -b v2.4.2 https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
bash

编译:

cd Micro-XRCE-DDS-Agent
mkdir build
cd build
cmake ..
make
bash

这里应该会有个报错,大家去 build/fastdds/tmp/fastdds-gitclone.cmake 里把 2.12.x 改为 v2.12.1 后重新 make 一下就可以了。

编译的过程会较长,需要进行一定等待,编译结束后进行安装:

sudo make install
sudo ldconfig /usr/local/lib/
bash

QGC 地面站的安装#

在后续启动 PX4+Gazebo 仿真时,如果丢失地面站的连接,会导致无法启动 PX4 飞控对无人机进行控制,因此需要在系统中安装 QGC 地面站。安装的方法我给出一个 CSDN 博主的链接,按照上面的步骤操作即可:

单机 Offboard 测试流程及开发简介#

现在所有的开发环境已经配置好了,我们现在进行 PX4 的 Offboard 模式的验证。

Offboard 模式是 PX4 中的一种特殊飞行模式,允许外部系统(如机载计算机、ROS2 节点等)通过 MAVLink 或 uXRCE-DDS 直接发送控制指令,实时控制无人机的姿态、位置或速度,从而实现自主飞行或高级任务。

首先创建 ROS2 的工作空间:

mkdir -p ~/ros2_ws/src
bash

随后下载源码(注意科学上网):

cd ~/ros2_ws/src
git clone https://github.com/PX4/px4_msgs.git -b release/1.14
git clone https://github.com/PX4/px4_ros_com.git -b release/v1.14
bash

进行编译:

cd ~/ros2_ws
colcon build
bash

更新环境并配置环境变量:

echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc
echo "export GZ_SIM_RESOURCE_PATH=\$HOME/.simulation-gazebo/models:\$GZ_SIM_RESOURCE_PATH" >> ~/.bashrc
source ~/.bashrc
bash

启动 Offboard 仿真#

现在我们启动 Offboard 仿真。首先打开已经装好的 QGC 地面站

终端 1 —— 打开通信:

MicroXRCEAgent udp4 -p 8888
bash
通信打开成功
图 6:通信打开成功

终端 2 —— 启动仿真:

cd ~/PX4-Autopilot
make px4_sitl gz_x500
bash

此时地面站会与 PX4 进行连接,Gazebo 启动,出现了 x500 的无人机。当 PX4 终端出现绿色的 ready for takeoff 时,说明仿真启动成功。有关这个使用 make 命令启动仿真的环节,我们在后续进行多无人机仿真时会详细解释。

终端显示成功连接地面站,出现绿色的 ready for takeoff,PX4 启动成功
图 7:终端显示成功连接地面站,出现绿色的 "ready for takeoff",PX4 启动成功
Gazebo 中出现单架无人机
图 8:Gazebo 中出现单架无人机

终端 3 —— 运行 Offboard 模式源码:

ros2 run px4_ros_com offboard_control
bash

我们可以发现 Gazebo 中无人机上升 5 米,Offboard 模式控制成功。

Offboard 模式控制成功
图 9:Offboard 模式控制成功

Offboard 模式开发流程#

我们在刚刚创建并下载好源码的 ~/ros2_ws 里找到 px4_ros_com 目录下的 CMakeLists.txt 文件,找到这三行:

add_executable(offboard_control src/examples/offboard/offboard_control.cpp)
ament_target_dependencies(offboard_control rclcpp px4_msgs)
install(TARGETS offboard_control DESTINATION lib/${PROJECT_NAME})
cmake

这是将 src/examples/offboard 中的 offboard_control.cpp 文件编译成可执行文件并命名为 offboard_control,同时依赖来源于 px4_msgs,我们可以打开 src/examples/offboard 目录便可以找到 offboard_control.cpp 源代码。

这个 C++ 代码为 Offboard 上升 5 米的源代码,后续基于此改控制逻辑
图 10:这个 C++ 代码为 Offboard 上升 5 米的源代码,后续基于此改控制逻辑

因此如果进行单机使用 Offboard 模式进行仿真,便可以按照以下流程开发:

  1. 在已经创建并且配置好环境的 ~/ros2_ws 这个 ROS2 工作空间下再创建一个包(和 px4_ros_com 目录并行)
  2. 在新创建的包中,在 /src 目录下编写基于 Offboard 模式进行控制的 C++/Python 代码
  3. 在新创建的包中的 CMakeLists.txt 中找到以下几行:
add_executable(offboard_control src/examples/offboard/offboard_control.cpp)
ament_target_dependencies(offboard_control rclcpp px4_msgs)
install(TARGETS offboard_control DESTINATION lib/${PROJECT_NAME})
cmake

将路径改为 C++/Python 代码的地址,并给他命名一个可执行文件的名字。在进行仿真前,一定要重新编译 ROS2 工作空间!

cd ~/ros2_ws
colcon build
bash

最后,仿照之前的方法打开 QGC 地面站、通信以及启动仿真,随后再打开一个新的终端:

ros2 run <包名> <可执行文件名>
bash

如果在 Gazebo 中看见无人机按照代码逻辑进行飞行,则仿真成功。


补充说明#

补充 1:使用 make px4_sitl gz_x500 命令启动仿真时,自动启动的 gz sim 仿真器的世界为 default,其 sdf 文件不再在 ~/.gz/worlds 里,而是在 ./PX4-Autopilot/Tools/simulation/gz/worlds 中。同理,所有的模型也均在 Tools/simulation 里,因此,在搭建仿真环境时,应该去到这些文件夹中直接修改 sdf 文件。

补充 2:在编写 C++/Python 代码进行 Offboard 模式控制时,需要注意坐标系的变换。在 PX4 中,坐标系为 NED 坐标系,即 North-East-Down,因此 x 坐标指向北,y 坐标指向东,z 坐标指向下(所有的高度为负值);而在 Gazebo Ignition 中,坐标系为 ENU 坐标系,此时 x 坐标指向东,y 坐标指向北,z 坐标指向上(高度为正值)。整理控制逻辑时需要注意坐标的换算。

至此,ROS2+PX4 在 Offboard 模式下进行单机仿真的基本流程就全部介绍完了。大家如果成功地跑通以上流程,接下来就可以基于此进行更多的单机仿真开发了。

多机(编队)的开发流程#

在前面的部分,我们完成了基于 ROS2+PX4 的单机仿真环境开发。现在我们开始进行多机的环境开发,为后续编队的控制逻辑仿真进行预先准备。

回顾单机启动#

我们先回顾一下启动单机仿真最主要的指令:

cd ~/PX4-Autopilot
make px4_sitl gz_x500
bash

这个 make 指令其实一共完成了三件事:

  1. 编译 PX4 源代码
  2. 启动 PX4
  3. 启动 Gazebo 仿真

但在多机仿真中,我们不需要反复地使用 make 指令,这样会导致每一架 x500 无人机单独启动了一个 Gazebo 仿真,而这不是我们想要的。因此在 Gazebo 环境中启动多机仿真,我们的目标为以下几个:

  1. 单独启动 Gazebo 仿真
  2. 分别启动 PX4,添加无人机进入 Gazebo 环境
  3. 建立通信

单独启动 Gazebo#

首先我们需要下载一个 Gazebo 的启动脚本(simulation-gazebo):

wget https://raw.githubusercontent.com/PX4/PX4-gazebo-models/main/simulation-gazebo
bash

随后在脚本所在的目录终端运行以下指令:

python3 simulation-gazebo
bash

常见问题:如果 Gazebo 窗口无法打开(闪退或黑屏),通常是因为显卡驱动不兼容或虚拟机缺少 GPU 直通。可以在命令前加上 LIBGL_ALWAYS_SOFTWARE=1,强制使用 CPU 软件渲染:

LIBGL_ALWAYS_SOFTWARE=1 python3 simulation-gazebo
bash

这个环境变量告诉 Mesa/OpenGL 使用 LLVMpipe 软件光栅化器代替硬件 GPU 加速。缺点是帧率会有所下降,但不影响仿真功能。

首次运行脚本后,会下载一些组件放在 .simulation-gazebo 下(在主目录里用 Ctrl+H 打开隐藏文件夹),其中的 /worlds/default.sdf 即为仿真的世界 sdf 文件,后续在这个文件里进行修改。

补充 3:此处需与单机仿真部分的补充 1 进行区别。这是单机和多机一个较大的不同。启动单机仿真时我们使用的是 make 指令,世界的 sdf 文件在 ./PX4-Autopilot/Tools/simulation/gz/worlds 中,但如果我们仔细看多机仿真时我们下载好的 simulation-gazebo.py 代码,会发现世界的 sdf 文件在 .simulation-gazebo 下,需要进行区别。

添加多架无人机#

在单独启动了 Gazebo 环境后,我们往其中添加无人机,此时我们不再使用 make 命令,而是用以下指令:

cd ~/PX4-Autopilot
PX4_GZ_STANDALONE=1 PX4_SYS_AUTOSTART=4001 PX4_GZ_MODEL_POSE="0,2" PX4_SIM_MODEL=gz_x500 ./build/px4_sitl_default/bin/px4 -i 0
bash

参数说明:

参数含义
PX4_GZ_STANDALONE=1使用 standalone 模式(不启动仿真,只启动 PX4,等待单独启动的仿真)
PX4_SYS_AUTOSTART=4001必须字段
PX4_GZ_MODEL_POSE="0,2"无人机初始位置,不同飞机位置应不同
PX4_SIM_MODEL=gz_x500飞机模型为 x500
-i 0无人机编号(第 0 号)

运行该指令后,我们应该可以在之前单独打开的 Gazebo 里看见出现了一架飞机。

现在我们再添加第二架飞机(编号为 -i 1,位置为 "0,1"):

PX4_GZ_STANDALONE=1 PX4_SYS_AUTOSTART=4001 PX4_GZ_MODEL_POSE="0,1" PX4_SIM_MODEL=gz_x500 ./build/px4_sitl_default/bin/px4 -i 1
bash

如果要添加更多的无人机,按此方法添加即可,也可以编写统一的脚本进行添加。

现在我们会发现在 Gazebo 里出现了两架并排的无人机,可以分别在他们启动 PX4 后的终端输入:

commander takeoff/land
plaintext

可以分别观察他们的起降情况。最后添加通信:

MicroXRCEAgent udp4 -p 8888
bash
成功启动 Gazebo 仿真,添加两架无人机,并添加通信,在 PX4 终端控制起降
图 11:成功启动 Gazebo 仿真,添加两架无人机,并添加通信,在 PX4 终端控制起降

至此,基于 ROS2+PX4 在 Gazebo 里进行无人机单机、多机仿真的环境开发就全部结束了。在下一篇文章中,我们将基于此环境实现 ROS2+PX4 多机 Offboard 编队控制,使用 leader-follower 算法进行双无人机编队飞行。除此之外,还可以基于此完成目标识别、路径规划等更多项目。万事开头难,希望本文能够给此方向的研究贡献一点微薄之力。

如果仿真仍有问题,大家可以参考 PX4 官方文档以及 Github 上相关项目资料。另外,如果你对 Betaflight 飞控感兴趣,也可以参考 Betaflight + Gazebo 软件在环仿真教程,了解另一种 SITL 仿真方案。环境的配置以及开发流程的熟悉是简单但是繁琐的过程,笔者作为初学者,提供一种自己的开发流程,同时也肯定会有其他更好的方式。如有错漏,欢迎指出,为后来者提供一个教训;如有更佳方式,也希望大家分享。

Gazebo 环境排错指南#

根据一年多来大家的 bug,这里汇总 Gazebo 多版本共存导致依赖冲突的排查和修复方法。

1. 检查当前安装了哪些 Gazebo 版本#

# 查看所有 Gazebo 相关包
dpkg -l | grep -E "^ii" | awk '{print $2}' | grep -E "^gz-|^libgz-|^sdformat|^libsdformat|python3-gz" | sort

# 查看可用的 Gazebo Sim 版本(多版本意味着冲突)
gz sim --versions

# 查看当前默认版本
gz sim --version
bash

正常状态:gz sim --versions 只输出一个版本号(如 8.9.0),所有 libgz-*-XX 都指向同一代(如全是 7 或全是 8)。

2. 版本冲突的典型表现#

# 症状 1:多个版本共存
gz sim --versions
# 输出:
# 8.9.0
# 7.9.0        ← 说明 Garden 和 Harmonic 共存,冲突!

# 症状 2:CMake 找到错误版本
grep "gz-sim_DIR" ~/PX4-Autopilot/build/px4_sitl_default/CMakeCache.txt
# 应与 gz sim --version 对应:Harmonic → gz-sim8,Garden → gz-sim7

# 症状 3:ROS2 桥接包版本不匹配
dpkg -l | grep ros-humble-ros-gz
# 应只有 gzharmonic 或只有 gzgarden,不能同时存在
bash

3. 修复:统一到单一 Gazebo 版本#

以 Harmonic (v8) 为例(ROS2 Humble 推荐,因为有对应桥接包):

# 1. 移除 Garden (v7) 所有包
sudo apt-get purge -y gz-garden gz-sim7-cli gz-launch6-cli gz-transport12-cli \
  libgz-sim7 libgz-sim7-dev libgz-sim7-plugins \
  libgz-launch6 libgz-launch6-dev \
  libgz-transport12 libgz-transport12-dev \
  libgz-fuel-tools8 libgz-fuel-tools8-dev \
  libgz-gui7 libgz-gui7-dev \
  libgz-msgs9 libgz-msgs9-dev \
  libgz-physics6 libgz-physics6-dev \
  libgz-rendering7 libgz-rendering7-dev \
  libgz-sensors7 libgz-sensors7-dev \
  libsdformat13 libsdformat13-dev sdformat13-sdf \
  python3-gz-sim7

# 2. 移除 Garden 的 ROS2 桥接
sudo apt-get purge -y ros-humble-ros-gzgarden*

# 3. 安装 Harmonic 的 ROS2 桥接
sudo apt-get install -y ros-humble-ros-gzharmonic

# 4. 验证
gz sim --versions  # 应只显示 8.9.0
dpkg -l | grep gz-garden    # 应无输出
dpkg -l | grep gz-harmonic  # 应显示已安装
bash

4. .bashrc 常见问题#

# 问题 1:source 重复(多次追加导致 PATH 越来越长)
grep "source.*setup.bash" ~/.bashrc | sort | uniq -c
# 如果某行出现超过 1 次,需要手动清理 ~/.bashrc

# 问题 2:ROS2 加载顺序错误
# 正确顺序:先 source /opt/ros/humble/setup.bash,再 source ~/ros2_ws/install/setup.bash
# 工作空间必须放在基础环境之后

# 问题 3:模型路径变量
# Gazebo Garden/Harmonic 使用 GZ_SIM_RESOURCE_PATH,不是 GAZEBO_MODEL_PATH
echo $GZ_SIM_RESOURCE_PATH  # 应指向模型目录
bash

5. 检查 PX4 编译目标与 Gazebo 版本是否一致#

# PX4 CMake 缓存记录的 gz-sim 版本
grep "gz-sim_DIR" ~/PX4-Autopilot/build/px4_sitl_default/CMakeCache.txt
# gz-sim8 → Harmonic
# gz-sim7 → Garden

# 如果版本与安装的 Gazebo 不一致,需要重新编译 PX4:
cd ~/PX4-Autopilot
make clean
make px4_sitl gz_x500
bash

6. 检查 ROS2 桥接包依赖#

# 确认桥接包的 SDFormat 依赖与 Gazebo 版本匹配
apt-cache depends ros-humble-ros-gzharmonic | grep sdformat
# Harmonic → libsdformat14-dev

# 确认无残留的 Garden 桥接
dpkg -l ros-humble-ros-gzgarden* 2>/dev/null
# 应显示 "没有找到" 或状态为 "un" (已卸载)
bash

参考资料#

ROS2+PX4 仿真环境开发教程
https://duduuu.xyz/zh/posts/px4-ros2-gazebo-simulation
Author dudu
Published at 2026年7月09日
阅读
总访问