C++实现卡尔曼滤波

/** 
 * Write a function 'filter()' that implements a multi-
 *   dimensional Kalman Filter for the example given
 */

#include <iostream>
#include <vector>
// Eigen 部分
#include <Eigen/Core>
#include <Eigen/Dense>

using std::cout;
using std::endl;
using std::vector;
using Eigen::VectorXd;
using Eigen::MatrixXd;

// Kalman Filter variables
VectorXd x;	// object state 障碍物状态矩阵
MatrixXd P;	// object covariance matrix 障碍物不确定性协方差
VectorXd u;	// external motion 外部的运动
MatrixXd F; // state transition matrix 状态转移矩阵
MatrixXd H;	// measurement matrix 测量矩阵
MatrixXd R;	// measurement covariance matrix 测量协方差矩阵
MatrixXd I; // Identity matrix 单位矩阵
MatrixXd Q;	// process covariance matrix 过程协方差矩阵

vector<VectorXd> measurements; // 测量值
void filter(VectorXd &x, MatrixXd &P); // 滤波函数


int main() {
  /**
   * Code used as example to work with Eigen matrices
   */
  // design the KF with 1D motion
  x = VectorXd(2); // 初始化障碍物状态矩阵 第一个为位置,第二个为速度
  x << 0, 0;

  P = MatrixXd(2, 2); // 初始化不确定性协方差矩阵, 刚开始,位置(0,0)的不确定性为1000,速度的不确定性为1000
  P << 1000, 0, 0, 1000;

  u = VectorXd(2); // 运动误差
  u << 0, 0;

  F = MatrixXd(2, 2); // 状态转移矩阵初始化
  F << 1, 1, 0, 1;

  H = MatrixXd(1, 2); // 测量矩阵
  H << 1, 0;

  R = MatrixXd(1, 1); // 测量协方差矩阵
  R << 1;

  I = MatrixXd::Identity(2, 2); // 单位矩阵

  Q = MatrixXd(2, 2); // 过程协方差矩阵
  Q << 0, 0, 0, 0;

  // create a list of measurements
  VectorXd single_meas(1); 
  single_meas << 1;
  measurements.push_back(single_meas);
  single_meas << 2;
  measurements.push_back(single_meas);
  single_meas << 3;
  measurements.push_back(single_meas);

  // call Kalman filter algorithm
  filter(x, P);

  return 0;
}


void filter(VectorXd &x, MatrixXd &P) {

  for (unsigned int n = 0; n < measurements.size(); ++n) {

    VectorXd z = measurements[n];
    // TODO: YOUR CODE HERE
    /**
     * KF Measurement update step
     */
    VectorXd y = z - H * x;
    MatrixXd Ht = H.transpose();
    MatrixXd S = H * P * Ht + R;
    MatrixXd Si = S.inverse();
    MatrixXd K = P * Ht * Si;

    // new state
    x = x + (K * y);
    P = (I - K * H) * P;

    /**
     * KF Prediction step
     */
    x = F * x + u;
    MatrixXd Ft = F.transpose();
    P = F * P * Ft + Q;

    cout << "x=" << endl
         << x << endl;
    cout << "P=" << endl
         << P << endl;
  }
}

首先,让我们快速复习一下卡尔曼滤波一维运动的例子。比如我们的目标是跟踪一个行人,他的状态时 x x x x x x由位置和速度表示, x = ( p v ) x=\begin{pmatrix} p \\ v\\ \end{pmatrix} x=(pv)

预测步骤

当我们设计卡尔曼滤波,我们必须定义两个线性方程: 状态转移方程和测量方程。状态转移方程就是:
x ′ = F ∗ x + n o i s e x'=F*x + noise x=Fx+noise
F就是
F = ( 1 Δ t 0 1 ) F=\begin{pmatrix} 1 &\Delta t \\ 0 & 1\\ \end{pmatrix} F=(10Δt1)
x ′ x' x就是预测目标在 Δ t \Delta t Δt之后的状态。
F F F是状态转移矩阵,与 x x x相乘获得 Δ t \Delta t Δt之后的目标状态。
线性运动模型通过恒定速度速度,新的位置来计算 p ′ p' p p ′ p' p计算为:
p ′ = p + v ∗ Δ t p' = p + v*\Delta t p=p+vΔt
这里的 p p p是旧位置, v v v是速度,因为速度恒定,所以新速度和旧速度一样 v ′ = v v'=v v=v
我们用矩阵的形式表达如下:
( p ′ v ′ ) = ( 1 Δ t 0 1 ) ( p v ) \begin{pmatrix} p'\\v' \end{pmatrix}=\begin{pmatrix} 1 &\Delta t \\ 0 & 1\\ \end{pmatrix} \begin{pmatrix} p\\v \end{pmatrix} (pv)=(10Δt1)(pv)
我们将目标的位置和速度是服从均值为 x x x的高斯分布。所以它可以代入卡尔曼等式 x ′ = F x + n o i s e x' = Fx+noise x=Fx+noise,我们计算状态向量的均值。噪声(noise)依然符合高斯分布,不过均值是0,因此noise=0也就是说噪声均值是0,所以等式就变成了 x ′ = F x x' = Fx x=Fx

因为噪声是不确定的,不确定性在Q矩阵中是作为加速度噪声。

更新步骤

作为更新步骤,我们使用测量函数来将状态向量映射到传感器的测量空间中。也就是将高维的状态信息变成低维的传感器的空间维度。举个例子,比如激光雷达只测量目标位置,但是扩张卡尔曼滤波建模目标的位置和速度。所以需要乘以 H H H矩阵从状态向量 x x x中将速度信息去掉。那么雷达测量的目标位置和我们预测的目标位置就可以进行比较了。
z = H ∗ x + ω z=H*x + \omega z=Hx+ω
其中 ω \omega ω代表的是传感器测量的传感器噪声。
所以对于激光雷达来说,测量方程就如下所示:
z = p ′ z=p' z=p
用矩阵来表示如下:
z = ( 1 0 ) ( p ′ v ′ ) z=\begin{pmatrix} 1 & 0 \end{pmatrix} \begin{pmatrix} p'\\v' \end{pmatrix} z=(10)(pv)
我们都知道,一般算法都是由包含预测新状态和协方差 P ′ P' P组成的预测步骤组成。我们还有包含用最新的测量来更新我们的估计和不确定性的测量更新步骤组成。

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
卡尔曼滤波是一种用于状态估计的优秀方法,其可以用于跟踪目标的位置、速度和加速度等。在C语言实现卡尔曼滤波跟踪,可以按照以下步骤来进行: 1. 定义状态向量和观测向量:根据具体的问题,定义状态向量和观测向量的维度。状态向量包括目标的位置、速度等状态变量,观测向量包括可以直接观测到的目标信息。 2. 初始化卡尔曼滤波器:定义初始状态向量、初始协方差矩阵和过程噪声协方差矩阵等参数。 3. 进行预测步骤:利用系统模型和状态转移矩阵进行状态预测,同时更新协方差矩阵。 4. 进行观测步骤:利用观测模型和观测矩阵将预测值映射到观测空间,同时计算残差和卡尔曼增益。 5. 进行修正步骤:根据计算得到的卡尔曼增益,对预测值进行修正,并更新状态向量和协方差矩阵。 6. 重复预测、观测和修正步骤:根据实际情况,不断重复进行预测、观测和修正步骤,以实现目标的跟踪。 在C语言中,可以利用矩阵运算库或者自行实现矩阵相关的操作,如矩阵相乘、矩阵加减等。同时,需要定义相关的函数来实现卡尔曼滤波算法中的各个步骤。在实际应用中,还需要根据具体问题进行参数调整和优化,以达到更好的跟踪效果。 综上所述,通过定义状态向量、观测向量,初始化卡尔曼滤波器,并按照预测、观测和修正的步骤进行迭代更新,就可以在C语言实现卡尔曼滤波跟踪。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Philtell

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值