卡尔曼滤波的理解以及参数调整、参数的意义、维度

一、前言

卡尔曼滤波器是一种最优线性状态估计方法(等价于“在最小均方误差准则下的最佳线性滤波器”),所谓状态估计就是通过数学方法寻求与观测数据最佳拟合的状态向量。

在移动机器人导航方面,卡尔曼滤波是最常用的状态估计方法。直观上来讲,卡尔曼滤波器在这里起了数据融合的作用,只需要输入当前的测量值(多个传感器数据)和上一个周期的估计值就能估计当前的状态,这个估计出来的当前状态综合考量了传感器数据(即所谓的观察值、测量值)和上一状态的数据,为当前最优估计,可以认为这个估计出来的值是最可靠的值。由于我们在SLAM中主要用它做位置估计,所以前面所谓的估计值就是估计位置坐标了,而输入的传感器数据包括码盘推算的位置、陀螺仪的角速度等(当然可以有多个陀螺仪和码盘),最后输出的最优估计用来作为机器人的当前位置被导航算法以外的其他程序所调用。

列举一下卡尔曼滤波的优点:采用递归方法解决线性滤波问题,只需要当前的测量值和前一个采样周期的估计值就能够进行状态估计,不需要大量的存储空间,每一步的计算量小,计算步骤清晰,非常适合计算机处理。

二、问题描述与定义

1、前提

首先明确卡尔曼滤波器的前提假设:

  • 信息过程的足够精确的模型,是由白噪声所激发的线性、离散和有限维动态系统(可以是时变的);
  • 每次测量信号都包含着附加的白噪声分量。

满足上述条件就可以使用卡尔曼滤波器。

2、问题描述

定义一个随机离散时间过程的状态向量 ,该过程用一个离散随机差分方程描述: 

xk=Axk1+Buk1+wk1

其中n维向量  xk 为k时刻的系统状态变量,n维向量 xk1  是k-1时刻的系统状态变量。A是状态转移矩阵或者过程增益矩阵,是 n×n  阶方阵,它将k-1时刻状态和当前的k时刻状态联系起来。B是可选的控制输入  uRl 的增益,在大多数实际情况下并没有控制增益,所以  Buk1 这一项很愉快的变成零了。  wk1 是n维向量,代表过程激励噪声,它对应了 xk  中每个分量的噪声,是期望为0,协方差为Q的高斯白噪声, wk ~ N(0,Q)  。 
再定义一个观测变量 ,得到观测方程: 
zk=Hxk+vk

其中观测值 zk 是m阶向量,状态变量 xk  是n阶向量。H是 m×n  阶矩阵,代表状态变量 xk  对测量变量  zk 的增益。观测噪声 vk  是期望为0,协方差为R的高斯白噪声, vk ~ N(0,R)  。

3、举例

如果对上面两个公式不太明白,我举一个例子说明: 
在目标跟踪的应用中,假设质点坐标为  (x,y) 是直接观测得到的,质点在x、y轴方向速度分别为 vx  、 vy ,那么系统状态变量  xk=(x,y,vx,vy)T ,系统观测变量  zk=(x¯,y¯)T  ,系统没有控制输入,所以状态方程就成了: 

xk=Axk1+wk1

它的状态转移矩阵A根据运动学公式确定: 
A=10000100Δt0100Δt01

其实用矩阵的形式写开上面的方程就很好理解了: 
xk=Axk1+wk1xyvxvyk=10000100Δt0100Δt01xyvxvyk1+wk1=x+Δtvxy+Δtvyvxvyk1+wk1

  • 这里简要说一下状态转移矩阵A的确定: 
    (1) 在标量卡尔曼滤波中,比如测量值是温度、湿度,一般认为下一个时刻该温度或者湿度维持不变,这种情况下状态转移矩阵通常就是标量1。 
    (2) 在导航和目标跟踪中卡尔曼滤波常被用来做位置估计,比如匀速直线运动(CV)和匀加速直线运动(CA): 
    ACV=100T10001,ACA=100T10T22T1

    在前面的举例中x,y方向上的运动就被微分近似为匀速直线运动。 
    (3) 若被估计的过程或观测变量与过程的关系是非线性的,此时不能够直接应用卡尔曼滤波(因为不满足上一节提到的卡尔曼滤波适用的前提必须是线性系统),这个时候扩展卡尔曼滤波(EKF)应运而生,它用雅克比矩阵将期望和方差线性化,从而将卡尔曼滤波扩展到非线性系统,但是EKF由于考虑了泰勒级数的展开,运算量大大增加。

该过程的观测方程为 

zk=Hxk+vk

它的观测矩阵H也是要指定的,它的目的是将m维的测量值转换到n维与状态变量相对应,由于直接观测的量是位置 zk=(x¯,y¯)T  ,我们只需要取状态变量的前两个元素就够了,所以H设计成如下: 
H=[10010000]

用矩阵形式写开就是 
zk=Hxk+vk[x¯y¯]k=[10010000]xyvxvy+vk=[xy]k+vk

  • 我再举一个简单例子: 
    一个运动目标的状态变量 xk=(x(k),x˙(k),x¨(k))T  ,其中第一项是目标在k时刻的位置,这里假设为一维坐标,第二项为k时刻的速度,第三项为k时刻的加速度,雷达仅能观测到目标的位置即 x(k)  ,那么它的状态转移矩阵就该设计成: 
    A=100Δt10Δt22Δt1

    它的观测矩阵就该设计成: 
    H=[100]

    到了这里怎么设计矩阵A和H应该有思路了吧。

三、算法流程

接下来就开始介绍卡尔曼滤波最核心的五个更新方程了

1、预测:

x^k¯=Ax^k1+Buk1

P^k¯=AP^k1AT+Q

2、更新:

x^k=x^k¯+Kk(zkHx^k¯)

Kk=P^k¯HTHP^k¯HT+R

P^k=(IKkH)P^k¯

先来解释一下公式中各个变量的含义: 
x^k¯ :表示k时刻先验状态估计值,这是算法根据前次迭代结果(就是上一次循环的后验估计值)做出的不可靠估计。

x^k x^k1 :分别表示k时刻、k-1时刻后验状态估计值,也就是要输出的该时刻最优估计值,这个值是卡尔曼滤波的结果。

A :表示状态转移矩阵,是 n×n  阶方阵,它是算法对状态变量进行预测的依据,状态转移矩阵如果不符合目标模型有可能导致滤波发散,它的确定请参看第二节中的举例。

B :表示可选的控制输入  uRl 的增益,在大多数实际情况下并没有控制增益。

uk1 :表示k-1时刻的控制增益,一般没有这个变量,可以设为0。

P^k¯ :表示k时刻的先验估计协方差,这个协方差矩阵只要确定了一开始的 P^0  ,后面都可以递推出来,而且初始协方差矩阵 P^0  只要不是为0,它的取值对滤波效果影响很小,都能很快收敛。

P^k P^k1 :分别表示k时刻、k-1时刻的后验估计协方差,是滤波结果之一。

Q :表示过程激励噪声的协方差,它是状态转移矩阵与实际过程之间的误差。这个矩阵是卡尔曼滤波中比较难确定的一个量,一般有两种思路:一是在某些稳定的过程可以假定它是固定的矩阵,通过寻找最优的Q值使滤波器获得更好的性能,这是调整滤波器参数的主要手段,Q一般是对角阵,且对角线上的值很小,便于快速收敛;二是在自适应卡尔曼滤波(AKF)中Q矩阵是随时间变化的。

Kk :表示卡尔曼增益,是滤波的中间结果。

zk :表示测量值,是m阶向量。

H :表示量测矩阵,是 m×n  阶矩阵,它把m维测量值转换到n维与状态变量相对应。

R :表示测量噪声协方差,它是一个数值,这是和仪器相关的一个特性,作为已知条件输入滤波器。需要注意的是这个值过大过小都会使滤波效果变差,且R取值越小收敛越快,所以可以通过实验手段寻找合适的R值再利用它进行真实的滤波。

四、算法实现

以下是一段卡尔曼滤波与平滑滤波的对

[plain]  view plain  copy
  1. clear  
  2. clc;  
  3. N=300;  
  4. CON = 25;%房间温度,假定温度是恒定的  
  5. %%%%%%%%%%%%%%%卡尔曼滤波%%%%%%%%%%%%%%%%%%%%%%  
  6. x = zeros(1,N);  
  7. y = 2^0.5 * randn(1,N) + CON;%加过程噪声的测量值  
  8.   
  9. x(1) = 1;  
  10. p = 10;  
  11.   
  12. Q = cov(randn(1,N));%过程噪声协方差  
  13. R = cov(randn(1,N));%观测噪声协方差  
  14. for k = 2 : N  
  15. x(k) = x(k - 1);%预估计k时刻状态变量的值  
  16. p = p + Q;%对应于预估值的协方差,由于状态变量是标量,状态转移矩阵A为数值1  
  17. kg = p / (p + R);%kalman gain  
  18. x(k) = x(k) + kg * (y(k) - x(k));  
  19. p = (1 - kg) * p;  
  20. end  
  21.   
  22.   
  23. %%%%%%%%%%%平滑滤波%%%%%%%%%%%%%%%%%%%%%%%%  
  24.   
  25. Filter_Wid = 10;  
  26. smooth_res = zeros(1,N);  
  27. for i = Filter_Wid + 1 : N  
  28. tempsum = 0;  
  29. for j = i - Filter_Wid : i - 1  
  30. tempsum = tempsum + y(j);  
  31. end  
  32. smooth_res(i) = tempsum / Filter_Wid;  
  33. end  
  34. % figure(1);  
  35. % hist(y);  
  36. t=1:N;  
  37. figure(1);  
  38. expValue = zeros(1,N);  
  39. for i = 1: N  
  40. expValue(i) = CON;  
  41. end  
  42. plot(t,expValue,'r',t,x,'g',t,y,'b',t,smooth_res,'k');  
  43. legend('real temperature','kalman result','measured value','smooth result');  
  44. axis([0 N 20 30])  
  45. xlabel('Sample Time');  
  46. ylabel('Room Temperature');  
  47. title('Smooth Filter VS Kalman Filter');  
[plain]  view plain  copy
  1. 结果如下图:   

这里写图片描述

五、引用

[1] 王学斌, 徐建宏, 张章. 卡尔曼滤波器参数分析与应用方法研究[J]. 计算机应用与软件, 2012, 29(6):212-215.

转载自:http://blog.csdn.net/u013453604/article/details/50301477


还有一篇写的挺好的:

中文版:http://blog.csdn.net/lybaihu/article/details/54943545

英文版:http://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/

这里还有一个有程序的,有助于理解。

http://blog.csdn.net/gdfsg/article/details/50904811

本来感觉已经理解了,但是看完opencv自带的例程之后又懵逼了。。。

有一段是这样写的

[cpp]  view plain  copy
  1. static void help()  
  2. {  
  3.     printf("\nExamle of c calls to OpenCV's Kalman filter.\n"  
  4.         "   Tracking of rotating point.\n"  
  5.         "   Rotation speed is constant.\n"  
  6.         "   Both state and measurements vectors are 1D (a point angle),\n"  
  7.         "   Measurement is the real point angle + gaussian noise.\n"  
  8.         "   The real and the estimated points are connected with yellow line segment,\n"  
  9.         "   the real and the measured points are connected with red line segment.\n"  
  10.         "   (if Kalman filter works correctly,\n"  
  11.         "    the yellow segment should be shorter than the red one).\n"  
  12.         "\n"  
  13.         "   Pressing any key (except ESC) will reset the tracking with a different speed.\n"  
  14.         "   Pressing ESC will stop the program.\n"  
  15.         );  
  16. }  

黄线是预测点(estimated points)与真实值得连线,红线是加了噪声的观测值(measured points)与真实值的连线。

我认为预测点和观测值是用于高斯融合求最优估计值的啊,他们两个都有噪声的,为什么去拿两个都有噪声的进行比较呢?而且黄线比红线段就是正常?





这里贴点opencv源码以便参考。

[cpp]  view plain  copy
  1. /* 
  2. standard Kalman filter (in G. Welch' and G. Bishop's notation): 
  3.  
  4.   x(k)=A*x(k-1)+B*u(k)+w(k)  p(w)~N(0,Q) 
  5.   z(k)=H*x(k)+v(k),   p(v)~N(0,R) 
  6. */  
  7. typedef struct CvKalman  
  8. {  
  9.     int MP;                     /* number of measurement vector dimensions */  
  10.     int DP;                     /* number of state vector dimensions */  
  11.     int CP;                     /* number of control vector dimensions */  
  12.   
  13.     /* backward compatibility fields */  
  14. #if 1  
  15.     float* PosterState;         /* =state_pre->data.fl */  
  16.     float* PriorState;          /* =state_post->data.fl */  
  17.     float* DynamMatr;           /* =transition_matrix->data.fl */  
  18.     float* MeasurementMatr;     /* =measurement_matrix->data.fl */  
  19.     float* MNCovariance;        /* =measurement_noise_cov->data.fl */  
  20.     float* PNCovariance;        /* =process_noise_cov->data.fl */  
  21.     float* KalmGainMatr;        /* =gain->data.fl */  
  22.     float* PriorErrorCovariance;/* =error_cov_pre->data.fl */  
  23.     float* PosterErrorCovariance;/* =error_cov_post->data.fl */  
  24.     float* Temp1;               /* temp1->data.fl */  
  25.     float* Temp2;               /* temp2->data.fl */  
  26. #endif  
  27.   
  28.     CvMat* state_pre;           /* predicted state (x'(k)): 
  29.                                     x(k)=A*x(k-1)+B*u(k) */  
  30.     CvMat* state_post;          /* corrected state (x(k)): 
  31.                                     x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) */  
  32.     CvMat* transition_matrix;   /* state transition matrix (A) */  
  33.     CvMat* control_matrix;      /* control matrix (B) 
  34.                                    (it is not used if there is no control)*/  
  35.     CvMat* measurement_matrix;  /* measurement matrix (H) */  
  36.     CvMat* process_noise_cov;   /* process noise covariance matrix (Q) */  
  37.     CvMat* measurement_noise_cov; /* measurement noise covariance matrix (R) */  
  38.     CvMat* error_cov_pre;       /* priori error estimate covariance matrix (P'(k)): 
  39.                                     P'(k)=A*P(k-1)*At + Q)*/  
  40.     CvMat* gain;                /* Kalman gain matrix (K(k)): 
  41.                                     K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)*/  
  42.     CvMat* error_cov_post;      /* posteriori error estimate covariance matrix (P(k)): 
  43.                                     P(k)=(I-K(k)*H)*P'(k) */  
  44.     CvMat* temp1;               /* temporary matrices */  
  45.     CvMat* temp2;  
  46.     CvMat* temp3;  
  47.     CvMat* temp4;  
  48.     CvMat* temp5;  
  49. } CvKalman;  
  50.   
  51. /* Creates Kalman filter and sets A, B, Q, R and state to some initial values */  
  52. CVAPI(CvKalman*) cvCreateKalman( int dynam_params, int measure_params,  
  53.                                  int control_params CV_DEFAULT(0));  
  54.   
  55. /* Releases Kalman filter state */  
  56. CVAPI(void)  cvReleaseKalman( CvKalman** kalman);  
  57.   
  58. /* Updates Kalman filter by time (predicts future state of the system) */  
  59. CVAPI(const CvMat*)  cvKalmanPredict( CvKalman* kalman,  
  60.                                       const CvMat* control CV_DEFAULT(NULL));  
  61.   
  62. /* Updates Kalman filter by measurement 
  63.    (corrects state of the system and internal matrices) */  
  64. CVAPI(const CvMat*)  cvKalmanCorrect( CvKalman* kalman, const CvMat* measurement );  

[cpp]  view plain  copy
  1. CV_IMPL const CvMat*  
  2. cvKalmanPredict( CvKalman* kalman, const CvMat* control )  
  3. {  
  4.     if( !kalman )  
  5.         CV_Error( CV_StsNullPtr, "" );  
  6.   
  7.     /* update the state */  
  8.     /* x'(k) = A*x(k) */  
  9.     cvMatMulAdd( kalman->transition_matrix, kalman->state_post, 0, kalman->state_pre );  
  10.   
  11.     if( control && kalman->CP > 0 )  
  12.         /* x'(k) = x'(k) + B*u(k) */  
  13.         cvMatMulAdd( kalman->control_matrix, control, kalman->state_pre, kalman->state_pre );  
  14.   
  15.     /* update error covariance matrices */  
  16.     /* temp1 = A*P(k) */  
  17.     cvMatMulAdd( kalman->transition_matrix, kalman->error_cov_post, 0, kalman->temp1 );  
  18.   
  19.     /* P'(k) = temp1*At + Q */  
  20.     cvGEMM( kalman->temp1, kalman->transition_matrix, 1, kalman->process_noise_cov, 1,  
  21.                      kalman->error_cov_pre, CV_GEMM_B_T );  
  22.   
  23.     /* handle the case when there will be measurement before the next predict */  
  24.     cvCopy(kalman->state_pre, kalman->state_post);  
  25.   
  26.     return kalman->state_pre;  
  27. }  
  28.   
  29.   
  30. CV_IMPL const CvMat*  
  31. cvKalmanCorrect( CvKalman* kalman, const CvMat* measurement )  
  32. {  
  33.     if( !kalman || !measurement )  
  34.         CV_Error( CV_StsNullPtr, "" );  
  35.   
  36.     /* temp2 = H*P'(k) */  
  37.     cvMatMulAdd( kalman->measurement_matrix, kalman->error_cov_pre, 0, kalman->temp2 );  
  38.     /* temp3 = temp2*Ht + R */  
  39.     cvGEMM( kalman->temp2, kalman->measurement_matrix, 1,  
  40.             kalman->measurement_noise_cov, 1, kalman->temp3, CV_GEMM_B_T );  
  41.   
  42.     /* temp4 = inv(temp3)*temp2 = Kt(k) */  
  43.     cvSolve( kalman->temp3, kalman->temp2, kalman->temp4, CV_SVD );  
  44.   
  45.     /* K(k) */  
  46.     cvTranspose( kalman->temp4, kalman->gain );  
  47.   
  48.     /* temp5 = z(k) - H*x'(k) */  
  49.     cvGEMM( kalman->measurement_matrix, kalman->state_pre, -1, measurement, 1, kalman->temp5 );  
  50.   
  51.     /* x(k) = x'(k) + K(k)*temp5 */  
  52.     cvMatMulAdd( kalman->gain, kalman->temp5, kalman->state_pre, kalman->state_post );  
  53.   
  54.     /* P(k) = P'(k) - K(k)*temp2 */  
  55.     cvGEMM( kalman->gain, kalman->temp2, -1, kalman->error_cov_pre, 1,  
  56.                      kalman->error_cov_post, 0 );  
  57.   
  58.     return kalman->state_post;  
  59. }  

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 卡尔曼滤波参数辨识是指通过使用卡尔曼滤波算法来估计系统中的参数。而MATLAB是一种常用的科学计算软件,提供了丰富的工具箱来支持卡尔曼滤波的实现。 在MATLAB中,CSDN是一个知识分享平台,用户可以在上面找到很多关于MATLAB和卡尔曼滤波等方面的教程和案例。 使用MATLAB进行卡尔曼滤波参数辨识,可以按照以下步骤进行: 1. 收集系统数据:首先,通过实验或观测收集系统的输入和输出数据。 2. 设置滤波算法:使用MATLAB中的卡尔曼滤波工具箱,设置滤波算法的相关参数,如初始状态估计、系统的状态转移方程和测量方程等。 3. 实施参数辨识:根据采集的系统数据和已知的观测模型,使用MATLAB的参数辨识工具箱来估计系统中的参数。 4. 运行滤波算法:根据辨识出的参数,使用MATLAB的卡尔曼滤波工具箱对系统的输入和输出数据进行滤波处理。 5. 分析结果:根据滤波结果,可以通过MATLAB的数据可视化工具箱,对滤波后的数据进行分析和展示,以评估滤波效果和参数辨识的准确性。 通过这些步骤,使用MATLAB进行卡尔曼滤波参数辨识可以很好地实现系统状态的估计和滤波处理,从而改善系统的观测和控制效果。在CSDN上可以找到相关的MATLAB教程和案例,提供了更多的细节和实例,有助于更好地理解和应用卡尔曼滤波参数辨识。 ### 回答2: 卡尔曼滤波是一种常用的估计和预测系统状态的方法,其中的参数辨识是指根据已有的观测数据来估计卡尔曼滤波模型中的协方差矩阵和噪声功率谱密度。在MATLAB中,可以使用CSDN(Covariance Steady-state Discal Normalization)方法来进行卡尔曼滤波参数的辨识。 CSDN是一种基于协方差矩阵的正规化方法,通过对协方差矩阵进行正规化,可以达到最佳的辨识效果。使用MATLAB实现CSDN方法时,可以按照以下步骤进行: 1. 收集实际系统的观测数据,并在MATLAB中导入这些数据。 2. 定义卡尔曼滤波模型的状态空间方程和观测方程,并初始化模型的初始状态和初始协方差矩阵。 3. 根据观测数据,使用卡尔曼滤波算法对系统的状态进行估计和预测。 4. 在滤波过程中,使用CSDN方法对协方差矩阵进行正规化。具体而言,CSDN方法通过求解特征值分解和奇异值分解,来获得正规化的协方差矩阵。 5. 根据CSDN方法得到的正规化的协方差矩阵,可以进一步估计和优化系统参数。根据实际情况,可以使用不同的参数优化方法,如最小二乘法或最大似然法。 6. 最后,可以通过比较实际观测数据和卡尔曼滤波估计的状态,来验证和评估模型的辨识效果。如果模型的辨识效果较好,则可以应用到类似的实际系统中。 总的来说,使用MATLAB和CSDN方法进行卡尔曼滤波参数的辨识,可以帮助我们更好地估计和预测系统的状态,提高系统的性能和准确性。 ### 回答3: 卡尔曼滤波是一种常用的信号处理和状态估计方法,它通过对系统的状态和观测值进行统计推断,对系统状态进行滤波和预测。卡尔曼滤波的关键是对系统的状态方程和观测方程进行描述和参数辨识。 在Matlab中使用卡尔曼滤波进行参数辨识,可以借助matlab自带的kalman函数进行操作。首先,需要对具体系统的状态方程和观测方程进行描述并确定初始状态及噪声方差。然后,使用kalman函数进行参数辨识。 具体步骤如下: 1. 确定系统的状态方程和观测方程。状态方程描述了系统状态的演进规律,而观测方程描述了观测值与状态之间的关系。 2. 设置初始状态和误差协方差矩阵。初始状态是指系统在初始时刻的状态,误差协方差矩阵描述了状态估计的不确定性。 3. 通过kalman函数进行参数辨识。具体参数包括系统的状态转移矩阵、观测矩阵、状态噪声协方差矩阵、观测噪声协方差矩阵等。 4. 根据kalman函数的输出结果进行状态估计和滤波。 需要注意的是,在使用kalman函数时,需要根据具体问题调整参数和矩阵的维度以便与系统相匹配。另外,kalman函数返回的结果包含估计状态和误差协方差矩阵,可以根据需要进行后续处理和分析。 以上就是使用Matlab进行卡尔曼滤波参数辨识的简单步骤和操作,希望对您有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值