2. 基于最后遥测帧的失联前状态还原

为什么先看最后几帧,而不是先看告警

失联告警只说明“岸端收不到数据了”,它本身不携带故障原因。真正能区分“通信先断”还是“平台先失控”的,是失联前最后若干帧遥测中关键量的变化形态。本案例的任务是:拿到一段失联前的遥测记录,按时间顺序还原航向、航速、深度、电池电压、通信信号质量五条曲线,找出是否存在突变点,并据此给出排障方向初判。

判读的核心不是看某一帧的绝对值,而是看谁先变、谁后变、变化是否连续。典型规律有三类:

  • 通信先劣化:信号质量(RSSI/信噪比)与丢包率先恶化,航向航速深度仍平稳,最后帧中断——指向链路问题。
  • 平台先异常:航向或深度出现阶跃/持续漂移,航速异常升高或归零,而信号质量在中断前仍正常——指向控制或推进问题。
  • 能源先塌陷:电池电压在数帧内快速下跌并伴随航速下降、通信功率不足——指向供电问题。

遥测帧结构与解析口径

假设平台按 1 Hz 上报,每帧含时间戳、航向(°)、航速(kn)、深度(m)、电池电压(V)、信号质量(dBm 或 0–100 归一值)、丢包率(%)。解析时先做三件事,避免误判:

  1. 统一时间基准:以平台帧时间戳为准,岸端接收时间只用于计算链路时延,不参与趋势判断。
  2. 标记缺帧:相邻帧时间差大于 1.5 倍上报周期即视为缺帧,缺帧本身是链路劣化的证据,不能简单插值抹平。
  3. 区分“突变”与“正常机动”:航向变化率超过设定阈值(示例取 30°/s)且持续不足 2 帧,视为突变;缓慢转向属于正常机动。
判读阈值应结合平台实际机动能力设定。下面示例中的阈值仅用于演示判读逻辑,不代表任何具体型号的指标。

失联前状态还原与突变点定位

下图把最后 12 帧的五条关键量按时间轴对齐呈现,并标出三个候选突变点:第 7 帧信号质量开始下滑、第 9 帧航向出现阶跃、第 11 帧后连续缺帧直至中断。通过“谁先变”可以快速锁定排障入口。

失联前最后 12 帧遥测趋势(1 Hz 上报) 横轴:帧序号(t-11 … t0,t0 为最后成功接收帧);纵轴:各量归一化趋势,仅示意变化形态 t-11 t-10 t-9 t-8 t-7 t-6 t-5 t-4 t-3 t-2 t-1 t0 航向 航速 深度 电池电压 信号质量 ① 信号质量开始下滑 ② 航向阶跃突变 ③ 连续缺帧 → 中断 判读结论(示例) · 信号质量先于航向异常下滑 · 航向阶跃出现在信号劣化之后 · 电压缓降,无塌陷特征 · 深度平稳,无进水/失控迹象 初判:优先排查通信链路 注:曲线为教学示例数据,用于演示“谁先变”的判读方法,非实测记录。

用脚本把判读过程固化下来

人工看曲线容易漏掉缺帧和细微阶跃。下面这段 Python 直接对遥测 CSV 做解析,输出每帧的时间差、各量变化率,并自动标记候选突变点。示例数据内嵌在脚本里,可直接运行验证逻辑。

import csv
import io

# 教学示例数据:帧序号, 航向(°), 航速(kn), 深度(m), 电压(V), 信号质量(0-100)
RAW = """seq,hdg,spd,depth,volt,signal
0,182.0,4.2,12.5,25.6,88
1,182.3,4.2,12.5,25.6,87
2,181.8,4.1,12.6,25.5,88
3,182.1,4.1,12.5,25.5,86
4,182.0,4.0,12.5,25.5,85
5,182.2,4.0,12.6,25.4,72
6,181.9,3.9,12.5,25.4,58
7,182.0,3.9,12.5,25.4,44
8,182.1,3.8,12.6,25.3,30
9,215.0,3.8,12.5,25.3,18
10,214.6,3.7,12.5,25.2,8
11,214.8,3.7,12.6,25.2,2
"""

# 判读阈值(示例,需按平台实际能力调整)
HDG_JUMP_DEG = 30.0      # 单帧航向变化超过此值视为阶跃
SIGNAL_DROP = 15.0       # 单帧信号质量下降超过此值视为劣化起点
VOLT_DROP = 0.5          # 单帧电压下降超过此值视为异常跌落
GAP_FACTOR = 1.5         # 帧间隔超过上报周期的1.5倍视为缺帧
PERIOD = 1.0             # 上报周期(s)

rows = list(csv.DictReader(io.StringIO(RAW)))
for r in rows:
    for k in ("hdg", "spd", "depth", "volt", "signal"):
        r[k] = float(r[k])

print(f"{'帧':>3} {'航向变化':>8} {'信号变化':>8} {'电压变化':>8}  标记")
events = []
for i in range(1, len(rows)):
    prev, cur = rows[i-1], rows[i]
    d_hdg = cur["hdg"] - prev["hdg"]
    d_sig = cur["signal"] - prev["signal"]
    d_volt = cur["volt"] - prev["volt"]
    flags = []
    if abs(d_hdg) > HDG_JUMP_DEG:
        flags.append("航向阶跃")
    if d_sig < -SIGNAL_DROP:
        flags.append("信号劣化")
    if d_volt < -VOLT_DROP:
        flags.append("电压跌落")
    if flags:
        events.append((cur["seq"], flags))
    print(f"{cur['seq']:>3} {d_hdg:>8.1f} {d_sig:>8.1f} {d_volt:>8.2f}  {'/'.join(flags) or '-'}")

# 按“谁先变”给出排障入口初判
first = {}
for seq, flags in events:
    for f in flags:
        first.setdefault(f, seq)
print("\n首次出现顺序:", first)
if "信号劣化" in first and (("航向阶跃" not in first) or first["信号劣化"] < first["航向阶跃"]):
    print("初判:通信链路优先排查")
elif "电压跌落" in first:
    print("初判:供电系统优先排查")
elif "航向阶跃" in first:
    print("初判:平台控制/推进优先排查")

运行后可以看到:信号质量在第 5 帧首次出现超过阈值的下降,航向阶跃出现在第 9 帧,电压全程无异常跌落。首次出现顺序为“信号劣化 → 航向阶跃”,因此初判指向通信链路。这与图中三个突变点的先后关系一致,说明脚本判读与人工判读互相印证。

若信号质量与航向几乎同帧突变,不能简单归因于链路。此时应检查该帧是否伴随姿态角速度异常,必要时把最后几帧原始报文完整导出,确认是否为平台失稳导致天线指向偏离,而非链路本身故障。

结果判读与排障入口对照

突变形态典型先后关系优先排查方向需补充的证据
信号质量先降,航向航速平稳信号 → 缺帧 → 中断通信链路(天线、馈线、电台、中继)各段链路信号强度与丢包率
航向阶跃或深度持续漂移姿态异常 → 信号劣化平台控制、舵机、推进器姿态角速度、控制指令回执
电压快速下跌伴航速下降电压 → 航速 → 通信功率不足电池组、供电配电各电池单体电压、负载电流
深度突变伴信号骤降深度 → 信号水声通信、耐压与进水深度传感器原始值、舱内湿度
遥测帧本身可能已被链路压缩或补发,出现“时间戳倒退”或“重复帧”时,应先按时间戳排序并去重,再做趋势判读,否则会把补发帧误判为突变。

交付物:失联前状态还原记录表

把上述判读结果整理成一张可直接填写的记录表,便于后续与链路分段测试、声速剖面核查等排查动作衔接。

字段填写内容(示例)
失联时刻 / 最后有效帧t0,帧序号 11
分析帧数12 帧(1 Hz)
缺帧情况t-1 至 t0 之间无缺帧,t0 后中断
航向趋势t-3 前稳定约 182°,t-3 阶跃至 215°
航速趋势4.2 → 3.7 kn,缓降
深度趋势12.5–12.6 m,平稳
电池电压趋势25.6 → 25.2 V,缓降,无跌落
信号质量趋势88 → 2,t-6 起持续下滑
首个突变点t-6 信号质量下降超阈值
初判排障入口通信链路
待补证据岸基—中继—艇载各段信号强度与丢包率

完成本表后,排障方向已从“失联”这一笼统告警收敛到“通信链路优先”,后续即可按链路分段测试逐段定位具体故障点。