加速度计与陀螺仪数据融合解算姿态

2024-02-06 22:50

本文主要是介绍加速度计与陀螺仪数据融合解算姿态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

加计和陀螺仪都能计算出姿态,但为何要对它们融合呢,是因为加速度计对振动之类的扰动很敏感,但长期数据计算出的姿态可信,而陀螺仪虽然对振动这些不敏感,但长期使用陀螺仪会出现漂移,因此我们要进行互补,短期相信陀螺,长期相信加计。不过,其实加计无法对航向角进行修正,修正航向角需要磁力计,也就是下次要总结的9轴数据融合。

在融合之前先要对传感器原始数据进行一些处理。理想情况下,加速度计水平放置时,XY轴应该是0输出的,仅Z轴输出1个G,因此,我们需要对加速度计进行XY轴的零点校准(注意Z轴可不能一起校准去了~);同样的,陀螺仪在水平静止放置时各轴输出应为0,因此需对陀螺仪进行三轴的校准。方法就是把机体标准水平静止放置时采集它个一两百次数据求个平均作为校准值保存起来喽,然后工作状态下各轴输出的数据就是采集来的数据减去校准值喽。仅此还不够,陀螺仪不进行滤波还可以接受,但加速度计噪声比较大,所以至少也得来个滑动窗口滤波,我用了20深度的滑动窗口,数据还是有很大波动,不过最后计算出的姿态角只有0.3度左右的抖动(我看大家一般都是建议8深度就够了,所以单滑动窗口滤波效果是没法做到更好了,可以考虑加个卡尔曼滤波?还没研究,不过这样处理器运算量就上去了)。(11.28补充:后面改对加计使用8深度滑动滤波,陀螺仪进行16阶凯撒窗滤波后只有0.1不到的波动,不过凯撒滤波参数的整定还不会,用的别人整定的一组参数,近期继续研究)。滤波效果如图:
quad4
接下来上六轴数据融合代码:(代码来源网络,我在前人的基础上再加些注释,稍作改动)

#defineKp 10.0f                        // 这里的KpKi是用于调整加速度计修正陀螺仪的速度
#defineKi 0.008f                        
#definehalfT 0.001f             // 采样周期的一半,用于求解四元数微分方程时计算角增量
floatq0 = 1, q1 = 0, q2 = 0, q3 = 0;    // 初始姿态四元数,由上篇博文提到的变换四元数公式得来
floatexInt = 0, eyInt = 0, ezInt = 0;    //当前加计测得的重力加速度在三轴上的分量//与用当前姿态计算得来的重力在三轴上的分量的误差的积分
voidIMUupdate(float gx, float gy, float gz, float ax, float ay, float az)//g表陀螺仪,a表加计
{float q0temp,q1temp,q2temp,q3temp;//四元数暂存变量,求解微分方程时要用float norm; //矢量的模或四元数的范数float vx, vy, vz;//当前姿态计算得来的重力在三轴上的分量float ex, ey, ez;//当前加计测得的重力加速度在三轴上的分量//与用当前姿态计算得来的重力在三轴上的分量的误差// 先把这些用得到的值算好float q0q0 = q0*q0;float q0q1 = q0*q1;float q0q2 = q0*q2;float q1q1 = q1*q1;float q1q3 = q1*q3;float q2q2 = q2*q2;float q2q3 = q2*q3;float q3q3 = q3*q3;      if(ax*ay*az==0)//加计处于自由落体状态时不进行姿态解算,因为会产生分母无穷大的情况return;norm = sqrt(ax*ax + ay*ay + az*az);//单位化加速度计,ax = ax /norm;// 这样变更了量程也不需要修改KP参数,因为这里归一化了ay = ay / norm;az = az / norm;//用当前姿态计算出重力在三个轴上的分量,//参考坐标n系转化到载体坐标b系的用四元数表示的方向余弦矩阵第三列即是(博文一中有提到)vx = 2*(q1q3 - q0q2);        vy = 2*(q0q1 + q2q3);vz = q0q0 - q1q1 - q2q2 + q3q3 ;//计算测得的重力与计算得重力间的误差,向量外积可以表示这一误差//原因我理解是因为两个向量是单位向量且sin0等于0//不过要是夹角是180度呢~这个还没理解ex = (ay*vz - az*vy) ;                                                                  ey = (az*vx - ax*vz) ;ez = (ax*vy - ay*vx) ;exInt = exInt + ex * Ki;                                           //对误差进行积分eyInt = eyInt + ey * Ki;ezInt = ezInt + ez * Ki;// adjusted gyroscope measurementsgx = gx + Kp*ex + exInt;  //将误差PI后补偿到陀螺仪,即补偿零点漂移gy = gy + Kp*ey + eyInt;gz = gz + Kp*ez + ezInt;    //这里的gz由于没有观测者进行矫正会产生漂移,表现出来的就是积分自增或自减//下面进行姿态的更新,也就是四元数微分方程的求解q0temp=q0;//暂存当前值用于计算q1temp=q1;//网上传的这份算法大多没有注意这个问题,在此更正q2temp=q2;q3temp=q3;//采用一阶毕卡解法,相关知识可参见《惯性器件与惯性导航系统》P212q0 = q0temp + (-q1temp*gx - q2temp*gy -q3temp*gz)*halfT;q1 = q1temp + (q0temp*gx + q2temp*gz -q3temp*gy)*halfT;q2 = q2temp + (q0temp*gy - q1temp*gz +q3temp*gx)*halfT;q3 = q3temp + (q0temp*gz + q1temp*gy -q2temp*gx)*halfT;//单位化四元数在空间旋转时不会拉伸,仅有旋转角度,这类似线性代数里的正交变换norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);q0 = q0 / norm;q1 = q1 / norm;q2 = q2 / norm;q3 = q3 / norm;//四元数到欧拉角的转换,公式推导见博文一//其中YAW航向角由于加速度计对其没有修正作用,因此此处直接用陀螺仪积分代替Q_ANGLE.Z = GYRO_I.Z; // yawQ_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)*57.3; // pitchQ_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1,-2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
}                                

这篇关于加速度计与陀螺仪数据融合解算姿态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/685795

相关文章

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

C#使用iText获取PDF的trailer数据的代码示例

《C#使用iText获取PDF的trailer数据的代码示例》开发程序debug的时候,看到了PDF有个trailer数据,挺有意思,于是考虑用代码把它读出来,那么就用到我们常用的iText框架了,所... 目录引言iText 核心概念C# 代码示例步骤 1: 确保已安装 iText步骤 2: C# 代码程

Pandas处理缺失数据的方式汇总

《Pandas处理缺失数据的方式汇总》许多教程中的数据与现实世界中的数据有很大不同,现实世界中的数据很少是干净且同质的,本文我们将讨论处理缺失数据的一些常规注意事项,了解Pandas如何表示缺失数据,... 目录缺失数据约定的权衡Pandas 中的缺失数据None 作为哨兵值NaN:缺失的数值数据Panda

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

JAVA实现亿级千万级数据顺序导出的示例代码

《JAVA实现亿级千万级数据顺序导出的示例代码》本文主要介绍了JAVA实现亿级千万级数据顺序导出的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 前提:主要考虑控制内存占用空间,避免出现同时导出,导致主程序OOM问题。实现思路:A.启用线程池

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本