2. PX4与传感器生态概览

在开始编写自定义传感器驱动之前,必须先建立一张“系统地图”:PX4 的软件架构长什么样,传感器在系统中处于什么位置,驱动又夹在哪一层之间。只有把这张地图看清楚,后续写 I2C/SPI 探测、注册 uORB 话题、发布 sensor_accel 等操作才不会变成“照抄模板”。本节从架构、传感器类型、驱动位置和典型应用场景四个角度,建立 PX4 传感器生态的整体认知。

一、PX4 的分层架构与传感器所处位置

PX4 采用典型的“分层 + 模块化”架构,自上而下大致可分为四层:应用层(飞行模式、任务、MAVLink 通信)、控制与估计层(姿态/位置控制器、EKF2 状态估计)、传感器抽象层(sensor 模块、uORB 话题)、驱动与总线层(具体驱动、I2C/SPI/UART/CAN 总线)。传感器驱动位于最底层,它负责把物理芯片的寄存器数据翻译成 PX4 内部统一格式的消息。

理解这一点的关键在于:驱动不直接参与控制,它只负责“采集 + 发布”。驱动通过 uORB 发布话题(如 sensor_accel、sensor_gyro、sensor_baro),上层估计与控制模块订阅这些话题。这种解耦让驱动开发变得相对独立——只要话题格式正确,上层无需关心你用的是哪家芯片。

PX4 分层架构与传感器驱动位置 应用层 飞行模式 · 任务规划 · MAVLink 通信 · 参数系统 控制与估计层 姿态/位置控制器 · EKF2 状态估计 · 传感器融合 传感器抽象层(uORB 话题) sensor_accel · sensor_gyro · sensor_baro · sensor_mag · distance_sensor ↑ 驱动发布话题,上层订阅话题,实现解耦 驱动与总线层 自定义驱动 · 官方驱动 · I2C / SPI / UART / CAN 总线 ← 本节及后续章节重点:在此层新增驱动模块 物理硬件层 IMU 芯片 · 气压计 · 磁力计 · 激光/超声波测距 · 外部传感器 数据自下而上流动

二、PX4 支持的传感器类型

PX4 生态中的传感器种类繁多,但按功能可归为几大类。每类传感器在系统中都有对应的话题和驱动框架,理解分类有助于快速定位自己该写哪类驱动。

传感器类别 典型芯片/器件 uORB 话题 总线
加速度计ICM-42688、BMI088sensor_accelSPI / I2C
陀螺仪ICM-42688、BMI088sensor_gyroSPI / I2C
磁力计IST8310、QMC5883sensor_magI2C
气压计BMP388、MS5611sensor_baroI2C / SPI
测距传感器TFmini、超声波distance_sensorUART / I2C
光流/视觉PMW3901、光流模块optical_flowSPI / UART
GNSSu-blox M9Nsensor_gpsUART

三、驱动在系统中的位置与工作流程

一个 PX4 传感器驱动的生命周期可以概括为“探测—初始化—采集—发布”四步。以 I2C 加速度计为例:驱动在启动时通过 probe() 读取 WHO_AM_I 寄存器确认芯片存在;随后配置量程、输出数据率(ODR)和滤波器;接着在定时器或中断驱动下周期性读取原始数据,做单位换算和温度补偿;最后通过 uORB 发布 sensor_accel 话题。

// 驱动核心流程伪代码
probe()        → 读 WHO_AM_I,确认芯片 ID
init()         → 配置量程、ODR、FIFO、中断
run()          → 周期读取原始数据
publish()      → 填充 sensor_accel_s 并 uORB 发布
关键认知:驱动是“翻译官”,不是“决策者”。它把芯片寄存器里的原始值翻译成 PX4 统一话题,上层 EKF2 和控制模块只认话题,不认芯片。因此自定义驱动的核心工作就是:正确读寄存器 + 正确填话题。

四、常见应用场景

自定义传感器驱动在真实项目中非常常见,典型场景包括:

  • 替换停产芯片:原厂 IMU 停产,需要把新芯片接入 PX4,保持话题不变。
  • 增加专用传感器:如农业植保需要下视激光测距,物流无人机需要称重传感器。
  • 提高采样率:竞速无人机需要更高 ODR 的陀螺仪数据,官方驱动不满足时自行优化。
  • 多传感器冗余:在同一总线上挂载多颗同型号 IMU,实现冗余投票。
  • 科研定制:实验平台需要接入非标传感器,如气体检测、辐射检测模块。

五、常见误区与复盘

误区一:认为驱动要自己实现滤波和融合。实际上滤波和融合由 EKF2 完成,驱动只需提供带时间戳的原始数据。
误区二:忽略时间戳。uORB 话题中的 timestamp 必须来自 hrt_absolute_time(),错误的时间戳会导致 EKF 发散。
误区三:直接修改官方驱动而不新建模块。建议新建独立驱动模块,避免升级 PX4 时冲突。
误区四:忘记注册到板级配置。驱动需要在 boards/ 对应板的 default.px4board 中启用,否则不会编译进固件。