1. 牵引试验原始数据通道映射与时间对齐

任务拆解:从多通道原始记录到统一时间基准数据集

城轨牵引性能试验中,采集系统通常同时记录牵引指令、牵引电机电流、牵引力(或力传感器电压)、车辆速度、网压、制动缸压力等通道。这些通道可能来自不同采集卡、不同总线周期,甚至不同起始触发时刻,直接拿来计算加速度或牵引特性会引入时间错位误差。本案例要完成两件事:通道语义映射(把采集系统里的通道编号/别名绑定到物理量与单位)和时间对齐(以牵引指令上升沿为 t=0,把各通道重采样到统一采样率),最后验证对齐后各通道首末时刻一致。

对齐基准约定:以牵引指令通道由 0 变为 1 的第一个采样点作为 t=0(单位 s)。所有通道时间戳统一换算为相对该时刻的秒值,正方向为试验进行方向。重采样采用线性插值,统一采样率取 100 Hz(周期 10 ms),该值应不小于原始各通道中最低采样率的 2 倍,否则需先降采样目标或改用保持插值。

通道映射配置表

映射配置是后续所有处理的唯一入口,必须显式记录原始通道名、物理量、单位、符号约定与量程,避免后续量纲混乱。下面是一份可直接套用的配置示例(示例参数,按实际采集系统替换):

原始通道名物理量单位符号约定量程原始采样率
AI0_TractCmd牵引指令—(0/1)1=牵引有效0~150 Hz
AI1_MotorCurr牵引电机电流A牵引为正-1000~1000200 Hz
AI2_TractForce牵引力kN牵引为正-200~200100 Hz
CAN_VehSpeed车辆速度km/h前进为正0~12020 Hz
AI3_LineVolt网压V—0~2000100 Hz

注意 CAN_VehSpeed 原始采样率仅 20 Hz,若目标统一为 100 Hz,插值会引入较大平滑误差,实际工程中应把统一采样率降到 20 Hz 或对该通道单独标注“低采样率通道,插值仅供参考”。本例为演示对齐流程,统一采样率取 20 Hz 更稳妥,下面代码按 20 Hz 实现。

多通道原始时间轴 → 以牵引指令上升沿为基准对齐 原始采集(各通道起始时刻不同) t_raw AI0_TractCmd 上升沿 AI1_MotorCurr 起始偏移 +0.30 s AI2_TractForce 起始偏移 +0.60 s CAN_VehSpeed 起始偏移 +0.90 s,20 Hz AI3_LineVolt 起始偏移 +0.45 s 以指令上升沿为 t=0,各通道时间戳减去自身起始偏移 对齐后统一时间轴(20 Hz,t=0 为牵引指令上升沿) t_aligned AI0_TractCmd AI1_MotorCurr AI2_TractForce t=0 t=T_end 各通道首末时刻必须一致

对齐实现(Python,可直接运行)

下面代码用 pandas 完成映射、基准定位、重采样与首末时刻校验。示例数据由代码内构造,用于演示流程,不代表真实试验结果。

import numpy as np
import pandas as pd

# 1) 通道映射配置:原始通道名 -> (物理量, 单位, 符号)
channel_map = {
    "AI0_TractCmd":   ("牵引指令", "0/1", 1),
    "AI1_MotorCurr":  ("牵引电机电流", "A", 1),
    "AI2_TractForce": ("牵引力", "kN", 1),
    "CAN_VehSpeed":   ("车辆速度", "km/h", 1),
    "AI3_LineVolt":   ("网压", "V", 1),
}

# 2) 构造示例原始数据:各通道起始时刻与采样率不同
rng = np.random.default_rng(0)
def make_channel(t0, fs, dur, base, noise):
    n = int(dur * fs)
    t = t0 + np.arange(n) / fs
    v = base + noise * rng.standard_normal(n)
    return pd.DataFrame({"t": t, "v": v})

raw = {
    "AI0_TractCmd":   make_channel(0.00, 50,  10, 0.0, 0.01),
    "AI1_MotorCurr":  make_channel(0.30, 200, 10, 120.0, 2.0),
    "AI2_TractForce": make_channel(0.60, 100, 10, 45.0, 0.5),
    "CAN_VehSpeed":   make_channel(0.90, 20,  10, 8.0, 0.1),
    "AI3_LineVolt":   make_channel(0.45, 100, 10, 1500.0, 5.0),
}
# 让牵引指令在 t=2.0 s 处由 0 变 1
cmd = raw["AI0_TractCmd"]
cmd.loc[cmd["t"] >= 2.0, "v"] = 1.0

# 3) 定位基准时刻:牵引指令首个 v>=0.5 的采样点
cmd_sorted = cmd.sort_values("t")
t0 = cmd_sorted.loc[cmd_sorted["v"] >= 0.5, "t"].iloc[0]
print(f"基准时刻 t0 = {t0:.3f} s")

# 4) 统一采样率(取各通道最低采样率,避免过度插值)
fs_target = 20.0
t_end = min(df["t"].max() for df in raw.values()) - t0
t_grid = np.arange(0.0, t_end, 1.0 / fs_target)

# 5) 各通道重采样到统一时间网格
aligned = pd.DataFrame({"t": t_grid})
for name, df in raw.items():
    df = df.sort_values("t").copy()
    df["t_rel"] = df["t"] - t0
    aligned[name] = np.interp(t_grid, df["t_rel"], df["v"])

# 6) 首末时刻一致性校验
print("对齐后各通道首末时刻:")
for name in raw:
    print(f"  {name}: 首={aligned['t'].iloc[0]:.3f}s, 末={aligned['t'].iloc[-1]:.3f}s")
assert aligned["t"].iloc[0] == 0.0
assert aligned["t"].iloc[-1] == t_grid[-1]
print("首末时刻一致性校验通过")

结果判读与常见问题

  • 基准定位失败:若牵引指令通道全程为 0,说明触发未发生或通道映射错误,应先核对映射表再重跑。
  • 末时刻不一致:各通道原始记录时长不同,取最短公共区间作为对齐终点,避免尾部插值外推产生虚假数据。
  • 低采样率通道:CAN_VehSpeed 仅 20 Hz,若强行插值到 100 Hz 会掩盖真实波动,本例统一取 20 Hz 是更稳妥的选择。
  • 符号约定:映射表中显式记录“牵引为正”,后续量纲统一与异常识别都依赖这一约定,不能省略。
对齐完成后建议立即输出一份对齐审计表:记录基准时刻、统一采样率、各通道原始首末时刻与对齐后首末时刻、插值方法。这份表是后续牵引力计算与异常识别的可追溯依据。