3. PX4日志系统:日志模块架构、触发机制与文件管理

做飞控调试这么多年,我有个习惯——拿到一架坠毁的飞机,第一件事不是拆硬件,而是读日志。说白了,日志就是飞控的「黑匣子」。PX4的日志系统设计得相当精巧,但很多人只停留在会用ulog命令的程度。今天我就带你把它拆开看看。

3.1 日志模块架构:谁在背后默默记录?

PX4的日志系统核心是一个叫logger的模块。它跑在px4_logger线程里,优先级不低。我刚开始看源码时,觉得这模块挺简单,不就是写文件嘛。后来才发现,它背后有一套完整的订阅-发布机制。

整个架构可以分成三层:

  • 数据源层:各个uORB主题,比如vehicle_attitudesensor_combinedactuator_outputs。这些是日志的原材料。
  • 调度层:logger模块内部有一个订阅管理器,它决定什么时候去读哪些主题的数据。
  • 存储层:数据经过格式化后,写入SD卡或内部Flash。格式是ULog,一种二进制日志格式。

嗯,这里要注意:logger模块并不是把所有主题都一股脑全记下来。它有一个订阅列表,你可以在启动参数里配置。我个人习惯是,调试阶段把IMUGPS姿态位置这几个核心主题全开,正式飞行时只保留必要的,省存储空间。

架构核心点

  • logger模块独立运行,不阻塞其他控制任务
  • 数据通过uORB消息队列传递,延迟极低
  • 支持多速率记录——高频数据(如IMU 1kHz)和低频数据(如GPS 10Hz)分开处理

下面这张图是我画的日志模块数据流,你看一眼就明白了:

数据源层 uORB 主题 sensor_combined vehicle_attitude 调度层 logger 模块 订阅管理器 多速率调度 存储层 ULog SD卡 触发机制 自动触发 / 手动触发 条件:解锁、故障、定时 文件命名规则 年月日_时分秒_序号.ulg 例:2025_03_21_14_30_00.ulg 存储位置 /fs/microsd/log/ 图:PX4日志模块架构与数据流

3.2 日志记录触发机制:什么时候开始写?

你可能会问:日志是从上电就开始记吗?不是的。PX4的日志触发机制很聪明,它分三种模式:

  1. 自动触发(默认):飞控解锁后自动开始记录,上锁后自动停止。这是最常用的模式。
  2. 手动触发:通过MAVLink命令或者logger start指令手动控制。我调试传感器时喜欢用这个模式,可以精确控制记录窗口。
  3. 条件触发:当检测到特定事件时触发,比如GPS丢失、高度异常、震动超标等。这个模式在故障分析时特别有用。

我的小技巧:在startup.sh里加上logger on,可以让飞控上电就开始记录。虽然会多占点存储,但万一飞机还没解锁就炸了呢?你想想看,这种场景我遇到过不止一次。

触发条件的具体参数在logger模块的配置里:

# 自动触发:解锁开始,上锁停止
param set LOG_MODE 0

# 手动触发:需要外部命令
param set LOG_MODE 1

# 条件触发:基于事件
param set LOG_MODE 2
param set LOG_LEVEL 3  # 记录级别,越高越详细

我曾经遇到过一个问题:飞机在空中突然日志停止了,落地后发现文件不完整。排查了半天,原来是SD卡写入速度跟不上,日志缓冲区满了就丢数据。后来我把LOG_BUFFER_SIZE调大了一倍,问题解决。

3.3 日志文件命名规则:一眼看出时间

PX4的日志文件命名非常直观,格式是:

YYYY_MM_DD_HH_MM_SS_序号.ulg

举个例子:2025_03_21_14_30_00_000.ulg,表示2025年3月21日14点30分00秒记录的第0个文件。

为什么要有序号?因为同一秒内可能触发多次记录。比如你快速解锁上锁三次,就会生成三个文件:

  • 2025_03_21_14_30_00_000.ulg
  • 2025_03_21_14_30_00_001.ulg
  • 2025_03_21_14_30_00_002.ulg

嗯,这里有个坑:如果你把飞控的RTC电池拆了,每次上电时间都会重置到1970年。那日志文件名就会变成1970_01_01_00_00_01_xxx.ulg。我刚开始用PX4时就被这个坑过,找了半天日志,发现全是1970年的,还以为穿越了。

避坑指南

  • 确保飞控的RTC电池有电,否则日志时间戳会乱
  • 如果使用GPS,飞控会自动同步UTC时间,文件名会正常
  • 室内调试时,建议手动设置系统时间:date 032114302025

3.4 日志文件存储位置:去哪找?

日志文件默认存储在SD卡的/fs/microsd/log/目录下。PX4会按日期创建子文件夹,结构如下:

/fs/microsd/log/
├── 2025-03-21/
│   ├── 2025_03_21_14_30_00_000.ulg
│   ├── 2025_03_21_14_35_12_001.ulg
│   └── 2025_03_21_15_00_00_002.ulg
├── 2025-03-22/
│   └── 2025_03_22_09_10_05_000.ulg
└── latest.px4log  # 指向最新日志的软链接

这个latest.px4log是个好东西。你通过QGroundControl下载日志时,默认就是下载这个文件。省得你在一堆文件里翻来翻去。

如果你没有插SD卡,日志会存到哪里?PX4会尝试写入内部Flash。但内部Flash空间有限,一般只能存几分钟的数据。我建议你:永远插SD卡。有一次我忘了插卡,飞完一看日志目录是空的,那种感觉……嗯,你懂的。

存储介质 路径 容量 建议
SD卡 /fs/microsd/log/ 取决于卡容量 首选,建议32GB以上
内部Flash /fs/mtd/log/ 通常几MB 仅应急使用
RAM(临时) /log 取决于内存 掉电丢失,不推荐

我的习惯:每次飞行前,我会在QGC里清空一次SD卡日志。这样落地后找日志特别快。另外,我建议把日志文件定期备份到电脑上,SD卡一旦损坏,所有数据就全没了。

好了,关于PX4日志系统的架构、触发机制、命名规则和存储位置,就讲这么多。说白了,日志就是你跟飞控对话的唯一途径。把日志系统搞明白,分析问题才能有的放矢。


专注资料整理