当前位置:首页 > 资讯 > 正文

Ensemble Kalman filter集合卡尔曼滤波

Ensemble Kalman filter集合卡尔曼滤波

在气象预测领域,很多时候,模型具有以上的量级,如果使用传统的卡尔曼滤波,协方差矩阵的更新将是一个~量级的计算操作,因此传统的卡尔曼滤波并不适用。集合卡尔曼滤波(Ensemble Kalman filter)用sample covariance模拟原本的协方差矩阵,用一个小的多的量级的矩阵运算代替原本的协方差矩阵更新。集合卡尔曼滤波与粒子滤波有相通之处,集合卡尔曼滤波假设用来做模拟的ensembles符合高斯分布。

本文将通过一个应用EnKF进行定位的python实例来初探集合卡尔曼滤波的概念。

根据参考【1】,集合卡尔曼滤波的公式为:

下面我们来看参考【2】中的代码:

for ip in range(NP):
        x = np.array([px[:, ip]]).T        #  Predict with random input sampling
        # 预测:给输入加上方差为Q的随机误差:
        ud1 = u[0, 0] + np.random.randn() * Q[0, 0] ** 0.5
        ud2 = u[1, 0] + np.random.randn() * Q[1, 1] ** 0.5
        ud = np.array([[ud1, ud2]]).T
        x = motion_model(x, ud)
        px[:, ip] = x[:, 0]

对应公式(10),给运动模型的输入加上qi,计算每一个ensemble的状态向量的值。

接下来:

        # 根据状态预测值x和观测值z获取路标点加上观测方差R的空间位置z_pos
        z_pos = observe_landmark_position(x, z)
        pz[:, ip] = z_pos[:, 0]

在这里我认为observe_landmark_position函数计算的其实是:

原因在计算(17)时会提到。

    x_ave = np.mean(px, axis=1)
    # 计算 x_f-x_f_bar
    x_dif = px - np.tile(x_ave, (NP, 1)).T

    z_ave = np.mean(pz, axis=1)
    # 计算 Hx_f-Hx_f_bar
    z_dif = pz - np.tile(z_ave, (NP, 1)).T

    U = 1 / (NP - 1) * x_dif @ z_dif.T
    V = 1 / (NP - 1) * z_dif @ z_dif.T

接下来和我认为分别对应(12)(13)。在计算卡尔曼增益时,原代码直接计算:

K = U @ np.linalg.inv(V)

不知为什么好像没有体现出(14)式中的观测协方差,难道是因为我在上面提到的中已经包含了观测噪声?

我对原代码进行了一些改动,加入了观测方差(不能保证理论上的正确性),改动后的定位效果目测与原先没什么区别。

    # 以下是我的改动:
    # 观测协方差矩阵:
    R_a = np.diag([R[0,0]/2, R[0,0]/2] * z.shape[0])
    # 原代码:K = U @ np.linalg.inv(V)分母不包含观测协方差矩阵,
    # 这似乎与参考论文所述K的计算方法不符,不知道为什么这样处理
    # 在加入观测协方差R计算K后,与不加R计算K在定位结果上**目测**没有什么差别
    K = U @ np.linalg.inv(V + R_a)  # Kalman Gain

最后计算残差并进行更新:

    # 获取观测的真值:
    z_lm_pos = z[:, [2, 3]].reshape(-1, )
    
    # 更新:在这里pz包含了Hx_f和观测噪声r
    px_hat = px + K @ (np.tile(z_lm_pos, (NP, 1)).T - pz)

在这里我们看到更新时直接用路标点真值减去了,这也是为什么上面我提到observe_landmark_position函数计算的其实是

完整的包含注释的python代码如下:

最新文章