卡尔曼滤波公式及推导

1、简介

\qquad 卡尔曼滤波(Kalman filtering)是一种线性系统状态最优估计算法。

2、离散卡尔曼滤波器

状态方程:
x k = A x k − 1 + B u k − 1 + w k − 1 x_k = Ax_{k-1}+Bu_{k-1}+w_{k-1} xk=Axk1+Buk1+wk1
观测方程:
z k = H x k + v k z_k = Hx_k+v_k zk=Hxk+vk
过程激励噪声和观测噪声为相互独立,正态分布的白噪声:
p ( w ) ∼ N ( 0 , Q ) p(w) \sim N(0,Q) p(w)N(0,Q)
p ( v ) ∼ N ( 0 , R ) p(v) \sim N(0,R) p(v)N(0,R)
卡尔曼滤波器用反馈控制的方法估计过程状态:滤波器估计过程某一时刻的状态,然后以(含噪声的)测量变量的方式获得反馈。因此卡尔曼滤波器可分为两个部分:时间更新方程和测量更新方程。

预测方程:
x ^ k − = A x ^ k − 1 + B u k − 1 \hat{x}_k^{-} = A\hat{x}_{k-1}+Bu_{k-1} x^k=Ax^k1+Buk1
P ^ k − = A P ^ k − 1 A T + Q \hat{P}_k^{-} = A\hat{P}_{k-1}A^T+Q P^k=AP^k1AT+Q
更新方程:
K k = P ^ k − H T ( H P ^ k − H T + R ) − 1 K_k = \hat{P}_k^-H^T(H\hat{P}_k^-H^T+R)^{-1} Kk=P^kHT(HP^kHT+R)1
x ^ k = x ^ k − + K k ( z k − H x ^ k − ) \hat{x}_k = \hat{x}_k^-+K_k(z_k-H\hat{x}_k^-) x^k=x^k+Kk(zkHx^k)
P ^ k = ( I − K k H ) P ^ k − \hat{P}_k = (I-K_kH)\hat{P}_k^- P^k=(IKkH)P^k

3、推导

这里设定的最优准则是使误差方差最小,即 P k P_k Pk的迹最小。依据这一准则,下面来推导卡尔曼增益 K K K的表达式。
首先
P k = E ( ( e k ) ( e k ) T ) P_k = E((e_k)(e_k)^T) Pk=E((ek)(ek)T)
其中, e k = x k − x ^ k = x k − x ^ k − − K k ( z k − H x ^ k − ) e_k=x_k-\hat{x}_k= x_k- \hat{x}_k^--K_k(z_k-H\hat{x}_k^-) ek=xkx^k=xkx^kKk(zkHx^k),将 z k = H x k + v k z_k=Hx_k+v_k zk=Hxk+vk代入上式,
P k = E ( ( I − K k H ) e ^ k − − K k v k ) ( I − K k H ) e ^ k − − K k v k ) T ) P_k = E((I-K_kH)\hat{e}^-_k-K_kv_k)(I-K_kH)\hat{e}^-_k-K_kv_k)^T) Pk=E((IKkH)e^kKkvk)(IKkH)e^kKkvk)T)
其中, e ^ k − = x k − x ^ k − \hat{e}^-_k=x_k-\hat{x}_k^- e^k=xkx^k
由于 v k v_k vk e ^ k − \hat{e}_k^- e^k相互独立,上式可以展开为:
P k = P ^ k − − 2 K k H P ^ k − + K k H P ^ k − H T K k T + K k R K k T P_k =\hat{P}_k^- -2K_kH\hat{P}^-_k+K_kH\hat{P}_k^-H^TK_k^T+K_kRK_k^T Pk=P^k2KkHP^k+KkHP^kHTKkT+KkRKkT
其中, P ^ k − = E ( e ^ k − ( e ^ k − ) T ) \hat{P}_k^-= E(\hat{e}^-_k(\hat{e}^-_k)^T) P^k=E(e^k(e^k)T)
所以
t r ( P k ) = t r ( P ^ k − ) − 2 t r ( K k H P ^ k − ) + t r ( K k H P ^ k − H T K k T ) + t r ( K k R K k T ) tr(P_k )=tr(\hat{P}_k^-) -2tr(K_kH\hat{P}^-_k)+tr(K_kH\hat{P}_k^-H^TK_k^T)+tr(K_kRK_k^T) tr(Pk)=tr(P^k)2tr(KkHP^k)+tr(KkHP^kHTKkT)+tr(KkRKkT)
上式对 K k K_k Kk求导,可得:
( K k ) o p t = P ^ k − H T ( H P ^ k − H T + R ) − 1 (K_k)_{opt}=\hat{P}_k^-H^T(H\hat{P}_k^-H^T+R)^{-1} (Kk)opt=P^kHT(HP^kHT+R)1
其中,使用到的两个迹的求导公式: d ( t r ( A B ) ) / d ( A ) = B T d(tr(AB))/d(A)=B^T d(tr(AB))/d(A)=BT, d ( t r ( A B A T ) ) / d ( A ) = 2 A B d(tr(ABA^T))/d(A)=2AB d(tr(ABAT))/d(A)=2AB

参考:https://www.bilibili.com/video/BV1hC4y1b7K7
一个简单的ekf例子:

#include<vector>
#include<Eigen/Core>
#include<stdlib.h>
#include<cmath>
#include<iostream>

using namespace std;
using namespace Eigen;

template<class T>
auto f = [](T s, T e, T dt)
{	
    vector<T> r;
    T b = s;
    for(;b<=e;b+=dt)
    {		
	r.push_back(b);
    }
    return r;
};


auto hx = [](Vector3d x)
{
    return sqrt(x(0)*x(0)+x(2)*x(2));
};

auto Hjacob(Vector3d xp){
    Vector3d H = Vector3d::Zero();
    H(0) = xp(0)/sqrt(xp(0)*xp(0)+xp(2)*xp(2));
    H(1) = 0;
    H(2) = xp(2)/sqrt(xp(0)*xp(0)+xp(2)*xp(2));
    return H;
};

class EKF
{
public:
    EKF(){}
    ~EKF(){}
public:
int posp = 0;
Matrix3d A,Q,P;
Vector3d x;
double R;
bool initialized = false;

double GetRadar(double dt)
{
    double vel = 100 + 5*rand()/double(RAND_MAX);
    double alt = 1000 + 10*rand()/double(RAND_MAX);
    double pos = posp + vel*dt;
    posp = pos;
    double v = 0 + pos*0.05*rand()/double(RAND_MAX);
    return sqrt(pos*pos + alt*alt)+v;
}

Vector3d RadarEKF(double z, double dt)
{

    if(!initialized)
    {
	Matrix3d m3d;
	m3d<<0,1,0,0,0,0,0,0,0;
	A = Matrix3d::Identity() + dt*m3d;
	Q << 0,0,0,0,0.001,0,0,0,0.001;
	R = 10;
	x<< 0,90,1100;
	P = 10*Matrix3d::Identity();
	initialized = true;
    }
    Vector3d H = Hjacob(x);
    Vector3d xp = A*x;
    Matrix3d Pp = A*P*A.transpose()+Q;
    Vector3d K = Pp*H/(H.transpose()*Pp*H+R);
    x = xp + K*(z-hx(xp));
    P = Pp - K*H.transpose()*Pp;

    return x;
}

};


int main()
{
    double dt = 0.05;
    double s = 0.0, e = 20.0;
    vector<double> t = f<double>(s,e,dt);
    int Nsamples = t.size();
    vector<Vector3d> Xsaved(Nsamples,Vector3d({0,0,0}));
    vector<double> Zsaved(Nsamples,0);
    EKF ekf;
    for(auto k=0;k<Nsamples;k++)
    {
	double r = ekf.GetRadar(dt);
	Vector3d pva = ekf.RadarEKF(r,dt);
	std::cout<<pva<<std::endl;
	Xsaved[k] = pva;
	Zsaved[k] = r;
    }
    
    return 0;	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值