3. 水下传感器类型与数据特性认知
水下多传感器融合的第一步不是写融合算法,而是把每个传感器的“脾气”摸清楚:它输出什么、多久输出一次、噪声长什么样、在时间和空间上能分辨多细。如果对数据特性没有基本认知,后面的时间同步、坐标变换和滤波融合都会建立在错误的假设上。本节围绕七类常见水下传感器展开,先建立数据特性的整体认识,再用 Python 实际加载并统计一组模拟数据,形成可复用的数据检查流程。
七类传感器的输出与特性对照
从融合视角看,传感器可以分为三类:运动与姿态类(DVL、IMU)、环境参数类(CTD、水听器)、感知成像类(侧扫声呐、多波束声呐、水下相机)。它们的采样率、噪声模型和时空分辨率差异极大,直接决定了融合时的预处理策略。
| 传感器 | 典型输出 | 采样率(示例) | 主要噪声/误差 | 时空分辨率 |
|---|---|---|---|---|
| CTD | 电导率、温度、深度(盐度由计算得出) | 1~8 Hz | 传感器漂移、热滞后、泵流扰动 | 单点测量,时间分辨率低,空间上仅代表探头附近水体 |
| DVL | 三轴对底速度、高度、波束有效标志 | 1~10 Hz | 底质相关偏差、波束丢失、野值 | 厘米级速度精度,空间上为波束足印范围 |
| IMU | 三轴加速度、三轴角速度(可含姿态) | 100~400 Hz | 零偏、随机游走、温漂、振动耦合 | 时间分辨率最高,误差随时间累积 |
| 侧扫声呐 | 左右舷回波强度序列(按 ping 组织) | 每 ping 数 Hz 至数十 Hz | 斑点噪声、增益不均、航迹畸变 | 沿航迹高分辨率,垂直航迹分辨率随距离下降 |
| 多波束声呐 | 每波束的距离与角度,形成测深点云 | 每 ping 数 Hz | 声速误差、波束角误差、底质影响 | 扇面覆盖,分辨率随开角和距离变化 |
| 水下相机 | 图像帧(RGB 或灰度) | 5~30 fps | 水体散射、光照不均、运动模糊 | 空间分辨率高,有效距离通常仅数米 |
| 水听器 | 声压时域波形(可转频谱) | 数十至数百 kHz 采样 | 环境噪声、平台自噪声、多径 | 时间连续,空间定位需阵列或配合其它信息 |
这张表最重要的信息不是具体数值,而是量级差异:IMU 每秒数百个样本,CTD 每秒只有几个,声呐按 ping 组织,相机按帧组织。融合前必须统一到同一时间基准,并对高频数据做降采样或对低频数据做插值,同时保留每个样本的时间戳与有效性标志。
用 Python 加载并做初步统计
下面用一组模拟数据演示完整流程。假设一次约 60 秒的潜航记录,IMU 以 100 Hz 输出,DVL 以 5 Hz 输出,CTD 以 2 Hz 输出。数据以 CSV 保存,字段包含时间戳、测量值和有效性标志。示例数值为合理假设,用于说明方法,不代表实测结果。
import numpy as np
import pandas as pd
# 模拟 IMU:100 Hz,含零偏与白噪声
fs_imu = 100.0
t_imu = np.arange(0, 60, 1/fs_imu)
acc_x = 0.02 * np.sin(2*np.pi*0.1*t_imu) + 0.01 + np.random.normal(0, 0.05, t_imu.size)
imu = pd.DataFrame({"t": t_imu, "acc_x": acc_x})
# 模拟 DVL:5 Hz,含少量野值
fs_dvl = 5.0
t_dvl = np.arange(0, 60, 1/fs_dvl)
vx = 0.8 + np.random.normal(0, 0.03, t_dvl.size)
vx[::37] += 1.5 # 人为注入野值
valid = np.ones(t_dvl.size, dtype=bool)
valid[::53] = False # 模拟波束丢失
dvl = pd.DataFrame({"t": t_dvl, "vx": vx, "valid": valid})
# 模拟 CTD:2 Hz,温度缓慢漂移
fs_ctd = 2.0
t_ctd = np.arange(0, 60, 1/fs_ctd)
temp = 18.5 + 0.002*t_ctd + np.random.normal(0, 0.01, t_ctd.size)
ctd = pd.DataFrame({"t": t_ctd, "temp": temp})
加载后先做三件事:检查时间戳是否单调、统计各通道的均值与标准差、按有效性标志过滤。对 DVL 的野值,可用中位数绝对偏差(MAD)做稳健判别:偏离中位数超过 5 倍 MAD 的样本标记为可疑。对 IMU,重点看静止段的标准差,它近似反映噪声底;若某轴标准差明显偏大,需怀疑振动耦合或安装松动。
def robust_outlier(series, k=5.0):
med = series.median()
mad = (series - med).abs().median()
return (series - med).abs() > k * mad
dvl["suspect"] = robust_outlier(dvl["vx"])
clean = dvl[dvl["valid"] & ~dvl["suspect"]]
print("IMU acc_x 均值/标准差:", imu.acc_x.mean().round(4), imu.acc_x.std().round(4))
print("DVL 原始样本数:", len(dvl), " 清洗后:", len(clean))
print("CTD 温度范围:", ctd.temp.min().round(3), "~", ctd.temp.max().round(3))
示例输出大致为:IMU 加速度均值接近 0.01、标准差约 0.05;DVL 原始 300 个样本,清洗后约 290 个;CTD 温度在 18.5 附近小幅波动。这些数字本身不重要,重要的是形成判断依据:标准差是否与传感器手册的噪声指标同量级、清洗比例是否异常偏高、温度变化速率是否物理上合理。若 DVL 清洗掉的比例超过 10%,就应回头检查底质或安装角度,而不是直接进入融合。
时空分辨率对融合的直接影响
时间分辨率决定对齐方式:IMU 与 DVL 相差 20 倍采样率,若直接把两者按行拼接,会严重错位;正确做法是以 IMU 时间轴为基准,对 DVL 速度做零阶保持或线性插值,并记录插值引入的误差。空间分辨率决定信息权重:多波束声呐在近距扇面内测深点密集,远距处点稀疏且误差增大,融合建图时应按距离给权重,而不是一视同仁。水下相机的有效距离通常只有几米,超过该距离的图像不应参与几何约束。
噪声特性则决定滤波器的观测噪声矩阵。IMU 的零偏是慢变误差,适合用随机游走建模;DVL 的野值是稀疏大误差,适合用稳健核函数或卡方检验抑制;CTD 的漂移是低频趋势,适合在长时间尺度上做平滑校正。把这些差异写进预处理和噪声模型,融合结果才可信。