平衡小车卡尔曼滤波算法

2023-05-16


最近研究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]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

平衡小车卡尔曼滤波算法 的相关文章

  • vscode怎么关掉/禁用源代码管理

    问题描述 运行项目时源代码管理自动运行 有时还报错实在不便 而运行本地项目时往往不用进行版本控制 xff0c 也就不需要vscode的源代码管理 解决方法 在设置中搜索GIT Enabled xff0c 将其关闭即可 如果求稳可以一并把gi
  • ‘com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor‘ 已经过时了导致出现返回total总为0的问题

    在配置类中去掉原有的依赖 他已经过时了 去掉之后 添加这个功能更多更新的Bean对象 64 Configuration span class token keyword public span span class token keywor
  • UnsatisfiedDependencyException: Error creating bean with name ‘subjectServiceImpl‘: Unsatisfied depe

    背景 看xml所在的路径不舒服 任性改资源路径 以为idea会帮我更新引用就以身试险了哈哈哈 报错信息是bean出现了创建错误 查了网上大部分的博客 一一排除后还是报错 网上大部分建议总结如下 1 先去排查service实现层有没有添加注解
  • Web server failed to start. Port 9020 was already in use./window环境

    Web server failed to start Port 9020 was already in use Web服务器无法启动 端口9020已在使用中 解决思路 xff1a 端口被占用了 xff0c 需要我们去杀死相应的进程 xff0
  • 怎么删除存在表关联的原有数据库表空间?

    怎么删除原有数据库表空间 xff1f 1 xff1a 查询所有的表空间 select tablespace name from sys dba tablespaces 2 xff1a 删除 普通删除 DROP TABLESPACE MESA
  • oracle数据库还原/finalshell/删除表空间/用户名冲突

    数据库10 0 1 131还原 1 首先进行数据库finalshell的配置 账号 xff1a mesadmin 密码 xff1a 2 加载oracle配置文件 sudo su su oracle source etc profile 3
  • C++中的数据类型及其所占字节

    1 整型 包括 xff1a short xff08 短整型 xff09 xff0c 占2个字节 xff1b int xff08 整型 xff09 xff0c 占4个字节 xff1b long xff08 长整型 xff09 xff0c 占4
  • C语言中的关键字

    C语言共有32个关键字 关键字不能作为常量名 变量名或其他标识符名称 根据关键字的作用 xff0c 可将关键字分为 xff1a 数据类型关键字 控制语句关键字 存储类型关键字和其它关键字这四类 数据类型关键字 xff08 12个 xff09
  • C语言字符串和字符串结束标志

    1 在C语言中 xff0c 是将字符串作为字符数组来处理的 2 C语言规定了一个 字符串结束标志 xff0c 以字符 0 作为结束标志 如果字符数组中存有若干字符 xff0c 前面九个字符都不是空字符 xff08 0 xff09 xff0c
  • C语言字符数组的输入和输出

    字符数组的输入输出有两种方法 xff1a xff08 1 xff09 逐个字符输入输出 用格式符 c 输入或输出一个字符 例如 span class token keyword int span span class token funct
  • android手机开启IPv6(电信)

    安卓手机开启IPv6 xff08 电信 xff09 系统设置找到移动网络 接入点 接入点选择CTNET 接入设置点进去可以找到APN协议 xff0c 选择IPv4 IPv6即可 实测手机这样设置后开热点笔记本 xff0c 能稳定获得ipv6
  • C语言 怎样定义函数

    1 定义函数 C语言要求 xff0c 在程序中用到的所有函数必须要 先定义 xff0c 后使用 定义函数应包括以下几个内容 xff1a xff08 1 xff09 指定函数的名字 xff0c 以便以后按名调用 xff08 2 xff09 指
  • C语言 函数的返回值

    通过函数调用使主调函数能得到一个确定的值 xff0c 这就是函数值 xff08 函数的返回值 xff09 1 函数的返回值是通过函数中的return语句获得的 return语句将被调用函数中的一个确定值带回到主调函数中去 如果需要从被调函数
  • C语言 函数的嵌套调用

    C语言的函数定义是互相平行 独立的 xff0c 也就是说 xff0c 在定义函数时 xff0c 一个函数内不能再定义另一个函数 xff0c 即不能嵌套定义 xff0c 但可以嵌套调用函数 xff0c 即 xff0c 在调用一个函数的过程中
  • C语言 Hanoi(汉诺)塔问题,用递归解决

    问题 古代有一个梵塔 xff0c 塔内有3个座A xff0c B xff0c C 开始时A座上有64个盘子 xff0c 盘子大小不等 xff0c 大的在下 xff0c 小的在上 有一个老和尚想把64个盘子从A作移到C座 xff0c 但规定每
  • C语言 数组元素的指针

    1 一个变量有地址 xff0c 一个数组包含若干个元素 xff0c 每个数组元素都在内存中占用存储单元 xff0c 它们都有相应的地址 2 指针变量既然可以指向变量 xff0c 当然也可以指向数组元素 xff08 把某一元素的地址放入一个指
  • Python 实验三 控制语句

    1 从键盘接收整数的一百分制成绩 xff08 0到100 xff0c 要求输出其对应的成绩等级A E 其中 xff0c 90分 xff08 包含 xff09 以上为A xff0c 80 89 xff08 均包含 xff09 分为B xff0
  • Python 实验四 常用数据结构(1)

    1 从键盘输入一个正整数列表 xff0c 以一1结束 xff0c 分别计算列表中奇数和偶数的和 n span class token operator 61 span span class token builtin int span sp
  • Python 实验四 常用数据结构(2)

    6 某企业为职工发放奖金 xff1a 如果入职超过5年 xff0c 且销售业绩超过15000元的员工 xff0c 奖金比例为0 2 xff1b 销售业绩超过10000元的员工 xff0c 奖金比例为0 15 xff1b 销售业绩超过5000
  • JavaScript之入门4篇(DOM节点操作)

    学习记录 xff1a 学习视频链接https www bilibili com video BV1Sy4y1C7ha p 61 194 amp spm id from 61 pageDriver 1 节点操作 xff1a 1 利用DOM提供

随机推荐

  • Please wait while Jenkins is getting ready to work (jenkins)

    如果界面提示Jenkins正在启动 请稍后 或者提示 Please wait while Jenkins is getting ready to work 解决方法 1 需要你进入jenkins的工作目录 xff0c 打开 hudson m
  • 异常点检测的应用场景与检测方法(含代码实操案例)

    异常点检测概述 这里常说的异常点 xff0c 目前并没有具体的严格定义 xff0c 大多数来讲 xff0c 检测异常点都是按照数据分布与业务逻辑结合进行主观判断是否属于异常点 关注金科应用研院 xff0c 回复 CSDN xff0c 领取风
  • ApacheDS搭建

    前提 安装jdk sudo apt get install openjdk 8 jdk 安装 先安装apacheds2 配置客户端远程登录 xff0c 这里使用Apache Directory Studio xff0c 配置界面如下 xff
  • Windows 10 内置linux执行带GUI的应用程序

    1 安装MobaXterm xff0c 并运行 2 打开内置的Linux xff0c 命令执行带GUI的运行程序即可
  • Repo介绍

    目录 1 概要2 工作原理 2 1 项目清单库 repo manifests 2 2 repo脚本库 repo repo 2 3 仓库目录和工作目录 3 使用介绍 3 1 init3 2 sync3 3 upload3 4 download
  • Android 8.0.0-r4源码目录结构详解

    android的移植按如下流程 1 android linux 内核的普通驱动移植 让内核可以在目标平台上运行起来 2 正确挂载文件系统 确保内核启动参数和 android 源代码 system core rootdir 目录下的 init
  • Android8.0.0-r4的编译系统

    一 概述 1 1 编译系统变化 从Android 7 0开始 xff0c android的编译系统发生了变化 xff0c 之前依赖Makefile组织编译系统 xff0c 从7 0开始逐步引入了kati soong optional未正式使
  • [Android Studio]Android Studio 三种添加插件的方式

    何给Android Studio添加插件 添加插件的路径有三种 xff0c 我把他们分类如下 xff1a 点击设置小按钮 点击 xff3b Plugins xff3d 这里展示的是你已经安装的插件 xff0c 我们可以点击插件名称 xff0
  • Gerrit 服务器插件安装-示例插件delete project

    gerrit2 X 中没法直接删除一个项目 xff0c 之前需要手工删除 xff0c 后来社区提供了一个插件delete project来搞定这个事 xff0c 安装方法如下 xff1a 到 gerritforge xff0c 找到对应的
  • Windows平台下载Android源码(整理)

    Google官方下载源码使用的系统Ubuntu系统 xff0c 不过现在我们需要在Windows系统中下载Android源码文件 网站的地址是 xff1a https android googlesource com 里面包括Android
  • Ubuntu 16.04 文件服务器--samba的安装和配置

    Samba是在Linux系统上实现的SMB xff08 Server Messages Block xff0c 信息服务块 xff09 协议的一款免费软件 它实现在局域网内共享文件和打印机 xff0c 是一个客户机 服务器型协议 客户机通过
  • 深入剖析Android音频之AudioTrack

    播放声音能够用MediaPlayer和AudioTrack xff0c 两者都提供了java API供应用开发人员使用 尽管都能够播放声音 但两者还是有非常大的差别的 当中最大的差别是MediaPlayer能够播放多种格式的声音文件 比如M
  • 树莓派4 运行 Tensorflow Lite

    树莓派4 运行 Tensorflow Lite 1 更新树莓派 span class token function sudo span apt update 2 下载安装脚本 span class token function git sp
  • 操作系统进程进行系统调用详细过程

    翻阅很多资料 xff0c 综合了各处所述进程在进行系统调用之后的状态会如何的解答 xff0c 以下是我个人理解 xff0c 欢迎各位读者纠错 PS 特别感谢以下这个帖子 xff0c 看完他们的讨论我才茅塞顿开 xff0c 非常感谢 xff0
  • 解决Ubuntu 找不到ARM64 的源的问题(转)

    Ubuntu 安装了NVIDIA的驱动还有DriveWokrs之后 xff0c 好像把系统添加了arm64的架构 xff0c 因此 xff0c 在源更新的时候 xff0c 也会更新arm64相关的源 xff0c 但是问题在于 xff0c 用
  • asp.net 实现打开文件所在的文件夹, 本地可以打开,发布后点击按钮没有反应的解决办法

    此类情况大概是安全范畴的问题 确定上传文件夹的共享 xff0c iis 以及电脑帐户 xff0c 以及aspnet 等是否有对应的相关权限 1 确认ASPNET 账户属于管理员级别 2 在 服务 里面找到 IIS Admin xff0c 双
  • numpy 和 tensor 的区别

    关系 xff1a 两者共享内存 xff0c 转换方便 xff0c 没有额外的开销 区别 xff1a 1 数据类型上面的区别 xff1a numpy 默认类型是 float64 int32 tensor 默认类型是float32 int64
  • 关于docker无法apt-get update的问题

    在看这篇文章https www jianshu com p 21d66ca6115e 有一个部分是 但是发现自己的 Node 没有ping命令 想着去apt get update 但是出现如下错误 只要在命令签名加上 sudo 就行
  • ubuntu下安装zip unzip

    安装命令 apt get install zip unzip 执行命令常见错误 xff1a 1 unable to locate package 解决办法 xff1a 执行sudo apt get update命令后再执行安装命令就可以了
  • 平衡小车卡尔曼滤波算法

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