1. PX4与传感器驱动概述

各位同学好,我是老张。做嵌入式飞控这行有十来年了,今天咱们开始聊PX4传感器驱动的编写。说实话,传感器驱动是飞控最底层的活,也是最重要的活——传感器数据不准,上层控制算法再牛也白搭。

这一章我们先搭个框架,把PX4的整体结构、传感器的作用、开发环境怎么配、还有那个神奇的uORB消息机制讲清楚。嗯,这些基础打牢了,后面写驱动才能顺手。

1.1 PX4架构简介

PX4的架构,说白了就是一套模块化的飞控软件。我刚开始接触时也觉得挺复杂,但拆开来看其实就三层:

  • 底层硬件抽象层——负责跟传感器、执行器打交道
  • 中间层(uORB + 模块管理器)——模块之间通信靠它
  • 上层应用层——姿态估计、位置控制、导航等等

你想想看,每个模块都是独立的小程序,通过uORB消息总线互相传数据。这样做的好处是啥?换传感器不用改上层代码,换个驱动模块就行。我在项目中遇到过好几次,客户临时要换IMU芯片,只要写个新驱动,上层完全不用动。

核心思想:模块化、消息驱动、可插拔。这是PX4能支持那么多硬件平台的根本原因。

PX4 软件架构简图 应用层 姿态估计 | 位置控制 | 导航 | 任务规划 中间层(uORB + 模块管理器) 消息总线 | 模块生命周期管理 | 参数系统 驱动层(传感器驱动) IMU | 磁力计 | 气压计 | GPS | 光流 | 距离传感器 数据流方向:传感器 → 驱动 → uORB → 应用层

1.2 传感器在无人机中的作用

无人机要飞稳,靠的就是传感器。说白了,传感器就是飞控的「眼睛」和「耳朵」。我打个比方:

  • IMU(惯性测量单元)——感知加速度和角速度,是飞控最核心的传感器。没有它,无人机就是瞎子。
  • 磁力计——相当于指南针,告诉飞控哪边是北。但容易受干扰,我在项目里吃过不少亏。
  • 气压计——测高度用的。温度变化、风的影响都会让它漂移。
  • GPS——室外定位的主力。但高楼遮挡、多径效应都是坑。
  • 光流/视觉传感器——室内或无GPS环境下的救星。

个人经验:传感器融合才是王道。单个传感器都有缺陷,但组合起来就能互补。PX4的EKF2算法就是干这个的——把IMU、GPS、磁力计、气压计的数据揉在一起,算出最靠谱的姿态和位置。

1.3 驱动开发环境搭建(Ubuntu + PX4 Firmware)

环境搭建这块,我踩过的坑比走过的路还多。这里直接给一套我验证过无数次的流程:

1.3.1 安装Ubuntu

建议用Ubuntu 20.04 LTS或22.04 LTS。别问我为什么不用Windows——PX4的编译工具链在Linux下最稳。

1.3.2 安装依赖

# 更新包列表
sudo apt update

# 安装基础工具
sudo apt install git zip cmake build-essential ninja-build

# 安装Python相关
sudo apt install python3-pip python3-venv

# 安装PX4依赖
sudo apt install protobuf-compiler libprotobuf-dev
sudo apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev

1.3.3 克隆PX4源码

git clone https://github.com/PX4/PX4-Autopilot.git --recursive
cd PX4-Autopilot

注意:一定要加 --recursive 参数!我刚开始就忘了这茬,结果编译到一半报错找不到子模块,折腾了半天才发现。

1.3.4 编译测试

make px4_sitl gazebo

第一次编译会比较慢,大概10-20分钟。如果顺利看到Gazebo界面弹出来,恭喜你,环境搭好了。

1.4 uORB消息机制基础

uORB是PX4里模块之间通信的「高速公路」。每个模块发布自己的消息,其他模块订阅感兴趣的消息。我刚开始学的时候觉得这概念挺抽象,后来写了个驱动就明白了——其实就是个发布/订阅模型。

1.4.1 核心概念

  • 主题(Topic)——消息的名字,比如 sensor_accelvehicle_attitude
  • 发布者(Publisher)——谁产生数据谁发布
  • 订阅者(Subscriber)——谁需要数据谁订阅

1.4.2 消息定义

消息结构定义在 msg/ 目录下,以 .msg 文件形式存在。举个例子:

# sensor_accel.msg
uint64 timestamp        # 时间戳,微秒
uint64 timestamp_sample # 采样时间
float32[3] x            # X轴加速度,m/s^2
float32[3] y            # Y轴加速度,m/s^2
float32[3] z            # Z轴加速度,m/s^2
uint32 device_id        # 设备ID

1.4.3 发布消息示例

// 在驱动中发布加速度数据
#include <uORB/uORB.h>
#include <uORB/topics/sensor_accel.h>

// 创建消息实例
struct sensor_accel_s accel_data = {};
accel_data.timestamp = hrt_absolute_time();
accel_data.x[0] = 0.1f;
accel_data.y[0] = 0.2f;
accel_data.z[0] = -9.8f;

// 发布消息
orb_advert_t accel_pub = orb_advertise(ORB_ID(sensor_accel), &accel_data);
orb_publish(ORB_ID(sensor_accel), accel_pub, &accel_data);

1.4.4 订阅消息示例

// 在应用层订阅加速度数据
int accel_sub = orb_subscribe(ORB_ID(sensor_accel));
struct sensor_accel_s accel_data;

while (true) {
    orb_copy(ORB_ID(sensor_accel), accel_sub, &accel_data);
    // 处理数据...
    px4_usleep(10000); // 10ms循环
}

关键点:uORB是异步的、非阻塞的。发布者只管发,订阅者只管收,互不等待。这种设计让PX4的实时性有了保障。

1.5 本章小结

这一章我们聊了PX4的模块化架构、传感器在无人机中的角色、开发环境的搭建步骤,还有uORB消息机制的基本用法。嗯,内容不少,但都是后面写驱动必须掌握的基础。

我个人建议你先把环境搭好,跑一遍编译,再试着写个简单的uORB发布/订阅程序。代码跑通了,信心就有了。下一章我们会深入传感器驱动的具体结构,到时候这些基础概念都会用上。


公众号:蓝海资料掘金营,微信deep3321