简介#
PX4 作为目前全世界广泛流行的开源飞控,在无人机设计和控制方面为开发人员带来便利。ROS 作为机器人操作系统,其提供的分布式通信架构简化了无人机编队仿真流程,通过 Gazebo 物理仿真引擎,可以提供真实的仿真环境。
ROS 目前已经更新到了 ROS2,相较于 ROS1,其应用性和可维护性会更加强大。目前已有的 ROS2+PX4 的仿真案例并不多,且伴随二者的不断更新,有很多环境配置的问题。笔者在这里提供一种个人的开发流程。
Ubuntu 系统的安装#
本环境基于 Ubuntu 22.04 系统进行搭建。大家可以安装虚拟机或者在 Windows 系统中安装双系统。在这里,笔者给出一个在 Windows11 下安装 Ubuntu 22.04 双系统的视频教程链接:
现在开始进行环境开发流程,这里给出一个博主的环境开发流程,与我们的环境搭建较为相似,简洁明了。如果只有单机仿真需求,也可以参考这篇资料进行环境搭建:
注意:在开始下列步骤之前,建议首先保证能够科学上网,且网速流畅,否则后续从 Github 克隆仓库时会中途闪退。
PX4 源码下载及编译#
首先从 Github 上克隆 PX4 源码,并且更新子模块:
git clone https://github.com/PX4/PX4-Autopilot.git --recursivebash由于后续环境配置会装很多东西,有可能难以完全清干净,建议在这一步完成后运行以下命令,备份 ~/PX4-Autopilot,以免后续环境配错需要重新克隆代码:
zip -r PX4-Autopilot.zip PX4-Autopilot/bash接着安装相关依赖:
bash ./PX4-Autopilot/Tools/setup/ubuntu.shbash此时 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/shutdownplaintext则可以控制无人机的起飞、降落以及关闭仿真。此时可以在 jmavsim 的 UI 中看到无人机的起降。到此步,PX4 的源代码下载和编译全部完成。
ROS2 及其相关依赖的安装#
我们使用 ROS2 Humble 进行开发,ROS2 及其依赖的安装和环境配置有些繁琐,在此我强烈建议各位使用”鱼香 ROS”的一键安装功能,在这里感谢其为 ROS 开发提供的便利。直接在 Ubuntu 的系统终端输入以下命令并按终端返回的指令安装即可:
wget http://fishros.com/install -O fishros && . fishrosbash其一键安装工具中还有 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-harmonicbash然后安装对应版本的 Gazebo-ROS2 通信桥(Harmonic 对应 gzharmonic):
sudo apt install ros-humble-ros-gzharmonicbash安装完成后验证版本唯一性(只应出现一个版本号):
gz sim --versions # 应只显示 8.9.0bash常见错误:不要安装
gz-garden或ros-humble-ros-gzgarden,那是 Gazebo Garden (v7),与 PX4 当前的gz-sim8编译目标不兼容。
MicroXRCE-DDS Agent 的安装#
根据官方文档说明,在 ROS2 中 PX4 使用 uXRCE-DDS 中间件来允许在配套计算机上发布和订阅 uORB 消息,而不再使用 MAVROS,我们按照官方案例进行下载、编译及安装。
下载源码:
git clone -b v2.4.2 https://github.com/eProsima/Micro-XRCE-DDS-Agent.gitbash编译:
cd Micro-XRCE-DDS-Agent
mkdir build
cd build
cmake ..
makebash这里应该会有个报错,大家去
build/fastdds/tmp/fastdds-gitclone.cmake里把2.12.x改为v2.12.1后重新make一下就可以了。
编译的过程会较长,需要进行一定等待,编译结束后进行安装:
sudo make install
sudo ldconfig /usr/local/lib/bashQGC 地面站的安装#
在后续启动 PX4+Gazebo 仿真时,如果丢失地面站的连接,会导致无法启动 PX4 飞控对无人机进行控制,因此需要在系统中安装 QGC 地面站。安装的方法我给出一个 CSDN 博主的链接,按照上面的步骤操作即可:
单机 Offboard 测试流程及开发简介#
现在所有的开发环境已经配置好了,我们现在进行 PX4 的 Offboard 模式的验证。
Offboard 模式是 PX4 中的一种特殊飞行模式,允许外部系统(如机载计算机、ROS2 节点等)通过 MAVLink 或 uXRCE-DDS 直接发送控制指令,实时控制无人机的姿态、位置或速度,从而实现自主飞行或高级任务。
首先创建 ROS2 的工作空间:
mkdir -p ~/ros2_ws/srcbash随后下载源码(注意科学上网):
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.14bash进行编译:
cd ~/ros2_ws
colcon buildbash更新环境并配置环境变量:
echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc
echo "export GZ_SIM_RESOURCE_PATH=\$HOME/.simulation-gazebo/models:\$GZ_SIM_RESOURCE_PATH" >> ~/.bashrc
source ~/.bashrcbash启动 Offboard 仿真#
现在我们启动 Offboard 仿真。首先打开已经装好的 QGC 地面站。
终端 1 —— 打开通信:
MicroXRCEAgent udp4 -p 8888bash
终端 2 —— 启动仿真:
cd ~/PX4-Autopilot
make px4_sitl gz_x500bash此时地面站会与 PX4 进行连接,Gazebo 启动,出现了 x500 的无人机。当 PX4 终端出现绿色的 ready for takeoff 时,说明仿真启动成功。有关这个使用 make 命令启动仿真的环节,我们在后续进行多无人机仿真时会详细解释。
终端 3 —— 运行 Offboard 模式源码:
ros2 run px4_ros_com offboard_controlbash我们可以发现 Gazebo 中无人机上升 5 米,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 源代码。
因此如果进行单机使用 Offboard 模式进行仿真,便可以按照以下流程开发:
- 在已经创建并且配置好环境的
~/ros2_ws这个 ROS2 工作空间下再创建一个包(和px4_ros_com目录并行) - 在新创建的包中,在
/src目录下编写基于 Offboard 模式进行控制的 C++/Python 代码 - 在新创建的包中的
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 buildbash最后,仿照之前的方法打开 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_x500bash这个 make 指令其实一共完成了三件事:
- 编译 PX4 源代码
- 启动 PX4
- 启动 Gazebo 仿真
但在多机仿真中,我们不需要反复地使用 make 指令,这样会导致每一架 x500 无人机单独启动了一个 Gazebo 仿真,而这不是我们想要的。因此在 Gazebo 环境中启动多机仿真,我们的目标为以下几个:
- 单独启动 Gazebo 仿真
- 分别启动 PX4,添加无人机进入 Gazebo 环境
- 建立通信
单独启动 Gazebo#
首先我们需要下载一个 Gazebo 的启动脚本(simulation-gazebo):
wget https://raw.githubusercontent.com/PX4/PX4-gazebo-models/main/simulation-gazebobash随后在脚本所在的目录终端运行以下指令:
python3 simulation-gazebobash常见问题:如果 Gazebo 窗口无法打开(闪退或黑屏),通常是因为显卡驱动不兼容或虚拟机缺少 GPU 直通。可以在命令前加上
LIBGL_ALWAYS_SOFTWARE=1,强制使用 CPU 软件渲染:bashLIBGL_ALWAYS_SOFTWARE=1 python3 simulation-gazebo这个环境变量告诉 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 0bash参数说明:
| 参数 | 含义 |
|---|---|
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 1bash如果要添加更多的无人机,按此方法添加即可,也可以编写统一的脚本进行添加。
现在我们会发现在 Gazebo 里出现了两架并排的无人机,可以分别在他们启动 PX4 后的终端输入:
commander takeoff/landplaintext可以分别观察他们的起降情况。最后添加通信:
MicroXRCEAgent udp4 -p 8888bash
至此,基于 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 --versionbash正常状态:
gz sim --versions只输出一个版本号(如8.9.0),所有libgz-*-X的X都指向同一代(如全是 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,不能同时存在bash3. 修复:统一到单一 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 # 应显示已安装bash4. .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 # 应指向模型目录bash5. 检查 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_x500bash6. 检查 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