滤波算法(四)—— 卡尔曼滤波算法

2023-05-16

一、算法介绍

        卡尔曼滤波是一个神奇的滤波算法,应用非常广泛,它是一种结合先验经验、测量更新的状态估计算法。

1、状态估计

        首先,对于一个我们关心的物理量,我们假设它符合下面的规律

x_{k}=ax_{k-1}

其中,x_{k}为该物理量本周期的实际值,x_{k-1}为该物理量上一个周期的实际值,当然这个物理量可能不符合这个规律,我们只是做了一个假设。不同的物理量符合的规律不同,是我们的经验,我们根据这个规律可以预测我们关心的物理量。比如,我们关心的物理量是车速,如果车辆接近匀速运动时,则a的取值为1,也就是这个周期与上个周期的速度相同。

        下面我们再来看一下这个物理量的测量公式

z_{k}=x_{k}+v_{k}

其中,z_{k}是这个物理量的测量值,v_{k}是测量噪声。我们对一个物理进行预测,测量是一个必不可少的手段,虽然测量的不一定准,但是在很大程度上体现了物理量的实际值。这个公式体现的就是实际值与测量值的关系。还是以车速为例,z_{k}是通过车速传感器得到的测量值。

        实际中,物理量一般不会像我们上面的公式那样简单,一般我们用下面的公式来表示

x_{k}=ax_{k-1}+bu_{k}

其中,bu_{k} 代表了处理噪声,这个噪声是处理模型与实际情况的差异,比如车速,他会受到人为加速、减速、路面不平等外界因素的影响。

        卡尔曼滤波的基本思想是综合利用上一次的状态和测量值来对物理量的状态进行预测估计。我们用\hat{x_{k}}来表示x_{k}的估计值,则有下面的公式

\hat{x}_{k}=\hat{x}_{k-1}+g_{k}\left ( z_{k}-\hat{x}_{k-1} \right )

在这个公式中,综合利用了上一个周期的估计值和这个周期的测量值来对x_{k}进行估计。其中,g_{k}叫做卡尔曼增益,这个公式与一阶滤波很相似,只不过卡尔曼增益是会变的,每个周期都会更新,一阶滤波的系数则是固定值。考虑极端的情况来分析增益的作用,当g_{k}=0时,增益为0,这时\hat{x}_{k}=\hat{x}_{k-1},这表示我们这个周期的估计值与上个周期是相同的,不信任当前的测量值;当g_{k}=1时,增益为1,这时\hat{x}_{k}=z_{k},这表示我们这个周期的估计值与测量值是相同的,不信任上个周期的估计值,在实际应用时,g_{k}介于0~1之间,它代表了对测量值的信任程度。

2、卡尔曼增益

        上面我们通过卡尔曼增益来估计物理量的值,那卡尔曼增益又是如何取值的呢?我们通过下面两个公式来计算并在每个周期进行迭代更新。

g_{k}=p_{k-1}/\left ( p_{k-1}+r \right )

p_{k}=\left ( 1-g_{k} \right )p_{k-1}

在上述公式中,r是测量噪声v_{k}的平均值,测量噪声是符合高斯分布的,一般可以从传感器厂商那里获得测量噪声的均值,如果无法获得可以根据采集到的数据给出一个经验值。r的大小对最终滤波效果的影响是比较大的。p_{k} 为本周期的预测误差。我们采用分析卡尔曼增益的方法来分析预测误差的作用,即采用假设极端情况的方法。假设前一次的预测误差p_{k-1}=0,根据第一个公式则g_{k}=0,根据上面的分析,这种情况估计值为上个周期的估计值;如果前一次的预测误差p_{k-1}=1,则增益变为1/\left ( 1+r \right ),一般r取值很小,所以g_{k}\approx 1,这种情况以新测量的值作为估计值。

        对于第二个公式,当卡尔曼增益为0时,p_{k}=p_{k-1},即采用上一个周期的预测误差;当增益为1时,p_{k}=0

3、完整卡尔曼滤波算法

        有了上面的推导,我们在下面列出来完成卡尔曼滤波的公式,卡尔曼滤波分为预测过程和更新过程两个过程,在公式中,我们又引入了缩放系数h,和协方差q

预测过程:

\hat{x}_{k}=a\hat{x}_{k-1}+bu_{k}

p_{k}=ap_{k-1}a+q

更新过程:

g_{k}=p_{k}h/\left ( hp_{k}h+r \right )

\hat{x}_{k}=\hat{x}_{k}+g_{k}\left ( z_{k}-h\hat{x}_{k} \right )

p_{k}=\left ( 1-g_{k}h \right )p_{k}

        上面的公式适合一维变量的卡尔曼滤波,将变量扩展到多维,用向量和矩阵替换上面的变量,就可以实现多维变量的卡尔曼滤波,下面的公式适用于多维变量。

预测过程:

\hat{x}_{k}=A\hat{x}_{k-1}+Bu_{k}

P_{k}=AP_{k-1}A^{T}+Q

更新过程:

G_{k}=P_{k}H^{T}\left ( HP_{k}H^{T}+R \right )^{-1}

\hat{x}_{k}=\hat{x}_{k}+G_{k}\left ( z_{k}-H\hat{x}_{k} \right )

P_{k}=\left ( 1-G_{k}H \right )P_{k}

二、实现代码

        下面我们通过c++代码来实现卡尔曼滤波算法,所实现的算法为一维滤波算法。首先定义卡尔曼滤波的参数

typedef struct{
    float filterValue;//滤波后的值
    float kalmanGain;//Kalamn增益
    float A;//状态矩阵
    float H;//观测矩阵
    float Q;//状态矩阵的方差
    float R;//观测矩阵的方差
    float P;//预测误差
    float B;
    float u;
}KalmanInfo;

下面是卡尔曼滤波器的初始化函数,在这个函数中,info为卡尔曼滤波参数的指针。初始化的参数是针对一个车速滤波过程的设置。

void Kalm::initKalmanFilter(KalmanInfo *info)
{
    info->A = 1;
    info->H = 1;
    info->P = 0.1;
    info->Q = 0.05;
    info->R = 0.1;
    info->B = 0.1;
    info->u = 0;
    info->filterValue = 0;
}

卡尔曼滤波过程函数,函数的输入info为卡尔曼滤波参数的指针,new_value为新的测量值,函数返回滤波后的估计值。

float Kalm::kalmanFilterFun(KalmanInfo *info, float new_value)
{
    float predictValue = info->A*info->filterValue+info->B*info->u;//计算预测值
    info->P = info->A*info->A*info->P + info->Q;//求协方差
    info->kalmanGain = info->P * info->H /(info->P * info->H * info->H + info->R);//计算卡尔曼增益
    info->filterValue = predictValue + (new_value - predictValue)*info->kalmanGain;//计算输出的值
    info->P = (1 - info->kalmanGain* info->H)*info->P;//更新协方差
    return info->filterValue;
}

三、示例

        下面我们通过是一个车速滤波的示例来体验卡尔曼滤波的效果。通过上面的介绍,R对滤波效果的影响比较大,在这个示例中,我们分别将R取为0.1和0.5,来看一下车速的滤波效果。首先R取为0.1时,滤波效果如下图所示。其中,蓝色线为滤波前的车速,红色线为滤波后的车速。从图中可以看到滤波后的信号与滤波前的信号跟随很好,滞后很小。基本波动被滤掉了,但也带入了一些波动。

下图为R取为0.5时的滤波效果,很明显,这张图信号的跟随效果比上图要差,滞后也多,但是滤波后曲线更平滑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

滤波算法(四)—— 卡尔曼滤波算法 的相关文章

随机推荐

  • C/C++笔记-写一个Makefile并链接QtCore库使用QString,QDebug

    如下cpp代码 xff0c 调用QDebug打印程序 xff1a include lt QDebug gt include lt QString gt int main int argc char argv QString testStr
  • C/C++笔记-分析带有Q_OBJECT继承QObject的类make流程

    此篇博文记录到个笔记时间2023 02 15 xff0c 发表到网上的时间是2023 05 03 这里以Qt5 5 1为例 xff0c 操作系统是centos 7 5版本 代码如下 xff1a MOCQtConsole pro QT 43
  • C/C++笔记-构造makefile使用MOC程序及编译,链接

    背景是这样的构造一个Test类 xff0c 使用了Q OBJECT宏 xff0c 和继承了QObject xff0c 也就是元对象 xff0c 这时 xff0c makefile需要如何写 如下代码 xff1a Test h ifndef
  • C++20新特性个人总结

    目录 1 关键字 1 1 concept 1 2 requires 1 3 typename 1 4 explicit 1 5 constexpr 1 6 char8 t 1 7 consteval 1 8 co await co yiel
  • MySQL | MySQL为什么建议不要使用视图

    MySQL为什么建议不要使用视图 一 什么是视图二 为什么不建议使用视图 一 什么是视图 官方定义 xff1a 视图是指计算机数据库中的视图 xff0c 是一个虚拟表 xff0c 其内容由查询定义 同真实的表一样 xff0c 视图包含一系列
  • 【数据标准】学院数据集标准规范-1.6-元数据XML

    XML概述 XML 基础教育教学资源元数据的数据模型定义了一个层次结构的概念模型 xff0c 层次结构的模型可以方便地表示包含许多元素和子元素的数据 XML非常适合表示层次结构的模型 XML文档就是层次结构的 xff0c 它由元素组成 xf
  • Python-音频处理之wav文件与十进制pcm文件的相互转换

    一 pcm转wav 1 pcm文件以十进制的格式保存 xff0c 因此读取pcm的txt文件时不用 rb 来读取 2 适用于写单通道wav文件 xff0c 多通道需要对数据进行reshape操作 import wave import str
  • webapp打包为Android的apk包的一种方法

    开发了个纯web的app小demo 想着最终集成到微信公众号上做个小功能 xff0c 并测试下如何跨平台的运行在Android上 关于如何打包为Android的安装包 xff0c 总结了下其中的一种方法 xff0c 使用cordova打包为
  • 滤波算法(二)—— 中位值滤波算法

    1 算法介绍 中位值滤波算法的实现方法是采集N个周期的数据 xff0c 去掉N个周期数据中的最大值和最小值 xff0c 取剩下的数据的平均值 中位值滤波算法特别适用于会偶然出现异常值的系统 中位值滤波算法应用比较广泛 xff0c 比如用于一
  • C++可变参数使用总结

    可变参数是指函数可以接受不定数量的参数 比如在printf函数 xff0c 如果做日志等功能也会用到 这里总结下可变参数的使用 c语言中的可变参数 先介绍下在c语言中的使用 xff0c c语言也支持可变参数 xff0c 只是需要借助下va
  • 替代notepad++,notepad--介绍及插件cmake编译

    Notepad 43 43 是一个文本编辑器小软件 xff0c 用来替代windows自带的记事本 然而Notepad 43 43 软件的作者太霸道 xff0c 如果你不赞同他的观点 xff0c Notepad 43 43 将会在你的源码里
  • [环境搭建] onlyoffice环境搭建(docker-compose)

    只介绍环境搭建 不介绍集成 一 环境要求 内核 xff1a Linux 操作系统 xff1a centos 或者 ubuntu 容器环境 xff1a docker 容器镜像 xff1a onlyoffice documentserver 二
  • WSL:系统迁移【WSL默认安装在C盘,可以将虚拟机移到任意位置】

    因为虚拟机 xff08 Ubuntu22 04 xff09 默认安装在C盘 xff0c 大量占用系统盘的空间 xff0c 所以迁移到其他盘中 查看安装的虚拟机 wsl l v 关闭所有正在运行的虚拟机 wsl shutdown 对需要迁移的
  • Microsoft 365 Copilot怎么安装,如何下载?

    Microsoft 365 Copilot是一款基于人工智能的数字助手 xff0c 旨在帮助Microsoft 365商业版的用户更轻松地管理其工作流程 它可以提供实时反馈 自动生成报告 优化时间表以及自动化办公任务等功能 xff0c 这些
  • 关于Sublime Text4 _4126

    目录 前言 一 下载安装 下载安装 二 汉化 Install PackageChineseLocalzations 三 激活 进入hexed网站编辑编辑改码另存为 四 运行 successfully 总结 前言 怕以后忘了 xff0c 上操
  • CSDN编写技巧--CSDN中高亮显示代码

    介绍一种好的格式如下 xff1a 实现的方法就是以原代码的形式显示页面 xff0c 然后复制以下代码 xff1a lt div style 61 34 BORDER BOTTOM cccccc 1px dashed BORDER LEFT
  • 去掉jOSN中的转义符

    json返回全都是带 39 39 的 于是要去掉这个反斜杠 但是OC里面的 39 39 是转义符 不能直接用 64 34 34 之类的表示 一顿搜索之后 找到了OC对转义字符的表示方法 如下 a Sound alert b 退格 f For
  • 微软 Win11 一个命令安装 Windows Linux 子系统(WSL)

    在最新的 Windows 11操作系统中 xff0c 你只需运行 wsl exe install 就可以安装运行 WSL 所需的一切 使用 wsl install 微软表示 xff0c 以前设置 WSL 的过程过于复杂 xff0c 涉及到开
  • linux服务器xrdp远程链接密码对了却password failed解决方法

    linux服务器xrdp远程链接密码对了却password failed解决方法 遇到问题问题定位解决参考链接 遇到问题 在win10下用自带的远程连接登陆服务器 xff0c 明明密码对了 xff0c 却无法登陆 xff0c 显示 pass
  • 滤波算法(四)—— 卡尔曼滤波算法

    一 算法介绍 卡尔曼滤波是一个神奇的滤波算法 xff0c 应用非常广泛 xff0c 它是一种结合先验经验 测量更新的状态估计算法 1 状态估计 首先 xff0c 对于一个我们关心的物理量 xff0c 我们假设它符合下面的规律 其中 xff0