滤波算法 | 无迹卡尔曼滤波(UKF)算法及其Python实现

news2024/11/28 10:56:15

文章目录

  • 简介
  • UKF滤波
    • 1. 概述和流程
    • 2. Python代码
      • 第一个版本
        • a. KF滤波
        • b. UKF滤波
      • 第一个版本

简介

上一篇文章,我们介绍了UKF滤波公式及其MATLAB代码。在做视觉测量的过程中,基于OpenCV的开发包比较多,因此我们将UKF的MATLAB代码转到python中,实现数据滤波效果。

UKF滤波

1. 概述和流程

UKF的公式这里就不再过多介绍了,具体内容请参见博客:UKF滤波公式及其MATLAB代码

这里简单把上一篇文章的公式和流程图粘贴一下。

求解流程

  1. 相比于一般的卡尔曼滤波,UKF算法增加了两次无迹变换,公式为:
    在这里插入图片描述
    权重和方差计算公式为:

  2. Sigma点传播:

在这里插入图片描述

  1. 计算x的预测值和协方差矩阵:

在这里插入图片描述
4. 得到一组新的Sigma点:

在这里插入图片描述
5. 代入观测方程中,得到测量量的预估值:
在这里插入图片描述

  1. 获得观测量的预测值和协方差矩阵:

在这里插入图片描述

  1. 更新状态变量和协方差矩阵:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

另外,每次写论文画卡尔曼流程图中,都找不到参考的模板。我自己画了个滤波流程图,不一定符合每个人的审美,以备参考:

在这里插入图片描述

2. Python代码

重点来了。。。

上代码。

第一个版本

UKF的python代码我一共写了两个版本。

第一个是我用ChatGPT直接生成了一个,经过数据实测,结果有点奇怪,不太像我想要的结果,每个模块之间的交互也跟我理解的不太一样。为了对比,这里也还是贴出来了,人家写的确实比我写的看着逼格好点。

ChatGPT输出的Python:

a. KF滤波


class KalmanFilter:
    def __init__(self, F, H, Q, R, P, x0):
        self.F = F
        self.H = H
        self.Q = Q
        self.R = R
        self.P = P
        self.x = x0

    def predict(self):
        self.x = self.F @ self.x
        self.P = self.F @ self.P @ self.F.T + self.Q

    def update(self, z):
        y = z - self.H @ self.x
        S = self.H @ self.P @ self.H.T + self.R
        K = self.P @ self.H.T @ np.linalg.inv(S)
        self.x = self.x + K @ y
        self.P = (np.eye(len(self.x)) - K @ self.H) @ self.P

b. UKF滤波


import numpy as np
from scipy.linalg import sqrtm

class UKF:
    def __init__(self, f, h, Q, R, P, x0):
        self.f = f
        self.h = h
        self.Q = Q
        self.R = R
        self.P = P
        self.x = x0
        self.n = x0.shape[0]
        self.m = None


    def predict(self):
        # Generate sigma points
        L = np.linalg.cholesky(self.P)
        W = np.concatenate((np.zeros((self.n, 1)), sqrtm(self.n * self.P)))
        X = np.concatenate((self.x, self.x + W, self.x - W), axis=1)

        # Predict sigma points
        Y = np.zeros((self.n, 2 * self.n + 1))
        for i in range(2 * self.n + 1):
            Y[:, i] = self.f(X[:, i])

        # Compute mean and covariance
        self.x = np.mean(Y, axis=1, keepdims=True)
        self.P = np.cov(Y) + self.Q

    def update(self, z):
        # Generate sigma points
        L = np.linalg.cholesky(self.P)
        W = np.concatenate((np.zeros((self.n, 1)), sqrtm(self.n * self.P)))
        X = np.concatenate((self.x, self.x + W, self.x - W), axis=1)

        # Predict measurements
        Z = np.zeros((self.m, 2 * self.n + 1))
        for i in range(2 * self.n + 1):
            Z[:, i] = self.h(X[:, i])

        # Compute mean and covariance
        z_mean = np.mean(Z, axis=1, keepdims=True)
        z_cov = np.cov(Z) + self.R

        # Compute cross-covariance
        xz_cov = np.zeros((self.n, self.m))
        for i in range(2 * self.n + 1):
            xz_cov += (X[:, i, np.newaxis] - self.x) @ (Z[:, i, np.newaxis] - z_mean).T
        xz_cov /= 2 * self.n

        # Compute Kalman gain
        K = xz_cov @ np.linalg.inv(z_cov)

        # Update estimate
        self.x += K @ (z - z_mean)
        self.P -= K @ z_cov @ K.T

第一个版本

第二个是我自己改的一个。参考MATLAB的流程,直接改成了python代码,没有做代码的优化,结果还挺好的,和MATLAB结果一致。


import math

import numpy as np
from scipy.linalg import sqrtm

class ukf:
    def __init__(self, f, h):
        self.f = f
        self.h = h
        self.Q = None
        self.R = None
        self.P = None
        self.x = None
        self.Z = None
        self.n = None
        self.m = None

    def GetParameter(self, Q, R, P, x0):
        self.Q = Q
        self.R = R
        self.P = P
        self.x = x0
        self.n = x0.shape[0]
        self.m = None

    def sigmas(self,x0, c):
        A = c * np.linalg.cholesky(self.P).T
        Y = (self.x * np.ones((self.n,self.n))).T
        Xset = np.concatenate((x0.reshape((-1,1)), Y+A, Y-A), axis=1)
        return Xset


    def ut1(self, Xsigma, Wm, Wc):
        LL = Xsigma.shape[1]
        Xmeans = np.zeros((self.n,1))
        Xsigma_pre = np.zeros((self.n, LL))
        for k in range(LL):
            Xsigma_pre[:,k] = self.f(Xsigma[:,k])
            Xmeans = Xmeans + Wm[0,k]* Xsigma_pre[:, k].reshape((self.n, 1))
        Xdiv = Xsigma_pre - np.tile(Xmeans,(1,LL))
        P  = np.dot(np.dot(Xdiv, np.diag(Wc.reshape((LL,)))), Xdiv.T) + self.Q

        return Xmeans, Xsigma_pre, P, Xdiv

    def ut2(self, Xsigma, Wm, Wc, m):
        LL = Xsigma.shape[1]
        Xmeans = np.zeros((m, 1))
        Xsigma_pre = np.zeros((m, LL))
        for k in range(LL):
            Xsigma_pre[:, k] = self.h(Xsigma[:, k])
            Xmeans = Xmeans + Wm[0, k] * Xsigma_pre[:, k].reshape((m, 1))
        Xdiv = Xsigma_pre - np.tile(Xmeans, (1, LL))
        P = np.dot(np.dot(Xdiv, np.diag(Wc.reshape((LL,)))), Xdiv.T) + self.R

        return Xmeans, Xsigma_pre, P, Xdiv


    def OutPutParameter(self, alpha_msm, x0, Q, R, P):

        z = np.array(alpha_msm).reshape((3, 1))

        self.GetParameter(Q, R, P, x0)

        l = self.n
        m = z.shape[0]
        alpha = 2
        ki = 3 - l
        beta = 2
        lamb = alpha ** 2 * (l + ki) - l
        c = l + lamb
        Wm = np.concatenate((np.array(lamb / c).reshape((-1,1)), 0.5 / c + np.zeros((1, 2 * l))), axis=1)
        Wc = Wm.copy()
        Wc[0][0] = Wc[0][0] + (1 - alpha ** 2 + beta)
        c = math.sqrt(c)

        Xsigmaset = self.sigmas(x0, c)
        X1means, X1, P1, X2 = self.ut1(Xsigmaset, Wm, Wc)
        Zpre, Z1, Pzz, Z2 = self.ut2(X1, Wm, Wc, m)

        Pxz = np.dot(np.dot(X2 , np.diag(Wc.reshape((self.n*2+1,)))), Z2.T)
        K =np.dot(Pxz , np.linalg.inv(Pzz))

        X = (X1means + np.dot(K, z - Zpre)).reshape((-1,))
        self.P = P1 - np.dot(K , Pxz.T)

        return X, self.P

这里把两个代码都公开出来,以供参考。

如有疑问,欢迎提问和指正。

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

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

相关文章

运维视角:rabbitmq教程(四)工作模式

今天这篇文章,通过python代码来测试rabbitmq交换机以及队列的工作模式,以此更加透彻的理解它的工作方式 一、简单模式 1、测试代码 生产者代码: import pikauser_info pika.PlainCredentials(admin, admin) connection pika.BlockingCon…

ICG-Hydrazide,吲哚菁绿-酰肼,ICG-HZ结构式,溶于二氯甲烷等部分有机溶剂,

ICG-Hydrazide,吲哚菁绿-酰肼 中文名称:吲哚菁绿-酰肼 英文名称:ICG-Hydrazide 英文别名:ICG-HZ 性状:粉末或固体 溶剂:溶于二氯甲烷等部分有机溶剂 稳定性:-20℃密封保存、置阴凉干燥处、防潮 分子…

vue上实现左右关联滚动

先看效果&#xff1a; 代码&#xff1a; <template><div class"container"><!-- 左侧fixed导航区域 --><div class"left"><divv-for"item in leftList":key"item.id"class"left_item":class&…

Angular学习之ControlValueAccessor接口详解

ControlValueAccessor 是什么&#xff1f;为什么需要使用 &#xff1f;下面本篇文章就来带大家了解Angular中的ControlValueAccessor组件接口&#xff0c;希望对大家有所帮助&#xff01; ControlValueAccessor 是什么&#xff1f; 简单来说ControlValueAccessor是一个接口&am…

【Linux 网络编程2】应用层协议--http;序列化和反序列化,get和post请求传参的区别,cookie和sesion,编写一个简单的http

目录 1.序列化和反序列化 2.HTTP协议 3.编写一个简单的http 3.2.简单的http的使用 3.3.get和post请求传参的区别 4.http的状态码分类 5.cookie和sesion 1.序列化和反序列化 1.1.序列化和反序列化的优势 序列化将结构体转化为长字符串&#xff0c;便于传输&#xff1b;反序…

MyBatis源码用了哪些设计模式?

MyBatis源码用了哪些设计模式&#xff1f;前言一、创建型模式工厂模式单例模式建造者模式二、结构型模式适配器模式代理模式组合模式装饰器模式三、行为型模式模板模式策略模式迭代器模式总结前言 在 MyBatis 的两万多行的框架源码中&#xff0c;使用了大量的设计模式对工程架…

Oracle OCP 19c 考试(1Z0-083)中关于Oracle不完全恢复的考点(文末附录像)

欢迎试看博主的专著《MySQL 8.0运维与优化》 下面是Oracle 19c OCP考试&#xff08;1Z0-083&#xff09;中关于Oracle不完全恢复的题目: A database is configured in ARCHIVELOG mode A full RMAN backup exists but no control file backup to trace has been taken A media…

Spatial-Temporal Graph ODE Networks for Traffic Flow Forecasting

Spatial-Temporal Graph ODE Networks for Traffic Flow Forecasting 摘要 交通流量的复杂性和长范围时空相关性是难点 经典现存的工作&#xff1a; 1.利用浅图神经网络&#xff08;shallow graph convolution networks&#xff09;和 时间提取模块去分别建模空间和时间依赖…

【Python3安装部署的保姆级教程】

如何在Windows 10上安装Python Python是一种越来越受欢迎的编程语言,无论是对于初学者还是有经验的开发者。Python灵活多用,擅长脚本、自动化、数据分析、机器学习和后端开发。在本教程中,你将学习如何使用Windows的Python安装程序在Windows 10上安装Python。 第一步 — 下…

Python3-错误和异常

Python3 错误和异常 作为 Python 初学者&#xff0c;在刚学习 Python 编程时&#xff0c;经常会看到一些报错信息&#xff0c;在前面我们没有提及&#xff0c;这章节我们会专门介绍。 Python 有两种错误很容易辨认&#xff1a;语法错误和异常。 Python assert&#xff08;断…

进程间通信IPC

进程间通信IPC (InterProcess Communication) 一、进程间通信的概念 每个进程各自有不同的用户地址空间&#xff0c;任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程之间要交换数据必须通过内核&#xff0c;在内核中开辟一块缓冲区&#xff0c;进程1把数据…

MySQL事务详解与隔离级别的实现

文章目录一、四个特性二、存在问题三、隔离级别四、实现原理0、SQL语句执行流程1&#xff09;buffer pool2&#xff09;执行流程1、日志1&#xff09;binlog2&#xff09;redolog3&#xff09;对比4&#xff09;undolog2、MVCC原理1&#xff09;隐式字段2&#xff09;undo log版…

气泡式水位计的安装方法详解

气泡水位计的安装实际上就是气管的安装&#xff0c;气管的安装是否正确将直接影响到仪器测量数据的结果&#xff0c;气泡水位计它由活塞泵产生的压缩空气流经测量管和气泡室&#xff0c;进入被测的水体中&#xff0c;测量管中的静压力与气泡室上的水位高度成正比。那么接下来就…

蓝桥杯集训·每日一题Week1

前缀和&#xff08;Monday&#xff09; AcWing 3956. 截断数组&#xff08;每日一题&#xff09; 思路&#xff1a; 首先可以预处理出前缀和。判断数组长度如果小于 333 或者前 nnn 项不是 333 的倍数&#xff0c;则可以直接输出 000。 否则就枚举所有 s[i]s[n]3s[i] \cfrac…

kali双网卡

先单独开启一个网卡&#xff0c;配置/etc/network/interfaces 修改为如下配置 This file describes the network interfaces available on your system and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* The loopb…

JVM系列——Java与线程,介绍线程原理和操作系统的关系

并发不一定要依赖多线程(如PHP中很常见的多进程并发)。 但是在Java里面谈论并发&#xff0c;基本上都与线程脱不开关系。因此我们讲一下从Java线程在虚拟机中的实现。 线程的实现 线程是比进程更轻量级的调度执行单位。 线程的引入&#xff0c;可以把一个进程的资源分配和执行调…

【深度强化学习】(3) Policy Gradients 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位分享一下基于策略的深度强化学习方法&#xff0c;策略梯度法是对策略进行建模&#xff0c;然后通过梯度上升更新策略网络的参数。我们使用了 OpenAI 的 gym 库&#xff0c;基于策略梯度法完成了一个小游戏。完整代码可以从我的 GitHub 中获得&…

原型模式(设计模式详解)

原型模式 描述 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许通过复制现有对象来创建新对象&#xff0c;而无需从头开始编写代码。 在原型模式中&#xff0c;一个原型对象作为模板&#xff0c;新的对象通过克隆这个原型对象而创…

MySQL OCP888题解048-letter N in slow query log(慢查询日志里的字母N)

文章目录1、原题1.1、英文原题1.2、中文翻译1.3、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3.1、知识点1&#xff1a;mysqldumpslow - 总结缓慢的查询日志文件4、实验4.1、实验14.1.1、实验目的4.1.2、实验前准备4.1.3、实验步骤4.1.4、实验结论5、总结1、原题 1.1…

dva01-初识

背景 React 本身只是一个 DOM 的抽象层&#xff0c;使用组件构建虚拟 DOM。如果开发大应用&#xff0c;还需要解决一个问题。 通信&#xff1a;React 只提供了一种传参手段&#xff0c;后续数据变化非常麻烦&#xff0c;无法适用于大应用。数据流&#xff1a;每次要更新数据&…