2. 卫星链路RSSI与丢包率的时序关联分析

为什么要把 RSSI 与丢包率放在同一时间轴上

浮标端通信日志里,RSSI 是逐秒(或逐包)记录的瞬时量,丢包率则是按卫星过顶窗口统计的比率量。两者采样粒度不同、时间基准也可能有偏差(浮标本地时钟 vs 过顶窗口起始时刻)。直接拿"过顶期间平均 RSSI"和"过顶丢包率"做一次相关,会掩盖 RSSI 在窗口内的骤降过程——而骤降恰恰是丢包突增最直接的诱因。因此本例的核心动作是:统一时间基准 → 重采样对齐 → 滑动窗口相关 → 定位骤降-突增配对。

数据准备与对齐口径

假设浮标日志导出为两张表(示例数据,非实测):

  • rssi_log.csv:字段 utc_time, rssi_dbm,采样间隔 1 s,RSSI 典型范围 −120 ~ −85 dBm。
  • pkt_log.csv:字段 utc_time, seq, acked,每包一条记录,acked=0 表示未收到确认(丢包)。

对齐口径约定:以 UTC 整秒为公共时间栅格;丢包率按 10 s 窗口统计(窗口内 acked=0 的包数 / 总包数);RSSI 在同一 10 s 窗口内取均值与最小值两个特征。这样每个时间点得到三元组 (t, rssi_mean, rssi_min, loss_rate)。

若浮标时钟与地面站存在固定偏移,先用过顶窗口的首包到达时刻做一次粗对齐,再检查对齐后 RSSI 曲线在窗口边沿是否出现台阶状跳变——有跳变说明偏移未消除。

滑动窗口相关系数的计算逻辑

对对齐后的序列,取窗口长度 W=60 个 10 s 点(即 10 分钟),步长 1 点,逐窗计算 Pearson 相关系数:

r_k = Σ[(x_i - x̄)(y_i - ȳ)] / sqrt(Σ(x_i - x̄)² · Σ(y_i - ȳ)²)
其中 x = rssi_mean(或 rssi_min),y = loss_rate,i ∈ [k, k+W)

预期符号为负:RSSI 越低,丢包率越高。若某窗口 r_k 接近 0 甚至为正,说明该时段丢包并非由信号强度主导(可能是协议重传、遮挡或调度问题),需要单独标记。

关键实现(Python,可直接运行)

import numpy as np
import pandas as pd

# 1) 读取并统一到 UTC 整秒
rssi = pd.read_csv("rssi_log.csv", parse_dates=["utc_time"])
pkt  = pd.read_csv("pkt_log.csv",  parse_dates=["utc_time"])
rssi["sec"] = rssi["utc_time"].dt.floor("s")
pkt["sec"]  = pkt["utc_time"].dt.floor("s")

# 2) 10 s 窗口聚合
rssi["win"] = rssi["sec"].dt.floor("10s")
pkt["win"]  = pkt["sec"].dt.floor("10s")

rssi_w = rssi.groupby("win")["rssi_dbm"].agg(rssi_mean="mean", rssi_min="min")
pkt_w  = pkt.groupby("win")["acked"].agg(loss_rate=lambda s: 1 - s.mean())

df = rssi_w.join(pkt_w, how="inner").sort_index().reset_index()
df = df.dropna(subset=["rssi_mean", "loss_rate"])

# 3) 滑动窗口 Pearson 相关(W=60 点,步长 1)
W = 60
def rolling_corr(x, y, w):
    out = np.full(len(x), np.nan)
    for k in range(len(x) - w + 1):
        xs, ys = x[k:k+w], y[k:k+w]
        if xs.std() == 0 or ys.std() == 0:
            continue
        out[k + w - 1] = np.corrcoef(xs, ys)[0, 1]
    return out

df["corr_mean"] = rolling_corr(df["rssi_mean"].values, df["loss_rate"].values, W)
df["corr_min"]  = rolling_corr(df["rssi_min"].values,  df["loss_rate"].values, W)

# 4) 识别 RSSI 骤降 + 丢包突增的配对事件
df["d_rssi"] = df["rssi_mean"].diff()
df["d_loss"] = df["loss_rate"].diff()
events = df[(df["d_rssi"] < -3.0) & (df["d_loss"] > 0.15)]
print(events[["win", "rssi_mean", "loss_rate", "d_rssi", "d_loss", "corr_mean"]])

阈值 −3 dB 与 +15% 是示例判据,需按实际链路噪声水平调整:先看 d_rssi 与 d_loss 的分布分位数,取约 90% 分位作为"骤降/突增"的门限,避免阈值过松导致事件泛滥。

时序关联的判读结构

下图把"原始 RSSI 序列 → 窗口聚合 → 滑动相关 → 事件配对"的判读关系画在一起,重点看 RSSI 骤降点与丢包突增点在时间轴上的相对位置,以及相关系数曲线在事件附近的负向凹陷。

RSSI 与丢包率的时序对齐与关联判读 公共时间栅格:UTC 整秒 · 聚合窗口:10 s · 滑动相关窗口:60 点 t₀ 过顶中段 t_end RSSI (dBm) −85 −120 RSSI 骤降 −3 dB 以上 丢包率 (%) 30 0 丢包突增 +15% 以上 滑动相关系数 r (W=60) +0.2 −1.0 r ≈ −0.85,强负相关 红色虚线:RSSI 骤降点与丢包突增点的时间对齐检查

结果判读与验证要点

  • 符号一致性:正常链路的 corr_mean 应稳定为负;若某窗口转正,优先检查该窗口内是否有大量重传包(seq 重复)或调度异常,而非直接归因于信号。
  • 时间滞后:RSSI 骤降与丢包突增之间可能存在 1~2 个 10 s 窗口的滞后(链路层重传缓冲)。可对 loss_rate 做 ±3 点平移后再算相关,取绝对值最大的滞后量作为实际响应延迟。
  • 事件配对验证:对每个 events 行,回查原始 pkt_log 中该窗口的 seq 连续性,确认丢包是连续段丢失还是随机散失——连续段丢失更符合 RSSI 骤降导致的链路中断特征。
  • 阈值敏感性:把 −3 dB / +15% 分别放宽到 −2 dB / +10% 与收紧到 −5 dB / +20%,观察事件数量变化;若事件数对阈值极敏感,说明判据不稳,应改用分位数门限。
相关系数只反映线性关联,不能直接作为因果结论。RSSI 骤降与丢包突增同时出现,仍可能是同一天线遮挡或姿态变化共同导致,需结合姿态数据(见后续案例)交叉验证。