【Python仿真】基于EKF的传感器融合定位

基于EKF的传感器融合定位(Python仿真)

  • 简述
  • 1. 背景介绍
    • 1.1. EKF扩展卡尔曼滤波
      • 1.1.1.概念
      • 1.1.2. 扩展卡尔曼滤波的主要步骤如下:
      • 1.1.3. 优、缺点
    • 1.2. 航位推算
    • 1.3. 目前航位算法的使用通常与卡尔曼滤波相结合使用
      • 2. 分段代码
    • 2.1. 导入需要的包
    • 2.2. 设置相关参数
    • 2.3. 输入
    • 2.4. 噪声添加
    • 2.5. 运动模型
    • 2.6. 观测模型
    • 2.7. 雅可比(Jacobian)运动模型
    • 2.8. 扩展卡尔曼滤波估计模型
      • 2.8.1. 预测
    • 2.9. 计算并绘制EKF协方差椭圆
    • 2.10. 主函数
  • 3. 代码运行结果展示与分析
    • 3.1. 实验结果展示
    • 3.2. EKF与航位推算的比较
      • 3.2.1. 非线性系统
      • 3.2.2. 高精度估计
      • 3.2.3. 适应不确定性
      • 3.2.4. 实时性

简述

用Python代码实现EKF的方法对比航位推算的结果,表明EKF的融合定位精度比单纯使用航位推算的精度更高。

1. 背景介绍

1.1. EKF扩展卡尔曼滤波

1.1.1.概念

卡尔曼滤波(Kalman Filtering)是一种用于估计系统状态的递归滤波方法,广泛应用于信号处理、控制系统、机器人技术等领域。扩展卡尔曼滤波(Extended Kalman Filtering)是卡尔曼滤波的一个扩展版本,用于非线性系统的状态估计。
在扩展卡尔曼滤波中,系统被建模为非线性动态系统,其中状态由一个非线性函数描述,并且状态的观测值受到高斯噪声的影响。扩展卡尔曼滤波通过线性化非线性函数来近似系统的动态特性,并利用卡尔曼滤波的递归算法来估计系统的状态。

1.1.2. 扩展卡尔曼滤波的主要步骤如下:

  • 初始化:设置系统的初始状态和协方差矩阵。
  • 预测:根据系统的动态模型和当前状态的估计值,预测下一个时刻的状态和协方差矩阵。
  • 线性化:将非线性函数线性化为一个雅可比矩阵,用于计算卡尔曼增益。
  • 更新:根据观测值和预测的状态值,计算卡尔曼增益,并更新状态的估计值和协方差矩阵。

1.1.3. 优、缺点

扩展卡尔曼滤波的优点是能够处理非线性系统,并且具有较好的估计性能。
然而,它对初始状态的估计要求较高,并且线性化过程可能引入估计误差。对于非线性程度较高的系统,线性化可能导致估计误差增大。
因此,在应用扩展卡尔曼滤波时,需要根据实际问题进行参数调整和误差分析,以保证滤波器的性能。

1.2. 航位推算

航位推算(Dead Reckoning)是一种在航海和航空中用于确定当前位置的方法。
其原理基于以下几个假设:

  • 起始点位置已知:航位推算需要知道起始点的经纬度坐标。
  • 航向角和速度已知:航位推算需要知道航行器的航向角和速度。
  • 没有外部干扰:航位推算假设在航行过程中没有外部干扰,如风、水流等。

基于以上假设,航位推算的原理可以描述如下:
1 . 根据起始点位置、航向角和速度,计算出航行器在单位时间内的位移向量
2 . 将位移向量累加到起始点的经纬度坐标上,得到航行器在单位时间后的预测位置。
不断重复步骤1和2,根据航行器的实际航向角和速度更新位移向量,并累加到当前位置上,得到航行器不断更新的位置。
航位推算的原理是基于航行器的运动学原理,通过不断地预测和更新位置,可以在一定程度上确定航行器的当前位置。然而,由于航位推算没有考虑外部干扰和误差累积的问题,所以在长时间航行中可能会产生较大的误差。因此,在实际航行中,航位推算通常会与其他导航方法(如卫星导航系统)结合使用,以提高位置的准确性和可靠性。

1.3. 目前航位算法的使用通常与卡尔曼滤波相结合使用

航位推算导航系统中位置和航向角的发散特性。航位推算导航的可观测性分析表明,所设计的系统能够提供一定时间内的位置和航向角。
但是,需要通过其他系统如绝对定位系统来补偿导航误差,以延长导航时间和距离。本代码将结合扩展卡尔曼滤波实现。

2. 分段代码

2.1. 导入需要的包

import numpy as np
import math
import matplotlib.pyplot as plt

2.2. 设置相关参数

# Estimation parameter of EKF 估计参数
Q = np.diag([0.1, 0.1, np.deg2rad(1.0), 1.0])**2
R = np.diag([1.0, np.deg2rad(40.0)])**2
#  Simulation parameter 仿真参数
Qsim = np.diag([0.5, 0.5])**2
Rsim = np.diag([1.0, np.deg2rad(30.0)])**2
DT = 0.1  # time tick [s] 时间刻度
SIM_TIME = 50.0  # simulation time [s] 模拟时间
show_animation = True

2.3. 输入

def calc_input():v = 1.0  # [m/s]yawrate = 0.1  # [rad/s]  偏航角速率u = np.matrix([v, yawrate]).Treturn u

2.4. 噪声添加

def observation(xTrue, xd, u):xTrue = motion_model(xTrue, u)# add noise to gps x-y  添加噪声到GPS x-yzx = xTrue[0, 0] + np.random.randn() * Qsim[0, 0]zy = xTrue[1, 0] + np.random.randn() * Qsim[1, 1]z = np.matrix([zx, zy])# add noise to input 给输入加噪ud1 = u[0, 0] + np.random.randn() * Rsim[0, 0]ud2 = u[1, 0] + np.random.randn() * Rsim[1, 1]ud = np.matrix([ud1, ud2]).Txd = motion_model(xd, ud)return xTrue, z, xd, ud

2.5. 运动模型

def motion_model(x, u):F = np.matrix([[1.0, 0, 0, 0],[0, 1.0, 0, 0],[0, 0, 1.0, 0],[0, 0, 0, 0]])B = np.matrix([[DT * math.cos(x[2, 0]), 0],[DT * math.sin(x[2, 0]), 0],[0.0, DT],[1.0, 0.0]])x = F * x + B * ureturn x

2.6. 观测模型

def observation_model(x):#  Observation ModelH = np.matrix([[1, 0, 0, 0],[0, 1, 0, 0]])z = H * xreturn z

2.7. 雅可比(Jacobian)运动模型

需要注意的是,雅可比运动模型是一种简化的模型,它基于一些假设和近似,可能不能完全准确地描述实际情况。然而,它仍然是解释群体扩散和迁移的有用工具,并且可以通过调整参数和引入更复杂的扩展模型来提高其准确性。

def jacobF(x, u):"""Jacobian of Motion Modelmotion modelx_{t+1} = x_t+v*dt*cos(yaw)y_{t+1} = y_t+v*dt*sin(yaw)yaw_{t+1} = yaw_t+omega*dtv_{t+1} = v{t}sodx/dyaw = -v*dt*sin(yaw)dx/dv = dt*cos(yaw)dy/dyaw = v*dt*cos(yaw)dy/dv = dt*sin(yaw)"""yaw = x[2, 0]v = u[0, 0]jF = np.matrix([[1.0, 0.0, -DT * v * math.sin(yaw), DT * math.cos(yaw)],[0.0, 1.0, DT * v * math.cos(yaw), DT * math.sin(yaw)],[0.0, 0.0, 1.0, 0.0],[0.0, 0.0, 0.0, 1.0]])return jFdef jacobH(x):# Jacobian of Observation Model 观测模型的雅可比矩阵jH = np.matrix([[1, 0, 0, 0],[0, 1, 0, 0]])return jH

2.8. 扩展卡尔曼滤波估计模型

2.8.1. 预测

  • 状态预测
    系统模型:假设非线性系统的状态方程可以表示为 xPred = f(xEst ,u) + z,其中 x_k 是当前时刻的状态向量,f() 是非线性函数,u是当前时刻的控制输入,z是过程噪声。
    预测状态:通过对系统模型进行线性化近似,使用雅可比矩阵(Jacobian Matrix)F_k 来近似表示状态方程:xPred = f̂(xEst, u),其中 xPred是预测的状态估计值,f̂() 是线性化后的状态更新函数。
  • 协方差预测
    预测协方差:使用雅可比矩阵 jF进行线性化近似,通过更新方程 PPred = jF * PEst * jF.T +Q 来计算预测的协方差矩阵,其中 PPred 是预测的协方差矩阵。
    测量模型:假设非线性系统的测量方程可以表示为 zPred = H * xPred其中 z_k 是当前时刻的测量向量,h() 是非线性函数,v_k 是测量噪声。
    预测测量:通过对测量模型进行线性化近似,使用雅可比矩阵 jH来近似表示测量方程:zPred = jH * xPred,其中 zPred是预测的测量值,H 是线性化后的测量函数。
    残差计算:计算残差向量 y = z.T – zPred 。
    残差协方差:假设测量噪声服从高斯分布,通过测量噪声协方差矩阵 R 来描述测量噪声的方差。
    估计卡尔曼增益:通过雅可比矩阵 jH 进行线性化近似,计算卡尔曼增益 K = PPred * jH.T * np.linalg.inv(S),其中 S = jH * PPred * jH.T + R 。
    更新状态估计值:使用卡尔曼增益将预测的状态估计值修正为最终的状态估计值 xEst = xPrede + K * y。
    更新协方差矩阵:使用卡尔曼增益将预测的协方差矩阵修正为最终的协方差矩阵 PEst = (I - K * jH) * Pred ,其中 I 是单位矩阵。
def ekf_estimation(xEst, PEst, z, u):#  PredictxPred = motion_model(xEst, u)jF = jacobF(xPred, u)PPred = jF * PEst * jF.T + Q#  UpdatejH = jacobH(xPred)zPred = observation_model(xPred)y = z.T - zPredS = jH * PPred * jH.T + RK = PPred * jH.T * np.linalg.inv(S)xEst = xPred + K * yPEst = (np.eye(len(xEst)) - K * jH) * PPredreturn xEst, PEst

2.9. 计算并绘制EKF协方差椭圆

def plot_covariance_ellipse(xEst, PEst):    # EKF估计的协方差椭圆Pxy = PEst[0:2, 0:2]eigval, eigvec = np.linalg.eig(Pxy)if eigval[0] >= eigval[1]:bigind = 0smallind = 1else:bigind = 1smallind = 0t = np.arange(0, 2 * math.pi + 0.1, 0.1)a = math.sqrt(eigval[bigind])b = math.sqrt(eigval[smallind])x = [a * math.cos(it) for it in t]y = [b * math.sin(it) for it in t]angle = math.atan2(eigvec[bigind, 1], eigvec[bigind, 0])R = np.matrix([[math.cos(angle), math.sin(angle)],[-math.sin(angle), math.cos(angle)]])fx = R * np.matrix([x, y])px = np.array(fx[0, :] + xEst[0, 0]).flatten()py = np.array(fx[1, :] + xEst[1, 0]).flatten()plt.plot(px, py, "--r")

2.10. 主函数

def main():print(__file__ + " start!!")time = 0.0# State Vector [x y yaw v]' 状态向量xEst = np.matrix(np.zeros((4, 1)))xTrue = np.matrix(np.zeros((4, 1)))PEst = np.eye(4)xDR = np.matrix(np.zeros((4, 1)))  # Dead reckoning 船位推算# historyhxEst = xEsthxTrue = xTruehxDR = xTruehz = np.zeros((1, 2))while SIM_TIME >= time:time += DTu = calc_input()xTrue, z, xDR, ud = observation(xTrue, xDR, u)xEst, PEst = ekf_estimation(xEst, PEst, z, ud)# store data history 存储数据历史hxEst = np.hstack((hxEst, xEst))hxDR = np.hstack((hxDR, xDR))hxTrue = np.hstack((hxTrue, xTrue))hz = np.vstack((hz, z))if show_animation:plt.rcParams['axes.unicode_minus'] = Falseplt.rcParams['font.sans-serif'] = ['SimHei']    #matplotlib.pyplot绘图显示中文plt.cla()plt.plot(hz[:, 0], hz[:, 1], ".g",label="定位观测点")  # 绿点为定位观测(如GPS)plt.plot(np.array(hxTrue[0, :]).flatten(),np.array(hxTrue[1, :]).flatten(), "-b",label="真实轨迹")    # 蓝线为真实轨迹plt.plot(np.array(hxDR[0, :]).flatten(),np.array(hxDR[1, :]).flatten(), "-k",label="航位推算轨迹")  # 黑线为航位推算轨迹plt.plot(np.array(hxEst[0, :]).flatten(),np.array(hxEst[1, :]).flatten(), "-r",label="EKF估计轨迹") # 红线为EKF估计轨迹plot_covariance_ellipse(xEst, PEst)plt.legend()plt.axis("equal")plt.grid(True)plt.pause(0.001)

3. 代码运行结果展示与分析

3.1. 实验结果展示

可以看出一开始航位推算的效果要优于EKF,是因为EKF还处于一个更新调整的阶段,随着时间的推进,航位推算的轨迹与真实的蓝色轨迹相差越来越大,红色的EKF轨迹与真实轨迹之间有误差,但在一定小的一个范围内。图中绿色的点是GPS的观测点,选取一个固定范围内的点来更新预测EKF的轨迹。
在这里插入图片描述

3.2. EKF与航位推算的比较

3.2.1. 非线性系统

船位推算通常涉及到非线性状态方程,如运动模型。
而扩展卡尔曼滤波能够通过对非线性系统进行线性化,使得可以在非线性系统中进行状态估计。

3.2.2. 高精度估计

扩展卡尔曼滤波通过在每个时间步骤上更新状态估计和协方差矩阵,能够提供对船位的高精度估计。通过不断的测量和预测更新过程,可以减小估计误差并产生更准确的船位估计结果。

3.2.3. 适应不确定性

扩展卡尔曼滤波能够处理系统和测量的不确定性。在船位推算中,存在各种误差来源,如传感器误差、环境影响等,扩展卡尔曼滤波能够通过动态调整协方差矩阵来适应这些不确定性,从而提供更鲁棒的航位估计。

3.2.4. 实时性

扩展卡尔曼滤波具有较高的计算效率和实时性,适用于需要实时船位推算的场景。
通过有效的算法设计和优化,扩展卡尔曼滤波能够在短时间内完成状态估计,适用于高频率的航位推算任务。

代码链接:GitHub - UI-Mario/EKF: 扩展卡尔曼滤波/ Extended Kalman Filter(EKF)

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

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

相关文章

wpf devexpress 添加GanttControl到项目

这个教程示范如何添加GanttControl 到你的项目使用内置GanttControl数据类。 要求 添加 Devexpress.Wpf.Gantt Nuget包到你的项目使用GanttControl. 数据模型 GanttControl携带和内置数据对象,可以使用创建视图模型: GanttTask 呈现甘特图任务 Gan…

记录将excel表无变形的弄进word里面来

之前关于这个问题记录过一篇文章: 将excel中的表快速复制粘贴进word中且不变形-CSDN博客 今天记录另外一种方法:举例表述,excel表如图: 按F12,出现“另存为...”对话框,选择“单个文件网页”,…

面向对象与面向过程的区别

面向对象 以对象为中心,把数据封装成为一个整体,其他数据无法直接修改它的数据,将问题分解成不同对象,然后给予对象相应的属性和行为。 面向过程 关注代码过程,直接一程序来处理数据,各模块之间有调用与…

oracle-buffer cache

段,区,块。 每当新建一个表,数据库会相应创建一个段。然后给这个段分配一个区。 一个区包含多个块。 区是oracle给段分配空间的最小单位。 块是oracle i\o的最小单位。 原则上,一个块包含多行数据。 dbf文件会被划分成一个一个…

Netty Review - 核心组件扫盲

文章目录 PreNetty Reactor 的工作架构图CodePOMServerClient Netty 重要组件taskQueue任务队列scheduleTaskQueue延时任务队列Future异步机制Bootstrap与ServerBootStrapgroup()channel()option()与childOption()ChannelPipelinebind()优雅地关闭EventLoopGroupChannleChannel…

今天遇到Windows 10里安装的Ubuntu(WSL)的缺点

随着技术的发展,越来越多开发者转向使用 Windows Subsystem for Linux(WSL)在 Windows 10 上进行开发,也就是说不用虚拟机,不用准备多一台电脑,只需要在Windows 10/11 里安装 WSL 就能体验 Linux 系统。因此…

邀请报名|11月24日阿里云原生 Serverless 技术实践营 深圳站

活动简介 “阿里云云原生 Serverless 技术实践营 ” 是一场以 Serverless 为主题的开发者活动,活动受众以关注 Serverless 技术的开发者、企业决策人、云原生领域创业者为主,活动形式为演讲、动手实操,让开发者通过一个下午的时间增进对 Ser…

how to find gcc openbug

https://gcc.gnu.org/bugzilla/query.cgi?formatadvanced

最全的接口自动化测试思路和实战:【推荐】混合测试自动化框架(关键字+数据驱动)

混合测试自动化框架(关键字数据驱动) 关键字驱动或表驱动的测试框架 这个框架需要开发数据表和关键字。这些数据表和关键字独立于执行它们的测试自动化工具,并可以用来“驱动"待测应用程序和数据的测试脚本代码,关键字驱动测试看上去与手工测…

mount /dev/mapper/centos-root on sysroot failed处理

今天发现centos7重启开不进去系统 通过查看日志主要告警如下 修复挂载目录 xfs_repair /dev/mapper/centos-root不行加-L参数 xfs_repair -L /dev/mapper/centos-root重启 reboot

云课五分钟-0Cg++默认版本和升级-std=c++17

前篇: 云课五分钟-0B快速排序C示例代码-注释和编译指令 视频: 云课五分钟-0Cg默认版本和升级-stdc17 文本: 在Linux系统中,可以通过以下步骤升级g: 打开终端,使用root权限或者sudo权限登录。输入以下命令…

基于灰狼算法(GWO)优化的VMD参数(GWO-VMD)

代码的使用说明 基于灰狼算法优化的VMD参数 代码的原理 基于灰狼算法(Grey Wolf Optimizer, GWO)优化的VMD参数(GWO-VMD)是一种结合了GWO和VMD算法的优化方法,用于信号分解和特征提取。 GWO是一种基于群体智能的优化…

lv11 嵌入式开发 ARM指令集中(伪操作与混合编程) 7

目录 1 伪指令 2 伪操作 3 C和汇编的混合编程 4 ATPCS协议 1 伪指令 本身不是指令,编译器可以将其替换成若干条等效指令 空指令NOP 指令LDR R1, [R2] 将R2指向的内存空间中的数据读取到R1寄存器 伪指令LDR R1, 0x12345678 R1 0x12345678 LDR伪指令可以将任…

小米真无线耳机 Air 2s产品蓝牙配对ubuntu20.04 笔记本电脑

小米真无线耳机 Air 2s产品蓝牙配对ubuntu20.04 笔记本电脑 1.我的笔记本是 22款联想拯救者y9000k,安装了双系统,ubuntu20.04。 2.打开耳机,按压侧面按钮2秒,指示灯显示白色闪烁。 3.打开ubunru20.04 系统右上角wifi的位置&…

vulnhub靶场—matrix-breakout-2-morpheus靶机

一,实验环境 靶机ip:192.168.150.131攻击机ip:192.168.150.130 二,信息收集 arp-scan -l 扫描网段,寻找靶机ip 使用工具nmap进行端口扫描 nmap -A -T4 -p- 192.168.150.131 通过信息收集发现了靶机有80和81这两个…

HP惠普光影精灵7笔记本Victus by HP 16.1英寸游戏本16-d0000原装出厂Windows11.21H2预装OEM系统

下载链接:https://pan.baidu.com/s/1LGNeQR1AF1XBJb5kfZca5w?pwdhwk6 提取码:hwk6 可适用的型号: 16-d0111tx,16-d0112tx,16-d0125tx,16-d0127tx,16-d0128tx,16-d0129tx&#…

JAVA多线程(5)

JAVA多线程(5) 线程安全问题概述 卖票问题分析 单窗口卖票 一个窗口(单线程)卖100张票没有问题 单线程程序是不会出现线程安全问题的 多个窗口卖不同的票 3个窗口一起卖票,卖的票不同,也不会出现问题 多线程程序,没有访问共享数据,不会产生问题 多个窗口卖相同的票 3个窗口…

【Go入门】 Go如何使得Web工作

【Go入门】 Go如何使得Web工作 前面小节介绍了如何通过Go搭建一个Web服务,我们可以看到简单应用一个net/http包就方便的搭建起来了。那么Go在底层到底是怎么做的呢?万变不离其宗,Go的Web服务工作也离不开我们第一小节介绍的Web工作方式。 w…

竞赛选题 深度学习花卉识别 - python 机器视觉 opencv

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &a…

Canal+Kafka实现MySQL与Redis数据同步(一)

CanalKafka实现MySQL与Redis数据同步(一) 前言 在很多业务情况下,我们都会在系统中加入redis缓存做查询优化。 如果数据库数据发生更新,这时候就需要在业务代码中写一段同步更新redis的代码。 这种数据同步的代码跟业务代码糅合…