卡尔曼滤波 Kalman Filter

Kalman滤波器是一种状态估计器,用于结合多个包含噪声的传感器数据。

Naive Kalman Filter

NKF是一种线性滤波器,要求系统动态为线性矩阵。

原理

Kalman滤波的核心思想是将系统状态建模为一个随时间变化的过程,并在每个时间步骤上对状态进行估计。它包括两个主要步骤:预测和更新。

  1. 预测(Prediction): 在这一步中,我们使用系统的动态模型来预测下一个时间步骤的状态。这个预测包括两个部分:状态预测和协方差预测。

    • 状态预测: 使用系统模型,例如运动方程,来预测下一个状态。在我们的小车示例中,状态可以包括位置和速度。

    • 协方差预测: 预测状态估计的不确定性,通常用协方差矩阵来表示。

  2. 更新(Update): 在这一步中,我们考虑测量值(传感器数据)来修正我们的状态估计。这个步骤也包括两个部分:卡尔曼增益计算和状态更新。

    • 卡尔曼增益计算: 卡尔曼增益是一个权重,用于衡量测量值和预测值的相对可信度。它的计算依赖于状态预测的不确定性和测量噪声的不确定性。

    • 状态更新: 使用测量值和卡尔曼增益来更新状态估计,以获得更准确的估计值。

实现

假设你有一个小车,你想使用Kalman滤波器来估计小车的位置。你已经有一些传感器数据来测量小车的位置,但这些数据可能会受到噪声的影响。

Kalman滤波的实现:

在Python中,你可以使用NumPy库来实现Kalman滤波。以下是一个简化的代码示例:

import numpy as np

# 初始化状态估计和协方差矩阵
x = np.array([0, 0])  # 初始状态估计,例如 [位置, 速度]
P = np.eye(2)  # 初始协方差矩阵

# 系统模型矩阵,例如小车的运动方程
A = np.array([[1, 1], [0, 1]])

# 测量矩阵,用于将状态映射到测量空间,这里的测量的是位置
H = np.array([1, 0])

# 测量噪声协方差,对位置的测量有误差
R = 1.0

# 过程噪声协方差
Q = np.eye(2) * 0.01

# 测量值
z = 1.2

# 先粗略估计一下
x_hat = np.dot(A, x) # 状态预测估计
P = np.dot(np.dot(A, P), A.T) + Q # 协方差估计

# 用测量值z修正估计
K = np.dot(np.dot(P, H.T), 1 / (np.dot(np.dot(H, P), H.T) + R)) # 计算卡尔曼增益
x = x_hat + K * (z - np.dot(H, x_hat)) # 状态修正:加上测量误差
P = P - np.dot(np.dot(K, H), P) # 协方差修正:加上测量误差

print("更新后的状态估计:", x)

Extended Kalman Filter

EKF的主要思想是在每一个时间步长处对非线性系统进行线性化,然后应用卡尔曼滤波器。具体来说,EKF通过在当前估计的状态处对系统的动力学和观测模型进行泰勒级数展开来获得线性化模型

Unscented Kalman Filter

无模型Kalman滤波(Unscented Kalman Filter,UKF)是一种用于估计非线性系统状态的滤波器,它不要求对系统模型进行线性化处理,因此适用于更广泛的应用领域。UKF的核心思想是使用一组称为sigma点的采样点来近似非线性系统的状态传播和测量函数,从而获得更准确的状态估计。

原理

1. Sigma点的选择: 在UKF中,首先选择一组sigma点,这些点会在状态空间中采样。通常,sigma点的选择是根据状态估计的均值和协方差矩阵来确定。sigma点被选为状态均值加上或减去多个标准差的值。

2. 状态传播(Prediction): 使用选定的sigma点来近似非线性系统的状态传播。对每个sigma点应用系统动态模型,从而获得在预测时刻的状态分布。这些预测的sigma点形成了一个状态预测的分布。

3. 状态更新(Update): 使用测量数据来修正状态预测。对每个预测的sigma点应用测量函数,以获得预测测量的分布。然后,通过加权平均这些测量预测,得到最终的状态估计和协方差矩阵。

4. 卡尔曼增益的计算: 类似于标准Kalman滤波,UKF也计算卡尔曼增益,用于在状态预测和测量更新之间进行平衡,考虑状态的不确定性和测量的不确定性。

实现

import numpy as np

def unscented_transform(x, P, alpha, beta, kappa):
    n = len(x)
    L = np.linalg.cholesky((n + kappa) * P)
    sigma_points = np.zeros((2 * n + 1, n))

    # 第一个Sigma点是状态估计均值
    sigma_points[0] = x

    # 生成其他Sigma点
    for i in range(n):
        sigma_points[i + 1] = x + L[i]
        sigma_points[i + n + 1] = x - L[i]

    return sigma_points

def ukf_predict(x, P, process_model, delta_t, alpha, beta, kappa):
    n = len(x)
    sigma_points = unscented_transform(x, P, alpha, beta, kappa)

    # 初始化预测后的状态和协方差矩阵
    x_pred = np.zeros(n)
    P_pred = np.zeros((n, n))

    # 使用Sigma点进行状态传播预测
    for i in range(2 * n + 1):
        sigma_point = sigma_points[i]
        x_pred += process_model(sigma_point, delta_t) / (2 * n + 1)

    # 计算协方差矩阵的预测值
    for i in range(2 * n + 1):
        diff = process_model(sigma_points[i], delta_t) - x_pred
        P_pred += np.outer(diff, diff) / (2 * n + 1)

    # 添加过程噪声协方差矩阵
    Q = np.eye(n)  # 过程噪声协方差矩阵,需要根据具体应用设定
    P_pred += Q

    return x_pred, P_pred

def ukf_update(x_pred, P_pred, measurement, measurement_model, R):
    n = len(x_pred)
    sigma_points = unscented_transform(x_pred, P_pred, alpha, beta, kappa)

    # 初始化测量预测和协方差矩阵
    z_pred = np.zeros(measurement.shape)
    Pzz = np.zeros((measurement.shape[0], measurement.shape[0]))
    Pxz = np.zeros((n, measurement.shape[0]))

    # 使用Sigma点进行测量预测
    for i in range(2 * n + 1):
        sigma_point = sigma_points[i]
        z_pred += measurement_model(sigma_point) / (2 * n + 1)

    # 计算协方差矩阵的测量预测值
    for i in range(2 * n + 1):
        diff_z = measurement_model(sigma_points[i]) - z_pred
        diff_x = sigma_points[i] - x_pred
        Pzz += np.outer(diff_z, diff_z) / (2 * n + 1)
        Pxz += np.outer(diff_x, diff_z) / (2 * n + 1)

    # 添加测量噪声协方差矩阵
    Pzz += R  # R是测量噪声协方差矩阵

    # 计算卡尔曼增益
    K = np.dot(Pxz, np.linalg.inv(Pzz))

    # 更新状态估计
    x_updated = x_pred + np.dot(K, (measurement - z_pred))

    # 更新协方差矩阵
    P_updated = P_pred - np.dot(np.dot(K, Pzz), K.T)

    return x_updated, P_updated

# 示例使用的过程模型和测量模型函数需要根据具体应用自行定义
def process_model(x, delta_t):
    # 根据系统动态模型更新状态
    # 这里假设状态不变,即匀速直线运动
    return x

def measurement_model(x):
    # 根据测量模型计算测量值
    # 这里假设测量值就是状态的值
    return x

# 初始化状态估计和协方差矩阵
x = np.array([0, 0])
P = np.eye(2)

# 定义参数
alpha = 0.001  # 调整Sigma点分布的参数
beta = 2.0     # 用于计算卡尔曼增益的参数
kappa = 0.0    # 控制Sigma点的分布,通常设为0

# 示例测量数据
measurement_data = np.array([1.2, 0.8])

# 时间步长
delta_t = 0.1

# 测量噪声协方差矩阵
R = np.eye(2) * 0.1  # 需要根据具体应用设定

# 预测步骤
x_pred, P_pred = ukf_predict(x, P, process_model, delta_t, alpha, beta, kappa)

# 更新步骤
x_updated, P_updated = ukf_update(x_pred, P_pred, measurement_data, measurement_model, R)

print("更新后的状态估计:", x_updated)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
卡尔曼滤波是一种用来估计系统状态的递归滤波算法,适用于线性系统且满足高斯分布的噪声。该滤波器是由R. E. Kalman提出的。 卡尔曼滤波的原理是基于两个假设:系统动态方程能由线性方程描述,测量方程能由线性方程描述。在每个时间步,卡尔曼滤波器通过两个步骤进行估计和更新:预测步骤和校正步骤。预测步骤是根据系统动态方程和上一个时间步的估计状态预测当前状态的均值和方差。校正步骤是根据测量方程和当前观测得到的测量值以及预测的状态,利用贝叶斯定理更新状态的均值和方差,得到最终的估计值。 推导卡尔曼滤波算法的公式如下: 预测步骤: 预测状态: $ x^- = A \cdot x + B \cdot u $ 预测状态协方差矩阵: $ P^- = A \cdot P \cdot A^T + Q $ 校正步骤: 卡尔曼增益: $ K = P^- \cdot H^T \cdot (H \cdot P^- \cdot H^T + R)^{-1} $ 修正后的状态: $ x = x^- + K \cdot (z - H \cdot x^-) $ 修正后的状态协方差矩阵: $ P = (I - K \cdot H) \cdot P^- $ 其中,x是系统状态向量,A是状态转移矩阵,B是输入矩阵,u是输入向量,P是后验状态的误差协方差矩阵,Q是预测误差协方差矩阵,H是测量矩阵,R是测量误差的协方差矩阵,z是观测向量。 通过上述公式的迭代,卡尔曼滤波器可以递归地估计系统的状态,并通过校正步骤利用最新的观测值来更新估计值。这种算法在估计方差较大的实时系统中具有优势,可以去除噪声和不确定性,提高系统的估计精度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值