14 卡尔曼滤波及代码实现

news2024/11/22 20:30:02

文章目录

    • 14 卡尔曼滤波及代码实现
      • 14.0 基本概念
      • 14.1 公式推导
      • 14.2 代码实现

14 卡尔曼滤波及代码实现

14.0 基本概念

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

通俗来说就是,线性数学模型算出预测值+传感器测量值=更准确的测量值。根据数学模型,由第 k k k 时刻的值递推得到第 k + 1 k+1 k+1 时刻的预测值,结合第 k + 1 k+1 k+1 时刻的观测值,得到第 k + 1 k+1 k+1 时刻更精准的值。

在这里插入图片描述

卡尔曼滤波主要用于 线性高斯系统

14.1 公式推导

(1)线性高斯系统表达

状态方程:

x k = A x k − 1 + B u k + w k \boldsymbol{x}_k = \boldsymbol{A}\boldsymbol{x}_{k-1}+\boldsymbol{B}\boldsymbol{u}_k+\boldsymbol{w}_k xk=Axk1+Buk+wk

观测方程:

z k = H x k + v k \boldsymbol{z}_k = \boldsymbol{H}\boldsymbol{x}_k+\boldsymbol{v}_k zk=Hxk+vk

其中, x k \boldsymbol{x}_k xk 为状态量, z k \boldsymbol{z}_k zk 为观测量, A \boldsymbol{A} A 为状态转移矩阵, B k \boldsymbol{B}_k Bk 为控制输入矩阵, H \boldsymbol{H} H 为状态观测矩阵。

w k \boldsymbol{w}_k wk 是过程噪声,服从高斯分布, w k \boldsymbol{w}_k wk 是观测噪声,也服从高斯分布,即:

w k ∼ N ( 0 , Q ) \boldsymbol{w}_k \sim N(0, \boldsymbol{Q}) wkN(0,Q)

v k ∼ N ( 0 , R ) \boldsymbol{v}_k \sim N(0, \boldsymbol{R}) vkN(0,R)

其中 Q \boldsymbol{Q} Q 是过程噪声的协方差, R \boldsymbol{R} R 是观测噪声的协方差。

卡尔曼滤波包括预测和更新两步。

(2)预测(先验)

预测是根据上一时刻的状态量,由状态方程预测出下一时刻的状态量 x ^ k − \hat{\boldsymbol{x}}_k^{-} x^k ,以及状态量误差协方差的先验估计矩阵 P k − \boldsymbol{P}_k^{-} Pk。这是没有加观测值的。

x ^ k − = A x ^ k − 1 + B u k \hat{\boldsymbol{x}}_k^{-} = \boldsymbol{A}\hat{\boldsymbol{x}}_{k-1}+\boldsymbol{B}\boldsymbol{u}_k x^k=Ax^k1+Buk

P k − = A P k − 1 A T + Q \boldsymbol{P}_k^{-}=\boldsymbol{AP}_{k-1}\boldsymbol{A}^T+\boldsymbol{Q} Pk=APk1AT+Q

其中, A x ^ k − 1 \boldsymbol{A}\hat{\boldsymbol{x}}_{k-1} Ax^k1 是上一时刻的最优估计。

(3)更新(后验)

加入观测,对预测值进行更新校正,得到最优后验估计。

首先计算增益矩阵

K k = P k − H T ( H P k − H T + R ) − 1 \boldsymbol{K}_k=\boldsymbol{P}_k^{-}\boldsymbol{H}^T(\boldsymbol{H}\boldsymbol{P}_k^{-}\boldsymbol{H}^T+\boldsymbol{R})^{-1} Kk=PkHT(HPkHT+R)1

更新状态量及其协方差矩阵

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

P k = ( I − K k H ) P k − \boldsymbol{P}_k=(\boldsymbol{I}-\boldsymbol{K}_k\boldsymbol{H})\boldsymbol{P}_k^{-} Pk=(IKkH)Pk

在这里插入图片描述

14.2 代码实现

以雷达追踪目标为背景,系统的状态方程为

[ x y V x V y a x a y ] k + 1 = [ 1 0 δ t 0 0.5 δ t 2 0 0 1 0 δ t 0 0.5 δ t 2 0 0 1 0 δ t 0 1 0 0 1 0 δ t 0 0 0 0 1 0 0 0 0 1 0 1 ] [ x y V x V y a x a y ] k \begin{bmatrix}x\\y\\Vx\\Vy\\ax\\ay\end{bmatrix}_{k+1}=\begin{bmatrix}1&0&\delta_t&0&0.5\delta_t^2&0\\0&1&0&\delta_t&0&0.5\delta_t^2\\0&0&1&0&\delta_t&0\\1&0&0&1&0&\delta_t\\0&0&0&0&1&0\\0&0&0&1&0&1\end{bmatrix}\begin{bmatrix}x\\y\\Vx\\Vy\\ax\\ay\end{bmatrix}_k xyVxVyaxay k+1= 100100010000δt010000δt01010.5δt20δt01000.5δt20δt01 xyVxVyaxay k

观测方程

[ x y ] k + 1 = [ 1 0 0 0 0 0 0 1 0 0 0 0 ] [ x y V x V y a x a y ] k \begin{bmatrix}x\\y\end{bmatrix}_{k+1}=\begin{bmatrix}1&0&0&0&0&0\\0&1&0&0&0&0\end{bmatrix}\begin{bmatrix}x\\y\\Vx\\Vy\\ax\\ay\end{bmatrix}_k [xy]k+1=[100100000000] xyVxVyaxay k

/***********************************************************                                          *
* Time: 2023/11/26
* Author: xiaocong
* Function: 卡尔曼滤波
***********************************************************/
#ifndef KALMANFILTER_H
#define KALMANFILTER_H

#include <eigen3/Eigen/Dense>
#include <iostream>

using namespace Eigen;
using namespace std;

class KalmanFilter
{
public:
    KalmanFilter(int stateSize, int measSize, int uSize);               // 构造函数
    void init(VectorXd& x, MatrixXd& P, MatrixXd& R, MatrixXd& Q);      // 初始化
    void predict(MatrixXd& A);
    void predict(MatrixXd& A, MatrixXd& B, VectorXd& u);            // 重载,针对有控制输入的情况
    VectorXd update(MatrixXd& H, VectorXd z_meas);                      // 更新
    ~KalmanFilter();                                                    // 析构函数

private:
    VectorXd x_;         // 状态变量
    VectorXd z_;         // 观测变量
    MatrixXd A_;         // 状态转移矩阵
    MatrixXd B_;         // 控制矩阵
    VectorXd u_;         // 控制变量
    MatrixXd P_;         // 状态值的协方差矩阵
    MatrixXd H_;         // 观测矩阵
    MatrixXd R_;         // 观测噪声协方差矩阵
    MatrixXd Q_;         // 过程噪声协方差矩阵
};

#endif //KALMANFILTER_H
#include "../inlude/KalmanFilter.h"


// 构造函数
KalmanFilter::KalmanFilter(int stateSize, int measSize, int uSize)
{
    if (stateSize == 0 || measSize == 0)
    {
        std::cerr << "Error, State size and measurement size must bigger than 0" << endl;
    }

    x_.resize(stateSize);
    x_.setZero();

    A_.resize(stateSize, stateSize);
    A_.setIdentity();

    u_.resize(uSize);
    u_.setZero();

    B_.resize(stateSize, uSize);
    B_.setZero();

    P_.resize(stateSize, stateSize);
    P_.setIdentity();

    H_.resize(measSize, stateSize);
    H_.setZero();

    Q_.resize(stateSize, stateSize);
    Q_.setIdentity();

    R_.resize(measSize, measSize);
    R_.setIdentity();
}

void KalmanFilter::init(VectorXd& x, MatrixXd& P, MatrixXd& R, MatrixXd& Q)
{
    x_ = x;
    P_ = P;
    R_ = R;
    Q_ = Q;
}

void KalmanFilter::predict(MatrixXd& A)         // 没有控制输入u
{
    A_ = A;
    x_ = A * x_;
    P_ = A_ * P_ * A_.transpose() + Q_;
}

void KalmanFilter::predict(MatrixXd& A, MatrixXd& B, VectorXd& u)       // 有控制输入u
{
    A_ = A;
    B_ = B;
    u_ = u;
    x_ = A * x_ + B * u_;
    P_ = A_ * P_ * A_.transpose() + Q_;
}

VectorXd KalmanFilter::update(MatrixXd& H, VectorXd z_meas)      // 更新
{
    H_ = H;
    MatrixXd temp = H_ * P_ * H_.transpose() + R_;
    MatrixXd K = P_ * H_.transpose() * temp.inverse();
    x_ = x_ + K * (z_meas - H_ * x_);               // 更新 x_k
    MatrixXd I = MatrixXd::Identity(x_.rows(), x_.rows());
    P_ = (I - K * H_) * P_;
    return x_;
}

KalmanFilter::~KalmanFilter()
{

}
#include "../inlude/KalmanFilter.h"
#include <fstream>

#define N 1000
#define T 0.01

double data_x[N], data_y[N];

// 模型函数
double sample(double x0, double v0, double acc, double t)
{
    return x0 + v0 * t + 0.5 * acc * t * t;
}

double getRand()
{
    return 0.5 * rand() / RAND_MAX - 0.25;   //[-0.25, 0.25)
}


int main()
{
    ofstream fout;
    fout.open("../data/data.txt");

    // 生成观测值
    double t;
    for (int i = 0; i < N; i++)
    {
        t = T * i;
        data_x[i] = sample(0, -4.0, 0.1, t) + getRand();
        data_y[i] = sample(0.1, 2.0, 0, t) + getRand();
    }

    int stateSize = 6;
    int measSize = 2;
    int uSize = 0;
    KalmanFilter kf(stateSize, measSize, uSize);

    Eigen::MatrixXd A(stateSize, stateSize);
    A << 1, 0, T, 0, 1 / 2 * T * T, 0,
        0, 1, 0, T, 0, 1 / 2 * T * T,
        0, 0, 1, 0, T, 0,
        0, 0, 0, 1, 0, T,
        0, 0, 0, 0, 1, 0,
        0, 0, 0, 0, 0, 1;

    Eigen::MatrixXd B(0, 0);
    Eigen::MatrixXd H(measSize, stateSize);
    H << 1, 0, 0, 0, 0, 0,
        0, 1, 0, 0, 0, 0;

    Eigen::MatrixXd P(stateSize, stateSize);
    P.setIdentity();

    Eigen::MatrixXd R(measSize, measSize);
    R.setIdentity() * 0.01;

    Eigen::MatrixXd Q(stateSize, stateSize);
    Q.setIdentity() * 0.001;

    Eigen::VectorXd x(stateSize);
    Eigen::VectorXd u(0);
    Eigen::VectorXd z_meas(measSize);
    z_meas.setZero();

    Eigen::VectorXd res(stateSize);         // 存储预测结果

    for (int i = 0; i < N; i++)
    {
        if (i == 0)         // 初始值
        {
            x << data_x[i], data_y[i], 0, 0, 0, 0;
            kf.init(x, P, R, Q);
            continue;
        }

        kf.predict(A);                         // 预测
        z_meas << data_x[i], data_y[i];        // 观测
        res << kf.update(H, z_meas);           // 更新
        fout << data_x[i] << " " << data_y[i] << " " << res[0] << " " << res[1] << " " << res[2] << " " << res[3] << " " << res[4] << " " << res[5] << endl;
    }

    fout.close();
    return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1878192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统总结:AI产品经理知识体系

算法demo更偏向于命题作文&#xff0c;而在产品商业化的时候&#xff0c;关键的第一步就在于基于场景&#xff0c;去重新定义问题&#xff01; 近两年人工智能行业在国内外得到了爆发试的增长&#xff0c;各大巨头纷纷布局成立了自己的人工智能实验室和研究院&#xff0c;但是我…

已解决问题 | 该扩展程序未列在 Chrome 网上应用店中,并可能是在您不知情的情况下添加的

在Chrome浏览器中&#xff0c;如果你看到“该扩展程序未列在 Chrome 网上应用店中&#xff0c;并可能是在您不知情的情况下添加的”这样的提示&#xff0c;通常是因为该扩展程序没有通过Chrome网上应用店进行安装。以下是解决这个问题的步骤&#xff1a; 解决办法&#xff1a;…

携程二面测开—中核

4.12 35min面试经验 自我介绍 在面试的开始&#xff0c;我简洁明了地进行了自我介绍&#xff0c;突出了我的教育背景、技能特长以及实习经历&#xff0c;为后续的面试内容打下了良好的基础。 实习的具体工作内容 在谈及实习经历时&#xff0c;我详细阐述了在实习期间所承担…

Sparse4D v1

Sparse4D: Multi-view 3D Object Detection with Sparse Spatial-Temporal Fusion 单位&#xff1a;地平线 GitHub&#xff1a;https://github.com/HorizonRobotics/Sparse4D 论文&#xff1a;https://arxiv.org/abs/2211.10581 时间&#xff1a;2022-11 找博主项目讨论方…

在Qt中,直接include <moc_xxxxx.cpp> 为什么不会出现符号冲突的错误?

在逛Qt官方社区的时候看到这样一个帖子&#xff1a; https://forum.qt.io/topic/117973/how-does-include-moc_-cpp-work 大概的意思是moc_xxx.cpp如果已经被编译器编译&#xff0c;那么在另一个cpp文件中include同一个moc_xxx.cpp应该出现符号冲突才对&#xff0c;但是Qt却能正…

音频Balance源码总结

音频Balance源码总结 何为音频Balance&#xff1f; 顾名思义&#xff0c;Balance及平衡&#xff0c;平衡也就是涉及多方&#xff0c;音频左右甚至四通道&#xff0c;调节所有通道的音量比&#xff0c;使用户在空间内听到各个通道的音频大小不一&#xff0c;好似置身于真实环境…

高考落幕,暑期西北行,甘肃美食等你来尝

高考结束&#xff0c;暑期来临&#xff0c;西北之旅成为许多人的热门选择。而来到甘肃&#xff0c;除了领略壮丽的自然风光和深厚的历史文化&#xff0c;甘肃特产和传统面点以其独特的风味和传统的制作工艺也为游客们带来了一场地道的甘肃美食体验。 平凉的美食&#x…

成立近30年,它如何找到政企采购突破点?

回看中国采购行业的发展&#xff0c;大致可以被分为四个阶段&#xff1a;上世纪90年代的传统采购时代、本世纪初的ERP采购时代、近10年的SRM采购时代以及2018年以来开启的数字化采购时代。近年来&#xff0c;大数据、人工智能和物联网的高速发展&#xff0c;为采购信息化提供底…

读书笔记-Java并发编程的艺术-第3章(Java内存模型)-第6节(final域的内存语义)

文章目录 3.6 final域的内存语义3.6.1 final 域的重排序规则3.6.2 写final 域的重排序规则3.6.3 读final 域的重排序规则3.6.4 final 域为引用类型3.6.5 为什么 final 引用不能从构造函数内“逸出”3.6.6 final 语义在处理器中的实现3.6.7 JSR-133 为什么要增强final 的语义 3.…

[知识点篇]《计算机组成原理》之计算机系统概述

1.1 计算机发展历程 世界上第一台电子数字计算机 1946年&#xff0c;ENIAC(Electronic Numerical Integrator And Computer)在美国宾夕法尼亚大学研制成功。性能低&#xff0c;耗费巨大&#xff0c;但却是科学史上的一次划时代的创新&#xff0c;奠定了电子计算机的基础&#x…

大语言模型(LLM)LangChain介绍

LangChain是一个利用大语言模型的能力开发各种下游应用的开源框架&#xff0c;它的核心理念是为各种大语言模型应用实现通用的接口&#xff0c;简化大语言模型应用的开发难度&#xff0c;主要的模块示意图为&#xff1a; Index&#xff1a;提供了各类文档导入、文本拆分、文本向…

Java 生成随机数的方法例子

前言 在实际开发中产生随机数的例子也是很普遍的,所以在程序中设计产生随机数操作很重要&#xff0c;这篇文章主要给大家介绍了关于Java随机数的几种获得方法&#xff0c;具有一定的参考价值。 一、Random 类 Random 类是从 JDK 1.0开始&#xff0c;它产生的随机数是伪随机数…

UML建模笔记

5个视图 设计。类&#xff0c;接口&#xff0c;对象如何协作。实现。组件&#xff0c;运行程序&#xff0c;文档关系。用例。用户功能期望。进程。并发与同步相关进程&#xff0c;线程。部署。部署到计算机。 建模目的 和客户共创追踪需求变更协同开发进度控制持续迭代测试生…

【SGX系列教程】(四)Intel-SGX 官方示例分析(SampleCode)——LocalAttestation

文章目录 一.LocalAttestation原理介绍1.1本地认证原理1.2 本地认证基本流程1.3 本地认证核心原理 二.源码分析2.1 README2.1.1 编译流程2.1.2 执行流程&#xff08;双进程执行 or 单进程执行&#xff0c;在后面执行部分有展示效果&#xff09;2.1.3 如何获取已签名的Enclave的…

青岛网站建设一般多少钱

青岛网站建设的价格一般会根据网站的规模、功能、设计风格等因素来定&#xff0c;价格会存在着一定的差异。一般来说&#xff0c;一个简单的网站建设可能在数千元到一万元之间&#xff0c;而一个复杂的大型网站建设可能会需要数万元到数十万元不等。所以在选择网站建设服务时&a…

DAY17-力扣刷题

1.相同的树 100. 相同的树 - 力扣&#xff08;LeetCode&#xff09; 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 class Solution {public…

守护你的每一步:揭秘电子厂劳保鞋的秘密

在电子厂的繁忙车间里&#xff0c;工友们忙碌的身影中&#xff0c;你是否注意到那一双双看似普通的劳保鞋&#xff1f;它们不仅承载着工人们辛勤的汗水&#xff0c;更是守护他们每一步安全的重要装备。今天&#xff0c;就让我们一起揭秘电子厂劳保鞋的秘密&#xff0c;看看它们…

一站式企业服务平台能够帮助企业解决哪些问题?

近年来一站式企业服务平台备受区域政府及园区管理者的青睐&#xff0c;充当着区域政府或园区的千里眼和顺风耳&#xff0c;可以用来捕捉与区域经济发展相关的信息&#xff0c;也可以用来倾听企业的诉求&#xff0c;更是成为了区域深抓企业服务的多面手。 同时&#xff0c;一站式…

【漏洞复现】学分制系统GetTimeTableData SQL注入

0x01 产品简介 学分制系统由上海鹏达计算机系统开发有限公司研发&#xff0c;是基于对职业教育特点和需求的深入理解&#xff0c;结合教育部相关文件精神&#xff0c;并广泛吸纳专家、学者意见而开发的一款综合性管理系统。系统采用模块化的设计方法&#xff0c;方便学校根据自…

Java对应C++ STL的用法

sort&#xff1a; 1&#xff1a;java.util.Arrays中的静态方法Arrays.sort()方法&#xff0c;针对基本数据类型和引用对象类型的数组元素排序 2&#xff1a;java.util.Collections中的静态方法的Collections.sort()方法&#xff0c;针对集合框架中的动态数组&#xff0c;链表&…