卡尔曼滤波(Kalman filtering)小结

2024-06-03 22:38

本文主要是介绍卡尔曼滤波(Kalman filtering)小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近项目用到了kalman滤波,本博文简单介绍下卡尔曼滤波器的概念、原理和应用,做个小结。

概念

卡尔曼滤波(Kalman filtering)一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。由于观测数据中包括系统中的噪声和干扰的影响,所以最优估计也可看作是滤波过程。

斯坦利·施密特(Stanley Schmidt)首次实现了卡尔曼滤波器。卡尔曼在NASA埃姆斯研究中心访问时,发现他的方法对于解决阿波罗计划的轨道预测很有用,后来阿波罗飞船的导航电脑使用了这种滤波器。 关于这种滤波器的论文由Swerling (1958), Kalman (1960)与 Kalman and Bucy (1961)发表[1]。

卡尔曼滤波的一个典型实例是从一组有限的,包含噪声的,对物体位置的观察序列(可能有偏差)预测出物体的位置的坐标及速度。在很多工程应用(如雷达、计算机视觉)中都可以找到它的身影。同时,卡尔曼滤波也是控制理论以及控制系统工程中的一个重要课题[2]。

应用

例如,对于雷达来说,人们感兴趣的是其能够跟踪目标。但目标的位置、速度、加速度的测量值往往在任何时候都有噪声。卡尔曼滤波利用目标的动态信息,设法去掉噪声的影响,得到一个关于目标位置的好的估计。这个估计可以是对当前目标位置的估计(滤波),也可以是对于将来位置的估计(预测),也可以是对过去位置的估计(插值或平滑)。
扩展卡尔曼滤波(EXTEND KALMAN FILTER, EKF)是由kalman filter考虑时间非线性的动态系统,常应用于目标跟踪系统。

kalman滤波器

理论上,kalman滤波器需要三个重要假设:
1)被建模的系统是线性的;
2)影响测量的噪声属于白噪声;
3)噪声本质上是高斯分布的。
第一条假设是指k时刻的系统状态可以用某个矩阵与k-1时刻的系统状态的乘积表示。余下两条假设,即噪声是高斯分布的白噪声,其含义为噪声与时间不相关,且只用均值和协方差就可以准确地为幅值建模。

在kalman滤波器滤波器应用中,一般考虑三种运动:
1)动态运动:这种运动是我们期望的前次测量时系统状态的直接结果,如匀速运动等。
2)控制运动:这种运动是我们期望的,由于某种已知的外部因素以某种原因施加于系统,如加速运动等。
3)随机运动:随机的无规则运动,在Kalman滤波器中,至少是可以用高斯模型有效地来建模。

以下是两个重要方程:
状态方程:

xk=Axk1+Buk1+qk1

观测方程:
yk=Hxk+rk

上两式子中,x(k)是k时刻的系统状态,u(k)是k时刻对系统的控制量。A是传输参数、B是控制参数,都是系统参数,对于多模型系统,他们为矩阵。y(k)是k时刻的测量值,H是测量系统的参数,对于多测量系统,H为状态转移矩阵。q(k)和r(k)分别表示状态和测量的噪声。他们被假设成高斯白噪声,他们的协方差分别是Q,R(这里我们假设他们不随系统状态变化而变化)。

KF算法流程如下图:
1
这里的K是kalman增益矩阵。

五个重要更新公式:
时间更新:

x^k=Ax^k1+Buk1 (1)

上标”-“表示“在新的测量之前”,求出先验估计 x^k ;
Pk=APk1AT+Q (2)

这个等式构成预测部分的基础,这告诉我们根据已看到的“我们可以期望什么”;
状态更新:
Kk=PkHT(HPkHT+R)1 (3)

这里给出所谓的Kalman增益或更新率或混合比例,告诉我们如何给定新信息相对已知信息的权重,在直接测量一个位置变量的一维例子中,状态误差是 σ2k1 ,测量误差是 σ2k K=σ2k1σ2k1+σ2k
x^k=x^k+Kk(ykHx^k) (4)

Pk=(IKkH)Pk (5)

得到“新的测量之后”,就可以用更新率K对 x^kPk 做更新得到最优的更新值 x^kPk

举例

以测量在停车场行驶的汽车为实际例子,汽车的状态用两个位置变量 x y,以及两个速度变量 vx vy 表示。这四个变量组成状态向量 xk 的元素。 dt 表示速度增量。这里假设的是动态运动模型。

xk=[x y vx vy]T

A=10000100dt0100dt01

当使用摄像机观测汽车的状态时,可能只观测量到位置变量:
yk=[yxyy]

状态转移矩阵H结构如下:

H=10000100

在该例子中,可能并不真正认为汽车速度不变,所以要设置 Q 来反应这个问题。对视频流用图像分析方法来测量汽车的位置,再根据对测量精确度的估计来选择R
这些量初始化完成后,嵌入到kalman滤波的那些公式中,便可以进行汽车位置估计。

在项目中,用kalman跟踪物体质心运动,建模思路跟这个汽车例子类似,因为运动不是匀速存在偏差(状态误差),因为检测器检测到的目标的质心的位置存在偏差(观测误差),而这些偏差和设定会影响到kalman的跟踪效果。

OpenCV demo

#include "opencv2/video/tracking.hpp"
#include "opencv2/highgui/highgui.hpp"#include <stdio.h>using namespace cv;static inline Point calcPoint(Point2f center, double R, double angle)
{return center + Point2f((float)cos(angle), (float)-sin(angle))*(float)R;
}static void help()
{printf( "\nExamle of c calls to OpenCV's Kalman filter.\n"
"   Tracking of rotating point.\n"
"   Rotation speed is constant.\n"
"   Both state and measurements vectors are 1D (a point angle),\n"
"   Measurement is the real point angle + gaussian noise.\n"
"   The real and the estimated points are connected with yellow line segment,\n"
"   the real and the measured points are connected with red line segment.\n"
"   (if Kalman filter works correctly,\n"
"    the yellow segment should be shorter than the red one).\n""\n"
"   Pressing any key (except ESC) will reset the tracking with a different speed.\n"
"   Pressing ESC will stop the program.\n");
}int main(int, char**)
{help();Mat img(500, 500, CV_8UC3);KalmanFilter KF(2, 1, 0);Mat state(2, 1, CV_32F); /* (phi, delta_phi) */Mat processNoise(2, 1, CV_32F);Mat measurement = Mat::zeros(1, 1, CV_32F);char code = (char)-1;for(;;){randn( state, Scalar::all(0), Scalar::all(0.1) );KF.transitionMatrix = *(Mat_<float>(2, 2) << 1, 1, 0, 1);setIdentity(KF.measurementMatrix);setIdentity(KF.processNoiseCov, Scalar::all(1e-5));setIdentity(KF.measurementNoiseCov, Scalar::all(1e-1));setIdentity(KF.errorCovPost, Scalar::all(1));randn(KF.statePost, Scalar::all(0), Scalar::all(0.1));for(;;){Point2f center(img.cols*0.5f, img.rows*0.5f);float R = img.cols/3.f;double stateAngle = state.at<float>(0);Point statePt = calcPoint(center, R, stateAngle);Mat prediction = KF.predict();double predictAngle = prediction.at<float>(0);Point predictPt = calcPoint(center, R, predictAngle);randn( measurement, Scalar::all(0), Scalar::all(KF.measurementNoiseCov.at<float>(0)));// generate measurementmeasurement += KF.measurementMatrix*state;double measAngle = measurement.at<float>(0);Point measPt = calcPoint(center, R, measAngle);// plot points#define drawCross( center, color, d )                                 \line( img, Point( center.x - d, center.y - d ),                \Point( center.x + d, center.y + d ), color, 1, CV_AA, 0); \line( img, Point( center.x + d, center.y - d ),                \Point( center.x - d, center.y + d ), color, 1, CV_AA, 0 )img = Scalar::all(0);drawCross( statePt, Scalar(255,255,255), 3 );drawCross( measPt, Scalar(0,0,255), 3 );drawCross( predictPt, Scalar(0,255,0), 3 );line( img, statePt, measPt, Scalar(0,0,255), 3, CV_AA, 0 );line( img, statePt, predictPt, Scalar(0,255,255), 3, CV_AA, 0 );if(theRNG().uniform(0,4) != 0)KF.correct(measurement);randn( processNoise, Scalar(0), Scalar::all(sqrt(KF.processNoiseCov.at<float>(0, 0))));state = KF.transitionMatrix*state + processNoise;imshow( "Kalman", img );code = (char)waitKey(100);if( code > 0 )break;}if( code == 27 || code == 'q' || code == 'Q' )break;}return 0;
}

运行效果:
2

3

4

<script type="math/tex; mode=display" id="MathJax-Element-26"></script>
个人觉得,Kalman filter算法的核心是新旧信息融合即将先验知识与观测数据结合得到新的估计,作用就是用来对系统状态进行 预估+ 校正

原文链接:http://blog.csdn.net/u011285477/article/details/52070900

参考资料:
[1]卡尔曼滤波-百度百科
[2]对Kalman(卡尔曼)滤波器的理解-CSDN博客
[3]Kalman滤波器从原理到实现-CSDN博客
[4]《学习OpenCV(中文版)》于仕琪、刘瑞祯 译 清华大学出版社 P384

这篇关于卡尔曼滤波(Kalman filtering)小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1028314

相关文章

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

C#中Guid类使用小结

《C#中Guid类使用小结》本文主要介绍了C#中Guid类用于生成和操作128位的唯一标识符,用于数据库主键及分布式系统,支持通过NewGuid、Parse等方法生成,感兴趣的可以了解一下... 目录前言一、什么是 Guid二、生成 Guid1. 使用 Guid.NewGuid() 方法2. 从字符串创建

Redis分片集群、数据读写规则问题小结

《Redis分片集群、数据读写规则问题小结》本文介绍了Redis分片集群的原理,通过数据分片和哈希槽机制解决单机内存限制与写瓶颈问题,实现分布式存储和高并发处理,但存在通信开销大、维护复杂及对事务支持... 目录一、分片集群解android决的问题二、分片集群图解 分片集群特征如何解决的上述问题?(与哨兵模

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

Python函数返回多个值的多种方法小结

《Python函数返回多个值的多种方法小结》在Python中,函数通常用于封装一段代码,使其可以重复调用,有时,我们希望一个函数能够返回多个值,Python提供了几种不同的方法来实现这一点,需要的朋友... 目录一、使用元组(Tuple):二、使用列表(list)三、使用字典(Dictionary)四、 使