我先把话说在前面:这套东西看着吓人,实际上拆开就是四块积木——PX4负责“飞控逻辑”,Gazebo负责“虚拟世界”,XRCE-DDS负责“中间通信”,QGC负责“地面站监控”。我当年从零开始搭的时候,光是搞清楚这四个东西怎么串起来就花了两天,网上教程各讲各的,没一篇能从头撸到尾。这篇文章就是把我踩过的坑、试出来的顺序、参数怎么调、报错怎么解,全部摊开写给你,照着做就能把整条链路跑通。
1. 这套系统到底是什么,为什么非要四个组件
1.1 从一次“虚拟试飞”说起
先打个比方。你想学开车,总不能一上来就租辆真车上路,又危险又费钱。无人机开发也一样,PX4是“车的驾驶逻辑”,Gazebo是“虚拟练车场”,QGC是“坐在副驾的教练”,XRCE-DDS则是“教练和车之间的对讲机”。四者合起来,你就能在电脑里完成从起飞、巡航到降落的完整验证,不用碰一次真机。
PX4是一套开源的飞控固件,跑在 Pixhawk 这类硬件上,也可以跑在电脑的仿真环境里。它负责姿态控制、位置估计、任务规划这些核心逻辑。Gazebo则是一个高保真物理仿真器,能模拟重力、风力、地面摩擦、传感器噪声,让虚拟飞机像真飞机一样被“吹”得东倒西歪。XRCE-DDS(XRTCE is the XRCE-DDS? 准确说是 eProsima 的 Micro XRCE-DDS)是PX4和外部世界通信的桥梁——PX4 内部用的是 uORB 消息机制,但 Gazebo 和 QGC 没法直接读 uORB,所以需要把 uORB 消息转成 DDS 标准消息,再通过 XRCE-DDS 这个轻量协议送出去。QGC(QGroundControl)则是地面站,让你在电脑屏幕上看到飞机姿态、地图位置、传感器数据,也可以直接下发指令。
这套组合最大的价值在于:你把“写代码—验证—改代码”的循环缩短到几分钟。真机试飞一次,从准备场地到检查电池再到回收飞机,少说半小时;Gazebo 里点一下重启,新代码立刻生效,还不用担心炸机。
1.2 四组件各自扮演的角色和协作流程
为了后面好理解,我把通信链路画成一条线:
Gazebo(虚拟传感器数据) → PX4(飞控核心,uORB消息) → XRCE-DDS代理(PX4内部协议→DDS协议) → QGC(地面站显示与控制)实际跑起来是这样的:Gazebo 里生成一个模拟的无人机模型,模型上挂着 IMU、GPS、气压计这些虚拟传感器。传感器数据通过 Gazebo 的插件接口送入 PX4。PX4 跑完姿态估计算法,输出电机指令,再通过 Gazebo 的电机插件驱动模型运动。同时,PX4 把状态信息打包成 uORB 消息,XRCE-DDS 代理把这些消息翻译成 DDS 标准格式,发给 QGC。QGC 收到后在界面上画出姿态、位置、电池电量,你也能在 QGC 里点“起飞”按钮,指令反向走这条链路回到 PX4。
这里有个容易懵的点:XRCE-DDS 到底是干嘛的?它全称叫 “eProsima Micro XRCE-DDS”,是 DDS 协议的极简实现。DDS 本身非常强大,但太重量级,不适合跑在 Pixhawk 这种资源有限的嵌入式设备上。XRCE-DDS 把 DDS 消息拆成一个轻量客户端(跑在 PX4 上)和一个代理(跑在电脑上)之间的通信,代理再和 QGC、其他 DDS 应用交互。简单说,它就是“嵌入式端和桌面端之间的翻译官”。
1.3 适合谁看,需要什么基础
这篇教程适合三类人:
- 刚入门的无人机爱好者,想看看 PX4 是怎么工作的,但暂时没条件飞真机;
- 做机器人或自动驾驶相关开发的同学,需要一套通用的仿真-通信-监控链路;
- 已经在用 ROS 2 的朋友,想把 PX4 接入现有系统——因为这套链路本质上和 ROS 2 的通信模型是通的。
基础方面,你需要会基本的 Linux 命令行操作,比如 cd、mkdir、export 这些。如果完全没碰过,建议先花半小时熟悉一下。C++或Python不是必须的,但会一点点能让你在改参数、看日志时更从容。整个搭建过程大概需要 2~4 小时,取决于网络速度和电脑性能。
2. 环境准备:Ubuntu 22.04 下的 ROS 2 和依赖安装
2.1 为什么要用 Ubuntu 22.04 + ROS 2 Humble
PX4 官方对 Ubuntu 20.04 和 22.04 都有支持,但我强烈建议直接用 22.04。原因有三:第一,ROS 2 Humble 是 22.04 的原生版本,装起来不用折腾 Python 依赖;第二,Gazebo 在 22.04 下的 Fortress 版本比老版 Gazebo 11 稳得多;第三,网上新教程基本都默认 22.04,遇到问题搜答案时命中率高。
ROS 2 在这套链路里的角色其实“隐身”——你不一定直接用 ROS 2 的节点,但 PX4 的许多工具链依赖 ROS 2 的底层库。比如微调通信时用的ros2 topic list命令,就是 ROS 2 自带的。所以先把 ROS 2 Humble 装好,等于给整个环境打了个地基。
2.2 一步步安装 ROS 2 Humble
安装 ROS 2 的官方方式是先添加 apt 源,再安装核心包。我在干净系统上实测过,按下面顺序执行不会出错:
sudo apt update && sudo apt install -y 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 sudo apt install -y ros-humble-desktop这最后一条命令会装一大堆包,包括 RViz、demo 节点这些,体积大概 3~4 GB。如果你硬盘紧张,可以只装ros-humble-ros-base,但桌面版省心,建议直接上。
装完后配置环境变量:
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc source ~/.bashrc验证是否成功:
ros2 run demo_nodes_cpp talker如果终端开始输出 “Publishing: 'Hello World'”,说明环境没问题。这个小测试很重要,因为后面 XRCE-DDS 的排错也会用到 ROS 2 的命令行工具。
2.3 安装 Gazebo Fortress 和 PX4 依赖
Gazebo 在 Ubuntu 22.04 下用 Fortress(代号 fortress),安装命令很简单,但有个坑:必须先装 ignition 的 apt 源,否则装出来的不是 Fortress。
sudo apt install -y lsb-release wget gnupg sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrfoundation-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrfoundation-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 install -y ignition-fortress装完验证:
ign gazebo --version如果输出类似 “Ignition Fortress 1.0.0”,就对了。注意命令是ign gazebo,不是gazebo——很多人卡在这一步,以为自己没装成功,其实只是老版本 Gazebo 和 Ignition 命令名不同。
PX4 的依赖相对零碎,官方脚本会帮我们处理。先把 PX4 源码克隆下来:
git clone https://github.com/PX4/PX4-Autopilot.git --recursive cd PX4-Autopilot然后运行官方脚本:
bash ./Tools/setup/ubuntu.sh脚本会装一堆 Python 包、交叉编译工具链、Ninja 等。这里容易遇到网络超时,脚本失败后重跑就行,它是幂等的,已经装好的包会跳过。我建议你提前把pip源换成国内镜像,能省半小时:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple注意ubuntu.sh需要 sudo 权限,而且中途会要求你按回车确认几次,别离开终端太远。
3. 编译 PX4 并用 Gazebo 启动仿真
3.1 编译时最容易翻车的几个点
PX4 的编译用的是 CMake + Ninja,命令看起来简单,但有不少暗坑。第一次编译时,先不要加任何额外参数,直接:
cd PX4-Autopilot make px4_sitl gazebo-classic这里有个特别容易混淆的点:gazebo-classic指的是老版 Gazebo 11,而我们在 22.04 上装的是 Ignition Fortress,所以应该用make px4_sitl gazebo(不带 classic)。如果你用错了 target,编译会提示找不到gazebo-classic的依赖,然后卡住。
正确的编译目标:
make px4_sitl gazebo这个命令会先下载所有子模块,然后编译 PX4 固件,再启动 Gazebo。第一次编译少说 20~30 分钟,取决于 CPU 性能。期间你能看到密密麻麻的编译日志,别慌,只要最后出现类似:
[100%] Built target px4 [100%] Built target gazebo__iris就说明成功了。编译成功后,会自动弹出一个 Gazebo 窗口,里面有一架 Iris 四旋翼停在草地上。同时终端里也会进入 PX4 的 SITL shell(类似pxh>提示符),这才是真正的飞控控制台。
3.2 编译参数背后的逻辑
make px4_sitl gazebo这条命令里的px4_sitl是编译目标,意思是 “PX4 Software-In-The-Loop”,也就是把 PX4 当作一个普通的 Linux 进程来跑,而不是烧录到硬件里。SITL 的好处是你能用 GDB 调试、能随时打断点、能打印任意变量,这在真机上是不可能的。
gazebo则是启动时使用的仿真器类型。PX4 支持好多仿真后端:Gazebo、Gazebo Classic、jMAVSim、AirSim 等。选哪个取决于你想要的保真度。Gazebo 支持多机、传感器噪声、复杂地形,是综合性最好的。
编译过程中会生成两个关键的可执行文件:
build/px4_sitl_default/bin/px4:SITL 模式的飞控主程序build/px4_sitl_default/etc:包含默认参数和模型配置
每次改代码后不需要全量重编,PX4 的增量编译做得不错。如果只改了某个模块,重新跑make px4_sitl gazebo会在几秒内完成。
3.3 启动后你该看到什么,怎么判断是否正常
Gazebo 窗口弹出后,终端里会出现 PX4 启动日志。重点看这几个地方:
- 有没有 “INFO [commander] LED: amber fast” 之类的灯光状态提示;
- 有没有 “INFO [mavlink] mode: Normal” 表示 MAVLink 通道已开启;
- 有没有报错 “ERROR [simulator] No vehicle found”,如果有,说明 Gazebo 模型没加载成功。
在pxh>提示符下,你可以输入:
pxh> commander start pxh> listener vehicle_attitudelistener会实时打印姿态数据,如果数值在正常范围(roll/pitch 接近 0,yaw 慢慢变化),说明飞控的估计算法已经跑起来了。这时你可以试着用键盘控制飞机(需要打开 QGC 并切换到 QGC 的虚拟摇杆),不过那部分等第四步再讲,先把通信链路通起来。
3.4 多机仿真:四组无人机一起跑
你搜到的热词里有“四组机器人gazebo”和“QGC地面站”,这里正好用得上。PX4 支持多机 SITL,最多能同时起几十架虚拟飞机。启动方式是在原有命令基础加-s参数指定实例编号,关于多机部分我后面详细展开。
在实际操作中,我建议先把单机跑顺,再去折腾多机,因为多机仿真里最烦人的不是 PX4,而是 Gazebo 的资源占用和端口分配。
4. XRCE-DDS 通信链路:从 PX4 到 QGC 的桥梁
4.1 XRCE-DDS 的安装与配置
PX4 的 DDS 支持是通过px4_ros_com这个仓库配合 Micro XRCE-DDS Agent 实现的。PX4 将 uORB 消息通过 Micro XRCE-DDS Client 发布出去,PC 端运行一个 XRCE-DDS Agent(代理),负责接收和转发。需要安装的是 Agent 这一端。
先装依赖再装 Agent:
sudo apt install -y cmake python3-pip pip3 install --user cflib cd ~ git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git cd Micro-XRCE-DDS-Agent mkdir build && cd build cmake .. make -j$(nproc) sudo make install装完后启动 Agent:
MicroXRCEAgent udp4 -p 8888这里的udp4表示使用 IPv4 UDP 通信,-p 8888是端口号。这个端口是 PX4 端默认的,别乱改,否则对不上。
4.2 让 PX4 启用 DDS 支持
PX4 固件默认不启用 DDS。要在 SITL 模式下开启,得设置一个环境变量后再启动 PX4:
export PX4_UXRCE_DDS_NS=px4 make px4_sitl gazebo这个PX4_UXRCE_DDS_NS是 DDS 的命名空间,所有 PX4 发布的 topic 都会带px4/前缀。在实际使用中,这个命名空间很关键,因为它能区分多架无人机——比如第一架用px4_1/,第二架用px4_2/。
启动后,PX4 会尝试连接localhost:8888上的 Agent。如果连接成功,你能在 PX4 终端看到类似:
INFO [uxrce_dds_client] Connecting to 127.0.0.1:8888 INFO [uxrce_dds_client] Connected to Agent如果没看到 “Connected”,八成是 Agent 没起来或者端口被占。这时回去检查 MicroXRCEAgent 的终端,按Ctrl+C重启即可。
4.3 验证通信:用 ros2 topic 查看
Agent 跑起来、PX4 也连上之后,怎么确认链路真的通了?最直接的方法是开一个终端,用 ROS 2 自带的命令查看 topic 列表:
source /opt/ros/humble/setup.bash ros2 topic list正常情况下你会看到一大堆px4/开头的 topic,比如:
/px4/vehicle_attitude /px4/vehicle_odometry /px4/vehicle_gps_position /px4/battery_status这时你可以订阅一个 topic 看看数据流:
ros2 topic echo /px4/vehicle_attitude如果不断输出姿态四元数数据,说明整条链路——PX4 → XRCE-DDS Client → Agent → DDS → ROS 2——已经通了。这也是我最喜欢的一步,因为终于能看到“看不见”的数据在流动。
4.4 XRCE-DDS 和 MAVLink 的区别,什么时候用哪个
很多新手会疑惑:PX4 不是本来就有 MAVLink 协议给 QGC 用吗,为什么还要多一层 XRCE-DDS?答案是两类协议服务的对象不同。
MAVLink 是 PX4 与地面站、遥控器之间的轻量级通信协议,带宽小、延迟低,适合传输控制指令和状态信息。QGC 默认就用 MAVLink,走 14550 端口(UDP)。
DDS 则是面向分布式系统的发布-订阅协议,适合机器人领域里多个模块之间传输数据,比如视觉模块给飞控发目标位置,或者飞控给机械臂发指令。DDS 支持服务质量(QoS)控制,消息更结构化,可扩展性更强。
在实际开发中,如果你只是用 QGC 监控,MAVLink 就够了;如果你打算把 PX4 接进 ROS 2 的生态,比如用 SLAM、路径规划、计算机视觉,DDS 才是正确选择。两条链路可以同时存在,互不干扰。这也是为什么你在后面的步骤里,既能用 QGC 遥测,又能用ros2 topic echo看数据。
5. QGC 地面站:连接虚拟飞机和控制起飞
5.1 安装 QGC,Linux 下要先装一套依赖
QGC 官方提供了 AppImage 打包好的可执行文件,但直接在 Ubuntu 22.04 上跑会遇到一个问题——缺少libfuse2。AppImage 依赖 FUSE 来挂载,而 22.04 默认没装。安装命令:
sudo apt install -y libfuse2然后下载 QGC:
wget https://d176tv9nk4hswc.cloudfront.net/downloads/QGroundControl.AppImage chmod +x QGroundControl.AppImage ./QGroundControl.AppImage第一次启动可能会弹窗提示 “Untrusted application”,这是 AppImage 的正常行为,点允许即可。QGC 启动后会自动搜索本地 14550 端口的 MAVLink 数据。由于 PX4 SITL 默认就把 MAVLink 数据发到本机 14550,QGC 应该秒连。
如果 QGC 界面没反应,检查一下防火墙:
sudo ufw allow 14550/udp allow 14550/tcp这是我在 Ubuntu 桌面上踩过的坑,默认防火墙不会挡本地回环流量,但某些定制的发行版会,所以还是放行一下保险。
5.2 在 QGC 里进行“内八解锁”和起飞
热词里提到“px4内八解锁要设置哪个参数”,这句其实是老玩家之间的黑话。PX4 默认模式下,遥控器摇杆不停旋转或者内八字摇杆(类似“ω”)即可解锁。但在 SITL 仿真里没有真实遥控器,你必须用 QGC 的“虚拟摇杆”功能。
设置路径:QGC 右上角齿轮(齿轮图标)→ 选择“虚拟摇杆”选项卡 → 启用虚拟摇杆 → 在界面里你会看到一个虚拟的十字摇杆。这时候你先在遥控器设置里把“解锁/上锁”开关映射到一个开关通道,推荐用RC_MAP_ARM_SW参数来映射,通常设置为通道 5 或 6。
具体参数调整:
COM_RC_IN_MODE设置为 “Joystick/No RC Checks”,让 PX4 在无遥控器情况下接受虚拟摇杆输入;RC_MAP_ARM_SW设置为你的解锁开关所在通道,比如 5;RC_MAP_FLTMODE设置为模式切换通道,比如 6,这样你才能在 QGC 里切换自稳/定高/任务模式。
修改参数后点“写入参数”,再点“应用”,PX4 会热加载参数,不用重启仿真。
然后在 QGC 主界面左侧的“状态”面板里,把飞行模式切到“位置控制”(Position)或“定高”(Altitude),再点“解锁”按钮。虚拟摇杆界面里同时出现一个数字油门滑条,把它推到 50% 以上,飞机就会缓慢起飞。你会发现 Gazebo 里的飞机模型真的离开了地面,QGC 里的地图上飞机图标也在移动。
这一步是整个教程里最有成就感的时刻,但也是翻车高发区。最常见的现象是点了解锁但没有反应,十有八九是COM_RC_IN_MODE没改对。
5.3 QGC 显示的数据从哪里来,怎么排查数据异常
QGC 界面上的姿态、速度、位置全部来自 MAVLink 消息。MAVLink 消息则是由 PX4 生成,通过 UDP 14550 端口发出来。如果 QGC 连上了但数据乱跳或不动,建议用 QGC 自带的 MAVLink Inspector 查看:右上角“分析工具” → “MAVLink Inspector”,能逐条查看消息内容和频率。
数据异常时优先看这几个:
- GPS 状态:SITL 模式下默认使用“室内模拟 GPS”,如果 Gazebo 环境没正确发布 GPS 插件,QGC 会显示 “No GPS”,此时飞机无法解锁;
- 姿态数据:如果 IMU 数据异常(比如加速度计数值爆表),多半是 Gazebo 的传感器插件没加载对,检查模型文件里的 sensor 配置;
- 电池电量:SITL 默认电池电压 100%,如果 QGC 显示电量不足,检查 PX4 的
BAT_SOURCE参数。
6. 进阶玩法:多机仿真和 ROS 2 生态集成
6.1 多机编队仿真:一次跑四架无人机
PX4 的多机仿真,本质上是同时启动多个 SITL 实例,每个实例占用不同的 UDP 端口。启动命令有固定格式:
cd PX4-Autopilot export PX4_SIM_MODEL=iris export PX4_SIM_NS=px4_1 make px4_sitl gazebo开第二个终端,换个命名空间再跑一次:
export PX4_SIM_MODEL=iris export PX4_SIM_NS=px4_2 make px4_sitl gazebo这样 Gazebo 里会出现两架 Iris,每架都有自己的pxh>控制台。PX4 官方还提供了一个多机脚本Tools/simulation/gazebo/sitl_multiple_run.sh,能一次性拉起多架。脚本基于起始 ID 生成不同端口,内部逻辑是:
- 每架飞机用不同 MAVLink 系统 ID(默认 1,第二架是 2)
- 每架飞机的 uORB 消息不互通,因为 PX4 用环境变量
PX4_SIM_NS隔离了命名空间 - XRCE-DDS 的命名空间也因此不同,不会并发冲突
多机仿真最常遇到的坑是:第二架飞机起不来,报 “Bind: Address already in use”。原因是第一架占用了默认端口 14540,第二架必须指定新端口。手动启动多机时加参数:
./Tools/simulation/gazebo/sitl_multiple_run.sh -n 4 -m iris脚本会自动分配端口,建议优先用它。
6.2 把 PX4 接进 ROS 2 的生态
如果你已经装好 ROS 2 Humble,想从 ROS 2 节点里控制 PX4,官方推荐用px4_ros_com仓库里的接口包。这个包能让你订阅 PX4 的 DDS topic,也能发布控制指令。
安装px4_ros_com:
cd ~ git clone https://github.com/PX4/px4_ros_com.git cd px4_ros_com colcon build source install/setup.bash然后就能在 Python 或 C++ 节点里读取 PX4 数据了。比如用 Python 订阅位置信息:
import rclpy from rclpy.node import Node from px4_msgs.msg import VehicleOdometry class OdometrySubscriber(Node): def __init__(self): super().__init__('odometry_subscriber') self.subscription = self.create_subscription( VehicleOdometry, '/px4/vehicle_odometry', self.listener_callback, 10 ) def listener_callback(self, msg): self.get_logger().info(f'Position: {msg.x:.2f}, {msg.y:.2f}, {msg.z:.2f}') rclpy.init() node = OdometrySubscriber() rclpy.spin(node)这套接口的价值在于,你可以用 ROS 2 的生态做视觉避障、路径规划,再把结果发回 PX4。举个实际例子:你可以在 Gazebo 里放一个障碍物,用 ROS 2 的 SLAM 算法建图,然后让 PX4 飞到一个避开障碍物的目标点——这在真实场地上调试成本极高,但仿真里就是改几行代码的事。
6.3 和 MoveIt2 联动:机械臂加无人机的想象空间
热词里有不少关于 MoveIt2、Panda 机械臂和 Gazebo 同步仿真。虽然这偏机器人臂的范畴,但这套架构完全可以复用:PX4 管飞、MoveIt2 管臂,两者都在 Gazebo 里仿真,通信都走 ROS 2。无人机和机械臂的组合在真实场景里叫“空中操作”,典型应用是空中抓取、空中巡检时用机械臂搭接传感器。
实现思路是:Gazebo 里把 Panda 机械臂模型挂到无人机底部,机械臂的控制节点用 MoveIt2 规划,无人机控制节点用 PX4,两者共享 ROS 2 的 TF 树,通过ros2 topic交换末端执行器位姿信息和机体现状态。这套玩法比较复杂,但底层就是咱们已经搭好的这四件套,只不过多了一个机械臂模型文件和控制节点。
如果你想玩这个方向,建议先单独把 Panda 在 Gazebo 里跑通,确认 MoveIt2 和 Gazebo 的仿真同步没问题——因为 MoveIt2 的物理仿真规划和 Gazebo 的执行之间经常存在位姿漂移,需要调 PID 和避障参数。
7. 常见问题速查表:我踩过的坑都在这
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| Gazebo 窗口黑屏或崩溃 | 显卡驱动不兼容或内存不足 | 加LIBGL_ALWAYS_SOFTWARE=1强制软渲染,或加大虚拟机内存到 4GB 以上 |
编译时卡在cmake下载依赖 | 网络问题 | 检查代理设置,或者手动下载所需依赖包放到缓存目录 |
PX4 启动后报No vehicle found | Gazebo 模型没加载或模型路径不对 | 确认是否在 PX4-Autopilot 目录下启动,检查PX4_SIM_MODEL环境变量 |
| QGC 连不上飞机 | MAVLink 端口不对或防火墙拦截 | 检查 PX4 终端是否输出 MAVLink 信息,netstat 查看 14550 端口是否监听 |
ros2 topic list看不到 px4 前缀的 topic | XRCE-DDS Agent 没启动或连接失败 | 确认 Agent 正在运行,PX4 终端有 “Connected to Agent” 日志 |
| 解锁时提示 “拒绝” | 参数没设置对 | 检查COM_RC_IN_MODE是否设为 Joystick,RC_MAP_ARM_SW是否按你的映射配置 |
| 多机跑第二架时端口占用 | 端口冲突 | 手动指定-p端口或使用多机脚本自动分配 |
| Gazebo 里无人机乱飞不受控 | 传感器噪声或控制器参数不对 | 打开 PX4 的mc_pos_control和mc_att_control日志,用 QGC 的参数调试图调节 PID |
7.1 我自己最值钱的两个排错经验
第一个是关于 DDS 通信的。我一开始怎么都连不上 Agent,后来发现是自己开了两个终端,第一个终端里 Agent 因为日志刷屏卡死,第二个终端再启动就端口冲突。解决办法是把 Agent 放进screen或者tmux会话里运行,这样既能看日志又不占终端,还能随时恢复。
第二个关于 Gazebo 卡顿。有一次飞机模型在天上抖动得厉害,我以为是控制参数没调好,折腾半天,最后发现是虚拟机只分配了 2GB 内存,Gazebo 的物理引擎跟 PX4 的控制器不同步。把虚拟机内存加到 6GB 后,问题立刻消失。仿真平台性能不足导致的“假故障”比真实故障更耗时间,遇到莫名其妙的问题,先看内存、CPU、GPU 占用。
7.2 Gazebo 保存地图卡死的解决办法
热词里有一条“gazebo保存地图卡死”,我也遇到过多次。这个卡死通常不是真的死锁,而是 Gazebo 的服务线程在处理大量纹理数据时卡住。解决方法是:保存地图时先暂停仿真,再执行保存命令。在 Gazebo 界面里,暂停按钮在左下角,点一下暂停,等几秒再保存,成功率会高很多。如果还是卡,用命令行方式保存:
ign service -s /world/default/save --reqtype ignition.msgs.String --reptype ignition.msgs.Boolean --req 'data: "world.sdf"'8. 从仿真到真机,你还需要注意什么
8.1 仿真里跑的代码,真机上不一定能直接跑
SITL 仿真最大的风险是“看起来一切正常,一上真机就炸”。原因是仿真环境忽略了大量真实世界的变量:桨叶柔性、电机响应延迟、电池电压跌落、GPS 漂移、地磁干扰、气压高度计噪声。PX4 的控制器在仿真里调得很稳,上真机后很可能频繁振荡甚至翻机。
我的建议是:仿真主要用于验证逻辑和算法流程,而不是用来“调参”。真正飞行前,你一定得在真机上重新做传感器校准、电调校准,再从头调 PID。仿真参数可以作为初值,但不要迷信它。
8.2 安全第一:仿真里可以放肆,真机上必须保守
仿真里你可以随便炸机,真机上炸一次可能损失几千块甚至引发安全事故。所以真机试飞前,务必在 QGC 里设置好以下安全参数:
RTL_ALT:返航高度,建议至少 15 米;NAV_RCL_ACT:遥控器失联后进入返航模式;COM_DISARM_LAND:着陆后自动上锁,防止意外二次起飞;BAT_LOW_ACT:低电量时自动返航。
这些参数在仿真里往往被忽略,但真正决定你的飞机能不能全身而退。
9. 一点个人体会,以及还能往哪个方向扩展
这套 PX4 + Gazebo + XRCE-DDS + QGC 的环境,一旦跑通,后面几乎所有 PX4 相关的开发——视觉避障、多机编队、自主航线、机械臂协同——都能在这个底座上做。我实际用下来的感受是,最花时间的不是安装,而是理解四个组件之间的数据流:谁产生数据、谁消费数据、谁做翻译、谁做展示。只要这条链路在脑子里清晰了,后面你查问题、加模块、换传感器,都会快很多。
最后分享一个小技巧:每次启动仿真前,先跑一遍git submodule update --init --recursive,确保子模块版本完整。我发现很多疑难杂症,最后都归结为子模块没更新到官方指定版本。这套环境的搭建虽然繁琐,但一旦稳定了,你的开发效率会远超只用真机调试的同学。真机留给验证,把快速迭代交给仿真,这才是现代无人机开发的正确姿势。