2. PX4与ArduPilot架构对比
PX4 与 ArduPilot 都是开源飞控软件栈,二者都能在 Pixhawk 系列硬件上运行,也都支持硬件在环(HIL)仿真,但它们的内部组织方式、驱动模型、通信机制和 HIL 接入路径存在明显差异。理解这些差异,直接决定你在做 HIL 时该从哪里接入仿真器、该改哪一层、该看哪条数据链。本节不泛泛比较“谁更好”,而是从飞控栈组成、传感器驱动、通信协议和 HIL 支持四个维度,把两者的结构关系讲清楚。
一、飞控栈组成:分层方式不同
PX4 采用“模块化中间件 + 独立任务”的结构。底层是 NuttX 实时操作系统(Pixhawk 系列)或 Linux(部分伴飞场景),其上运行 uORB 发布/订阅消息总线。传感器驱动、姿态估计(EKF2)、位置控制、姿态控制、导航、commander 状态机、mavlink 模块等,都是独立模块,通过 uORB 主题交换数据。例如 sensor_combined、vehicle_attitude、vehicle_local_position、actuator_controls_0 都是 uORB 主题。模块之间不直接调用,而是发布和订阅,因此替换或旁路某一层相对容易。
ArduPilot 采用“库 + 主循环调度”的结构。核心是 AP_Vehicle 派生出的 ArduCopter、ArduPlane、ArduRover 等机型类,传感器、EKF、控制律、MAVLink 等以库(library)形式被链接进同一个固件。主循环按固定频率调度 update(),各库通过 AP_HAL 硬件抽象层访问底层。相比 PX4 的“消息总线 + 模块”,ArduPilot 更接近“单体固件 + 库调用”,模块边界由 C++ 类接口体现,而不是运行时的消息主题。
这一差异对 HIL 的影响很直接:PX4 可以在 uORB 层注入仿真传感器数据,也可以整体替换 simulator 模块;ArduPilot 则通常通过 AP_HAL 的 SIM 后端或 SITL 编译选项,把传感器读取和电机输出重定向到仿真器。
二、传感器驱动:注册模型与 HAL 抽象
PX4 的传感器驱动通常以独立模块存在,例如 mpu6000、icm20689、ms5611、ist8310。驱动启动后向 sensors 模块注册,由 sensors 统一做校准、滤波和发布,最终形成 sensor_combined、vehicle_imu 等主题。也就是说,PX4 的驱动与数据发布之间隔了一层 sensors 聚合模块,HIL 时可以用 simulator 模块直接发布这些主题,绕过真实 SPI/I2C 驱动。
ArduPilot 的传感器驱动以 AP_InertialSensor 后端形式组织,例如 AP_InertialSensor_MPU6000、AP_InertialSensor_ICM20689。驱动通过 AP_HAL::SPIDevice 或 I2CDevice 访问总线,采样后交给 AP_InertialSensor 前端做统一处理和发布。HIL 时,ArduPilot 使用 AP_InertialSensor_SITL 等 SITL 后端,从仿真器接收 IMU 数据,而不是从真实总线读取。因此,ArduPilot 的 HIL 接入更靠近 HAL 层,PX4 的 HIL 接入更靠近 uORB 消息层。
三、通信协议:MAVLink 是共同语言,但内部链路不同
两者对外都使用 MAVLink 与地面站通信,也都支持 MAVLink 2。区别在于内部:PX4 的 mavlink 模块订阅 uORB 主题,把 vehicle_attitude、vehicle_global_position 等转成 MAVLink 消息;ArduPilot 的 GCS_MAVLink 库则从各库直接取数据组包。对 HIL 而言,这意味着 PX4 的 HIL 数据流通常表现为“仿真器 → simulator 模块 → uORB → mavlink 模块 → 地面站”,而 ArduPilot 是“仿真器 → AP_HAL_SITL → 各库 → GCS_MAVLink → 地面站”。
此外,PX4 还支持 uXRCE-DDS、RTPS 等与伴飞计算机通信;ArduPilot 则常用 MAVLink 转发、AP_DDS(较新版本)或直接串口协议。做 HIL 时,如果你要注入外部导航数据,PX4 更倾向通过 uORB 主题或 MAVLink 消息,ArduPilot 更倾向通过 MAVLink 或 HAL 层重定向。
四、HIL 支持差异与共同点
共同点很明确:两者都支持 SITL/HIL 仿真,都能与 Gazebo、jMAVSim(PX4 侧)、JSBSim(ArduPilot 侧)等仿真器联动,都通过 MAVLink 的 HIL 相关消息(如 HIL_SENSOR、HIL_GPS、HIL_STATE_QUATERNION)或自定义 UDP 包交换数据,都能在无真实硬件的情况下验证姿态估计、控制律和任务逻辑。
差异在于接入层次和配置方式。PX4 的 HIL 通常通过 make px4_sitl 或 simulator 模块启动,仿真器与飞控之间用 UDP 交换 HIL_SENSOR 等消息,飞控内部走 uORB。ArduPilot 的 HIL 通常通过 sim_vehicle.py 启动 SITL,使用 AP_HAL_SITL 把传感器和输出重定向到仿真器,飞控内部走库调用。PX4 更强调“消息级替换”,ArduPilot 更强调“HAL 级替换”。
uorb top 中 sensor_combined、vehicle_attitude 是否更新;ArduPilot 侧优先检查 SIM 后端是否被编译进来、AP_HAL_SITL 是否收到仿真数据。两者都用 MAVLink 看 ATTITUDE、GLOBAL_POSITION_INT 是否合理。
五、对比速查表
| 维度 | PX4 | ArduPilot |
|---|---|---|
| 飞控栈组织 | uORB 消息总线 + 独立模块 | 库调用 + 主循环调度 |
| 传感器驱动 | 独立驱动模块,经 sensors 聚合发布 uORB 主题 | AP_InertialSensor 等后端,经 AP_HAL 访问总线 |
| 内部通信 | uORB 发布/订阅 | C++ 类接口直接调用 |
| 对外协议 | MAVLink、uXRCE-DDS、RTPS | MAVLink、AP_DDS(新版本) |
| HIL 接入层 | simulator 模块 + uORB 主题注入 | AP_HAL_SITL + 传感器/输出重定向 |
| 常用仿真器 | Gazebo、jMAVSim | Gazebo、JSBSim |
| HIL 消息 | HIL_SENSOR、HIL_GPS 等 MAVLink 消息 | HIL_SENSOR、HIL_GPS 等 MAVLink 消息 |
总结来看,PX4 与 ArduPilot 在 HIL 上的共同点是“都用 MAVLink 交换仿真数据、都能脱离真实硬件验证飞控逻辑”,差异在于“PX4 从消息层接入、ArduPilot 从 HAL 层接入”。掌握这一点,你在搭建 HIL 环境时就能快速判断该改哪个模块、该看哪条数据、该在哪里注入故障,而不是盲目试错。