扩展卡尔曼滤波算法 EKF

2023-05-16

扩展卡尔曼滤波的仿真案例,参考书为北航宇航学院王可东老师的Kalman滤波基础及Matlab仿真
一、状态模型:
在这里插入图片描述
二、测量模型:
在这里插入图片描述
状态方程和测量方程中的噪声均为期望为零的白噪声。
三、状态模型和测量模型的线性化(Jacobian矩阵):
在这里插入图片描述
四、状态模型和测量模型的噪声矩阵及初始状态及协方差矩阵:
在这里插入图片描述
五、C++ 仿真源码:
EKF.h

#pragma once
#include <fstream>     
#include <string>   
#include <iostream>
#include <Eigen/Dense>
#include "RandomGenerate.h"

class EKF
{
public:
	EKF();
	virtual ~EKF();
	void Filter();      // 扩展卡尔曼滤波主函数

private:
	void Initialize();             // 初始化相关参数
	void GenerateXreal(int k);     // 生成状态向量真实值
	void GenerateZreal();          // 生成测量向量值
	
	Eigen::Vector2d Nonlinearf(int k);                                                          // 非线性状态方程(非线性映射)
	Eigen::Matrix2d JacobianMatrixF();                                                          // 计算状态方程雅可比矩阵(线性化矩阵)
	void Prediction(const Eigen::Vector2d& f, const Eigen::Matrix2d& F);                        // 一步预测
	Eigen::Vector2d Nonlinearh();                                                               // 非线性测量方程
	Eigen::Matrix2d JacobianMatrixH();                                                          // 计算测量方程雅可比矩阵(线性化矩阵)
	void Update(const Eigen::Vector2d& h, const Eigen::Matrix2d& H);                            // 测量更新

private:
	Eigen::Vector2d xpre;          // 状态向量预测值

	Eigen::Matrix2d Ppre;          // 状态协方差矩阵预测值

	Eigen::Matrix2d Q;             // 状态方程噪声矩阵

	Eigen::Matrix2d R;             // 测量方程噪声矩阵

	Eigen::Matrix2d K;             // 卡尔曼增益矩阵

	Eigen::Vector2d xest;          // 状态向量估计值

	Eigen::Matrix2d Pest;          // 状态协方差矩阵估计值

	Eigen::Vector2d xreal;         // 状态向量真实值

	Eigen::Vector2d zreal;         // 测量向量值

private:
	std::string FileName;          // 文件名

	std::ofstream outFile;         // 文件路径
};

EKF.cpp

#include "EKF.h"

// 构造函数
EKF::EKF() : FileName("./FilterEKF.txt"), outFile(FileName, std::ios::out)
{
	// 初始化相关参数
	Initialize();
}

// 析构函数
EKF::~EKF()
{

}

// 初始化相关参数
void EKF::Initialize()
{
	// 初始化状态方程噪声矩阵
	Q << 0.01, 0,
		 0, 0.1;

	// 初始化测量方程噪声矩阵
	R << 1, 0,
		 0, 0.1;

	// 初始化状态协方差矩阵估计值
	Pest << 10, 0,
			0, 10;

	// 初始化状态向量估计值
	xest << 1, 1;

	// 真实值
	xreal = xest;

	return;
}

// 生成状态向量真实值
void EKF::GenerateXreal(int k)
{
	xreal(0) = xreal(1) * sin(xreal(0)) + 0.1 * k + sqrt(Q(0,0)) * getRandom();
	xreal(1) = xreal(0) + cos(xreal(1)) * cos(xreal(1)) - 0.1 * k + sqrt(Q(1, 1)) * getRandom();

	return;
}

// 生成测量向量值
void EKF::GenerateZreal()
{
	zreal(0) = xreal.norm() + sqrt(R(0, 0)) * getRandom();;
	zreal(1) = atan(xreal(0) / xreal(1)) + sqrt(R(1, 1)) * getRandom();

	return;
}

// 非线性状态方程(非线性映射)
Eigen::Vector2d EKF::Nonlinearf(int k)
{
	Eigen::Vector2d f;
	f(0) = xest(1) * sin(xest(0)) + 0.1 * k;
	f(1) = xest(0) + cos(xest(1)) * cos(xest(1)) - 0.1 * k;
	return f;
}

// 计算状态方程雅可比矩阵(线性化矩阵)
Eigen::Matrix2d EKF::JacobianMatrixF()
{
	Eigen::Matrix2d F;
	F(0, 0) = xest(1) * cos(xest(0));
	F(0, 1) = sin(xest(0));
	F(1, 0) = 1.0;
	F(1, 1) = -sin(2*xest(1));
	return F;
}

// 一步预测
void EKF::Prediction(const Eigen::Vector2d &f, const Eigen::Matrix2d &F)
{
	// 状态向量预测值
	xpre = f;

	Eigen::Matrix2d Pxx = F * Pest * F.transpose();

	// 状态协方差矩阵预测值
	Ppre = Pxx + Q;

	return;
}

// 非线性测量方程
Eigen::Vector2d EKF::Nonlinearh()
{
	Eigen::Vector2d h;
	h(0) = xpre.norm();
	h(1) = atan(xpre(0) / xpre(1));
	return h;
}

// 计算测量方程雅可比矩阵(线性化矩阵)
Eigen::Matrix2d EKF::JacobianMatrixH()
{
	Eigen::Matrix2d H;
	double a = xpre.norm();
	H(0, 0) = xpre(0) / a;
	H(0, 1) = xpre(1) / a;
	H(1, 0) = xpre(1) / (a * a);
	H(1, 1) = -xpre(0) / (a * a);
	return H;
}

// 测量更新
void EKF::Update(const Eigen::Vector2d& h, const Eigen::Matrix2d& H)
{
	Eigen::Matrix2d Pzz = H * Ppre * H.transpose();
	Eigen::Matrix2d Pvv = Pzz + R;
	Eigen::Matrix2d Pxz = Ppre * H.transpose();

	K = Pxz * Pvv.inverse();
	xest = xpre + (K * (zreal - h));
	Pest = Ppre - (K * Pvv * K.transpose());
	return;
}

// 扩展卡尔曼滤波主函数
void EKF::Filter()
{
	std::cout << "请输入采样点个数:" << std::endl;
	int num;
	std::cin >> num;

	for (int i = 0; i != num; i++)
	{
		// 生成状态向量真实值
		GenerateXreal(i);

		// 生成测量向量值
		GenerateZreal();

		// 非线性状态方程(非线性映射)
		Eigen::Vector2d f = Nonlinearf(i);

		// 计算状态方程雅可比矩阵(线性化矩阵)
		Eigen::Matrix2d F = JacobianMatrixF();

		// 一步预测
		Prediction(f, F);

		// 非线性测量方程
		Eigen::Vector2d h = Nonlinearh();

		// 计算测量方程雅可比矩阵(线性化矩阵)
		Eigen::Matrix2d H = JacobianMatrixH();

		// 测量更新
		Update(h, H);

		// 保存到文件
		outFile << xreal(0) << ", " << xreal(1) << ", " << xest(0) << ", " << xest(1) << ", " << xpre(0) << ", " << xpre(1) << std::endl;

		// 输出到控制台
		//std::cout<< i <<":  " << abs(xreal(0)-xest(0)) << ", " << abs(xreal(1) - xest(1)) << std::endl;
	}
	return;
}

demo.cpp

#include "UKF.h"
#include "EKF.h"

int main()
{
	UKF ukf;
	//ukf.Filter();

	EKF ekf;
	ekf.Filter();

	system("pause");
	return 0;
}

六、仿真结果:

%% 测试 C++ 程序的可行性。
clear;
clc;

%% 读入C++数据
x = dlmread('Filter.txt');
n = length(x(:,1));
t = 1 : n;

%% 状态
figure;
plot(t, x(:,1), '*-');
hold on;
plot(t, x(:,2), 'o-');
legend('real1','real2');
title('状态');
xlabel('时间/s');
grid on;

%% 状态1
figure;
plot(t, x(:,1), 's-', t, x(:,3), 'o-', t, x(:,5),'*-');
legend('real1','est1','pre1');
title('状态1');
xlabel('时间/s');
grid on;

%% 状态2
figure;
plot(t, x(:,2), 's-', t, x(:,4), 'o-', t, x(:,6),'*-');
legend('real2','est2','pre2');
title('状态2');
xlabel('时间/s');
grid on;

%% 状态1误差
figure;
plot(t, x(:,1)-x(:,3), 'o-', t, x(:,1)-x(:,5),'*-');
legend('est1','pre1');
title('状态1误差');
xlabel('时间/s');
grid on;

%% 状态2误差
figure;
plot(t, x(:,2)-x(:,4), 'o-', t, x(:,2)-x(:,6),'*-');
legend('est2','pre2');
title('状态2误差');
xlabel('时间/s');
grid on;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由图 1、图 2 可知,这两个状态虽然是非线性的,但是其总体趋势都呈线性变化,即非线性程度较弱,因此采用 EKF 滤波算法有望实现较好的估计结果;由图 3、图4 来看,EKF 滤波效果较好,对状态 1 和状态 2 均能很好的估计,滤波误差较小,且滤波(估计)的精度比预测的精度高。

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

扩展卡尔曼滤波算法 EKF 的相关文章

  • 滤波学习理解----EKF(一)

    最近回到slam方向了 xff0c 所以有时间整理一下最近的收获 最复杂也是最简单的模块 滤波 引入 那么滤波是什么呢 xff1f 滤波就是由于观测observation xff08 OB xff09 天生具备的误差和噪声 当有多个信号源观
  • EKF之雅克比矩阵(一)

    扩展卡尔曼滤波 EKF EKF之雅克比矩阵 文章目录 扩展卡尔曼滤波 EKF 前言一 什么是线性化 xff1f 二 雅克比矩阵1 矩阵的几何含义2 非线性矩阵与基底的关系3 雅克比矩阵 三 工程中雅克比矩阵如何应用总结 前言 一般的卡尔曼滤
  • CDKF、UKF和EKF滤波算法

    转载自 xff1a https mp weixin qq com s umv72zAB i3luzyIvXpvYw CDKF UKF和EKF滤波算法 凌拓智能TBUS TBUS社区 今天 之前一直和大家探讨在TSLAM室内定位算法中 xff
  • 任何的卡尔曼滤波器的研究都要紧紧围绕状态与方差的传播特性。 让我想起MSCKF是误差状态的EKF模型。

    任何的卡尔曼滤波器的研究都要紧紧围绕状态与方差的传播特性 让我想起MSCKF是误差状态的EKF模型 传播特性应该就是指预测方差或者递推方程 xff1f https blog csdn net sinat 16643223 article d
  • PX4 EKF模块解读含matlab代码

    这里主要介绍px4里面的定位模块 xff0c 即EKF库 1 状态向量与协方差的预测 1 Px4的状态向量为24维 xff0c 其如下所示 xff1a x 61
  • PX4 EKF中的多传感器融合方法

    文章目录 1 滤波方法及状态预测1 1 EKF 滤波方程1 2 KF 滤波方程1 3 PX4中的状态量及其预测1 3 1 状态量1 3 2 姿态四元数一步预测1 3 3 速度 位置一步预测1 3 4 协方差阵预测 2 磁三轴数据融合2 1
  • PX4利用matlab推导生成 EKF中雅可比矩阵的方法

    文章目录 一 Matlab的Symbolic Maths Toolbox是什么二 PX4 EKF中需要的雅可比矩阵三 Matlab脚本解析参考来源 PX4实际使用了Matlab的Symbolic Maths Toolbox来进行雅可比矩阵的
  • px4 EKF中Q、R阵设置的思考

    关于Q R的讨论 Q阵 xff0c 状态转移误差矩阵 xff0c 代表从Xt 1到Xt过程中 xff0c 状态转移和真实过程之间的误差 xff0c 具体其中变量可能是对状态转移有影响的变量 xff0c 比如在有一些场景下 xff0c 可能为
  • ros入门(六)--imu融合里程计robot_pose_ekf扩展卡尔曼融合包

    IMU 一般具有两个基本器件 xff1a 加速计和陀螺仪 主要用于测量自身位姿 xff0c 位姿包括位置和姿态 最近在研究imu 融合里程计方面的内容 xff0c 初学一些内容 xff0c 总结一下 xff1a 环境信息 xff1a Ubu
  • 扩展卡尔曼滤波(EKF)

    本篇文章是看完http blog csdn net adamshan article details 78265754这篇文章后再加上自己的理解写的 xff0c 如果侵权可以联系我删除 xff0c 如果有不对的地方请您不啬赐教 xff01
  • EKF SLAM Matlab仿真实践详解(附源码)

    EKF SLAM Matlab仿真实践详解 xff08 附源码 xff09 为提供更好的阅读体验 xff0c 详细内容及源码请移步https github com Nrusher EKF SLAM 或 https gitee com nru
  • (11)EKF - (1.3) EKF1调参参数

    系列文章目录 11 EKF 1 导航综述和调参 文章目录 系列文章目录 前言 3 1 AHRS EKF USE 3 2 EKF ABIAS PNOISE
  • (11)EKF - (2.7) EKF2调参参数

    系列文章目录 11 EKF 2 EKF2估算系统 文章目录 系列文章目录 前言 7 1 EK2 ENABLE
  • Pixhawk之姿态解算篇(5)_ECF/EKF/GD介绍

    一 开篇 很久没更新blog了 xff0c 最近研究的东西比较杂乱 xff0c 也整理了很多东西 xff0c 没有来的及更新 xff0c 最近发现很多小伙伴都开始写blog了 xff0c 在不更新就要 被落后了 兄弟们 xff0c 等等我啊
  • EKF SLAM 以及MSCKF 学习

    参考 xff1a https zhuanlan zhihu com p 21381490 https citeseerx ist psu edu viewdoc download jsessionid 61 FA1024834F74311E
  • PX4_ECL_EKF代码分析2

    写在前面 源码版本 xff1a 1 6 0rc1 源码位置1 xff1a Firmware 1 6 0rc1 src modules ekf2 main cpp 源码位置2 xff1a Firmware 1 6 0rc1 src lib e
  • 寻找APM中EKF的五大公式

    EKF核心代码位置 AP NavEKF2 cpp 进入该函数 进入该函数 xff0c 然后可以看到关键部分 xff0c 也即卡尔曼五个公式的地方 下面介绍每个公式的具体位置 28状态值 首先要知道选用的状态值有哪些 xff0c 28状态值
  • 控制算法学习 四、扩展卡尔曼滤波EKF

    控制算法学习 四 扩展卡尔曼滤波EKF 前言非线性系统状态 观测方程线性化扩展卡尔曼滤波EKF后记 前言 经典卡尔曼滤波的使用场景是线性系统 xff0c 但现实应用时 xff0c 大多数系统都是非线性的 扩展卡尔曼滤波 xff08 Exte
  • EKF SLAM

    EKF 方法是解决 SLAM 问题的一种经典方法 xff0c 其应用依赖于运动模型和观测模型的高斯噪声假设 在 SLAM 问题首次提出不久后 xff0c Smith 和 Cheesman 及 Durrant Whyte对机器人和路标间的几何
  • (1)robot_pose_ekf扩展卡尔曼滤波功能包的使用方法

    这里写自定义目录标题 robot pose ekf功能包的编译安装如何使用机器人姿势EKF 编译运行robot pose ekf订阅的话题发布的话题机器人姿态ekf如何工作参考文章 robot pose ekf功能包的编译安装 ros wi

随机推荐

  • 数据库习题及答案5

    模拟测验1 一 1 2 3 4 5 6 7 8 9 10 A D C c D A C A A C 一 选择题 xff08 在每个小题四个备选答案中选出一个正确答案 xff0c 填在题末的括号中 xff09 xff08 本大题共10小题 xf
  • Attention Model(mechanism) 的 套路

    最近刷了一些attention相关的paper 照着here的列表 43 自己搜的paper xff0c 网上相关的资料也有很多 xff0c 在此只讲一讲自己对于attention的理解 xff0c 力求做到简洁明了 一 attention
  • springMVC常用注解

    在java框架中 xff0c 使用注解的作用就是注入属性 一 Spring常用注解 64 Component xff1a 标注一个普通的Spring Bean类 64 Controller xff1a 标注一个控制器组件类 64 Servi
  • Ubuntu16.04运行.sh文件

    前言 xff1a 最近在学 Linux内核分析 xff0c 实验做的是哈工大的oslab Linux 0 11 xff0c 然后下载了相应的压缩包 解压之后发现需要运行setup sh文件 xff0c 原先以为是因为没有切换到root命令所
  • 服务器conda,pip命令用不了解决方法

    服务器创建用户后 xff0c 不知道为啥基本命令可以用 xff0c 但是conda xff0c pip等不能使用 xff0c 度娘后一行命令解决 xff0c 命令如下 source span class token operator spa
  • Base64资源

    Base64资源 在线转Base64工具 http www jsons cn img2base64 鲸鱼 maskImage src 61 39 data image png base64 iVBORw0KGgoAAAANSUhEUgAAA
  • Linux驱动开发

    本文为一个简单的字符设备驱动 xff0c 涉及驱动编写 测试程序编写 Makefile编写 驱动加载 卸载 xff0c 运行于Linux虚拟机 xff0c 不涉及底层配置 撰写本文的主要目的为记录一下驱动的开发流程 xff0c 参考了正点原
  • SpringBoot MVC配置

    SpringBoot MVC配置 在使用 SpringBoot 进行实际的项目开发前 xff0c 最后再了解一下 SpringBoot 中对于 MVC 的配置 xff01 仍对应 SpringBoot 03 Web 项目 1 MVC配置简介
  • Python常用的运算符

    1 算术运算符 xff1a 43 xff1a 加法 xff1a 减法 xff1a 乘法 xff1a 除法 xff1a 求两个数的余数 例如 xff1a 10 3 输出为1 xff1a 整除 例如 xff1a 10 3 输出为3 xff1a
  • npm报错 TypeError [ERR_INVALID_ARG_TYPE]: The “path“ argument must be of type string.Received undefine

    npm报错 TypeError ERR INVALID ARG TYPE The path argument must be of type string Received undefined 解决办法 xff1a 1 修改static文件
  • 持之以恒(一)位姿转换:姿态 / 四元数 / 旋转矩阵 / 欧拉角 及 位姿矩阵

    文章目录 1 简介1 1 位姿的几种表示形式1 2 姿态转换在线工具 2 位姿转换接口2 1 旋转向量 转 四元数2 2 四元数 转 旋转向量2 3 四元数 与 旋转矩阵 3 机器人相关应用3 1 不同厂家协作机器人的位姿表示形式 1 简介
  • 在pgsql中利用regexp_matches提取出正则并且用, 分隔开。

    在pgsql中利用regexp matches提取出正则并且用 xff0c 分隔开 span class token keyword SELECT span string agg span class token punctuation s
  • 推荐系统经典论文文献及业界应用

    Survey方面的文章及资料 Adomavicius G Tuzhilin A Toward the next generation of recommender systems A survey of the state of the a
  • TIOBE 编程语言排行,各个语言优缺点,以及你适合那种编程语言

    TIOBE 编程语言排行前10中 xff0c 各个编程语言的优缺点如下 xff1a Python 优点 xff1a 易学易用 xff0c 具有大量的第三方库和工具支持 xff0c 适用于数据分析 人工智能等领域 缺点 xff1a 运行速度相
  • ssh整合

    ssh整合 思路pom依赖几大框架的配置文件配置struts xml测试 思路 SSH是 struts 43 spring 43 hibernate的一个集成框架 1 导入所需要的pom依赖 2 几大框架的配置文件 xff08 web xm
  • JavaFX程序入门

    JavaFX程序入门 一 JavaFX基本概念 JavaFX的图形用户界面 xff08 GUI xff09 通常称为场景图 xff0c 场景图是构建JavaFX应用程序的起点 场景图除了包括布局面板 UI控件 图像 媒体 图表等 xff0c
  • 二叉树4:二叉树求树高度(超级详细)

    一 思路 什么是树高 xff1f 树的高度 或深度 就是树中结点的最大层数 在这里使用后序遍历的递归算法 对每一个结点都进行如下操作 xff1a 后序遍历其左子树求树高后序遍历其右子树求树高对这个结点进行下面操作 xff1a 比较其左右子树
  • lottie.js动画的使用(JSON动画)

    在public文件中引入lottie js data json 对应图片 1 引入lottie lt script src 61 34 lottie js 34 gt lt script gt 2 页面引入代码 lt div id 61 3
  • spring(idea版)

    spring 文章目录 xff1a 1 spring简介2 IOC推导原型及本质3 第一个spring程序4 IOC创建对象的方式5 spring配置说明6 Dl依赖注入环境 依赖注入的方式 7 bean的作用域8 自动装配bean9 用注
  • 扩展卡尔曼滤波算法 EKF

    扩展卡尔曼滤波的仿真案例 xff0c 参考书为北航宇航学院王可东老师的Kalman滤波基础及Matlab仿真 一 状态模型 xff1a 二 测量模型 xff1a 状态方程和测量方程中的噪声均为期望为零的白噪声 三 状态模型和测量模型的线性化