卡尔曼滤波算法(C语言)

news2025/5/12 14:55:33

此处感谢华南虎和互联网的众多大佬的无偿分享。

入门常识

先简单了解以下概念:叠加性,齐次性。

用大白话讲,叠加性:多个输入对输出有影响。齐次性:输入放大多少倍,输出也跟着放大多少倍

卡尔曼滤波符合这两个特性。

卡尔曼滤波 :修正值 = 估计值 + 观测值。符合叠加性和齐次性。

协方差的基础知识

把Xt代入,然后将式子进行化简。

公式推导

基础公式理解

对于卡尔曼滤波,我们可以先从状态方程和观测方程开始理解,重点搞懂重点是状态方程和观测方程的实际含义。
 

状态方程公式的参数解析。Xk:当前状态值,Uk:输入值, Wk:过程噪声。A,B为系数。

观测方程公式的参数解析。Yk:观测值。Xk:当前状态值。Vk:观测噪声

简单理解:Vk是不可避免的仪器系统误差,Wk是由外界因素引起的误差。

Q:过程噪声的方差。R:观测噪声的方差。

最优估计值,先验估计值,(观测值)后验估计值。

卡尔曼滤波其实就是取估计值和测量值之间重合的部分。两个概率之间重合的部分。

卡尔曼的实现过程

使用上一次的最优结果预测当前值,同时使用观测值修正之前预测的当前值,得到最终结果(修正后的结果叫做最优估计)。

不需要严格推导,了解是什么意思,怎么用即可。

状态更新方程

卡尔曼增益化简后

过程噪声少,Q可以取小一点。反之,过程噪声大,Q取大一点。

传感器误差小,R可以取小一点。反之,传感器误差大,R取大一点。

执行流程

卡尔曼滤波算法介绍

基本思想:通过不精确的测量来估测真实值。测出来的是不精确的测量值,再利用数学模型和不精确的测量来估测真实值。

一句话概括:根据系统模型和现有状态预测下一刻的状态,然后根据实际的测量结果进行校正。

使用场景:卡尔曼主要用来多传感器的数据融合,单一传感器建议用其他滤波算法。

如何使用?

以下面的代码为例:先定义好卡尔曼滤波结构体,并为其赋值。之后把结构体参数传入,把要过滤的数据传入。卡尔曼滤波算法就会把过滤好的数据,放在其结构体的输出成员中存储好。我们再用变量把卡尔曼滤波结构体中的输出成员的值接收到就行了。

代码

kalman.c

/**
 * 一维卡尔曼滤波器实现
 * @param ekf 卡尔曼滤波器结构体指针,包含滤波所需参数
 * @param input 当前时刻的测量值
 * 
 * 算法流程说明:
 * 1. 预测阶段:根据上一时刻的状态估计当前状态
 * 2. 计算卡尔曼增益:确定测量值和预测值的权重
 * 3. 更新估计:结合预测值和测量值得到最优估计
 * 4. 更新协方差:为下一时刻的预测做准备
 */
void kalman_1(struct _1_ekf_filter *ekf, float input)
{
    // 1. 预测协方差矩阵(时间更新)
    // Now_P = LastP + Q
    // 预测误差 = 上一时刻误差 + 过程噪声
    // Q值越大,表明系统模型越不可靠,滤波器对新测量值更敏感
    ekf->Now_P = ekf->LastP + ekf->Q;
    
    // 2. 计算卡尔曼增益
    // Kg = Now_P / (Now_P + R)
    // 卡尔曼增益权衡预测值和测量值的权重
    // R值越大(测量噪声大),增益越小,更信任预测值
    ekf->Kg = ekf->Now_P / (ekf->Now_P + ekf->R);
    
    // 3. 状态更新方程(测量更新)
    // out = out + Kg * (input - out)
    // 本质是预测值与测量值的加权融合
    // 当Kg=1时完全信任测量值,当Kg=0时完全信任预测值
    ekf->out = ekf->out + ekf->Kg * (input - ekf->out);
    
    // 4. 更新误差协方差矩阵
    // LastP = (1-Kg) * Now_P
    // 更新当前估计误差,用于下一时刻的预测
    // 随着迭代进行,P值会收敛到稳态
    ekf->LastP = (1 - ekf->Kg) * ekf->Now_P;
}

kalman.h

#ifndef _KALMAN_H    // 防止头文件被重复包含
#define _KALMAN_H

// 定义一维扩展卡尔曼滤波器结构体
struct _1_ekf_filter
{
	float LastP;    // 上一时刻的协方差(预测误差)
	float Now_P;    // 当前时刻的协方差(估计误差)
	float out;      // 滤波器输出值(最优估计值)
	float Kg;       // 卡尔曼增益,权衡预测值和测量值的权重
	float Q;        // 过程噪声协方差,反映系统模型的不确定性
	float R;        // 测量噪声协方差,反映测量设备的不确定性
};

// 一维卡尔曼滤波器函数
// 参数:ekf-卡尔曼滤波器结构体指针,input-当前时刻的测量值
extern void kalman_1(struct _1_ekf_filter *ekf, float input);

#endif // _KALMAN_H

调用示例

最后我们要使用的数据在结构体的.out中

for (i = 0; i < 6; i++) // 处理读取的数据
	{
		pMpu[i] = (((int16_t)buffer[i << 1] << 8) | buffer[(i << 1) + 1]) - MpuOffset[i]; // 整合为16bit,并减去水平静止校准值
		if (i < 3)																		  // 以下对加速度做卡尔曼滤波
		{
			{
				static struct _1_ekf_filter ekf[3] = {{0.02, 0, 0, 0, 0.001, 0.543}, {0.02, 0, 0, 0, 0.001, 0.543}, {0.02, 0, 0, 0, 0.001, 0.543}};
				kalman_1(&ekf[i], (float)pMpu[i]); // 一维卡尔曼
				pMpu[i] = (int16_t)ekf[i].out;
			}
		}

		// 如果是陀螺仪数据,进行低通滤波
		if (i > 2) // 以下对角速度做一阶低通滤波
		{
			uint8_t k = i - 3;
			const float factor = 0.15f; // 滤波系数
			static float tBuff[3];		// 滤波缓冲区

			pMpu[i] = tBuff[k] = tBuff[k] * (1 - factor) + pMpu[i] * factor;
		}
	}

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

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

相关文章

ENSP-OSPF综合实验

AR4中通过ospf获取的其他区域路由信息&#xff0c;并且通过路由汇总后简化路由信息 实现全网通&#xff0c;以及单向重发布&#xff0c;以及通过缺省双向访问&#xff0c; 通过stub简化过滤四类五类lsa&#xff0c;简化ospf路由信息 通过nssa简化ospf信息 区域汇总简化R4路由信…

电池单元和电极性能

电芯设计中的挑战 对于电池制造商来说&#xff0c;提高电池能量和功率密度至关重要。在高功率密度和长循环寿命之间取得平衡是电池设计中的关键挑战&#xff0c;通常需要仔细优化材料、电极结构和热管理系统。另一个关键挑战是通过优化重量体积比来降低电池单元的总体成本。 工…

软件设计师-错题笔记-软件工程基础知识

1. 解析&#xff1a; A&#xff1a;体系结构设计是概要设计的重要内容&#xff0c;它关注系统整体的架构&#xff0c;包括系统由哪些子系统组成、子系统之间的关系等 B&#xff1a;数据库设计在概要设计阶段会涉及数据库的逻辑结构设计等内容&#xff0c;如确定数据库的表结…

销售管理系统使用全攻略:从基础配置到数据分析

如果你是一名刚接手公司销售管理系统的销售经理&#xff0c;你会深刻体会到一个好工具的重要性。如果老板突然要查看季度销售数据时&#xff0c;就不用手忙脚乱地翻找各种Excel表格。 今天就来分享我的经验&#xff0c;希望能帮助到同样需要快速上手的朋友。 系统基础配置指南 …

PowerShell 脚本中文乱码处理

问题描述 脚本带中文&#xff0c;执行时命令行窗口会显示出乱码 示例 Write-Host "测试成功&#xff01;"解决方法 问了DeepSeek&#xff0c;让确认是不是 UTF8 无 BOM 格式 事实证明方向对了 但是确认信息有偏差 改成 UTF8 with BOM 使用任意支持修改编码的文本…

前端性能指标及优化策略——从加载、渲染和交互阶段分别解读详解并以Webpack+Vue项目为例进行解读

按照加载阶段、渲染阶段和交互阶段三个维度进行系统性阐述&#xff1a; 在现代 Web 开发中&#xff0c;性能不再是锦上添花&#xff0c;而是决定用户体验与业务成败的关键因素。为了全面监控与优化网页性能&#xff0c;我们可以将性能指标划分为加载阶段、渲染阶段、和交互阶段…

RDD实现单词计数

Scala&#xff08;Spark Shell&#xff09;方法 如果你在 spark-shell&#xff08;Scala 环境&#xff09;中运行&#xff1a; 1. 启动 Spark Shell spark-shell &#xff08;确保 Spark 已安装&#xff0c;PATH 配置正确&#xff09; 2. 执行单词统计 // 1. 读取文件&am…

Java快速上手之实验七

1&#xff0e;编写鼠标事件响应程序MouseEventDemo.java&#xff0c;当鼠标进入和离开窗口时给出相应显示&#xff0c;当按下、弹起时显示当前鼠标的坐标值。 2&#xff0e;编写鼠标事件响应程序MouseMotionEventDemo.java&#xff0c;当鼠标在窗口内移动时显示鼠标的坐标值。 …

可视化图解算法36: 序列化二叉树-I(二叉树序列化与反序列化)

1. 题目 描述 请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树&#xff0c;不对序列化之后的字符串进行约束&#xff0c;但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。 二叉树的序列化(Serialize)是指&#xff1a;把一棵二叉树按照某种遍…

Vivado FPGA 开发 | 创建工程 / 仿真 / 烧录

注&#xff1a;本文为 “Vivado FPGA 开发 | 创建工程 / 仿真 / 烧录” 相关文章合辑。 略作重排&#xff0c;未整理去重。 如有内容异常&#xff0c;请看原文。 Vivado 开发流程&#xff08;手把手教学实例&#xff09;&#xff08;FPGA&#xff09; 不完美先生 于 2018-04-…

Javascript:数组和函数

数组 创建数组 使用new创建 let arrnew array(数组大小); 直接赋值创建 let Arr2[];let Arr3[1,A,"HELLLO"]; 这里JS的数组里面的元素属性可以各不相同 演示代码 <script>let Arr1new Array(5);let Arr2[];let Arr3[1,A,"HELLLO"];console.…

无锁秒杀系统设计:基于Java的高效实现

引言 在电商促销活动中&#xff0c;秒杀场景是非常常见的。为了确保高并发下的数据一致性、性能以及用户体验&#xff0c;本文将介绍几种不依赖 Redis 实现的无锁秒杀方案&#xff0c;并提供简化后的 Java 代码示例和架构图。 一、基于数据库乐观锁机制 ✅ 实现思路&#xf…

NCCL N卡通信机制

转自我的博客&#xff1a;https://shar-pen.github.io/2025/05/05/torch-distributed-series/nccl_communication/ from IPython.display import Image import logging import torch import torch.distributed as distpytorch 分布式相关api torch.distributed.init_process_…

Alpha3DCS公差分析系统_国产替代的3D精度管控方案-SNK施努卡

随着智能制造发展规划的深入推进&#xff0c;工业软件国产化替代已上升为国家战略。在公差分析这一细分领域&#xff0c;长期被国外软件垄断的局面正被打破。 苏州施努卡自主研发的Alpha3DCS&#xff0c;凭借完全自主知识产权和军工级安全标准&#xff0c;成为国内实现三维公差…

ABB电机控制和保护单元与Profibus DP主站转Modbus TCP网关快速通讯案例

ABB电机控制和保护单元与Profibus DP主站转Modbus TCP网关快速通讯案例 在现代工业自动化系统中&#xff0c;设备之间的互联互通至关重要。Profibus DP和Modbus TCP是两种常见的通信协议&#xff0c;分别应用于不同的场景。为了实现这两种协议的相互转换&#xff0c;Profibus …

0基础 | L298N电机驱动模块 | 使用指南

引言 在嵌入式系统开发中&#xff0c;电机驱动是一个常见且重要的功能。L298N是一款高电压、大电流电机驱动芯片&#xff0c;广泛应用于各种电机控制场景&#xff0c;如直流电机的正反转、调速&#xff0c;以及步进电机的驱动等。本文将详细介绍如何使用51单片机来控制L298N电…

【金仓数据库征文】金仓数据库:创新驱动,引领数据库行业新未来

一、引言 在数字化转型的时代洪流中&#xff0c;数据已跃升为企业的核心资产&#xff0c;宛如企业运营与发展的 “数字命脉”。从企业日常运营的精细化管理&#xff0c;到战略决策的高瞻远瞩制定&#xff1b;从客户关系管理的深度耕耘&#xff0c;到供应链优化的全面协同&…

大模型系列(五)--- GPT3: Language Models are Few-Shot Learners

论文链接&#xff1a; Language Models are Few-Shot Learners 点评&#xff1a; GPT3把参数规模扩大到1750亿&#xff0c;且在少样本场景下性能优异。对于所有任务&#xff0c;GPT-3均未进行任何梯度更新或微调&#xff0c;仅通过纯文本交互形式接收任务描述和少量示例。然而&…

Qt QCheckBox 使用

1.开发背景 Qt QCheckBox 是勾选组件&#xff0c;具体使用方法可以参考 Qt 官方文档&#xff0c;这里只是记录使用过程中常用的方法示例和遇到的一些问题。 2.开发需求 QCheckBox 使用和踩坑 3.开发环境 Window10 Qt5.12.2 QtCreator4.8.2 4.功能简介 4.1 简单接口 QChec…

系统架构-面向服务架构(SOA)

概述 服务指的是系统对外提供的功能集 从应用的角度定义&#xff0c;可以认为SOA是一种应用框架&#xff0c;将日常业务划分为单独的业务功能和流程&#xff08;即服务&#xff09;&#xff0c;SOA使用户可以构建、部署和整合这些服务。 从软件的基本原理定义&#xff0c;SO…