零基础-学习卡尔曼滤波(第二章:逐步推导公式)

前言

第一章内有原理理解的两部分,没看建议先看。闲话少说,祝君好运!!

参考

  1. 【卡尔曼滤波器】,真的是大佬讲课!!牛逼就完事了。(主要参考)
  2. 图解卡尔曼滤波(Kalman Filter)

3. 卡尔曼增益超详细数学推导

(一大波公式即将来临,如果看不懂,还是建议看参考1的DR_CAN的视频!!)

实际情况中我们无法得到下面这种带有噪声的精确模型:

预测方程: x k = A x k − 1 + B u k + w k − 1 观测方程: z k = H x k + v k 预测方程:x_k=Ax_{k-1}+Bu_{k}+w_{k-1} \\ 观测方程:z_k=Hx_k+v_k 预测方程:xk=Axk1+Buk+wk1观测方程:zk=Hxk+vk

我们可以得到的就是这种不带噪声的预测方程和观测方程:

预测方程: x k = A x k − 1 + B u k 观测方程: z k = H x k 预测方程:x_k=Ax_{k-1}+Bu_{k} \\ 观测方程:z_k=Hx_k 预测方程:xk=Axk1+Buk观测方程:zk=Hxk

将观测方程转换一下就得到下面两个方程:

x ^ k − = A x ^ k − 1 + B u k x ^ k m e a = H − z k \hat{x}_k^- =A\hat{x}_{k-1}+Bu_{k} \\ \hat{x}_{kmea}=H^-z_k \\ x^k=Ax^k1+Bukx^kmea=Hzk

其中 x ^ k − \hat{x}_k^- x^k表示只经过预测得到的先验估计 x ^ k − 1 \hat{x}_{k-1} x^k1表示上一次的后验估计(融合后得出来的更准确的值), x ^ k m e a \hat{x}_{kmea} x^kmea表示测出来的结果。

现在我们拥有两个结果,一个是算出来的结果 x ^ k − \hat{x}_k^- x^k,一个是测出来的结果 x ^ k m e a \hat{x}_{kmea} x^kmea,但是我们的这两个结果都不准确,我们可以利用上面数据融合的思想进行融合得到更加准确的结果。

后验估计: x ^ k = x ^ k − + G ( H − z k − x ^ k − ) G ∈ [ 0 , 1 ] 我们对 G 进行一个变换: G = K k H ,即可得到下面公式: x ^ k = x ^ k − + K k ( z k − H x ^ k − ) K k ∈ [ 0 , H − ] 后验估计:\hat{x}_k=\hat{x}_k^-+G(H^-z_k-\hat{x}_k^-)\\ G \in [0,1]\\ 我们对G进行一个变换:G=K_kH,即可得到下面公式:\\ \hat{x}_k=\hat{x}_k^-+K_k(z_k-H\hat{x}_k^-)\\ K_k\in[0,H^-] 后验估计:x^k=x^k+G(Hzkx^k)G[0,1]我们对G进行一个变换:G=KkH,即可得到下面公式:x^k=x^k+Kk(zkHx^k)Kk[0,H]

这个公式就是卡尔曼滤波中的一个重要公式!!

x ^ k = x ^ k − + K k ( z k − H x ^ k − ) − − − − − − − ( 1 ) \hat{x}_k=\hat{x}_k^-+K_k(z_k-H\hat{x}_k^-)-------(1)\\ x^k=x^k+Kk(zkHx^k)1

  • 我们得到了后验估计的计算方法,现在目标很明确就是需要找到一个 K k K_k Kk使得后验估计 x ^ k \hat{x}_k x^k趋近于真实值 x k x_k xk

可以显而易见的发现这个 K k K_k Kk肯定和两个噪声有关,如果测量噪声很大,则让后验估计偏向于预测值,如果预测噪声很大则让后验估计偏向于测量值。

为了求解问题,我们需要首先定义误差 e k = x k − x ^ k e_k=x_k-\hat{x}_k ek=xkx^k,这个是后验预测和真实值的误差。假设这个误差也服从正态分布,即为 P ( e k ) ∼ ( 0 , p ) P(e_k)\sim (0,p) P(ek)(0,p),其中协方差p的计算为: p = E [ e e T ] p=E[ee^T] p=E[eeT]我们需要后验估计 x ^ k \hat{x}_k x^k最接近真实值 x k {x}_k xk就说明需要误差的协方差的迹 t r ( p ) tr(p) tr(p)最小(因为误差服从期望为0的正态分布)。

这里提到真实值并不是需要得到真实,因为真实值是无法得知的,只是理论计算的过程需要。
迹:就是矩阵的对角线元素和。
为什么是协方差的迹:将协方差写出来即可知对角线元素为每个元素的方差,方差和最小就说明最接近真实值。

接下来我们需要求解 K k K_k Kk取哪个值的时,协方差的迹( t r ( p ) tr(p) tr(p))最小,接下来将会是比较多公式的一个推导,但是公式一步一步看都能看懂。

我们知道误差的协方差为: p = E [ e e T ] 将误差的定义公式 e k = x k − x ^ k 带入可得如下: p = E [ ( x k − x ^ k ) ( x k − x ^ k ) T ] − − − − − ( 2 ) 我们知道误差的协方差为:p=E[ee^T]\\ 将误差的定义公式e_k=x_k-\hat{x}_k带入可得如下:\\ p=E[(x_k-\hat{x}_k)(x_k-\hat{x}_k)^T]-----(2)\\ 我们知道误差的协方差为:p=E[eeT]将误差的定义公式ek=xkx^k带入可得如下:p=E[(xkx^k)(xkx^k)T]2

然后将后验误差的公式( 1 )带入可得 ( x k − x ^ k ) 为如下: x k − x ^ k = x k − ( x ^ k − + K k ( z k − H x ^ k − ) ) 将上式展开可得如下: x k − x ^ k = x k − x ^ k − − K k z k + K k H x ^ k − 然后将真实的观测值的公式 z k = H x k + v k 带入上式可得如下: x k − x ^ k = x k − x ^ k − − K k H x k − K k v k + K k H x ^ k − 然后提出 K k H 可得如下: x k − x ^ k = ( x k − x ^ k − ) − K k H ( x k − x ^ k − ) − K k v k 合并 x k − x ^ k − 可得如下: x k − x ^ k = ( I − K k H ) ( x k − x ^ k − ) − K k v k 我们将 x k − x ^ k − 作为先验估计 x ^ k − 的误差 ( 回忆 e k 的定义 ) , 将先验估计 x ^ k − 的误差记作 e k − , 整理可得如下: x k − x ^ k = ( I − K k H ) e k − − K k v k 然后将后验误差的公式(1)带入可得(x_k-\hat{x}_k)为如下:\\ x_k-\hat{x}_k=x_k-(\hat{x}_k^-+K_k(z_k-H\hat{x}_k^-))\\ 将上式展开可得如下:\\ x_k-\hat{x}_k=x_k-\hat{x}_k^--K_kz_k+K_kH\hat{x}_k^-\\ 然后将真实的观测值的公式z_k=Hx_k+v_k带入上式可得如下:\\ x_k-\hat{x}_k=x_k-\hat{x}_k^--K_kHx_k-K_kv_k+K_kH\hat{x}_k^-\\ 然后提出K_kH可得如下:\\ x_k-\hat{x}_k=(x_k-\hat{x}_k^-)-K_kH(x_k-\hat{x}_k^-)-K_kv_k\\ 合并x_k-\hat{x}_k^-可得如下:\\ x_k-\hat{x}_k=(I-K_kH)(x_k-\hat{x}_k^-)-K_kv_k\\ 我们将x_k-\hat{x}_k^-作为先验估计\hat{x}_k^-的误差(回忆e_k的定义),\\ 将先验估计\hat{x}_k^-的误差记作e_k^-,整理可得如下:\\ x_k-\hat{x}_k=(I-K_kH)e_k^--K_kv_k\\ 然后将后验误差的公式(1)带入可得(xkx^k)为如下:xkx^k=xk(x^k+Kk(zkHx^k))将上式展开可得如下:xkx^k=xkx^kKkzk+KkHx^k然后将真实的观测值的公式zk=Hxk+vk带入上式可得如下:xkx^k=xkx^kKkHxkKkvk+KkHx^k然后提出KkH可得如下:xkx^k=(xkx^k)KkH(xkx^k)Kkvk合并xkx^k可得如下:xkx^k=(IKkH)(xkx^k)Kkvk我们将xkx^k作为先验估计x^k的误差(回忆ek的定义)将先验估计x^k的误差记作ek,整理可得如下:xkx^k=(IKkH)ekKkvk

然后带入( 2 )中可得如下: p = E [ ( ( I − K k H ) e k − − K k v k ) ( ( I − K k H ) e k − − K k v k ) T ] 然后将后面转置部分展开可如下: − − − − − − − − − − − − − − − − − − − − 补充知识: ( A B ) T = B T A T , ( A + B ) T = A T + B T − − − − − − − − − − − − − − − − − − − − p = E [ ( ( I − K k H ) e k − − K k v k ) ( e k − T ( I − K k H ) T − v k T K k T ) ] 然后将括号展开可得如下: p = E [ ( I − K k H ) e k − e k − T ( I − K k H ) T − ( I − K k H ) e k − v k T K k T − K k v k e k − T ( I − K k H ) T + K k v k v k T K k T ] 将求期望的符号 E 拿进去: p = E ( ( I − K k H ) e k − e k − T ( I − K k H ) T ) − E ( ( I − K k H ) e k − v k T K k T ) − E ( K k v k e k − T ( I − K k H ) T ) + E ( K k v k v k T K k T ) 然后带入(2)中可得如下:\\ p=E[((I-K_kH)e_k^--K_kv_k)((I-K_kH)e_k^--K_kv_k)^T]\\ 然后将后面转置部分展开可如下:\\ --------------------\\ 补充知识:(AB)^T=B^TA^T,(A+B)^T=A^T+B^T\\ --------------------\\ p=E[((I-K_kH)e_k^--K_kv_k)(e_k^{-T}(I-K_kH)^T-v_k^TK_k^T)]\\ 然后将括号展开可得如下:\\ p=E[(I-K_kH)e_k^-e_k^{-T}(I-K_kH)^T-(I-K_kH)e_k^-v_k^TK_k^T\\ -K_kv_ke_k^{-T}(I-K_kH)^T+K_kv_kv_k^TK_k^T]\\ 将求期望的符号E拿进去:\\ p=E((I-K_kH)e_k^-e_k^{-T}(I-K_kH)^T)-E((I-K_kH)e_k^-v_k^TK_k^T)\\ -E(K_kv_ke_k^{-T}(I-K_kH)^T)+E(K_kv_kv_k^TK_k^T)\\ 然后带入(2)中可得如下:p=E[((IKkH)ekKkvk)((IKkH)ekKkvk)T]然后将后面转置部分展开可如下:补充知识:(AB)T=BTAT,(A+B)T=AT+BTp=E[((IKkH)ekKkvk)(ekT(IKkH)TvkTKkT)]然后将括号展开可得如下:p=E[(IKkH)ekekT(IKkH)T(IKkH)ekvkTKkTKkvkekT(IKkH)T+KkvkvkTKkT]将求期望的符号E拿进去:p=E((IKkH)ekekT(IKkH)T)E((IKkH)ekvkTKkT)E(KkvkekT(IKkH)T)+E(KkvkvkTKkT)

对第二部分 E ( ( I − K k H ) e k − v k T K k T ) 进行单独分析: 其中 I − K k H 和 K k T 为常数可以直接提出来,可得如下: ( I − K k H ) E ( e k − v k T ) K k T − − − − − − − − − − − − − − − − − − − − 补充知识:如果 A B 相互独立有: E ( A B ) = E ( A ) E ( B ) − − − − − − − − − − − − − − − − − − − − 很明显 e k − , v k T 这两个相互独立,可以使用上面补充知识 由 E ( e k − ) , E ( v k T ) 都为 0 ,所以本部分就为 0 ,可以忽略。 同理可得第三部分也为 0 ,忽略。 对第二部分E((I-K_kH)e_k^-v_k^TK_k^T)进行单独分析:\\ 其中I-K_kH和K_k^T为常数可以直接提出来,可得如下:\\ (I-K_kH)E(e_k^-v_k^T)K_k^T\\ --------------------\\ 补充知识:如果AB相互独立有:E(AB)=E(A)E(B)\\ --------------------\\ 很明显e_k^-,v_k^T这两个相互独立,可以使用上面补充知识\\ 由E(e_k^-),E(v_k^T)都为0,所以本部分就为0,可以忽略。\\ 同理可得第三部分也为0,忽略。\\ 对第二部分E((IKkH)ekvkTKkT)进行单独分析:其中IKkHKkT为常数可以直接提出来,可得如下:(IKkH)E(ekvkT)KkT补充知识:如果AB相互独立有:E(AB)=E(A)E(B)很明显ek,vkT这两个相互独立,可以使用上面补充知识E(ek),E(vkT)都为0,所以本部分就为0,可以忽略。同理可得第三部分也为0,忽略。

最终得到 p 为如下: p = E ( ( I − K k H ) e k − e k − T ( I − K k H ) T ) + E ( K k v k v k T K k T ) 同样将常数项提取出来,可得如下: p = ( I − K k H ) E ( e k − e k − T ) ( I − K k H ) T + K k E ( v k v k T ) K k T 我们可以得到 E ( e k − e k − T ) 即为先验误差的协方差矩阵 p k − 并且,我们上面已经定义了 E ( v k v k T ) 即为观测值的噪声协方差矩阵 R 于是上面的公式可以写成如下: p = ( I − K k H ) p k − ( I − K k H ) T + K k R K k T 然后将前半部分展开可得如下: p = ( p k − − K k H p k − ) ( I − K k H ) T + K k R K k T p = ( p k − − K k H p k − ) ( I T − H T K k T ) + K k R K k T p = ( p k − − p k − H T K k T − K k H p k − + K k H p k − H T K k T ) + K k R K k T 最终得到第 k 次的协方差矩阵为: p k = p k − − p k − H T K k T − K k H p k − + K k H p k − H T K k T + K k R K k T − − ( 7 ) 最终得到p为如下:\\ p=E((I-K_kH)e_k^-e_k^{-T}(I-K_kH)^T)+E(K_kv_kv_k^TK_k^T)\\ 同样将常数项提取出来,可得如下:\\ p=(I-K_kH)E(e_k^-e_k^{-T})(I-K_kH)^T+K_kE(v_kv_k^T)K_k^T\\ 我们可以得到E(e_k^-e_k^{-T})即为先验误差的协方差矩阵p_k^-\\ 并且,我们上面已经定义了E(v_kv_k^T)即为观测值的噪声协方差矩阵R\\ 于是上面的公式可以写成如下:\\ p=(I-K_kH)p_k^-(I-K_kH)^T+K_kRK_k^T\\ 然后将前半部分展开可得如下:\\ p=(p_k^--K_kHp_k^-)(I-K_kH)^T+K_kRK_k^T\\ p=(p_k^--K_kHp_k^-)(I^T-H^TK_k^T)+K_kRK_k^T\\ p=(p_k^--p_k^-H^TK_k^T-K_kHp_k^-+K_kHp_k^-H^TK_k^T)+K_kRK_k^T\\ 最终得到第k次的协方差矩阵为:\\ p_k=p_k^--p_k^-H^TK_k^T-K_kHp_k^-+K_kHp_k^-H^TK_k^T+K_kRK_k^T--(7)\\ 最终得到p为如下:p=E((IKkH)ekekT(IKkH)T)+E(KkvkvkTKkT)同样将常数项提取出来,可得如下:p=(IKkH)E(ekekT)(IKkH)T+KkE(vkvkT)KkT我们可以得到E(ekekT)即为先验误差的协方差矩阵pk并且,我们上面已经定义了E(vkvkT)即为观测值的噪声协方差矩阵R于是上面的公式可以写成如下:p=(IKkH)pk(IKkH)T+KkRKkT然后将前半部分展开可得如下:p=(pkKkHpk)(IKkH)T+KkRKkTp=(pkKkHpk)(ITHTKkT)+KkRKkTp=(pkpkHTKkTKkHpk+KkHpkHTKkT)+KkRKkT最终得到第k次的协方差矩阵为:pk=pkpkHTKkTKkHpk+KkHpkHTKkT+KkRKkT(7)

现在需要求迹 t r ( p k ) 的最小值,即为如下: t r ( p k ) = t r ( p k − ) − t r ( p k − H T K k T ) − 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(p_k)=tr(p_k^-)-tr(p_k^-H^TK_k^T)-tr(K_kHp_k^-)+\\ tr(K_kHp_k^-H^TK_k^T)+tr(K_kRK_k^T)\\ 现在需要求迹tr(pk)的最小值,即为如下:tr(pk)=tr(pk)tr(pkHTKkT)tr(KkHpk)+tr(KkHpkHTKkT)+tr(KkRKkT)

我们分析一下第三部分 K k H p k − 的转置: ( K k H p k − ) T = p k − T ( K k H ) T = p k − T H T K k T 并且我们知道协方差矩阵的转置是其本身,所以有如下: ( K k H p k − ) T = p k − H T K k T = 第二部分 我们分析一下第三部分K_kHp_k^-的转置:\\ (K_kHp_k^-)^T=p_k^{-T}(K_kH)^T=p_k^{-T}H^TK_k^T\\ 并且我们知道协方差矩阵的转置是其本身,所以有如下:\\ (K_kHp_k^-)^T=p_k^{-}H^TK_k^T=第二部分\\ 我们分析一下第三部分KkHpk的转置:(KkHpk)T=pkT(KkH)T=pkTHTKkT并且我们知道协方差矩阵的转置是其本身,所以有如下:(KkHpk)T=pkHTKkT=第二部分

所以可得如下: 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(p_k^-)-2tr(K_kHp_k^-)+tr(K_kHp_k^-H^TK_k^T)+tr(K_kRK_k^T)\\ 所以可得如下:tr(pk)=tr(pk)2tr(KkHpk)+tr(KkHpkHTKkT)+tr(KkRKkT)

现在目标很明确就是取一个合适的 K k 使得 t r ( p k ) 最小: 很明显就是直接对 t r ( p k ) 求导令其为 0 即可,如下: d t r ( p k ) d K k = 0 d 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 ) d K k = 0 现在目标很明确就是取一个合适的K_k使得tr(p_k)最小:\\ 很明显就是直接对tr(p_k)求导令其为0即可,如下:\\ \frac{d_{tr(p_k)}}{d_{K_k}}=0\\ \frac{d_{tr(p_k^-)-2tr(K_kHp_k^-)+tr(K_kHp_k^-H^TK_k^T)+tr(K_kRK_k^T)}}{d_{K_k}}=0\\ 现在目标很明确就是取一个合适的Kk使得tr(pk)最小:很明显就是直接对tr(pk)求导令其为0即可,如下:dKkdtr(pk)=0dKkdtr(pk)2tr(KkHpk)+tr(KkHpkHTKkT)+tr(KkRKkT)=0

− − − − − − − − − − − − − − − − − − − − 补充知识:矩阵求导 ( 可自行举例验证 ) d t r ( A B ) d A = B T d t r ( A B A T ) d A = 2 A B 提示如下: 假设 A = [ a 11 a 12 a 21 a 22 ] d t r ( A B ) d A = [ ∂ t r ( A B ) ∂ a 11 ∂ t r ( A B ) ∂ a 12 ∂ t r ( A B ) ∂ a 21 ∂ t r ( A B ) ∂ a 22 ] − − − − − − − − − − − − − − − − − − − − --------------------\\ 补充知识:矩阵求导(可自行举例验证)\\ \frac{d_{tr(AB)}}{d_A}=B^T\\ \frac{d_{tr(ABA^T)}}{d_A}=2AB\\ 提示如下:\\ 假设A=\begin{bmatrix} a_{11} & a_{12}\\ a_{21} & a_{22} \end{bmatrix}\\ \frac{d_{tr(AB)}}{d_A}= \begin{bmatrix} \frac{\partial tr(AB)}{\partial a_{11}} & \frac{\partial tr(AB)}{\partial a_{12}}\\ \frac{\partial tr(AB)}{\partial a_{21}} & \frac{\partial tr(AB)}{\partial a_{22}} \end{bmatrix}\\ --------------------\\ 补充知识:矩阵求导(可自行举例验证)dAdtr(AB)=BTdAdtr(ABAT)=2AB提示如下:假设A=[a11a21a12a22]dAdtr(AB)=[a11tr(AB)a21tr(AB)a12tr(AB)a22tr(AB)]

求导可得如下: 0 − 2 ( H p k − ) T + 2 K k H p k − H T + 2 K k R = 0 − p k − T H T + K k H p k − H T + K k R = 0 − p k − T H T + K k ( H p k − H T + R ) = 0 协方差矩阵的转置是其本身,所以有如下: − p k − H T + K k ( H p k − H T + R ) = 0 K k ( H p k − H T + R ) = p k − H T 最终得到 K k 的表达式: K k = p k − H T H p k − H T + R − − − − − − ( 3 ) 这个就是大名鼎鼎的卡尔曼增益!!!! 求导可得如下:\\ 0-2(Hp_k^-)^T+2K_kHp_k^-H^T+2K_kR=0\\ -p_k^{-T}H^T+K_kHp_k^-H^T+K_kR=0\\ -p_k^{-T}H^T+K_k(Hp_k^-H^T+R)=0\\ 协方差矩阵的转置是其本身,所以有如下:\\ -p_k^{-}H^T+K_k(Hp_k^-H^T+R)=0\\ K_k(Hp_k^-H^T+R)=p_k^{-}H^T\\ 最终得到K_k的表达式:\\ K_k=\frac{p_k^{-}H^T}{Hp_k^-H^T+R}------(3)\\ 这个就是大名鼎鼎的卡尔曼增益!!!! 求导可得如下:02(Hpk)T+2KkHpkHT+2KkR=0pkTHT+KkHpkHT+KkR=0pkTHT+Kk(HpkHT+R)=0协方差矩阵的转置是其本身,所以有如下:pkHT+Kk(HpkHT+R)=0Kk(HpkHT+R)=pkHT最终得到Kk的表达式:Kk=HpkHT+RpkHT(3)这个就是大名鼎鼎的卡尔曼增益!!!!

公式推导在这里算是结束了一大步了,依据公式(1)结合公式(3)可以分析出来,当 R R R很小时(观测噪声很小), K k K_k Kk H − 1 H^{-1} H1,带入(1)可得后验估计偏向于观测值。当 R R R很da时(观测噪声很大), K k K_k Kk 0 0 0,带入(1)可得后验估计偏向于预测值。这是符合我们的认知的。

其实我们现在一共已经有三个方程了(先验估计、后验估计、卡尔曼增益),现在只差误差协方差矩阵的推导就完成了整个卡尔曼滤波的推导了。这将会在下一节进行数学推导。胜利就在眼前!!!

4. 误差协方差矩阵的推导

首先我们回顾一下已经有的方程:

1. 系统状态方程 预测方程: x k = A x k − 1 + B u k + w k − 1 − − − − w ∼ p ( 0 , Q ) 观测方程: z k = H x k + v k − − − − v ∼ p ( 0 , R ) 1 . 系统状态方程\\ 预测方程:x_k=Ax_{k-1}+Bu_k+w_{k-1} ---- w\sim p(0,Q)\\ 观测方程:z_k=Hx_k+v_k ---- v\sim p(0,R)\\ 1.系统状态方程预测方程:xk=Axk1+Buk+wk1wp(0,Q)观测方程:zk=Hxk+vkvp(0,R)

2. 融合方程 先验估计: x ^ k − = A x ^ k − 1 + B u k 后验估计: x ^ k = x ^ k − + K k ( z k − H x ^ k − ) 卡尔曼增益: K k = p k − H T H p k − H T + R 2. 融合方程\\ 先验估计:\hat{x}^-_k=A\hat{x}_{k-1}+Bu_{k}\\ 后验估计:\hat{x}_k=\hat{x}^-_k+K_k(z_k-H\hat{x}^-_k)\\ 卡尔曼增益:K_k=\frac{p_k^{-}H^T}{Hp_k^-H^T+R} 2.融合方程先验估计:x^k=Ax^k1+Buk后验估计:x^k=x^k+Kk(zkHx^k)卡尔曼增益:Kk=HpkHT+RpkHT

可以看出融合方程这一步中只有 p k − p^-_k pk是未知的所以现在求 p k − p^-_k pk就可以完成整个卡尔曼滤波的公式:

p k − p^-_k pk是先验误差的协方差矩阵,下面开始推导先验误差的协方差矩阵的方程:

p k − = E [ e k − e k − T ] − − − − ( 4 ) 由上面的方程可以得到先验误差的方程为: e k − = x k − x ^ k − 将 x k , x ^ k − 带入方程可以得到如下: e k − = ( A x k − 1 + B u k + w k − 1 ) − ( A x ^ k − 1 + B u k ) e k − = A x k − 1 + B u k + w k − 1 − A x ^ k − 1 − B u k e k − = A x k − 1 + w k − 1 − A x ^ k − 1 e k − = A ( x k − 1 − x ^ k − 1 ) + w k − 1 其中 x k − 1 − x ^ k − 1 就是后验误差 e k − 1 ,所以可得: e k − = A e k − 1 + w k − 1 − − − ( 5 ) p^-_k=E[e^-_ke^{-T}_k]----(4)\\ 由上面的方程可以得到先验误差的方程为:\\ e^{-}_k=x_k-\hat{x}^-_k\\ 将x_k,\hat{x}^-_k带入方程可以得到如下:\\ e^-_k=(Ax_{k-1}+Bu_k+w_{k-1})-(A\hat{x}_{k-1}+Bu_{k})\\ e^-_k=Ax_{k-1}+Bu_k+w_{k-1}-A\hat{x}_{k-1}-Bu_{k}\\ e^-_k=Ax_{k-1}+w_{k-1}-A\hat{x}_{k-1}\\ e^-_k=A(x_{k-1}-\hat{x}_{k-1})+w_{k-1}\\ 其中x_{k-1}-\hat{x}_{k-1}就是后验误差e_{k-1},所以可得:\\ e^-_k=Ae_{k-1}+w_{k-1}---(5)\\ pk=E[ekekT]4由上面的方程可以得到先验误差的方程为:ek=xkx^kxkx^k带入方程可以得到如下:ek=(Axk1+Buk+wk1)(Ax^k1+Buk)ek=Axk1+Buk+wk1Ax^k1Bukek=Axk1+wk1Ax^k1ek=A(xk1x^k1)+wk1其中xk1x^k1就是后验误差ek1,所以可得:ek=Aek1+wk15

然后将方程( 5 )带入( 4 )中可以得到如下: p k − = E [ ( A e k − 1 + w k − 1 ) ( A e k − 1 + w k − 1 ) T ] 展开转置部分: p k − = E [ ( A e k − 1 + w k − 1 ) ( e k − 1 T A T + w k − 1 T ) ] 继续展开可得: p k − = E [ A e k − 1 e k − 1 T A T + A e k − 1 w k − 1 T + w k − 1 e k − 1 T A T + w k − 1 w k − 1 T ] p k − = E ( A e k − 1 e k − 1 T A T ) + E ( A e k − 1 w k − 1 T ) + E ( w k − 1 e k − 1 T A T ) + E ( w k − 1 w k − 1 T ) 分析第二部分 ( A e k − 1 w k − 1 T ) : 其中 e k − 1 和 w k − 1 相互独立(因为 e k − 1 = x k − 1 − x ^ k − 1 并且 x k − 1 只和 w k − 2 有关,所以 e k − 1 和 w k − 1 相互独立 ) 所以第二部分 ( A e k − 1 w k − 1 T ) 为 0 第三部分同理为 0 ,整理上式有: p k − = E ( A e k − 1 e k − 1 T A T ) + E ( w k − 1 w k − 1 T ) p k − = A E ( e k − 1 e k − 1 T ) A T + E ( w k − 1 w k − 1 T ) 由之前计算可得: E ( e k − 1 e k − 1 T ) 为后验误差的协方差矩阵,记为 p k − 1 : E ( w k − 1 w k − 1 T ) 为预测方程的噪声的协方差矩阵 Q 然后将方程(5)带入(4)中可以得到如下:\\ p^-_k=E[(Ae_{k-1}+w_{k-1})(Ae_{k-1}+w_{k-1})^T]\\ 展开转置部分:\\ p^-_k=E[(Ae_{k-1}+w_{k-1})(e_{k-1}^TA^T+w_{k-1}^T)]\\ 继续展开可得:\\ p^-_k=E[Ae_{k-1}e_{k-1}^TA^T+Ae_{k-1}w_{k-1}^T+w_{k-1}e_{k-1}^TA^T+w_{k-1}w_{k-1}^T]\\ p^-_k=E(Ae_{k-1}e_{k-1}^TA^T)+E(Ae_{k-1}w_{k-1}^T)+E(w_{k-1}e_{k-1}^TA^T)+E(w_{k-1}w_{k-1}^T)\\ 分析第二部分(Ae_{k-1}w_{k-1}^T):\\ 其中e_{k-1}和w_{k-1}相互独立(因为e_{k-1}=x_{k-1}-\hat{x}_{k-1}\\ 并且x_{k-1}只和w_{k-2}有关,所以e_{k-1}和w_{k-1}相互独立)\\ 所以第二部分(Ae_{k-1}w_{k-1}^T)为0\\ 第三部分同理为0,整理上式有:\\ p^-_k=E(Ae_{k-1}e_{k-1}^TA^T)+E(w_{k-1}w_{k-1}^T)\\ p^-_k=AE(e_{k-1}e_{k-1}^T)A^T+E(w_{k-1}w_{k-1}^T)\\ 由之前计算可得:\\ E(e_{k-1}e_{k-1}^T)为后验误差的协方差矩阵,记为p_{k-1}:\\ E(w_{k-1}w_{k-1}^T)为预测方程的噪声的协方差矩阵Q\\ 然后将方程(5)带入(4)中可以得到如下:pk=E[(Aek1+wk1)(Aek1+wk1)T]展开转置部分:pk=E[(Aek1+wk1)(ek1TAT+wk1T)]继续展开可得:pk=E[Aek1ek1TAT+Aek1wk1T+wk1ek1TAT+wk1wk1T]pk=E(Aek1ek1TAT)+E(Aek1wk1T)+E(wk1ek1TAT)+E(wk1wk1T)分析第二部分(Aek1wk1T)其中ek1wk1相互独立(因为ek1=xk1x^k1并且xk1只和wk2有关,所以ek1wk1相互独立)所以第二部分(Aek1wk1T)0第三部分同理为0,整理上式有:pk=E(Aek1ek1TAT)+E(wk1wk1T)pk=AE(ek1ek1T)AT+E(wk1wk1T)由之前计算可得:E(ek1ek1T)为后验误差的协方差矩阵,记为pk1E(wk1wk1T)为预测方程的噪声的协方差矩阵Q

总结以上计算可得,先验误差的协方差矩阵为: p k − = A p k − 1 A T + Q − − − − ( 6 ) 总结以上计算可得,先验误差的协方差矩阵为:\\ p^-_k=Ap_{k-1}A^T+Q----(6)\\ 总结以上计算可得,先验误差的协方差矩阵为:pk=Apk1AT+Q(6)

注意这里先验误差的协方差矩阵的计算方程中还有一个未知的东西就是 p k − 1 p_{k-1} pk1就是上一次的后验误差的协方差矩阵,接下来继续推导最后一个方程。

这里回忆一下好像之前我们推导过这个 p k − 1 往上翻我们找到方程( 7 ) p k = p k − − p k − H T K k T − K k H p k − + K k H p k − H T K k T + K k R K k T 我们进行变换: p k = p k − − p k − H T K k T − K k H p k − + K k ( H p k − H T + R ) K k T 然后将卡尔曼增益 K k 带入第三部分可得如下: p k = p k − − p k − H T K k T − K k H p k − + p k − H T H p k − H T + R ( H p k − H T + R ) K k T p k = p k − − p k − H T K k T − K k H p k − + p k − H T K k T 第二部分和最后一部分相同,抵消掉,得到如下: p k = p k − − K k H p k − p k = ( I − K k H ) p k − − − − − ( 8 ) 这就是完成了误差协方差的更新。 这里回忆一下好像之前我们推导过这个p_{k-1}\\ 往上翻我们找到方程(7)\\ p_k=p_k^--p_k^-H^TK_k^T-K_kHp_k^-+K_kHp_k^-H^TK_k^T+K_kRK_k^T\\ 我们进行变换:\\ p_k=p_k^--p_k^-H^TK_k^T-K_kHp_k^-+K_k(Hp_k^-H^T+R)K_k^T\\ 然后将卡尔曼增益K_k带入第三部分可得如下:\\ p_k=p_k^--p_k^-H^TK_k^T-K_kHp_k^-+\frac{p_k^{-}H^T}{Hp_k^-H^T+R}(Hp_k^-H^T+R)K_k^T\\ p_k=p_k^--p_k^-H^TK_k^T-K_kHp_k^-+p_k^{-}H^TK_k^T\\ 第二部分和最后一部分相同,抵消掉,得到如下:\\ p_k=p_k^--K_kHp_k^-\\ p_k=(I-K_kH)p_k^-----(8)\\ 这就是完成了误差协方差的更新。 这里回忆一下好像之前我们推导过这个pk1往上翻我们找到方程(7pk=pkpkHTKkTKkHpk+KkHpkHTKkT+KkRKkT我们进行变换:pk=pkpkHTKkTKkHpk+Kk(HpkHT+R)KkT然后将卡尔曼增益Kk带入第三部分可得如下:pk=pkpkHTKkTKkHpk+HpkHT+RpkHT(HpkHT+R)KkTpk=pkpkHTKkTKkHpk+pkHTKkT第二部分和最后一部分相同,抵消掉,得到如下:pk=pkKkHpkpk=(IKkH)pk8这就是完成了误差协方差的更新。

直到这一步我们将所有未知的东西都给出了计算方法,以上已经完成了整个卡尔曼滤波的数学推导。接下来进行一下总结。

5. 总结

1. 系统状态方程 预测方程: x k = A x k − 1 + B u k + w k − 1 − − − − w ∼ p ( 0 , Q ) 观测方程: z k = H x k + v k − − − − v ∼ p ( 0 , R ) 1 . 系统状态方程\\ 预测方程:x_k=Ax_{k-1}+Bu_k+w_{k-1} ---- w\sim p(0,Q)\\ 观测方程:z_k=Hx_k+v_k ---- v\sim p(0,R)\\ 1.系统状态方程预测方程:xk=Axk1+Buk+wk1wp(0,Q)观测方程:zk=Hxk+vkvp(0,R)

2. 融合方程 先验估计: x ^ k − = A x ^ k − 1 + B u k 后验估计: x ^ k = x ^ k − + K k ( z k − H x ^ k − ) 卡尔曼增益: K k = p k − H T H p k − H T + R 先验误差协方差: p k − = A p k − 1 A T + Q 更新误差协方差: p k = ( I − K k H ) p k − 2. 融合方程\\ 先验估计:\hat{x}^-_k=A\hat{x}_{k-1}+Bu_{k}\\ 后验估计:\hat{x}_k=\hat{x}^-_k+K_k(z_k-H\hat{x}^-_k)\\ 卡尔曼增益:K_k=\frac{p_k^{-}H^T}{Hp_k^-H^T+R}\\ 先验误差协方差:p^-_k=Ap_{k-1}A^T+Q\\ 更新误差协方差:p_k=(I-K_kH)p_k^-\\ 2.融合方程先验估计:x^k=Ax^k1+Buk后验估计:x^k=x^k+Kk(zkHx^k)卡尔曼增益:Kk=HpkHT+RpkHT先验误差协方差:pk=Apk1AT+Q更新误差协方差:pk=(IKkH)pk

将第二部分按照预测和矫正进行分列,可得如下两组卡尔曼滤波的方程(最终方程):

预测: 先验估计: x ^ k − = A x ^ k − 1 + B u k 先验误差协方差: p k − = A p k − 1 A T + Q 预测:\\ 先验估计:\hat{x}^-_k=A\hat{x}_{k-1}+Bu_{k}\\ 先验误差协方差:p^-_k=Ap_{k-1}A^T+Q\\ 预测:先验估计:x^k=Ax^k1+Buk先验误差协方差:pk=Apk1AT+Q

矫正: 卡尔曼增益: K k = p k − H T H p k − H T + R 后验估计: x ^ k = x ^ k − + K k ( z k − H x ^ k − ) 更新误差协方差: p k = ( I − K k H ) p k − 矫正:\\ 卡尔曼增益:K_k=\frac{p_k^{-}H^T}{Hp_k^-H^T+R}\\ 后验估计:\hat{x}_k=\hat{x}^-_k+K_k(z_k-H\hat{x}^-_k)\\ 更新误差协方差:p_k=(I-K_kH)p_k^-\\ 矫正:卡尔曼增益:Kk=HpkHT+RpkHT后验估计:x^k=x^k+Kk(zkHx^k)更新误差协方差:pk=(IKkH)pk

完结撒花!!!


代码实现

#include <cmath>
#include <random> // Need this for sampling from distributions
#include <vector>
#include <fstream>
#include <iostream>
#include <Eigen/Eigen>

using namespace std;

class kalman_filter
{
private:
	// -------------预测方程参数-------------
	// 状态转移矩阵,上一时刻的状态转移到当前时刻
	Eigen::Matrix2d A;
	// 控制输入矩阵B
	Eigen::Matrix2d B;
	// 过程噪声协方差矩阵Q,p(w)~N(0,Q),噪声来自真实世界中的不确定性
	Eigen::Matrix2d Q;

	// -------------观测方程参数-------------
	// 状态观测矩阵
	Eigen::Matrix2d H;
	// # 观测噪声协方差矩阵R,p(v)~N(0,R),噪声来自测量过程中的不确定性
	Eigen::Matrix2d R;

	// -------------系统变量-------------
	Eigen::Vector2d X0; // 初始位置与速度
	Eigen::Matrix2d P0; // 状态估计协方差矩阵P初始化
	Eigen::Vector2d X_true; // 真实状态
	Eigen::Vector2d X_Prior; // 先验估计
	Eigen::Vector2d X_posterior; // 后验估计
	Eigen::Matrix2d P_Prior; // 状态先验误差协方差矩阵P
	Eigen::Matrix2d P_posterior; // 状态后验误差协方差矩阵P
	Eigen::Vector2d Z_measure; // 观测值
	Eigen::Matrix2d K; // 卡尔曼增益
	Eigen::Matrix2d I; // 单位矩阵

	// -------------数据记录-------------
	std::vector<double> speed_true; // 真实记录
	std::vector<double> position_true;

	std::vector<double> speed_measure; // 测量记录
    std::vector<double> position_measure;

    std::vector<double> speed_prior_est; //先验估计
    std::vector<double> position_prior_est;

    std::vector<double> speed_posterior_est; // 后验估计
    std::vector<double> position_posterior_est;

public:
	kalman_filter(/* args */);
	~kalman_filter();
	void kalman_filter_demo();
	double gaussian_distribution_generator(double mu, double sigma);
};

kalman_filter::kalman_filter(/* args */) //初始化参数
{
	// 系统参数初始化
	A << 1,1,  0,1;
	B << 0,0,  0,0;
	Q << 0.1,0,  0,0.1;
	H << 1,0,  0,1;
	R << 1,0,  0,1;
	X0 << 0,1;
	P0 << 1,0,  0,1;
	I << 1,0, 0,1;

	X_true = X0;
	X_posterior = X0;
	P_posterior = P0;
}

kalman_filter::~kalman_filter()
{
}

double kalman_filter::gaussian_distribution_generator(double mu, double sigma)
{
	std::random_device rd{};
    std::mt19937 gen{rd()};
	std::normal_distribution<double> w{mu,sigma};
	return w(gen);
}

void kalman_filter::kalman_filter_demo()
{
	fstream f;
	f.open("../data.txt",ios::out);
	for(int i = 0; i < 30; i++)
	{
		// -----------------------生成真实值----------------------
		Eigen::Vector2d w;
		w << gaussian_distribution_generator(0,Q(0,0)),
			 gaussian_distribution_generator(0,Q(1,1));
		// 生成当前时刻状态的估计值(这里没有控制矩阵)
		X_true = A*X_true + w;
		position_true.push_back(X_true(0,0));
		speed_true.push_back(X_true(1,0));

		// -----------------------生成观测值----------------------
		Eigen::Vector2d v;
		v << gaussian_distribution_generator(0,R(0,0)),
			 gaussian_distribution_generator(0,R(1,1));
		// 生成当前时刻状态的测量值
		Z_measure = H*X_true + v;
		position_measure.push_back(Z_measure(0,0));
		speed_measure.push_back(Z_measure(1,0));

		// ----------------------以下开始进行卡尔曼滤波---------------------

		// ----------------------先验估计---------------------
		X_Prior = A*X_posterior;
		position_prior_est.push_back(X_Prior(0,0));
		speed_prior_est.push_back(X_Prior(1,0));

		// // ----------------------先验误差协方差---------------------
		P_Prior = (A*P_posterior)*A.transpose() + Q;

		// // ----------------------卡尔曼增益---------------------
		K = (P_Prior*H.transpose())*((H*P_Prior)*H.transpose()+R).inverse();

		// // ----------------------后验估计---------------------
		X_posterior = X_Prior + K*(Z_measure - H*X_Prior);
		position_posterior_est.push_back(X_posterior(0,0));
		speed_posterior_est.push_back(X_posterior(1,0));

		// // ----------------------后验估计---------------------
		P_posterior = (I - K*H)*P_Prior;

		// 保存到文件中
		f<< position_true.back() << " " << speed_true.back() << " "
		 << position_measure.back() << " " << speed_measure.back() << " "
		 << position_prior_est.back() << " " << speed_prior_est.back() << " "
		 << position_posterior_est.back() << " " << speed_posterior_est.back() << " "
		<<endl;
	}
	f.close();
}



int main(int argc, char **argv)
{
	kalman_filter kf;
	kf.kalman_filter_demo();
    return 0;
}

第一次写博客,希望给点建议。这算是一个个人学习笔记吧,主要是参考DR_CAN的视频,讲的非常好!!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值