4. DVL 刻度因数误差建模与在线估计
为什么要把刻度因数放进状态量
DVL 输出的对地速度本质上是多普勒频移换算结果,换算系数 K 由声速、发射频率、波束几何等决定。实际中声速随水温盐度变化、波束角存在装配偏差,导致真实速度与 DVL 报告速度之间差一个比例因子:v_true = (1 + s)·v_dvl,其中 s 即刻度因数误差(典型量级 0.5%~2%)。若只把它当噪声,滤波会把这个系统性偏差吸收进速度状态,造成航位推算持续漂移。正确做法是把 s 扩展为状态量,用 INS 与 DVL 的速度差作为观测,让滤波器在线辨识它。
状态扩展与观测方程设计
在松耦合 15 维状态(位置、速度、姿态、陀螺零偏、加计零偏)基础上追加一维 s,得到 16 维状态。刻度因数误差建模为随机常数(或极慢随机游走):
s(k+1) = s(k) + w_s, w_s ~ N(0, q_s·dt)
观测取 INS 速度与 DVL 速度之差。设 DVL 在载体系测得速度经姿态投影到导航系为 v_dvl^n,则观测方程对 s 是线性的:
z = v_ins^n - v_dvl^n = H·x + v
H 中速度块为 I3,刻度因数对应列为 v_dvl^n(3×1)
关键点:H 的刻度因数列不是常数,而是当前 DVL 导航系速度本身。这意味着载体必须有速度激励,该状态才可观测;静止时 v_dvl^n≈0,s 完全不可观,滤波器不应在此阶段强行更新它。
实现:16 维滤波核心代码
下面给出可直接运行的 Python 实现(仅依赖 numpy),包含状态扩展、观测矩阵构造、闭环补偿与仿真验证。为聚焦刻度因数,姿态与零偏用简化模型,但状态维度与观测结构保持真实。
import numpy as np
dt = 0.01 # 滤波周期 100 Hz
T = 120.0 # 仿真时长
N = int(T/dt)
s_true = 0.012 # 真实刻度因数误差 1.2%
# 状态: [px,py,pz, vx,vy,vz, roll,pitch,yaw, bgx,bgy,bgz, bax,bay,baz, s]
n = 16
x = np.zeros(n)
P = np.diag([1,1,1, 0.5,0.5,0.5, 0.01,0.01,0.05,
1e-6,1e-6,1e-6, 1e-4,1e-4,1e-4, 0.02**2])
Q = np.diag([0,0,0, 0.02**2,0.02**2,0.02**2,
1e-6,1e-6,1e-6, 1e-10,1e-10,1e-10,
1e-8,1e-8,1e-8, 1e-10]) * dt
R = np.eye(3) * 0.05**2 # DVL 速度噪声 0.05 m/s
def f(x):
xn = x.copy()
xn[0:3] += x[3:6]*dt
return xn
def F_jac(x):
F = np.eye(n)
F[0:3,3:6] = np.eye(3)*dt
return F
def H_mat(v_dvl_n):
H = np.zeros((3,n))
H[0:3,3:6] = np.eye(3)
H[0:3,15] = v_dvl_n # 刻度因数观测列
return H
# 仿真真值:载体做变速机动(保证可观测)
t = np.arange(N)*dt
v_true = np.stack([3.0+2.0*np.sin(0.05*t),
1.5*np.cos(0.08*t),
0.2*np.sin(0.1*t)], axis=1)
s_hist, v_err = [], []
for k in range(N):
# 预测
x = f(x)
F = F_jac(x)
P = F @ P @ F.T + Q
# DVL 测量:真实速度被刻度因数污染 + 噪声
v_dvl_n = v_true[k] * (1 + s_true) + np.random.randn(3)*0.05
v_ins_n = x[3:6]
# 观测更新
z = v_ins_n - v_dvl_n
H = H_mat(v_dvl_n)
S = H @ P @ H.T + R
K = P @ H.T @ np.linalg.inv(S)
x = x + K @ z
P = (np.eye(n) - K @ H) @ P
# 闭环补偿:用 ŝ 修正 DVL 速度
v_corr = v_dvl_n / (1 + x[15])
x[3:6] = v_corr # 简化:直接以补偿后速度作为速度状态
s_hist.append(x[15])
v_err.append(np.linalg.norm(x[3:6] - v_true[k]))
print(f"最终刻度因数估计: {x[15]:.4f} 真值: {s_true:.4f}")
print(f"稳态速度误差 RMS: {np.sqrt(np.mean(np.square(v_err[N//2:]))):.4f} m/s")
收敛过程与精度改善判读
运行上述代码,可观察到两个典型现象:
- 刻度因数收敛:
ŝ从初值 0 出发,在约 20~30 s 内单调逼近 0.012,之后在 ±0.001 内小幅波动。收敛速度取决于P_s初值、q_s与速度激励幅度。 - 速度精度改善:未补偿时速度误差约等于
s_true·|v| ≈ 0.012×3.5 ≈ 0.042 m/s;补偿后稳态 RMS 降至 0.01 m/s 量级,改善约 4 倍。
若
ŝ 长时间不收敛,先检查 H[0:3,15] 是否用了导航系 DVL 速度而非载体系;再检查 P_s 初值是否过小(过小则滤波器"不相信"该状态需要修正)。静止或匀速直线航段中
v_dvl^n 接近常值甚至为零,s 的可观测性急剧下降。工程上可设置门限:当 |v_dvl^n| < 0.5 m/s 时冻结 s 的更新(令 K[15,:]=0),避免滤波器在弱激励下把噪声误判为刻度因数。参数整定速查
| 参数 | 含义 | 推荐初值 | 调整方向 |
|---|---|---|---|
P_s(0) | 刻度因数先验方差 | (0.02)² | 偏大→收敛快但初期抖动大 |
q_s | 随机游走强度 | 1e-10 | 偏大→跟踪慢变但稳态噪声大 |
R | DVL 速度噪声方差 | (0.05)² | 按实测 DVL 噪声标定 |
| 激励门限 | 冻结更新的速度阈值 | 0.5 m/s | 按 DVL 噪声水平调整 |