4. 状态提取:从日志中提取飞行模式、GPS坐标与姿态角

日志文件拿到手了,接下来干什么?

我个人习惯,第一步不是急着看数据,而是先问自己三个问题:飞机现在在什么模式?它飞到了哪里?它姿态怎么样?这三个问题,对应着飞行模式、GPS坐标和姿态角。说白了,这就是状态提取的核心。

我在项目中遇到过不少新手,一上来就盯着传感器原始值看,结果越看越晕。你想想看,没有上下文的数据,跟天书有什么区别?

4.1 飞行模式提取

飞行模式决定了飞控的行为逻辑。手动模式、增稳模式、悬停模式、自动航线模式……每种模式下,飞控对遥控器指令的响应方式完全不同。

关键点:飞行模式通常以枚举值或字符串形式记录在日志中。不同固件(如PX4、ArduPilot)的编码方式不同,但提取逻辑大同小异。

以PX4固件为例,飞行模式信息通常出现在 vehicle_status 或 commander_state 主题中。我一般这样提取:

# 伪代码示例:提取飞行模式
def extract_flight_mode(log_entry):
    # 假设日志中有一个字段 'nav_state'
    mode_map = {
        0: '手动模式',
        1: '增稳模式',
        2: '悬停模式',
        3: '自动起飞',
        4: '自动降落',
        5: '自动航线',
        6: '返航',
        7: '定点模式',
        8: '降落模式'
    }
    mode_code = log_entry.get('nav_state', -1)
    return mode_map.get(mode_code, '未知模式')

我的小技巧:提取模式时,别忘了记录时间戳。我曾经排查一个“无故切换模式”的故障,最后发现是遥控器通道抖动导致的模式误切。没有时间戳,你根本没法把模式变化和遥控器信号关联起来。

实际日志中,模式切换往往伴随着状态变化。我建议你做一个模式变化的时间线,这样一眼就能看出飞行过程中经历了哪些阶段。

时间戳 (s) 模式代码 模式名称 备注
0.0 0 手动模式 起飞前准备
5.2 2 悬停模式 起飞后切悬停
30.1 5 自动航线 开始执行任务
120.5 6 返航 触发低电量保护

4.2 GPS坐标提取

GPS坐标是飞行器位置的直接体现。提取时,我关注三个核心数据:纬度、经度、海拔高度。

嗯,这里要注意。不同日志系统对GPS数据的命名可能不一样。PX4里常见的是 vehicle_gps_position 主题,ArduPilot里则是 GPS 消息。字段名也可能有差异,比如 lat、latitude、Lat……

避坑指南:我曾经遇到过一个日志,GPS坐标的数值看起来正常,但画到地图上却偏了十万八千里。后来发现,日志里存的是度分格式,而我默认用了度格式解析。提取前,一定要确认坐标的格式和单位!

标准的GPS坐标提取流程,我一般这样写:

# 伪代码示例:提取GPS坐标
def extract_gps(log_entry):
    # 假设日志字段为 lat_deg, lon_deg, alt_m
    lat = log_entry.get('lat_deg', None)
    lon = log_entry.get('lon_deg', None)
    alt = log_entry.get('alt_m', None)
    
    # 简单的有效性检查
    if lat is None or lon is None:
        return None
    
    # 检查范围:纬度[-90, 90],经度[-180, 180]
    if not (-90 <= lat <= 90) or not (-180 <= lon <= 180):
        print(f"警告:GPS坐标超出合理范围 - lat={lat}, lon={lon}")
        return None
    
    return {
        'latitude': lat,
        'longitude': lon,
        'altitude': alt
    }

提取GPS坐标时,我还会顺带检查几个关键指标:

  • 卫星数量:少于6颗星,定位精度堪忧
  • 定位类型:3D定位还是2D定位?2D定位没有高度信息
  • 水平精度因子(HDOP):大于2.0时,位置抖动会比较明显

实战经验:有一次我分析一个“飞行器漂移”的案例,发现GPS坐标在悬停时持续缓慢漂移。检查HDOP后发现,当天卫星几何分布很差,HDOP高达3.5。这不是飞控的问题,是GPS本身精度不够。

4.3 姿态角提取(Roll/Pitch/Yaw)

姿态角是飞行器的“骨架”。Roll(横滚)、Pitch(俯仰)、Yaw(偏航),这三个角度描述了飞行器相对于地面的朝向。

提取姿态角时,我通常会从 vehicle_attitude 或 ATT 消息中获取。但这里有个坑——很多飞控内部用四元数表示姿态,而不是直接存欧拉角。

我的习惯:如果日志里只有四元数,我会先转换成欧拉角再分析。转换公式不复杂,但要注意万向锁问题。不过说实话,对于大多数飞行场景,万向锁很少遇到,不用太担心。

四元数转欧拉角的代码,我常用的版本:

import math

def quaternion_to_euler(q):
    # q = [w, x, y, z]
    w, x, y, z = q
    
    # Roll (x-axis rotation)
    sinr_cosp = 2.0 * (w * x + y * z)
    cosr_cosp = 1.0 - 2.0 * (x * x + y * y)
    roll = math.atan2(sinr_cosp, cosr_cosp)
    
    # Pitch (y-axis rotation)
    sinp = 2.0 * (w * y - z * x)
    if abs(sinp) >= 1:
        pitch = math.copysign(math.pi / 2, sinp)  # 处理万向锁
    else:
        pitch = math.asin(sinp)
    
    # Yaw (z-axis rotation)
    siny_cosp = 2.0 * (w * z + x * y)
    cosy_cosp = 1.0 - 2.0 * (y * y + z * z)
    yaw = math.atan2(siny_cosp, cosy_cosp)
    
    return roll, pitch, yaw

提取姿态角后,我一般会关注几个典型特征:

  • Roll和Pitch的波动范围:悬停时通常在±5°以内,如果超过±10°,说明有风扰或飞控参数有问题
  • Yaw的变化率:快速偏航可能意味着航向控制失效
  • 姿态角与遥控器指令的对应关系:打杆后姿态响应是否及时?有没有延迟或超调?

避坑指南:我曾经分析过一个“炸机”日志,发现Pitch角在坠毁前瞬间达到了-90°。一开始以为是飞控失控,后来仔细看时间戳才发现,那是坠地后传感器受到冲击产生的异常数据。提取姿态角时,一定要结合飞行阶段判断数据是否合理。

4.4 状态提取的整体流程

把飞行模式、GPS坐标、姿态角三者结合起来,你就能构建出飞行器状态的完整画像。我个人习惯用一张流程图来梳理这个提取过程:

状态提取流程图 状态提取核心流程 原始日志文件 日志解析与字段映射 飞行模式提取 nav_state / mode GPS坐标提取 lat / lon / alt 姿态角提取 Roll / Pitch / Yaw 数据有效性校验 结构化状态数据 💡 校验要点 范围检查 / 单位确认 时间戳对齐 / 异常值过滤

这张图展示了我做状态提取时的标准流程。从原始日志开始,经过解析、并行提取、校验,最后得到结构化的状态数据。每一步都有对应的检查点,确保提取出来的数据是可靠的。

4.5 实战:从日志中提取完整状态

说了这么多,我们来个实际的例子。假设你拿到了一段PX4日志,里面包含以下字段:

timestamp, nav_state, lat_deg, lon_deg, alt_m, qw, qx, qy, qz
0.0, 0, 31.2304, 121.4737, 10.0, 1.0, 0.0, 0.0, 0.0
5.0, 2, 31.2305, 121.4738, 12.5, 0.999, 0.01, 0.02, 0.03
10.0, 5, 31.2306, 121.4739, 15.0, 0.998, 0.02, 0.01, 0.05

提取步骤很简单:

  1. 解析飞行模式:根据nav_state值,映射为对应的模式名称
  2. 提取GPS坐标:直接读取lat_deg、lon_deg、alt_m
  3. 计算姿态角:将四元数(qw, qx, qy, qz)转换为Roll、Pitch、Yaw

提取后的结果应该是这样的:

时间 (s) 飞行模式 纬度 经度 高度 (m) Roll (°) Pitch (°) Yaw (°)
0.0 手动模式 31.2304 121.4737 10.0 0.0 0.0 0.0
5.0 悬停模式 31.2305 121.4738 12.5 1.1 2.3 3.4
10.0 自动航线 31.2306 121.4739 15.0 2.3 1.1 5.7

核心思路:状态提取不是简单的数据拷贝,而是有目的的筛选和转换。你提取什么、怎么提取,取决于你要分析什么问题。排查“模式切换异常”就重点看模式时间线,分析“定位漂移”就重点看GPS和姿态的关联。