【控制算法笔记】卡尔曼滤波(二)——基于状态空间表达的KF基本计算流程以及Python实现

本文是个人学习笔记,包含个人理解,如有错误欢迎指正。

KF算法更多的情况下会用来处理复杂的非线性数据,尤其是当对象特征或检测的状态量不止一个时就得使用状态方程的方法,利用线性代数的计算方式来解决噪声的估计问题。这其中涉及到多个变量数据的融合,协方差的计算等概念。

基于正态分布的样本数据融合-Data Fusion

在实际的数据采集中,通常可能有多个传感器来共同采集一个数据,由于传感器生产运输安装和实际系统的动态扰动,每个传感器采集的数据可能都会存在噪声。人们通常认为这些噪声是符合一个正态分布的随机量,所以我们就可以从多个传感器得到多组符合正态分布的观测样本,怎么将这些数据融合到一起,进而达到降低噪声干扰的目的呢?那就是数据融合(Data Fusion)
假设有两个样本的分布,两个分布都符合正态分布,那从样本数据出发,能够得到两组数据的样本均值和样本方差,一共四个变量。 E ( X ) = 1 n ∑ i = 0 n x i S ( X ) = 1 n − 1 ∑ i = 0 n ( x i − x ˉ ) 2 E(X)=\frac{1}{n}\sum_{i=0}^{n}x_i \quad S(X)=\frac{1}{n-1}\sum_{i=0}^{n}(x_i-\bar{x} )^2 E(X)=n1i=0nxiS(X)=n11i=0n(xixˉ)2 对于我们观测到的两组样本数据,根据卡尔曼估计的原理可以认为在同一个时刻,估计的实际数据满足 Z ^ = Z 1 + K ⋅ ( Z 2 − Z 1 ) \hat{Z} =Z_1 +K\cdot (Z_2-Z_1) Z^=Z1+K(Z2Z1) 其中Z一二是k时刻观测到的两个样本数据,当存在一个K能够使得   Z ^ \ \hat{Z}  Z^ 的方差取得最小值的时候,就认为通过k求出的估计值是概率上最符合两个样本的实际值。
根据概率论中基本的方差计算公式可以得到: S ( Z ^ ) = S { Z 1 + K ⋅ ( Z 2 − Z 1 ) } = S { ( 1 − K ) Z 1 + K ⋅ Z 2 } S(\hat{Z}) = S \left \{ Z_1 +K\cdot (Z_2-Z_1) \right \} =S \left \{(1-K)Z_1+K\cdot Z_2 \right \} S(Z^)=S{Z1+K(Z2Z1)}=S{(1K)Z1+KZ2} 由于观测的样本数据之间相互独立,所以可得 ⇒ S ( Z ^ ) = S [ ( 1 − K ) Z 1 ] + S ( K ⋅ Z 2 ) = ( 1 − K ) 2 ⋅ S ( Z 1 ) + K 2 S ( Z 2 ) \Rightarrow S(\hat{Z})=S[(1-K)Z_1]+S(K\cdot Z_2)=(1-K)^2\cdot S(Z_1)+K^2S(Z_2) S(Z^)=S[(1K)Z1]+S(KZ2)=(1K)2S(Z1)+K2S(Z2) 对等式右端求导,并令导数为0可得: ⇒ S ( Z ^ ) ′ = − 2 ⋅ ( 1 − K ) ⋅ S ( Z 1 ) + 2 ⋅ K ⋅ S ( Z 2 ) = 0 \Rightarrow S(\hat{Z})'=-2\cdot (1-K)\cdot S(Z_1)+2\cdot K\cdot S(Z_2)=0 S(Z^)=2(1K)S(Z1)+2KS(Z2)=0 ⇒ S ( Z ^ ) ′ = ( 1 − K ) ⋅ S ( Z 1 ) + K ⋅ S ( Z 2 ) = 0 \Rightarrow S(\hat{Z})'= (1-K)\cdot S(Z_1)+K\cdot S(Z_2)=0 S(Z^)=(1K)S(Z1)+KS(Z2)=0 ⇒ k = S ( Z 1 ) S ( Z 1 ) + S ( Z 2 ) \Rightarrow k=\frac{S(Z_1)}{S(Z_1)+S(Z_2)} k=S(Z1)+S(Z2)S(Z1) 所以求出了K取值,可以得到概率上最优的融合数据。融合后的数据符合正态分布,且 S ( Z ^ ) = ( 1 − K ) 2 ⋅ S ( Z 1 ) + K 2 ⋅ S ( Z 2 ) E ( Z ^ ) = ( 1 − K ) ⋅ E ( Z 1 ) + K ⋅ E ( Z 2 ) S(\hat{Z} )=(1-K)^2\cdot S(Z_1)+K^2\cdot S(Z_2) \quad E(\hat{Z})=(1-K)\cdot E(Z_1)+K\cdot E(Z_2) S(Z^)=(1K)2S(Z1)+K2S(Z2)E(Z^)=(1K)E(Z1)+KE(Z2)


协方差矩阵-Covariance Matrix

当样本数据特征不再是一维数据时,往往将多维的数据计算转化到线性代数的计算,所以为了能在多维数据中计算样本的方差数据,我们必须学习样本的协方差矩阵。
现在假设存在三组样本观测数据: X = [ x 1 x 2 x 3 ] Y = [ y 1 y 2 y 3 ] Z = [ z 1 z 2 z 3 ] X=\begin{bmatrix} x_1\\x_2 \\x_3 \end{bmatrix} \quad Y=\begin{bmatrix} y_1 \\y_2 \\y_3 \end{bmatrix} \quad Z=\begin{bmatrix} z_1 \\z_2 \\z_3 \end{bmatrix} X= x1x2x3 Y= y1y2y3 Z= z1z2z3 每组样本可以计算出各自的方差,总的样本方差可以描述为: σ 2 = S ( X ) + S ( Y ) + S ( Z ) = σ ( X ) 2 + σ ( Y ) 2 + σ ( Z ) 2 \sigma^2 =S(X)+S(Y)+S(Z)=\sigma(X)^2+\sigma(Y)^2+\sigma(Z)^2 σ2=S(X)+S(Y)+S(Z)=σ(X)2+σ(Y)2+σ(Z)2 从而可以将总的样本方差使用二次型表示: S ⃗ = [ σ x 2 σ x σ y σ x σ z σ y σ x σ y 2 σ y σ z σ z σ x σ z σ y σ z 2 ] \vec{S} =\begin{bmatrix} {\sigma_x}^2 & \sigma_x\sigma_y & \sigma_x\sigma_z\\ \sigma_y\sigma_x & {\sigma_y}^2 & \sigma_y\sigma_z\\ \sigma_z\sigma_x & \sigma_z\sigma_y & {\sigma_z}^2 \end{bmatrix} S = σx2σyσxσzσxσxσyσy2σzσyσxσzσyσzσz2 其中   σ x 2 \ {\sigma_x}^2  σx2是样本的方差   σ x σ y \ \sigma_x\sigma_y  σxσy是x和y的样本协方差。这样的协方差矩阵通过一定的变换可以加快计算机计算的效率。为此需要引入协方差过度矩阵。
我们令协方差过度矩阵为: a = [ x 1 y 1 z 1 x 2 y 2 z 2 x 3 y 3 z 3 ] − 1 3 [ 1 1 1 1 1 1 1 1 1 ] [ x 1 y 1 z 1 x 2 y 2 z 2 x 3 y 3 z 3 ] a=\begin{bmatrix} x_1 & y_1 & z_1\\ x_2 & y_2 & z_2\\ x_3 & y_3 & z_3 \end{bmatrix} -\frac{1}{3} \begin{bmatrix} 1 & 1 & 1\\ 1 & 1 & 1\\ 1 & 1 & 1 \end{bmatrix} \begin{bmatrix} x_1 & y_1 & z_1\\ x_2 & y_2 & z_2\\ x_3 & y_3 & z_3 \end{bmatrix} a= x1x2x3y1y2y3z1z2z3 31 111111111 x1x2x3y1y2y3z1z2z3 上式中有第一项矩阵为样本数据矩阵,后一项的值就是样本的平均值。通过过度矩阵相乘可以得到协方差矩阵为: P = 1 3 a T a P = \frac{1}{3} a^Ta P=31aTa 这样就能通过矩阵的方式加快计算。


状态空间理论

在经典的控制系统中,使用传递函数的形式描述系统输入和输出之间的关系,传递函数所计算的是系统外部的联系。在现代控制系统中,通过对控制系统内部参数建立状态变量进而通过系统微分方程建立状态状态空间表达式。
正是通过状态空间的思想,可以进一步的在此基础上拓展出复杂系统的卡尔曼滤波计算。通常对一个实际的离散系统,可以表达为: X k = A X k − 1 + B u k − 1 + w k − 1 Z k = H X k + V k \begin{matrix} X_k=AX_{k-1}+B{\large u} _{k-1}+{\large w} _{k-1}\\ Z_k=HX_k+V_k \end{matrix} Xk=AXk1+Buk1+wk1Zk=HXk+Vk上式是一个基本的离散形式状态空间表达式,第一行描述输入和状态变量关系,最后一项是系统工作过程中数据产生的过程噪声。第二行描述了输出和状态变量的关系,最后一项是输出数据的测量噪声,在次基础上就可以使用卡尔曼滤波来实时估计当前状态变量的估计值。
通过系统的状态空间方程的形式可以进一步的推导出KF(卡尔曼滤波)的核心参数卡尔曼增益。

状态空间下的KF核心公式

基于上面的离散系统状态空间表达式和数据融合中的概率论计算方法,可以得到,对于
X k = A X k − 1 + B u k − 1 + w k − 1 Z k = H X k + V k \begin{matrix} X_k=AX_{k-1}+B{\large u} _{k-1}+{\large w} _{k-1}\\ Z_k=HX_k+V_k \end{matrix} Xk=AXk1+Buk1+wk1Zk=HXk+Vk 有预测阶段: X ^ k − = A X ^ k − 1 P k − = A P k − 1 A T + Q \begin{matrix} \hat{X}^-_k=A\hat{X}_{k-1} \\ P^-_k=AP_{k-1}A^T+Q \end{matrix} X^k=AX^k1Pk=APk1AT+Q 其中X为状态变量,A为状态矩阵,Q为噪声协方差矩阵,P为过程噪声矩阵。
随后在矫正参数阶段有当前时刻的卡尔曼增益: K k = P k − H T H P k − H T + R K_k=\frac{P^-_kH^T}{HP^-_kH^T+R} Kk=HPkHT+RPkHT
当前时刻的估计值: X ^ k = X ^ k − + K k ( Z k − H X ^ k − ) \hat{X}_k=\hat{X}^-_k+K_k(Z_k-H\hat{X}^-_k) X^k=X^k+Kk(ZkHX^k) 以及当前时刻的过程估计误差: P k = ( I − K k H ) P k − P_k=(I-K_kH)P^-_k Pk=(IKkH)Pk

二维KF位置估计-Python

假设对一个移动的小车,使用小车的位置x和y坐标作为状态变量,通过附加位置数据的随机噪声,并迭代来计算估计的位置:

import numpy as np
import matplotlib.pyplot as plt

# 状态空间模型参数
dt = 0.1  # 采样时间间隔
A = np.array([[1, dt],
              [0, 1]])  # 状态转移矩阵,描述系统的演化

H = np.array([[1, 0],
              [0, 1]])  # 观测矩阵,描述测量和状态的关系

# 过程噪声和测量噪声的协方差矩阵
Q = np.diag([0.1, 0.1])  # 过程噪声协方差矩阵
R = np.diag([5, 5])  # 测量噪声协方差矩阵

# 初始状态估计
x_hat = np.array([0, 0])  # 初始状态估计
P = np.diag([4, 1])  # 初始状态协方差矩阵

# 生成实际运动的轨迹数据
true_states = []
for t in range(50):
    x_hat = np.dot(A, x_hat) + np.array([1, 1])  # 在X方向上正向运动,在Y方向上正向运动
    true_states.append(x_hat)

true_states = np.array(true_states)

# 模拟测量数据(带有噪声)
measurements = np.dot(H, true_states.T).T + np.random.multivariate_normal([0, 0], R, size=len(true_states))

# 存储估计值
estimated_states = []

# 卡尔曼滤波过程
for z in measurements:
    # 预测步骤
    x_hat_minus = np.dot(A, x_hat)
    P_minus = np.dot(np.dot(A, P), A.T) + Q

    # 更新步骤
    K = np.dot(np.dot(P_minus, H.T), np.linalg.inv(np.dot(np.dot(H, P_minus), H.T) + R))
    x_hat = x_hat_minus + np.dot(K, z - np.dot(H, x_hat_minus))
    P = np.dot((np.eye(2) - np.dot(K, H)), P_minus)

    estimated_states.append(x_hat)

estimated_states = np.array(estimated_states)

# 绘制真实轨迹和估计值
plt.plot(true_states[:, 0], true_states[:, 1], 'b',label='True States', linestyle='--')
plt.plot(measurements[:, 0], measurements[:, 1], 'ro', label='Measurements')
plt.plot(estimated_states[:, 0], estimated_states[:, 1],'bo', label='Estimated States')

plt.title('State Space Kalman Filter Example')
plt.xlabel('X Position')
plt.ylabel('Y Position')
plt.legend()
plt.show()

将生成的带噪声轨迹数据和KF估计的位置数据用散点的方式绘制出来,其中红色为带噪声的模拟测量位置,蓝色为KF估计的位置。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++实现满天星效果静态图片

用编程C实现随机生成不同效果的星星,实现看星星的效果图片,借助EasyX图形化工具!!! 在vs2019中新建文件夹,并且注意在项目目录下保存两张小人的抬头观看背景的图片 将下面代码粘贴进去实现效果: #define _CRT_SECURE_NO_WARNIN…

前端canvas项目实战——简历制作网站(三)——右侧属性栏(线条宽度样式)

目录 前言一、效果展示二、实现步骤1. 实现线条宽度(strokeWidth)的属性模块2. 实线线条样式(strokeDashArray)的属性模块3. 意料之外的“联动” 三、Show u the code后记 前言 上一篇博文中,我们初步实现了右侧属性栏…

IDEA 创建maven项目没有src

环境: IntelliJ IDEA 2022.3.3 (Ultimate Edition) JDK 17 Windows 11 10.0 Maven 3.9.5 创建maven项目的时候没有src目录 试过网上说的重新配置maven库,增加vm-options,并没有什么用。直到我看见了 正常创建就好了。

QoS服务质量

内存QoS——服务质量(Quality of Service) 作用:如果不开启QoS,会通过内存复用技术,动态调整虚拟机的资源,如果说有一台跑核心业务,然后通过QoS技术,通过限额,预留&…

思考,是世界上最有趣的事

经常有读者问我: 你总说我们要多思考,可是每天的生活就那样,究竟要怎么思考,思考什么呢? 跟大家分享我上周日的一天: 读完一篇推理小说,写了一篇书评发给作者,并跟作者聊了聊写作的…

vivado 配置I/O端口

配置I/O端口 AMD设备支持可配置的SelectIO™ 接口驱动程序和接收器,支持各种标准接口。这些标准接口包括输出的可编程控制强度和转换速率,使用DCI的片上终端,以及内部VREF的生成。你可以配置一个或多个I/O端口以定义I/O标准、驱动器强度、转…

LaTeX基础使用【系列四】

🌈个人主页:godspeed_lucip 🔥 系列专栏:LaTeX基础使用 🦄1 LaTeX的多行数学公式🐠1.1 导入包🐠1.2 gather环境:多行公式🐠1.3 gather\* :无编号公式&#x1…

【Javaweb程序】【C00156】基于SSM餐饮管理系统(论文+PPT)

基于SSM餐饮管理系统(论文PPT) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的餐饮管理系统 本系统分为前台用户模块和后台管理员模块 其中前台用户模块的权限:当游客打开系统的网址后,首先看到的就是首页…

Day01_Java概述(JDK的下载安装,初学者常见错误)

文章目录 JavaSE_Day01 Java概述学习目标1.1 JavaSE课程体系介绍1.2 计算机语言概述1、计算机语言是什么2、计算机语言发展3、计算机语言分类4、计算机语言排行榜 1.3 Java语言概述1、Java语言发展历史2、Java是最好的语言吗?3、Java语言的特点4、Java生态圈5、Java…

【MySQL】学习如何通过DML更新数据库的数据

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-QIqURn9fNFMjLD9l {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

【贪吃蛇:C语言实现】

文章目录 前言1.了解Win32API相关知识1.1什么是Win32API1.2设置控制台的大小、名称1.3控制台上的光标1.4 GetStdHandle(获得控制台信息)1.5 SetConsoleCursorPosition(设置光标位置)1.6 GetConsoleCursorInfo(获得光标…

mysql 存储过程学习

存储过程介绍 1.1 SQL指令执行过程 从SQL执行的流程中我们分析存在的问题: 1.如果我们需要重复多次执行相同的SQL,SQL执行都需要通过连接传递到MySQL,并且需要经过编译和执行的步骤; 2.如果我们需要执行多个SQL指令,并且第二个SQL指令需要…

Linux文本三剑客---awk

awk(是一种处理文本文件的应用程序,它依次处理文件的每一行,并读取里面的每一个字段。) awk 包含几个特殊的内建变量(可直接用)如下所示: 1、获取根分区剩余大小 #可以使用df -h命令来查看所有…

AlexNet,ZFNet详解

1 AlexNet 网络结构 对于AlexNet网络来说,因为当时资源环境受限,他从第一步卷积开始就把一个图像分到两个GPU上训练,然后中间进行组合最后进行融合成全连接成1000个置信度 1 得到一张3x224x224的图像,然后进行11x11的卷积&…

1|Java代码是怎么跑起来的?

相信每个Java程序员都想过一个问题: “我写的Java代码时怎样在机器上跑起来的?“🤔 这篇文章就尝试把这个问题说一下✍ Java代码执行流程 二话不说先把图丢出来: 大概经历了这么几个步骤: 一位高级程序猿&#xff0…

竞赛练一练 第31期:GESP和电子学会相关题目练习

Day20:CIE一级2020.09_小鸡与鸭妈拥抱 1. 准备工作 (1)背景:Farm; (2)角色:Chick、Duck。 2. 功能实现 (1)角色的初始位置、方向和造型如图所示。 (2&am…

DualSPHysics v5.0源码编译教程,新手入门

目录 一、前期准备1. 安装C编译器2. 安装CUDA 二、下载源码三、编译四、报错解决五、验证 一、前期准备 DualSPHysics是可以编译运行在CPU和GPU上的,所以需要安装C编译器:例如gcc,和CUDA编译器:nvcc。 如果电脑上不支持CUDA&…

【笔试常见编程题01】删除公共字符串、组队竞赛、倒置字符串、排序子序列

1. 删除公共字符串 输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。 例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.” 输入描述 每个测试输入包含2个字符串 输出描述 输出删除后的…

翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二 1. 将任何静态图表转换为动态数据可视化 ChatGPT Vision 不仅可以将涂鸦变成功能齐全的 Streamlit 应用程序,还…

Python算法题集_无重复字符的最长子串

本文为Python算法题集之一的代码示例 题目3:无重复字符的最长子串 说明:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "a…