平衡小车卡尔曼滤波算法


最近研究STM32的自平衡小车,发现有两座必过的大山,一为卡尔曼滤波,二为PID算法。
网上看了很多关于卡尔曼滤波的代码,感觉写得真不咋地。一怒之下,自己重写,不废话,贴代码



[pre lang="C" line="1" file="kalman.h"]/**
  ******************************************************************************
  * @file    kalman.h
  * @author  willieon
  * @version V0.1
  * @date    January-2015
  * @brief   卡尔曼滤波算法 
  *        
  *
  ******************************************************************************
  * @attention
  *本人对卡尔曼的粗略理解:以本次测量角速度(陀螺仪测量值)的积分得出的角度值
  * 与上次最优角度值的方差产生一个权重来衡量本次测量角度(加速度测量值)
  * 与上次最优角度值,从而产生新的最优角度值。好吧,比较拗口,有误处忘指正。
  *
  ******************************************************************************
  */

#ifndef __KALMAN_H__
#define __KALMAN_H__


#define Q_angle                        0.001        角度过程噪声的协方差
#define Q_gyro                        0.003        角速度过程噪声的协方差
#define R_angle                        0.5                测量噪声的协方差(即是测量偏差)
#define dt                                0.01                        卡尔曼滤波采样频率
#define C_0                                1

/**************卡尔曼运算变量定义**********************
*
***由于卡尔曼为递推运算,结构体需定义为全局变量
***在实际运用中只需定义一个KalmanCountData类型的变量即可
***无需用户定义多个中间变量,简化函数的使用
*/
typedef struct
{
        float                                Q_bias;                最优估计值的偏差,即估计出来的陀螺仪的漂移量
        float                                Angle_err;                实测角度与陀螺仪积分角度的差值
        float                                PCt_0;                                
        float                                PCt_1; 
        float                                E;                        计算的过程量
        float                                K_0;                        含有卡尔曼增益的另外一个函数,用于计算最优估计值
        float                                K_1;                        含有卡尔曼增益的函数,用于计算最优估计值的偏差
        float                                t_0;                                
        float                                t_1;
        float                                Pdot[4];                Pdot[4] = {0,0,0,0};过程协方差矩阵的微分矩阵
        float                                PP[2][2];                PP[2][2] = { { 1, 0 },{ 0, 1 } };协方差(covariance)
        float                                Angle_Final;        后验估计最优角度值(即系统处理最终值)
        float                                Gyro_Final;        后验估计最优角速度值

}KalmanCountData;

void Kalman_Filter(float Accel,        float Gyro ,KalmanCountData * Kalman_Struct);
void Kalman_Filter_Init(KalmanCountData * Kalman_Struct);



#endif

[/pre]

kalman.c

[pre lang="C" line="1"  file="kalman.c"]
#include "kalman.h"


/**
  ******************************************************************************
  * @file    void Kalman_Filter_Init(KalmanCountData * Kalman_Struct)
  * @author  willieon
  * @version V0.1
  * @date    January-2015
  * @brief   卡尔曼滤波计算中间量初始化
  *        
  *
  ******************************************************************************
  * @attention
  *
  * 
  * 
  *
  ******************************************************************************
  */

void Kalman_Filter_Init(KalmanCountData * Kalman_Struct)
{
        Kalman_Struct -> Angle_err                 = 0;
        Kalman_Struct -> Q_bias                         = 0;
        Kalman_Struct -> PCt_0                         = 0;
        Kalman_Struct -> PCt_1                         = 0;
        Kalman_Struct -> E                                 = 0;
        Kalman_Struct -> K_0                         = 0;
        Kalman_Struct -> K_1                         = 0;
        Kalman_Struct -> t_0                         = 0;
        Kalman_Struct -> t_1                         = 0;
        Kalman_Struct -> Pdot[0]                 = 0;
        Kalman_Struct -> Pdot[1]                 = 0;
        Kalman_Struct -> Pdot[2]                 = 0;
        Kalman_Struct -> Pdot[3]                 = 0;        
        Kalman_Struct -> PP[0][0]                 = 1;
        Kalman_Struct -> PP[0][1]                 = 0;
        Kalman_Struct -> PP[1][0]                 = 0;
        Kalman_Struct -> PP[1][1]                 = 1;        
        Kalman_Struct -> Angle_Final         = 0;
        Kalman_Struct -> Gyro_Final                 = 0;

}


/**
  ******************************************************************************
  * @file    void Kalman_Filter(float Accel,        float Gyro ,KalmanCountData * Kalman_Struct)
  * @author  willieon
  * @version V0.1
  * @date    January-2015
  * @brief   卡尔曼滤波计算
  *        
  *
  ******************************************************************************
  * @attention
  *                Accel:加速度计数据处理后进来的角度值
  *                Gyro :陀螺仪数据处理后进来的角速度值
  *                Kalman_Struct:递推运算所需要的中间变量,由用户定义为全局结构体变量
  *                Kalman_Struct -> Angle_Final  为滤波后角度最优值
  *                Kalman_Struct -> Gyro_Final   为后验角度值
  ******************************************************************************
  */

void Kalman_Filter(float Accel,        float Gyro ,KalmanCountData * Kalman_Struct)
{
                //陀螺仪积分角度(先验估计)
                Kalman_Struct -> Angle_Final += (Gyro - Kalman_Struct -> Q_bias) * dt; 
                
                //先验估计误差协方差的微分
                Kalman_Struct -> Pdot[0] = Q_angle - Kalman_Struct -> PP[0][1] - Kalman_Struct -> PP[1][0]; 
                Kalman_Struct -> Pdot[1] = - Kalman_Struct -> PP[1][1];
                Kalman_Struct -> Pdot[2] = - Kalman_Struct -> PP[1][1];
                Kalman_Struct -> Pdot[3] = Q_gyro;
                
                //先验估计误差协方差的积分
                Kalman_Struct -> PP[0][0] += Kalman_Struct -> Pdot[0] * dt;   
                Kalman_Struct -> PP[0][1] += Kalman_Struct -> Pdot[1] * dt;   
                Kalman_Struct -> PP[1][0] += Kalman_Struct -> Pdot[2] * dt;
                Kalman_Struct -> PP[1][1] += Kalman_Struct -> Pdot[3] * dt;
                
                //计算角度偏差
                Kalman_Struct -> Angle_err = Accel - Kalman_Struct -> Angle_Final;        
                
                //卡尔曼增益计算
                Kalman_Struct -> PCt_0 = C_0 * Kalman_Struct -> PP[0][0];
                Kalman_Struct -> PCt_1 = C_0 * Kalman_Struct -> PP[1][0];
                
                Kalman_Struct -> E = R_angle + C_0 * Kalman_Struct -> PCt_0;
                
                Kalman_Struct -> K_0 = Kalman_Struct -> PCt_0 / Kalman_Struct -> E;
                Kalman_Struct -> K_1 = Kalman_Struct -> PCt_1 / Kalman_Struct -> E;
                
                //后验估计误差协方差计算
                Kalman_Struct -> t_0 = Kalman_Struct -> PCt_0;
                Kalman_Struct -> t_1 = C_0 * Kalman_Struct -> PP[0][1];

                Kalman_Struct -> PP[0][0] -= Kalman_Struct -> K_0 * Kalman_Struct -> t_0;                 
                Kalman_Struct -> PP[0][1] -= Kalman_Struct -> K_0 * Kalman_Struct -> t_1;
                Kalman_Struct -> PP[1][0] -= Kalman_Struct -> K_1 * Kalman_Struct -> t_0;
                Kalman_Struct -> PP[1][1] -= Kalman_Struct -> K_1 * Kalman_Struct -> t_1;

                Kalman_Struct -> Angle_Final += Kalman_Struct -> K_0 * Kalman_Struct -> Angle_err;         //后验估计最优角度值
                Kalman_Struct -> Q_bias        += Kalman_Struct -> K_1 * Kalman_Struct -> Angle_err;                 //更新最优估计值的偏差
                Kalman_Struct -> Gyro_Final   = Gyro - Kalman_Struct -> Q_bias;                                                 //更新最优角速度值

}

[/pre]

代码可以放在实际工程中使用,也可以用VS等C编译工具进行实验学习。在VS中的main()实例使用如下

[pre lang="C" line="1" file="main.c"]
#include "kalman.h"

#include "stdio.h"

#include "stdlib.h"

void main(void)
{


        KalmanCountData k;
        //定义一个卡尔曼运算结构体
        Kalman_Filter_Init(&k);
        //讲运算变量初始化
        int m,n;        

           for(int a = 0;a<80;a++)
        //测试80次
        {

                //m,n为1到100的随机数
                m = 1+ rand() %100;

                n = 1+ rand() %100;

                //卡尔曼滤波,传递2个测量值以及运算结构体
        
        Kalman_Filter((float)m,(float)n,&k);

                //打印结果
                printf("%d and %d is %f - %f\r\n",m,n,k.Angle_Final,k.K_0);
        
        }




}
[/pre]

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

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

相关文章

IOS 为UILabel添加长按复制功能

IOS 为UILabel添加长按复制功能 在iOS中下面三个控件&#xff0c;自身就有复制-粘贴的功能&#xff1a; 1、UITextView 2、UITextField 3、UIWebView UIKit framework提供了几个类和协议方便我们在自己的应用程序中实现剪贴板的功能。 1、UIPasteboard&#xff1a;我们可以向其…

navicat 的查询功能

navicat的查询的位置在&#xff1a; 在编辑器界面写代码&#xff0c;代码完成后点左上角的运行。 代码&#xff1a; create&#xff08;创建&#xff09; table&#xff08;一个表&#xff09; <xxx>尖括号内的内容必填——我要创建并查询一个名叫做xxx的表 &#xff08…

c++ sleep函数_Linux 多线程应用中如何编写安全的信号处理函数

关于代码的可重入性&#xff0c;设计开发人员一般只考虑到线程安全&#xff0c;异步信号处理函数的安全却往往被忽略。本文首先介绍如何编写安全的异步信号处理函数&#xff1b;然后举例说明在多线程应用中如何构建模型让异步信号在指定的线程中以同步的方式处理。Linux 多线程…

css特殊情况

如果一个父级div和一个子级div&#xff0c;要给父级div加&#xff08;opacity&#xff09;透明度那子级div也会继承父级元素的透明度。那给父级元素加透明度就不用opacity加透明度&#xff0c;使用background:rgba(120,120,120,0.7);实现效果&#xff0c;r,g,b分别代表红&#…

CoreAnimation (CALayer 动画)

CoreAnimation基本介绍&#xff1a; CoreAnimation动画位于iOS框架的Media层CoreAnimation动画实现需要添加QuartzCore.FrameworkCoreAnimation基本上是LayerAnimationCoreAnimation分类&#xff1a; CoreAnimation作用&#xff1a; CoreAnimation CALayer基本介绍 CALayer的常…

汇编为什么分段执行总是执行不了_iOS汇编教程(六)CPU 指令重排与内存屏障...

系列文章iOS 汇编入门教程(一)ARM64 汇编基础iOS 汇编入门教程(二)在 Xcode 工程中嵌入汇编代码iOS 汇编入门教程(三)汇编中的 Section 与数据存取iOS 汇编教程(四)基于 LLDB 动态调试快速分析系统函数的实现iOS 汇编教程(五)Objc Block 的内存布局和汇编表示前言具有 ARM 体系…

GD32 使用stm32 固件库

1、 系统 1) 晶振起振区别 描述&#xff1a;启动时间&#xff0c;GD32 与STM32 启动时间都是2ms&#xff0c;实际上GD 的执行效率快&#xff0c;所以ST 的HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)是2ms&#xff0c;但是这个宏定义值在GD 上时间就更加短了&#xff0c;所以要加大…

干将莫邪

干将莫邪也为凡铁铸成&#xff0c;只是善加锻造、融入心神&#xff0c;而成上古神兵。宝剑从来都是双刃&#xff0c;正邪之道&#xff0c;存乎一心。

js反混淆还原工具_SATURN反混淆框架

本文为看雪论坛精华文章看雪论坛作者ID&#xff1a;梦野间摘要&#xff1a;近几年&#xff0c;软件的混淆强度一直在不断提升。基于编译器的混淆已经成为业界事实上的标准&#xff0c;最近的一些论文也表明软件的保护方式使用的是编译器级别的混淆。在这篇文章中&#xff0c;我…

android 弹起键盘把ui顶上去的解决办法

键盘输入框上面的ui布局必须为Relative相对布局。然后设置 <activityandroid:name".activity.HomeActivity"Android:windowSoftInputMode"adjustPan|stateHidden"></activity>转载于:https://www.cnblogs.com/zhaoleigege/p/5925831.html

python 多线程并发_寻找python大神!!!python如何多线程并发?

不是大神。尝试回答一下。 首先解释下什么叫做线程&#xff0c;什么叫做进程&#xff0c;在解释这两个概念前&#xff0c;我们还需要明白什么叫做GIL全局解释器锁。GIL 全局解释器锁&#xff1a; GIL(全局解释器锁&#xff0c;GIL 只有cpython有)&#xff1a;在同一个时刻&…

Nginx/Apache发大招

导读网站程序的上传目录通常是不需要PHP执行解释权限&#xff0c;通过限制目录的PHP执行权限可以提网站的安全性&#xff0c;减少被攻击的机率。下面和大家一起分享下如何在Apache和Nginx禁止上传目录里PHP的执行权限。 Apache下禁止指定目录运行PHP脚本在虚拟主机配置文件中增…

第二轮冲刺-Runner站立会议08

今天完成的内容&#xff1a;简单的做了一下主界面的美化和日历界面的美化 遇到的问题&#xff1a;美化按钮还不能自己自定义按钮 如何解决&#xff1a;暂无思路 明天将要进行的内容&#xff1a;调试bug 转载于:https://www.cnblogs.com/Againzg/p/5544301.html

STM32串口通信中使用printf发送数据配置方法 开发环境 Keil

STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) 已有 12456 次阅读2011-6-29 23:29 | 在STM32串口通信程序中使用printf发送数据&#xff0c;非常的方便。可在刚开始使用的时候总是遇到问题&#xff0c;常见的是硬件访真时无法进入main主函数&#xff0c;其实…

dmp文件查看表空间_innoDb文件

一&#xff0e;文件总体概述InnoDb文件主要有以下文件1. 参数文件&#xff1a;启动需要的各种参数作2. 日志文件&#xff1a;记录mysql实例某种条件做出的响应而写入的文件&#xff0c;如错误日志、二进制日志、慢查询日志、查询日志等3. Socket文件&#xff1a;连接需要的文件…

论文笔记之:Deep Attention Recurrent Q-Network

Deep Attention Recurrent Q-Network 5vision groups 摘要&#xff1a;本文将 DQN 引入了 Attention 机制&#xff0c;使得学习更具有方向性和指导性。&#xff08;前段时间做一个工作打算就这么干&#xff0c;谁想到&#xff0c;这么快就被这几个孩子给实现了&#xff0c;自愧…

Codeforces Round #354 (Div. 2)

贪心 A Nicholas and Permutation #include <bits/stdc.h>typedef long long ll; const int N 1e5 5; int a[105]; int pos[105];int main() {int n;scanf ("%d", &n);for (int i1; i<n; i) {scanf ("%d", ai);pos[a[i]] i;}int ans abs …

linux c程序中内核态与用户态内存存储问题

Unix/Linux的体系架构 如上图所示&#xff0c;从宏观上来看&#xff0c;Linux操作系统的体系架构分为用户态和内核态&#xff08;或者用户空间和内核&#xff09;。内核从本质上看是一种软件——控制计算机的硬件资源&#xff0c;并提供上层应用程序运行的环境。用户态即上层应…

线程自动退出_C++基础 多线程笔记(一)

join & detachjoin和detach为最基本的用法&#xff0c;join可以使主线程&#xff08;main函数&#xff09;等待子线程&#xff08;自定义的function_1函数&#xff09;完成后再退出程序&#xff0c;而detach可以使子线程与主线程毫无关联的独立运行&#xff0c;当主线程执行…

WEB在线预览PDF

这是我在博客园发表的第一篇文章。以后会陆续把在线预览其他格式文档的解决方案发表出来。 解决思路&#xff1a;把pdf转换成html显示。 在线预览pdf我暂时了解3种解决方案&#xff0c;欢迎大家补充。 方案一&#xff1a; 利用pdf2html软件将PDF转换成HTML。 用法: PDF2HTML [选…