日志文件结构:bin文件格式解析、消息ID与消息类型、时间戳与同步机制

各位同学,今天我们来聊聊日志文件的结构。说实话,我刚开始接触ArduPilot时,对着那些.bin文件也是一头雾水。后来在项目里被日志坑过几次,才真正下功夫去研究它。嗯,今天就把这些经验分享给你们。

bin文件格式解析

ArduPilot的日志文件,后缀是.bin。很多人以为它是二进制文件,其实不完全是。它更像是一种「紧凑型」的二进制格式,说白了就是尽量省空间。

每个.bin文件由三部分组成:

  • 文件头:固定16字节,包含文件格式版本号、固件类型等元信息
  • 消息块:核心数据,一条一条的消息挨着存
  • 文件尾:固定8字节,标记文件结束

消息块的结构是这样的:

typedef struct {
    uint16_t msg_len;    // 消息长度(2字节)
    uint8_t  msg_type;   // 消息类型(1字节)
    uint8_t  data[];     // 消息数据(变长)
} log_message_t;

每个消息块前面都有2字节的长度字段。我习惯用这个字段来快速跳过不需要的消息,在分析大日志时特别有用。

关键点:bin文件没有索引结构,只能顺序读取。所以解析时要从头读到尾,不能随机跳转。

消息ID与消息类型

消息类型字段是一个uint8_t,取值范围0-255。ArduPilot把常用的消息类型定义在AP_Logger.h里。我挑几个最常用的给你们看看:

消息ID 名称 说明 频率
0x01 FMT 格式定义消息 文件开头一次
0x02 PARM 参数记录 启动时一次
0x03 GPS GPS数据 5-10Hz
0x04 IMU 加速度计/陀螺仪 100-400Hz
0x05 MAG 磁力计 10-50Hz
0x06 BARO 气压计 25Hz
0x07 RCIN 遥控器输入 50Hz
0x08 RCOU 遥控器输出 50Hz
0x09 ATT 姿态数据 50-100Hz
0x0A MODE 飞行模式切换 事件触发

你可能会问:为什么FMT消息只在文件开头出现一次?

因为FMT消息定义了后续所有消息的「数据格式」。它告诉解析器:GPS消息有哪几个字段,每个字段是什么类型。没有FMT,你根本不知道后面的二进制数据该怎么解读。

我的习惯:拿到一个陌生日志,我第一件事就是检查FMT消息。如果FMT缺失或损坏,这日志基本废了。我曾经在野外调试时遇到过这种情况,当时真想砸遥控器。

时间戳与同步机制

时间戳是日志分析中最容易出问题的地方。ArduPilot使用两种时间戳:

  • 系统时间戳:从飞控上电开始计时的微秒数,存在每个消息的头部
  • GPS时间戳:来自GPS模块的UTC时间,存在GPS消息里

系统时间戳是单调递增的,但有个坑——它会在飞控重启时归零。所以如果你看到时间戳突然变小,别慌,可能是飞控重启了。

同步机制是这样的:

// 每个消息的时间戳结构
typedef struct {
    uint32_t timestamp_us;  // 系统时间戳,微秒
    uint8_t  msg_type;      // 消息类型
    uint8_t  data[];        // 消息数据
} log_msg_with_ts_t;

时间戳的单位是微秒,但实际精度取决于传感器。IMU数据的时间戳精度很高,能达到微秒级。但GPS数据的时间戳精度只有毫秒级,因为GPS模块本身就有延迟。

注意:不同消息的时间戳不能直接比较!IMU和GPS的时间戳来自不同的时钟源,它们之间有漂移。我曾经在分析一次炸机事故时,就是因为直接比较了IMU和GPS的时间戳,得出了错误的结论。后来才发现,需要先用GPS时间戳校准系统时间戳。

校准方法其实不复杂:找到一条同时包含系统时间戳和GPS时间戳的消息(比如GPS消息),计算出偏移量,然后应用到所有消息上。这样就能把不同传感器的数据对齐到同一个时间轴上。

我个人习惯在分析日志时,先画一个时间轴,把各个传感器的数据标上去。这样能直观地看到数据是否对齐,有没有时间上的错位。

避坑指南:我曾经在分析一次飞行日志时,发现IMU数据和GPS数据的时间差竟然有200毫秒。一开始以为是传感器坏了,后来才发现是飞控的时钟源配置有问题。所以,如果你发现时间戳对不上,先检查飞控的时钟配置,别急着换硬件。

好了,关于日志文件结构就讲这么多。记住三点:bin文件是顺序结构,消息ID决定了数据类型,时间戳需要校准才能用。下次你们拿到一个日志文件,应该知道怎么下手了吧?

日志文件结构解析 .bin 日志文件 文件头 (16B) 消息块序列 (变长) 文件尾 (8B) 单个消息块结构 msg_len (2B) msg_type (1B) data (变长) 消息类型示例 (msg_type) 0x01 FMT 0x03 GPS 0x04 IMU 0x07 RCIN 0x09 ATT 0x0A MODE 时间戳同步:系统时间戳 + GPS时间戳 → 校准对齐

实用技巧:如果你用Mission Planner下载日志,它会自动帮你解析bin文件。但如果你想自己写解析工具,记住先读FMT消息,再读其他消息。顺序搞反了,数据就是一堆乱码。

嗯,今天就到这里。记住,日志分析是个细致活,多动手、多对比,慢慢就有感觉了。

专注资料整理