1. 轨检传感器漂移现象识别与初步分类

为什么先分类,再排障

轨检车在运行中采集的传感器原始数据,往往同时混有真实轨道不平顺、车辆振动和传感器自身漂移。若直接拿原始波形去判断“传感器坏了”,很容易把轨道病害误判为设备故障。因此第一步不是校准、也不是拆换传感器,而是把漂移现象按形态分成三类:缓慢偏移、阶跃跳变、周期性波动。三类现象的成因链、验证手段和后续处理完全不同,分类错了,后面的排障就会南辕北辙。

本节的处理对象是轨检车导出的原始检测数据(如里程、时间戳、各传感器通道输出)。核心思路是:先做趋势分离,把慢变成分与快变成分拆开;再用形态判据把三类现象区分开;最后按统一字段记录,形成可追溯的分类台账。

输入:轨检车原始检测数据 里程 / 时间戳 · 传感器通道输出序列 · 采样间隔 · 车辆速度 · 检测区段标记 趋势分离 滑动中值/低通提取慢变趋势 + 残差得快变成分 ① 缓慢偏移 趋势项持续单向漂移 判据:趋势斜率稳定、无突变点 典型诱因:零点漂移 / 温漂累积 后续:静态基线校准、温漂排查 ② 阶跃跳变 某一时刻输出突然跳变并保持 判据:单点大跳变、跳后基线平移 典型诱因:接插件松动 / 供电瞬断 后续:查连接、查供电、查通信 ③ 周期性波动 输出叠加固定频率振荡 判据:频谱出现稳定主频峰 典型诱因:轮对不圆 / 悬挂共振 / 干扰 后续:频谱定位、查机械与干扰源 分类记录台账(每通道一条) 通道号 · 区段里程 · 现象类别 · 起止位置 · 幅值/斜率/主频 · 置信度 · 待验证项 → 移交后续排障(校准 / 温漂 / 连接 / 机械)

三类漂移的形态判据

分类不能靠“看着像”,要落到可计算的判据上。下面给出本节使用的判据,均基于趋势分离后的结果:设原始序列为 x[n],用窗口长度 W 的滑动中值得到趋势 t[n],残差 r[n] = x[n] − t[n]。

现象类别主要观察对象判据(示例阈值)典型诱因方向
缓慢偏移 趋势项 t[n] 趋势斜率符号稳定,累计偏移超过量程的 2%,且无单点跳变 零点漂移、温漂累积、基准电压缓变
阶跃跳变 残差 r[n] 的差分 相邻采样差分绝对值超过 5 倍残差标准差,跳后基线平移且保持 接插件松动、供电瞬断、通信丢帧
周期性波动 残差 r[n] 的频谱 频谱出现单一主频峰,峰值超过噪声底 6 dB,且主频与速度/轮径相关 轮对不圆、悬挂共振、电磁干扰
阈值只是示例起点,实际应结合车型、传感器量程和轨检精度要求标定。关键是三类判据分别作用在趋势项、差分、频谱三个不同域上,互不混淆。

用一段可运行的分类脚本落地

下面脚本只依赖标准库,输入是一段模拟的传感器输出(含三类现象各一段),输出每个通道的分类结果。真实使用时把 load_channel 换成读取轨检车导出文件即可,其余逻辑不变。

import math, statistics

def moving_median(x, w):
    half = w // 2
    out = []
    for i in range(len(x)):
        lo, hi = max(0, i - half), min(len(x), i + half + 1)
        out.append(statistics.median(x[lo:hi]))
    return out

def classify(x, fs=100.0, jump_k=5.0, slope_ratio=0.02, peak_db=6.0):
    n = len(x)
    t = moving_median(x, 21)                 # 趋势项
    r = [x[i] - t[i] for i in range(n)]      # 残差
    span = max(x) - min(x) or 1e-9

    # 1) 阶跃:残差差分超限
    d = [r[i] - r[i-1] for i in range(1, n)]
    sd = statistics.pstdev(d) or 1e-9
    jumps = [i+1 for i, v in enumerate(d) if abs(v) > jump_k * sd]

    # 2) 缓慢偏移:趋势首尾差占比
    drift = abs(t[-1] - t[0]) / span

    # 3) 周期性:残差自相关找主频(简化版)
    mean_r = statistics.mean(r)
    rc = [sum((r[i]-mean_r)*(r[i]-mean_r) for i in range(n-lag)) / n
          for lag in range(1, min(n//2, 200))]
    peak = max(rc) if rc else 0
    noise = statistics.median(rc) if rc else 1e-9
    periodic = peak > noise * (10 ** (peak_db / 10.0))

    if jumps:
        return "阶跃跳变", {"跳变点": jumps[:5], "差分阈值": round(jump_k*sd, 4)}
    if drift > slope_ratio:
        return "缓慢偏移", {"趋势首尾差占比": round(drift, 4)}
    if periodic:
        return "周期性波动", {"主频峰/噪声底": round(peak/noise, 2)}
    return "未见明显漂移", {}

# 构造示例数据:前段缓慢上升,中段阶跃,后段叠加正弦
fs = 100.0
x = []
for i in range(300):
    x.append(0.02 * i / 100.0)                       # 缓慢偏移
for i in range(300, 600):
    x.append(0.06 + (0.5 if i >= 450 else 0.0))      # 阶跃
for i in range(600, 900):
    x.append(0.5 + 0.08 * math.sin(2*math.pi*3.0*i/fs))  # 3 Hz 周期波动

print(classify(x, fs))

运行后预期输出类似 ('阶跃跳变', {'跳变点': [450], '差分阈值': ...})。注意脚本按“阶跃优先、偏移次之、周期最后”的顺序判断,因为阶跃会污染趋势项和频谱,必须先剔除。若某通道同时出现两类现象,应在台账中记录主类别并备注次类别,避免后续排障只盯一个方向。

分类记录台账示例

分类结果要能直接交给下一环节使用,字段必须包含定位信息和判据数值,否则后续无法复核。下面是一条填写示例(数据为教学示例,非实测):

通道区段里程现象类别起止位置关键判据值置信度待验证项
左高低 K120+300 ~ K121+800 缓慢偏移 全程单向 趋势首尾差占比 3.1% 高 静态基线校准、温漂对比
右轨向 K122+050 阶跃跳变 单点 差分 6.8 倍残差标准差 高 接插件、供电、通信丢帧
车体垂向 K123+000 ~ K124+200 周期性波动 连续区段 主频 3.0 Hz,峰/噪 8.4 中 轮对不圆、悬挂共振
分类阶段只做“现象归类”,不下“传感器已损坏”的结论。缓慢偏移可能是真实轨道长波不平顺,周期性波动也可能是真实轨道周期性病害,必须结合轨道台账和重复检测结果交叉验证后再进入排障。

结果判读与常见误判

  • 把轨道病害当漂移:同一区段多次检测若波形位置随里程稳定复现,更可能是轨道本身;漂移通常随设备状态变化而不随里程固定。
  • 把阶跃当缓慢偏移:阶跃后基线平移,若只用首尾差判断会被误归为偏移,所以必须先做差分检测。
  • 把周期性波动当噪声:噪声无稳定主频,周期波动在频谱上有明确峰,且主频常与速度、轮径相关,可用变速检测验证。
  • 窗口长度选错:趋势窗口过短会把慢漂当残差,过长会把阶跃抹平,建议窗口覆盖至少 2 个完整波动周期。

完成本节分类后,每个异常通道都应有一条带判据数值的记录,并能回答三个问题:属于哪一类、定位在哪、下一步该验证什么。这三项齐备,才具备移交后续排障的条件。