卡尔曼滤波(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

相关文章

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Flutter打包APK的几种方式小结

《Flutter打包APK的几种方式小结》Flutter打包不同于RN,Flutter可以在AndroidStudio里编写Flutter代码并最终打包为APK,本篇主要阐述涉及到的几种打包方式,通... 目录前言1. android原生打包APK方式2. Flutter通过原生工程打包方式3. Futte

Docker镜像pull失败两种解决办法小结

《Docker镜像pull失败两种解决办法小结》有时候我们在拉取Docker镜像的过程中会遇到一些问题,:本文主要介绍Docker镜像pull失败两种解决办法的相关资料,文中通过代码介绍的非常详细... 目录docker 镜像 pull 失败解决办法1DrQwWCocker 镜像 pull 失败解决方法2总

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Ollama Python 使用小结

《OllamaPython使用小结》Ollama提供了PythonSDK,使得开发者能够在Python环境中轻松集成和使用本地运行的模型进行自然语言处理任务,具有一定的参考价值,感兴趣的可以了解一... 目录安装 python SDK启动本地服务使用 Ollama 的 Python SDK 进行推理自定义客

java String.join()的使用小结

《javaString.join()的使用小结》String.join()是Java8引入的一个实用方法,用于将多个字符串按照指定分隔符连接成一个字符串,本文主要介绍了javaString.join... 目录1. 方法定义2. 基本用法2.1 拼接多个字符串2.2 拼接集合中的字符串3. 使用场景和示例3

Qt 中 isHidden 和 isVisible 的区别与使用小结

《Qt中isHidden和isVisible的区别与使用小结》Qt中的isHidden()和isVisible()方法都用于查询组件显示或隐藏状态,然而,它们有很大的区别,了解它们对于正确操... 目录1. 基础概念2. 区别清见3. 实际案例4. 注意事项5. 总结1. 基础概念Qt 中的 isHidd

SQL中的CASE WHEN用法小结

《SQL中的CASEWHEN用法小结》文章详细介绍了SQL中的CASEWHEN函数及其用法,包括简单CASEWHEN和CASEWHEN条件表达式两种形式,并通过多个实际场景展示了如何使用CASEWH... 目录一、简单CASE WHEN函数:二、CASE WHEN条件表达式函数三、常用场景场景1:不同状态展