HardwareDriver/mpu6050/m451/imu.c

264 lines
7.9 KiB
C

/******************************************************************************************************
* Update the PID parameters.
*
* @param[in] pid A pointer to the pid object.
* @param[in] measured The measured value
* @param[in] updateError Set to TRUE if error should be calculated.
* Set to False if pidSetError() has been used.
* @return PID algorithm output
*******************************************************************************************************/
#include "imu.h"
#include "myMath.h"
#include <math.h>
static float NormAcc;
//float ex_int = 0, ey_int = 0, ez_int = 0; //X、Y、Z轴的比例误差
//float q0 = 1, q1 = 0, q2 = 0, q3 = 0; //定义四元素
//float his_q0 = 1, his_q1 = 0, his_q2 = 0, his_q3 = 0;
//float q0_yaw = 1, q1_yaw = 0, q2_yaw = 0, q3_yaw = 0; //弥补Mahony算法在无地磁情况解算Yaw轴满足不了大扰动要求的现象
//float his_q0_yaw = 1, his_q1_yaw = 0, his_q2_yaw = 0, his_q3_yaw = 0;
//void GetAngle(const stMpu *pMpu,void *pAngE, float dt)
//{
// static const float KpDef = 0.85f ;
// static const float KiDef = 0.0035f;
// const float Gyro_Gr = 0.0005326f; //面计算度每秒,转换弧度每秒则 0.03051756 * 0.0174533f = 0.0005326
// float HalfTime = 0.5 * dt;
// float gx = pMpu->gyroX * Gyro_Gr;
// float gy = pMpu->gyroY * Gyro_Gr;
// float gz = pMpu->gyroZ * Gyro_Gr;
// float ax = pMpu->accX;
// float ay = pMpu->accY;
// float az = pMpu->accZ;
//
// float vx, vy, vz;
// float ex, ey, ez;
//
// static float his_q0q0;
// static float his_q0q1;
// static float his_q0q2;
// static float his_q1q1;
// static float his_q1q3;
// static float his_q2q2;
// static float his_q2q3;
// static float his_q3q3;
//
// float q0q0;
// float q0q1;
// float q0q2;
// float q1q1;
// float q1q3;
// float q2q2;
// float q2q3;
// float q3q3;
//
// float q0_yawq0_yaw;
// float q1_yawq1_yaw;
// float q2_yawq2_yaw;
// float q3_yawq3_yaw;
// float q1_yawq2_yaw;
// float q0_yawq3_yaw;
//
////**************************Yaw轴计算******************************
//
// //Yaw轴四元素的微分方程
// q0_yaw = his_q0_yaw + (-his_q1_yaw * gx - his_q2_yaw * gy - his_q3_yaw * gz) * HalfTime;
// q1_yaw = his_q1_yaw + ( his_q0_yaw * gx + his_q2_yaw * gz - his_q3_yaw * gy) * HalfTime;
// q2_yaw = his_q2_yaw + ( his_q0_yaw * gy - his_q1_yaw * gz + his_q3_yaw * gx) * HalfTime;
// q3_yaw = his_q3_yaw + ( his_q0_yaw * gz + his_q1_yaw * gy - his_q2_yaw * gx) * HalfTime;
//
// q0_yawq0_yaw = q0_yaw * q0_yaw;
// q1_yawq1_yaw = q1_yaw * q1_yaw;
// q2_yawq2_yaw = q2_yaw * q2_yaw;
// q3_yawq3_yaw = q3_yaw * q3_yaw;
// q1_yawq2_yaw = q1_yaw * q2_yaw;
// q0_yawq3_yaw = q0_yaw * q3_yaw;
//
// //规范化Yaw轴四元数
// norm = Q_rsqrt(q0_yawq0_yaw + q1_yawq1_yaw + q2_yawq2_yaw + q3_yawq3_yaw);
// q0_yaw = q0_yaw * norm;
// q1_yaw = q1_yaw * norm;
// q2_yaw = q2_yaw * norm;
// q3_yaw = q3_yaw * norm;
//
// //if(ax * ay * az == 0)
// //return ;
//
// //归一化加速度计值
// norm = Q_rsqrt(ax * ax + ay * ay + az * az);
// ax = ax * norm;
// ay = ay * norm;
// az = az * norm;
//
// //由姿态阵估计重力方向和流量/变迁
// vx = 2 * (his_q1q3 - his_q0q2);
// vy = 2 * (his_q0q1 + his_q2q3);
// vz = his_q0q0 - his_q1q1 - his_q2q2 + his_q3q3;
//
// //向量外积再相减得到差分就是误差 两个单位向量的差积即为误差向量
// ex = (ay * vz - az * vy) ;
// ey = (az * vx - ax * vz) ;
// ez = (ax * vy - ay * vx) ;
// //对误差进行PI计算
// ex_int = ex_int + ex * KiDef;
// ey_int = ey_int + ey * KiDef;
// ez_int = ez_int + ez * KiDef;
// //校正陀螺仪
// gx = gx + KpDef * ex + ex_int;
// gy = gy + KpDef * ey + ey_int;
// gz = gz + KpDef * ez + ez_int;
//
// //四元素的微分方程
// q0 = his_q0 + (-his_q1 * gx - his_q2 * gy - his_q3 * gz) * HalfTime;
// q1 = his_q1 + ( his_q0 * gx + his_q2 * gz - his_q3 * gy) * HalfTime;
// q2 = his_q2 + ( his_q0 * gy - his_q1 * gz + his_q3 * gx) * HalfTime;
// q3 = his_q3 + ( his_q0 * gz + his_q1 * gy - his_q2 * gx) * HalfTime;
// q0q0 = q0 * q0;
// q0q1 = q0 * q1;
// q0q2 = q0 * q2;
// q1q1 = q1 * q1;
// q1q3 = q1 * q3;
// q2q2 = q2 * q2;
// q2q3 = q2 * q3;
// q3q3 = q3 * q3;
// //规范化Pitch、Roll轴四元数
// norm = Q_rsqrt(q0q0 + q1q1 + q2q2 + q3q3);
// q0 = q0 * norm;
// q1 = q1 * norm;
// q2 = q2 * norm;
// q3 = q3 * norm;
//
// //求解欧拉角
// *((float *)pAngE+2) = atan2f(2 * q2q3 + 2 * q0q1, -2 * q1q1 - 2 * q2q2 + 1) * RtA; //ROLL
// *((float *)pAngE+1) = asin(2 * q0q2 -2 * q1q3) * 57.3; //PITCH
// *(float *)pAngE = atan2f(2 * q1_yawq2_yaw + 2 * q0_yawq3_yaw, -2 * q2_yawq2_yaw - 2 * q3_yawq3_yaw + 1) * RtA; //YAW
//
//
// //存储更替相应的四元数
// his_q0_yaw = q0_yaw;
// his_q1_yaw = q1_yaw;
// his_q2_yaw = q2_yaw;
// his_q3_yaw = q3_yaw;
// his_q0 = q0;
// his_q1 = q1;
// his_q2 = q2;
// his_q3 = q3;
//
// his_q0q0 = q0q0;
// his_q0q1 = q0q1;
// his_q0q2 = q0q2;
// his_q1q1 = q1q1;
// his_q1q3 = q1q3;
// his_q2q2 = q2q2;
// his_q2q3 = q2q3;
// his_q3q3 = q3q3;
//}
typedef volatile struct {
float q0;
float q1;
float q2;
float q3;
} Quaternion;
void GetAngle(const _st_Mpu *pMpu,_st_AngE *pAngE, float dt)
{
volatile struct V{
float x;
float y;
float z;
} Gravity,Acc,Gyro,AccGravity;
static struct V GyroIntegError = {0};
static float KpDef = 0.8f ;
static float KiDef = 0.0003f;
static Quaternion NumQ = {1, 0, 0, 0};
float q0_t,q1_t,q2_t,q3_t;
//float NormAcc;
float NormQuat;
float HalfTime = dt * 0.5f;
// 提取等效旋转矩阵中的重力分量
Gravity.x = 2*(NumQ.q1 * NumQ.q3 - NumQ.q0 * NumQ.q2);
Gravity.y = 2*(NumQ.q0 * NumQ.q1 + NumQ.q2 * NumQ.q3);
Gravity.z = 1-2*(NumQ.q1 * NumQ.q1 + NumQ.q2 * NumQ.q2);
// 加速度归一化
NormAcc = Q_rsqrt(squa(MPU6050.accX)+ squa(MPU6050.accY) +squa(MPU6050.accZ));
Acc.x = pMpu->accX * NormAcc;
Acc.y = pMpu->accY * NormAcc;
Acc.z = pMpu->accZ * NormAcc;
//向量差乘得出的值
AccGravity.x = (Acc.y * Gravity.z - Acc.z * Gravity.y);
AccGravity.y = (Acc.z * Gravity.x - Acc.x * Gravity.z);
AccGravity.z = (Acc.x * Gravity.y - Acc.y * Gravity.x);
//再做加速度积分补偿角速度的补偿值
GyroIntegError.x += AccGravity.x * KiDef;
GyroIntegError.y += AccGravity.y * KiDef;
GyroIntegError.z += AccGravity.z * KiDef;
//角速度融合加速度积分补偿值
Gyro.x = pMpu->gyroX * Gyro_Gr + KpDef * AccGravity.x + GyroIntegError.x;//弧度制
Gyro.y = pMpu->gyroY * Gyro_Gr + KpDef * AccGravity.y + GyroIntegError.y;
Gyro.z = pMpu->gyroZ * Gyro_Gr + KpDef * AccGravity.z + GyroIntegError.z;
// 一阶龙格库塔法, 更新四元数
q0_t = (-NumQ.q1*Gyro.x - NumQ.q2*Gyro.y - NumQ.q3*Gyro.z) * HalfTime;
q1_t = ( NumQ.q0*Gyro.x - NumQ.q3*Gyro.y + NumQ.q2*Gyro.z) * HalfTime;
q2_t = ( NumQ.q3*Gyro.x + NumQ.q0*Gyro.y - NumQ.q1*Gyro.z) * HalfTime;
q3_t = (-NumQ.q2*Gyro.x + NumQ.q1*Gyro.y + NumQ.q0*Gyro.z) * HalfTime;
NumQ.q0 += q0_t;
NumQ.q1 += q1_t;
NumQ.q2 += q2_t;
NumQ.q3 += q3_t;
// 四元数归一化
NormQuat = Q_rsqrt(squa(NumQ.q0) + squa(NumQ.q1) + squa(NumQ.q2) + squa(NumQ.q3));
NumQ.q0 *= NormQuat;
NumQ.q1 *= NormQuat;
NumQ.q2 *= NormQuat;
NumQ.q3 *= NormQuat;
// 四元数转欧拉角
{
#ifdef YAW_GYRO
*(float *)pAngE = atan2f(2 * NumQ.q1 *NumQ.q2 + 2 * NumQ.q0 * NumQ.q3, 1 - 2 * NumQ.q2 *NumQ.q2 - 2 * NumQ.q3 * NumQ.q3) * RtA; //yaw
#else
float yaw_G = pMpu->gyroZ * Gyro_G;
if((yaw_G > 3.0f) || (yaw_G < -3.0f)) //数据太小可以认为是干扰,不是偏航动作
{
pAngE->yaw += yaw_G * dt;
}
#endif
pAngE->pitch = asin(2 * NumQ.q0 *NumQ.q2 - 2 * NumQ.q1 * NumQ.q3) * RtA;
pAngE->roll = atan2(2 * NumQ.q2 *NumQ.q3 + 2 * NumQ.q0 * NumQ.q1, 1 - 2 * NumQ.q1 *NumQ.q1 - 2 * NumQ.q2 * NumQ.q2) * RtA; //PITCH
}
}
/***************************************************END OF FILE***************************************************/