1. 陀螺仪原始数据读取与时间对齐

为什么“时间对齐”是方位角解算的第一道关口

陀螺定向仪导出文件通常同时包含三类记录:时间戳(采样时刻)、角速度(陀螺敏感轴的瞬时输出,单位 °/s 或 °/h)、角度增量(相邻采样间的积分角,单位 °)。这三类数据往往来自不同采样率或不同起始时刻的通道,若直接按行号拼接,会造成“角速度与角度增量错位”,积分后方位角出现系统性偏差。本节任务是把导出文件解析成统一时间基准的干净序列。

导出文件的典型结构与解析要点

假设某型陀螺定向仪导出的文本文件为逐行记录,字段以逗号分隔,首行为表头。示例(教学假设数据):

# t_ms,gyro_rate_dps,angle_inc_deg,temp_c
0,0.0121,0.0000,25.1
10,0.0118,0.0001,25.1
20,0.0125,0.0001,25.1
...

解析时必须处理三件事:①跳过注释行与表头;②把 t_ms 统一换算为秒;③识别缺失值(空字段或 NaN)并标记,而不是静默填 0。下面给出可直接运行的 Python 解析与对齐实现。

import numpy as np

def load_gyro_export(path):
    """解析陀螺定向仪导出文件,返回统一时间基准的字典。"""
    t_ms, rate, dtheta, temp = [], [], [], []
    with open(path, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith("#"):
                continue
            parts = [p.strip() for p in line.split(",")]
            if parts[0].lower() in ("t_ms", "time"):   # 表头
                continue
            try:
                t_ms.append(float(parts[0]))
                rate.append(float(parts[1]) if parts[1] else np.nan)
                dtheta.append(float(parts[2]) if parts[2] else np.nan)
                temp.append(float(parts[3]) if len(parts) > 3 and parts[3] else np.nan)
            except ValueError:
                continue  # 跳过损坏行
    return {
        "t_s": np.array(t_ms) / 1000.0,
        "rate_dps": np.array(rate),
        "dtheta_deg": np.array(dtheta),
        "temp_c": np.array(temp),
    }

def align_to_common_grid(data, fs=100.0):
    """把角速度与角度增量重采样到同一等间隔时间栅格。"""
    t = data["t_s"]
    t0, t1 = t[0], t[-1]
    grid = np.arange(t0, t1 + 1e-9, 1.0 / fs)

    def interp(series):
        valid = ~np.isnan(series)
        return np.interp(grid, t[valid], series[valid])

    rate_g = interp(data["rate_dps"])
    dtheta_g = interp(data["dtheta_deg"])
    # 用角速度积分重建角度增量,作为对齐后的校验量
    dtheta_from_rate = rate_g / fs
    return {
        "t_grid": grid,
        "rate_dps": rate_g,
        "dtheta_deg": dtheta_g,
        "dtheta_from_rate": dtheta_from_rate,
    }

对齐结果的自检:用积分角与增量角互相印证

对齐是否可信,不能只看“程序没报错”。一个稳定的自检方法是:把对齐后的角速度按采样间隔积分,得到 dtheta_from_rate,再与文件中的 dtheta_deg 逐点比较。若两者在静止段差异应接近 0;在转动段差异应小于一个采样周期的量化误差。示例判读(教学假设):

检查项预期现象异常含义
时间戳单调递增差值恒为正存在回绕或重复行,需去重
采样间隔抖动标准差 < 1 ms丢帧或时钟不稳,需插值补齐
积分角 vs 增量角静止段 |差| < 0.001°通道错位或单位不一致
缺失值比例< 0.5%过高说明导出中断,需重采
对齐时优先使用“时间戳插值”而不是“按行号截断”。行号对齐只在两通道采样率完全一致且无丢帧时成立,工程上很难保证。
陀螺导出数据 → 时间对齐 → 干净输入 导出文件 t_ms gyro_rate dθ 0 0.0121 0.0000 10 0.0118 0.0001 20 0.0125 0.0001 … 含注释/表头/缺失 解析与清洗 • 跳过 # 注释行 • t_ms → t_s • 空字段标记 NaN • 丢弃损坏行 • 检查时间单调性 统一时间栅格 fs = 100 Hz grid = t0 … t1 角速度插值 增量角插值 积分角重建校验 干净输入 t_grid rate_dps dtheta_deg dθ_from_rate 对齐自检:积分角 vs 增量角 t dθ dtheta_deg dθ_from_rate 判读阈值 静止段 |差| < 0.001° 转动段 < 1 个采样量化误差 超限 → 查通道错位/单位

常见错位与处理

  • 单位混用:角速度字段为 °/h 而角度增量为 °,直接积分会差 3600 倍。解析时统一到 °/s。
  • 起始时刻不同:角速度通道从 0 ms 开始、增量角通道从 5 ms 开始,按行号拼接会整体错位。必须按时间戳插值。
  • 时间戳回绕:部分设备用 16 位毫秒计数,约 65.5 s 回绕一次。检测到负差值时加 65536 ms 修正。
  • 缺失值:不要用 0 填充,否则会在积分中引入台阶。用 np.nan 标记后仅对有效点插值。
对齐后的序列必须保留原始时间戳与插值标记,便于后续零偏标定(例2)和标度因数校验(例3)追溯数据来源,避免把插值点误当作实测点。

交付物:对齐检查清单

序号检查动作通过条件
1时间戳单调递增diff(t_s) 全部 > 0
2采样间隔稳定std(diff) < 1 ms
3缺失值统计NaN 比例 < 0.5%
4积分角与增量角一致静止段 |差| < 0.001°
5输出栅格覆盖全程grid 首尾与原始 t 首尾一致

完成以上解析、对齐与自检后,得到的 t_grid / rate_dps / dtheta_deg 即为后续方位角解算的干净输入。