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