简介:本资源是面向无人机开发者、高校师生及自动驾驶研究者的通用仿真平台,聚焦PX4飞控、ROS中间件与Gazebo物理仿真三者深度集成,解决真实飞行测试成本高、风险大、迭代慢等核心痛点,适用于自主导航算法验证、避障策略开发、遥感任务仿真及教学实验等场景。压缩包为910.34MB的ZIP文件,包含完整XTDrone-master源码、ROS功能包、PX4固件配置、Gazebo世界模型及启动脚本等,其中C++/Python节点代码支撑控制逻辑,launch与SDF文件实现环境与系统快速部署,配置文档详述多机型适配与通信桥接机制。目前已有3215人学习下载,用户可直接复现虚拟飞行全流程,获取开箱即用的软硬件在环测试框架、模块化调试接口及典型任务(如定点悬停、路径跟踪、传感器数据闭环)的参考实现,显著降低从理论到仿真的落地门槛。
1. 为什么我最后选了PX4 + ROS + Gazebo这套组合
先说结论:如果你打算认真搞无人机算法开发,而不是只想看飞机在屏幕里转圈,那PX4、ROS和Gazebo这套组合仍然是目前最稳妥、资料最全、社区最活跃的通用仿真方案。我前后试过几套别的路子,折腾一圈又回到了这儿。
很多人一开始会被“仿真平台”四个字劝退,觉得又要装Linux又要配环境,门槛太高。但换个角度想:真机试错一次的成本,够你在仿真里把同一个场景跑几百遍。炸机、撞墙、飞丢、GPS漂移,这些在仿真里都是几秒钟重启的事。更实在的是,仿真平台能帮你把控制逻辑、感知算法、通信链路全跑通,再上真机时心里有底得多。
这套平台能做什么?简单说,就是在一台电脑里用Gazebo搭建虚拟世界和无人机模型,用PX4跑飞控逻辑,用ROS把传感器数据、控制指令、状态信息全部串起来。你可以仿真悬停、定点、航线飞行,也能接上视觉SLAM、路径规划、目标跟踪这些上层算法。从学生做课题到工程师预研新功能,基本都是这条路。
它适合谁?想入门无人机开发的爱好者,做毕设或科研的本科生研究生,还有想在公司里快速验证算法的开发者。只要你愿意花两三天把环境弄好,后面省下的时间绝对值得。
2. 搭建前的整体思路:先别急着敲命令
2.1 把三个角色的分工搞清楚再动手
PX4、ROS、Gazebo这三个东西,很多人一开始分不清谁管什么,结果出了问题也不知道该查谁。我习惯用一个比方来理解:
- Gazebo是“舞台布景”,负责搭建虚拟世界,包括地形、光照、障碍物,以及无人机本体的外观、质量和碰撞模型。它只负责把物理世界模拟出来。
- PX4是“驾驶员的大脑”,负责飞行控制。它接收期望位置或速度,结合IMU、气压计、GPS这些传感器数据,算出电机油门输出。它就是跑在真机上的那份飞控固件,只不过在仿真里跑在PC上。
- ROS是“通讯总线”,负责让各个模块互相说话。传感器数据从Gazebo出来,经过ROS话题发给算法;算法算出的控制指令,通过ROS发给PX4;PX4的状态再通过ROS回报给上层。
理解了这三个分工,很多配置问题就迎刃而解。比如Gazebo里飞机没动,先看是PX4没解锁还是没有启停指令;算法收不到图像,先查ROS话题名对不对;电机转速异常,多半是模型或者物理参数没配对。
2.2 版本选型是最大的隐藏坑
这套仿真平台最折磨人的不是原理,而是版本匹配。我见过太多人卡在编译错误上,最后发现是Ubuntu版本和ROS版本对不上。推荐一套目前最省心的组合:
- Ubuntu 22.04
- ROS 2 Humble(也可以用ROS 1 Noetic,后面细说)
- Gazebo Classic 11(注意不是Gazebo Ignition,虽然Ignition也能用,但PX4官方支持和文档还是以Classic为主)
- PX4 Autopilot的main分支或者v1.14左右的稳定版
为什么推荐Ubuntu 22.04 + ROS 2 Humble?因为这是当前资料最充足、踩坑记录最多的组合。你要是用Ubuntu 24.04配ROS 2 Jazzy,也能跑,但很多依赖包、示例代码还没完全跟上,出了问题搜索都搜不到。别在最前沿当小白鼠,做仿真平台追求的是稳定复现。
如果你之前接触过ROS 1,用Noetic也能跑PX4仿真,而且现在很多老教程还停留在ROS 1。但我的建议是:如果是新项目,直接上ROS 2。因为ROS 1停止维护是早晚的事,将来你想接新的算法库、新的硬件驱动,ROS 2的生态明显更活跃。我这里主要讲ROS 2 Humble的路径,ROS 1的差异点会单独提一下。
2.3 虚拟机还是双系统,我推荐虚拟机
很多人在第一步就纠结:要不要装双系统?我的答案是:如果你只是做仿真开发,虚拟机完全够用,而且更安全。Vmware Workstation Player免费版就能跑,分配4核CPU、8GB内存、100GB磁盘,跑PX4 + Gazebo Classic + RViz2,只要不开巨型地图,流畅度可以接受。
双系统的优势是性能损耗小,但劣势是切换麻烦,而且一旦搞坏系统,修复成本高。虚拟机的好处是快照功能,环境配好之后打一个快照,后面再怎么折腾都能一键还原。我自己的开发机就是Windows宿主机 + Ubuntu虚拟机,除了大型点云地图偶尔有点卡,其他完全没问题。要是你的电脑内存小于16GB,建议先加内存再跑仿真。
3. 环境搭建实操:从零到起飞的全过程
3.1 第一步:安装ROS 2 Humble
装ROS 2最忌讳的事情就是自己一条条去官网复制命令。官网步骤没错,但容易漏掉依赖,而且国内网络拉取软件源经常超时。我推荐直接用鱼香ROS的一键安装脚本,这工具在无人机和机器人圈子里口碑不错,能省掉八成麻烦。
wget http://fishros.com/install -O fishros && chmod +x fishros && ./fishros运行之后按提示选择ROS 2 Humble桌面版安装。如果你的网络不好,脚本会让你选择国内镜像源,选一个延迟低的就行。装完后记得验证:
source /opt/ros/humble/setup.bash ros2 run demo_nodes_cpp talker再开一个终端:
source /opt/ros/humble/setup.bash ros2 run demo_nodes_py listener能看到talker和listener在互相发消息,ROS 2就算装好了。注意,每次新开终端都要先source,不然找不到ros2命令。把这句话写进~/.bashrc里可以省事:
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc source ~/.bashrc3.2 第二步:安装Gazebo Classic 11
用ROS 2的apt源直接装Gazebo也很方便,但有个坑:Ubuntu 22.04默认源里的Gazebo是Ignition版本,不是Classic。PX4官方现在主要支持Gazebo Classic,所以一定要指定版本。
最稳妥的方式是用PX4官方给的安装脚本,它会帮你把Gazebo Classic、依赖库、无人机模型全部搞定:
git clone https://github.com/PX4/PX4-Autopilot.git --recursive cd PX4-Autopilot bash ./Tools/setup/ubuntu.sh这个脚本会安装ROS 2 Humble、Gazebo Classic、MAVSDK、QGroundControl等一堆工具。脚本跑完基本就齐活了。如果你的网络在拉PX4子模块时特别慢,可以试试用代理或者换一个时间段。实在不行,去Gitee找PX4的镜像仓库也行,但注意子模块也要一起拉。
装完Gazebo后验证一下:
gazebo --version如果打印出Gazebo multi-robot simulator,version 11.x.x,说明装好了。
3.3 第三步:编译PX4固件并启动仿真
PX4的源码下载下来后,还需要编译固件。这里的“固件”并不是真的要刷到飞控板上,而是编译出一个可以在本机运行的进程,Gazebo里那个飞机模型跟这个进程通过共享内存或者UDP通信。
编译前先把PX4-Autopilot目录里的子模块更新完整:
cd PX4-Autopilot git submodule update --init --recursive然后编译,指定仿真平台的硬件配置为px4_sitl_default:
make px4_sitl gazebo-classic第一次编译时间很长,我当初等了差不多二十分钟,取决于CPU性能。编译过程会下载一些工具链,比如xtensa编译器,这是用来编译PX4内部使用的DSP库的。很多人卡在这一步,提示fetching xtensa compilers后一直不动。这是因为拉取工具链的服务器在国外。解决办法是手动下载对应压缩包放到指定目录,或者直接用一条命令绕过这些不必要的东西。如果只是做纯仿真,不需要编译实际飞控固件的话,可以设定跳过:
export PX4_IGNORE_XTENSA_COMPILER=1 make px4_sitl gazebo-classic如果编译成功,终端会输出一堆启动信息,然后自动打开一个Gazebo窗口,里面有一架标准的PX4四旋翼无人机。同时终端会进入一个nuttx shell,这里面可以执行PX4的内部命令,比如commander takeoff、commander land。
3.4 第四步:启动ROS 2桥接
PX4和ROS 2之间默认不直接通信,需要启动一个桥接节点。PX4提供了px4-ros2-interface-lib和microRTPS桥,现在最常用的是通过Micro XRCE-DDS Agent。在PX4固件里默认已经开启了通过UDP连接的MicroRTPS桥,所以只要启动一个Agent,ROS 2就能收到PX4的话题了。
在另一个终端运行:
cd PX4-Autopilot source Tools/setup_gazebo.bash source install/setup.bash ros2 run micro_rtps_agent micro_rtps_agent -t UDP如果提示找不到micro_rtps_agent,需要先编译它:
make px4_sitl rtps启动Agent后,再启动ROS 2接口包:
cd PX4-Autopilot source install/setup.bash ros2 launch px4_ros_com sensor_combined_listener.launch.py如果能看到不停的传感器数据打印,说明PX4和ROS 2链路通了。此时你用ros2 topic list能看到一堆话题,比如/fmu/out/vehicle_attitude、/fmu/out/vehicle_odometry等。
4. 核心细节解析:仿真里每个环节为什么这么配
4.1 无人机模型与物理参数的关联
Gazebo里的飞机模型不是画个好看的外壳就行,它的每个部件都要有正确的质量、惯性张量和碰撞体积。PX4官方默认的iris模型,参数是参照真实四旋翼设定的,比如机架重量、电机最大推力、空气阻力系数。你在仿真里改一个参数,直接影响悬停油门、姿态响应速度。
我做过一个实验:把模型质量从1.5kg改成2.0kg,其他不变,结果起飞油门从0.55变成了0.68,姿态响应也变迟钝了。所以如果你要仿真自己的机架,一定要去改model.sdf里的<mass>和<inertia>,否则控制参数没有参考意义。
4.2 PX4的SITL模式与真机的差异
SITL(Software In The Loop)意味着飞控代码运行在PC上,用的是PC的时钟和CPU,和真机的ARM芯片有差异。所以仿真里能验证的是控制逻辑、状态估计、任务规划,不能验证的是实时性、驱动层代码。比如在仿真里PID参数调到完美,上真机可能还是会有震荡,因为真机的传感器噪声更大、执行器延迟更高。
另一个差异是传感器模型。Gazebo里可以给IMU加高斯噪声,给GPS加漂移,但默认情况下一些传感器是理想化的。你在做视觉SLAM算法时,最好在Gazebo里给相机加上噪声和畸变,否则仿真里跑得好好的,真机上一团糟。
4.3 时间同步和通信机制
PX4和Gazebo之间的同步是通过Gazebo的插件实现的,PX4有一个mavlink_interface插件,从SIM_GZ端口接收飞机状态,然后把电机指令发送回Gazebo。这个通信频率很高,通常250Hz。ROS 2话题的频率不一样,比如姿态话题是30Hz,位置话题是10Hz。做算法时要搞清楚每个话题的频率,不然滤波也好、控制也好,很容易把频率不匹配当成参数问题去调,浪费不少时间。
用ros2 topic hz /fmu/out/vehicle_attitude可以实时查看话题频率。如果频率远低于预期,先查CPU占用,或者看看是不是有太多节点抢资源。
5. 实操过程与核心环节实现
5.1 一次完整的起飞、悬停、降落任务
环境就绪后,第一次完整任务建议用QGroundControl地面站来做,因为直观、容易理解,还能看到PX4内部状态。启动PX4 SITL后,再开一个终端启动QGroundControl。注意QGC在SITL模式下会自动连接UDP端口14550。
等QGC界面上出现飞机图标、显示GPS正常后,按以下顺序操作:
- 点击“飞行规划”标签,在无人机位置附近设置一个起飞点。
- 点击“上传”按钮,把航线传到飞控。
- 点击“起飞”按钮,回到飞行界面,确认滑块解锁。
- 拨动弹窗里的起飞开关,飞机开始起飞并悬停在2.5米高度。
- 点击“返航”或“降落”,飞机自动下降。
如果你不想开QGC,也可以在PX4的shell里用命令控制:
commander takeoff commander land但这只是最简单的任务,实际开发中你可能要写一个ROS 2节点,去订阅位置信息,然后通过发布指令来控制飞机。
5.2 用ROS 2节点控制无人机起飞
PX4的ROS 2接口提供了OffboardControlMode和TrajectorySetpoint等自定义消息。在offboard模式下,PX4不再执行内部任务,而是完全听从来自ROS 2的期望设定值。这种模式非常适合做路径规划、视觉跟踪等上层算法。
下面是一个最小化的offboard起飞示例,用Python写的,简化了很多错误处理,但足以跑通流程:
import rclpy from rclpy.node import Node from px4_msgs.msg import OffboardControlMode, TrajectorySetpoint, VehicleCommand import time class OffboardControl(Node): def __init__(self): super().__init__('offboard_control') self.publisher_offboard = self.create_publisher(OffboardControlMode, '/fmu/in/offboard_control_mode', 10) self.publisher_trajectory = self.create_publisher(TrajectorySetpoint, '/fmu/in/trajectory_setpoint', 10) self.publisher_command = self.create_publisher(VehicleCommand, '/fmu/in/vehicle_command', 10) self.timer = self.create_timer(0.1, self.send_commands) self.start_time = time.time() def send_commands(self): # 发送offboard控制模式,位置控制 offboard_msg = OffboardControlMode() offboard_msg.timestamp = int(time.time() * 1e6) offboard_msg.position = True offboard_msg.velocity = False offboard_msg.acceleration = False self.publisher_offboard.publish(offboard_msg) # 设置期望位置:先悬停在起点上方10米 traj_msg = TrajectorySetpoint() traj_msg.timestamp = int(time.time() * 1e6) traj_msg.position = [0.0, 0.0, -10.0] # NED坐标,Z向下,所以-10是向上10米 traj_msg.vx = 0.0 traj_msg.vy = 0.0 traj_msg.vz = 0.0 traj_msg.yaw = 0.0 self.publisher_trajectory.publish(traj_msg) # 在3秒后切换为offboard模式并解锁 if time.time() - self.start_time > 3.0: command = VehicleCommand() command.timestamp = int(time.time() * 1e6) command.command = 400 # VEHICLE_CMD_DO_SET_MODE command.param1 = 1.0 # MAV_MODE_FLAG_CUSTOM_MODE_ENABLED command.param2 = 2.0 # PX4_CUSTOM_MAIN_MODE_OFFBOARD self.publisher_command.publish(command) arm_command = VehicleCommand() arm_command.timestamp = int(time.time() * 1e6) arm_command.command = 400 # 这里要换成分组命令,出于示例简化 # 实际解锁命令是MAV_CMD_COMPONENT_ARM_DISARM (400) arm_command.param1 = 1.0 self.publisher_command.publish(arm_command) def main(args=None): rclpy.init(args=args) node = OffboardControl() rclpy.spin(node) node.destroy_node() rclpy.shutdown()这个示例里我故意简化了命令细节,实际跑的时候注意两点:一是解锁和切换模式通常要分开发,而且PX4要求offboard模式之前必须先收到持续1秒以上的期望值;二是坐标系是NED(北东地),Z轴向下为正,所以向上飞要写负值。很多新手在这上面栽过跟头,飞机一解锁就往地上怼。
5.3 如何添加机载相机并实时查看图像
Gazebo里默认的iris模型不带相机。要做视觉仿真,需要往无人机模型里添加一个相机传感器插件。最简单的方式是用PX4官方的iris_stereo_camera模型,它自带双目相机。启动命令:
make px4_sitl gazebo-classic_iris_stereo_camera启动后,ROS 2里会有/camera话题,可以通过ros2 run rqt_image_view rqt_image_view查看图像。如果你用的是普通iris模型,也可以通过修改model.sdf加入相机插件,但新手还是直接用官方带相机的模型比较省事。
另外,如果要仿真激光雷达或深度相机,Gazebo里有对应的传感器插件。我建议先用gazebo_ros_camera、gazebo_ros_depth_camera等插件,它们能直接把传感器数据转换成ROS话题,省去写驱动的麻烦。
6. 常见问题与排查技巧实录
6.1 编译时报错找不到GL/glew.h
这个错误通常是因为缺少OpenGL开发库。Gazebo的渲染需要OpenGL支持,在虚拟机里尤其容易出问题。解决办法:
sudo apt install libglew-dev libopencv-dev libgazebo11-dev如果还报其他依赖缺失,一般用sudo apt --fix-broken install再来一遍。虚拟机里还要检查3D加速是否开启,VMware里请务必在虚拟机设置里勾选“加速3D图形”,否则Gazebo渲染会卡到怀疑人生。
6.2 Gazebo启动后黑屏或飞机消失
这个问题八成是模型加载失败或路径问题。PX4启动时依赖PX4_SIM_MODEL环境变量来定位模型文件。如果你从别的目录启动PX4,没有source环境脚本,就会找不到模型。
我习惯的做法是在启动PX4前,先执行:
cd PX4-Autopilot source Tools/setup_gazebo.bash source install/setup.bash export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:$(pwd) export PX4_SIM_MODEL=iris然后再make px4_sitl gazebo-classic。如果是在ROS 2 launch文件里启动,也要确保环境变量传递正确。
6.3 ROS 2收不到PX4的话题
先确认微RTPS Agent跑起来了没,再确认px4_ros_com里的监听节点是否正常。常见问题是没有编译ROS 2接口包:
cd px4_msgs colcon build source install/setup.bash注意,每次编译完新消息包后,都要在终端里重新source,否则ros2 topic list看不到新话题。
另外,PX4启动时和Agent的UDP端口需要一致。默认PX4用2022/2023端口,Agent也监听这个端口。如果你在启动脚本里改过端口,两边要同步改。
6.4 虚拟机性能不够导致仿真很卡
仿真卡顿最影响心情,解决办法有优先级:
- 把Gazebo里的图形渲染窗口缩小,减少视图渲染负担。
- 关掉QGroundControl的3D地图显示,用2D地图代替。
- 在启动Gazebo之前,把虚拟机内存加大到12GB以上,分给CPU核心数不少于4个。
- 降低Gazebo的物理更新频率,但这会影响仿真精度,慎用。
如果以上都做了还是卡,那就别开太复杂的地图环境,用空的empty.world就够了。
7. 仿真平台的扩展:从单机到编队再到复杂场景
7.1 多无人机编队仿真
学会单机仿真后,很多人会想试试编队。PX4支持多机SITL仿真,但需要给每架飞机分配不同的实例编号和端口。在Gazebo里启动多台iris模型,然后通过mavlink端口区分。编队控制算法通常跑在ROS 2上层,用rclcpp或者rclpy发布多路期望指令,分别控制不同飞机。
编队仿真最大的坑是端口冲突,每架飞机的通信端口必须不同。我建议把端口管理写成一个shell脚本,比如make px4_sitl gazebo-classic_iris_1和_iris_2这种形式,PX4官方已经支持多机启动,照着文档做成功率会高很多。
7.2 接入SLAM与导航栈
如果你想做自主导航,常见的组合是Cartographer或SLAM Toolbox + Nav2。在Gazebo里你可以放一个室内环境模型,然后让无人机搭载激光雷达或深度相机,绕场飞行建图,再用Nav2做路径规划。之前不少博主推荐在Ubuntu 24.04上装Gazebo + SLAM Toolbox + Nav2,我就在22.04上试过,也一样能跑,而且更稳。
关键在于传感器话题要和SLAM算法要求一致。比如SLAM Toolbox通常接收/scan话题的LaserScan消息,如果你的激光雷达发布的是PointCloud2,需要先转换。Gazebo里如何设置雷达扫描角度和频率,直接影响建图质量。我建议仿真时把雷达的噪声调低一点,采样频率调到10Hz以上,这样建图效果接近真机中较好的雷达。
7.3 在Gazebo里造一个自己的测试场地
Gazebo的模型库支持自定义环境。你可以用building_editor创建墙面、障碍物,也可以把网上下载的3D模型导入。但要注意:模型面的数量影响仿真性能,太精细的模型会导致帧率下降。我一般用简单的方块和圆柱体搭出障碍物场景,既够用又流畅。
在world文件里可以放置多个模型,也可以动态生成。如果要在固定场景中反复测试,用world文件最方便。PX4启动时会默认加载empty.world,换成自己的世界文件,在launch或启动命令里指定即可。
8. 一些关于平台选型和未来方向的大实话
8.1 为什么我不建议新手直接碰“强化学习”类的仿真平台
最近看到很多人讨论mjlab、mujoco这类机器人强化学习平台。确实,它们在训练RL策略时比Gazebo高效不少,尤其是需要大量并行采样时。但如果你还在学无人机基础控制、状态估计,或者是想先跑通整个通信链路,Gazebo + PX4是更好的选择。原因在于PX4本身就是一套完整的飞控系统,而MuJoCo等平台更偏重环境物理模拟,飞控逻辑需要你自己写。
当然,等你在Gazebo里把任务跑明白了,想让无人机自主学习避障,可以把Gazebo和RL工具结合。目前也有PX4 + Gazebo + RL的开源项目,比如用OpenAI Gym包装PX4的接口,训练端到端策略。这个方向值得关注,但不是零基础就能上手。
8.2 PX4版本和硬件的匹配问题
我在实操中发现,PX4的main分支变化很快,每周都有新commit。如果你是为了复现某个论文,最好固定一个tag。比如v1.13、v1.14都是比较稳定的版本。编译时在make px4_sitl gazebo-classic前可以先git checkout v1.14.0,这样能减少很多意外错误。
如果后续要上真机,仿真的PX4代码和真机PX4代码是同一份,但你需要根据飞控硬件选择不同的make目标。比如用Pixhawk 4就要编译px4_fmu-v5_default。在仿真里验证过的算法,真机上不一定完全复现,但控制逻辑和发布的话题格式是一样的,差别主要在执行层面。
8.3 一个稳定可复现的仿真环境是团队的资产
最后说一句掏心窝的话。很多项目一开始图省事,随便装个环境,两个人各装各的,最后代码合并时各种环境问题。我强烈建议你把环境搭建过程写成自动化脚本,或者做一个虚拟机镜像。团队里新成员来了,直接拷贝镜像、导入虚拟机,10分钟就能开始开发,而不是花两天配环境。我用Vmware的OVA模板封装过一套环境,分发给同事后效率提升明显。如果你愿意,甚至可以用Docker跑PX4 SITL,把Gazebo和ROS都容器化,但这需要GPU透传,配置复杂度更高,性价比因人而异。
根据我的经验,仿真平台的价值,不在于它多逼真,而在于它能让你在一天之内完成几十次飞行试验。每一次试验都能留下log,能复现bug,能对比算法改进前后的效果。这种快速迭代的能力,真机很难做到。所以别怕开头那两天的环境搭建折腾,迈过去之后,你会发现新世界的大门已经打开了。
本文还有配套的精品资源,点击获取