Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
GurvIMU.cpp
00001 #include "GurvIMU.h" 00002 #include "MPU6050.h" 00003 #include "mbed.h" 00004 00005 #define M_PI 3.1415926535897932384626433832795 00006 00007 #define twoKpDef (2.0f * 1.0f) // 2 * proportional gain 00008 #define twoKiDef (2.0f * 0.0f) // 2 * integral gain 00009 00010 00011 GurvIMU::GurvIMU() 00012 { 00013 //MPU 00014 mpu = MPU6050(0x69); //0x69 = MPU6050 I2C ADDRESS 00015 00016 // Variable definitions 00017 q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame 00018 twoKp = twoKpDef; // 2 * proportional gain (Kp) 00019 twoKi = twoKiDef; // 2 * integral gain (Ki) 00020 integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki 00021 cycle_nb = 0; 00022 timer_us.start(); 00023 } 00024 00025 //Function definitions 00026 00027 void GurvIMU::getValues(float * values) 00028 { 00029 int16_t accgyroval[6]; 00030 mpu.getMotion6(&accgyroval[0], &accgyroval[1], &accgyroval[2], &accgyroval[3], &accgyroval[4], &accgyroval[5]); 00031 for(int i = 0; i<3; i++) values[i] = (float) accgyroval[i]; 00032 for(int i = 3; i<6; i++) values[i] = (accgyroval[i]-offset[i]) * (M_PI / 180) / 16.4f; 00033 } 00034 00035 void GurvIMU::getVerticalAcceleration(float av) 00036 { 00037 float values[6]; 00038 float q[4]; // quaternion 00039 float g_x, g_y, g_z; // estimated gravity direction 00040 getQ(q); 00041 00042 g_x = 2 * (q[1]*q[3] - q[0]*q[2]); 00043 g_y = 2 * (q[0]*q[1] + q[2]*q[3]); 00044 g_z = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; 00045 00046 getValues(values); 00047 av = g_x*values[0]+g_y*values[1]+g_z*values[2]-offset[2]; 00048 } 00049 00050 00051 void GurvIMU::getOffset(void) 00052 { 00053 int sample_nb = 50; 00054 float values[6]; 00055 for(int i=0; i<6 ; i++) offset[i] = 0; 00056 for(int i=0; i<sample_nb; i++) { 00057 getValues(values); 00058 for(int j=0; j<6; j++) offset[j]+=values[j]; 00059 } 00060 for(int j=0; j<6; j++) offset[j]/=sample_nb; 00061 } 00062 00063 00064 void GurvIMU::AHRS_update(float gx, float gy, float gz, float ax, float ay, float az) 00065 { 00066 float recipNorm; 00067 float halfvx, halfvy, halfvz; 00068 float halfex, halfey, halfez; 00069 float qa, qb, qc; 00070 00071 dt_us=timer_us.read_us(); 00072 sample_freq = 1.0 / ((dt_us) / 1000000.0); 00073 timer_us.reset(); 00074 00075 // Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation) 00076 if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { 00077 00078 // Normalise accelerometer measurement 00079 recipNorm = invSqrt(ax * ax + ay * ay + az * az); 00080 ax *= recipNorm; 00081 ay *= recipNorm; 00082 az *= recipNorm; 00083 00084 // Estimated direction of gravity 00085 halfvx = q1 * q3 - q0 * q2; 00086 halfvy = q0 * q1 + q2 * q3; 00087 halfvz = q0 * q0 - 0.5f + q3 * q3; 00088 00089 // Error is sum of cross product between estimated and measured direction of gravity 00090 halfex = (ay * halfvz - az * halfvy); 00091 halfey = (az * halfvx - ax * halfvz); 00092 halfez = (ax * halfvy - ay * halfvx); 00093 00094 // Compute and apply integral feedback if enabled 00095 if(twoKi > 0.0f) { 00096 integralFBx += twoKi * halfex * (1.0f / sample_freq); // integral error scaled by Ki 00097 integralFBy += twoKi * halfey * (1.0f / sample_freq); 00098 integralFBz += twoKi * halfez * (1.0f / sample_freq); 00099 gx += integralFBx; // apply integral feedback 00100 gy += integralFBy; 00101 gz += integralFBz; 00102 } 00103 else { 00104 integralFBx = 0.0f; // prevent integral windup 00105 integralFBy = 0.0f; 00106 integralFBz = 0.0f; 00107 } 00108 00109 // Apply proportional feedback 00110 gx += twoKp * halfex; 00111 gy += twoKp * halfey; 00112 gz += twoKp * halfez; 00113 } 00114 00115 // Integrate rate of change of quaternion 00116 gx *= (0.5f * (1.0f / sample_freq)); // pre-multiply common factors 00117 gy *= (0.5f * (1.0f / sample_freq)); 00118 gz *= (0.5f * (1.0f / sample_freq)); 00119 qa = q0; 00120 qb = q1; 00121 qc = q2; 00122 q0 += (-qb * gx - qc * gy - q3 * gz); 00123 q1 += (qa * gx + qc * gz - q3 * gy); 00124 q2 += (qa * gy - qb * gz + q3 * gx); 00125 q3 += (qa * gz + qb * gy - qc * gx); 00126 00127 // Normalise quaternion 00128 recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); 00129 q0 *= recipNorm; 00130 q1 *= recipNorm; 00131 q2 *= recipNorm; 00132 q3 *= recipNorm; 00133 } 00134 00135 void GurvIMU::getQ(float * q) { 00136 float val[6]; 00137 getValues(val); 00138 //while(cycle_nb < 1000){ 00139 AHRS_update(val[3], val[4], val[5], val[0], val[1], val[2]); 00140 //cycle_nb++;} 00141 00142 q[0] = q0; 00143 q[1] = q1; 00144 q[2] = q2; 00145 q[3] = q3; 00146 00147 } 00148 00149 void GurvIMU::getYawPitchRollRad(float * ypr) { 00150 float q[4]; // quaternion 00151 float g_x, g_y, g_z; // estimated gravity direction 00152 getQ(q); 00153 00154 g_x = 2 * (q[1]*q[3] - q[0]*q[2]); 00155 g_y = 2 * (q[0]*q[1] + q[2]*q[3]); 00156 g_z = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; 00157 00158 ypr[0] = atan2(2 * q[1] * q[2] - 2 * q[0] * q[3], 2 * q[0]*q[0] + 2 * q[1] * q[1] - 1); 00159 ypr[1] = atan(g_x * invSqrt(g_y*g_y + g_z*g_z)); 00160 ypr[2] = atan(g_y * invSqrt(g_x*g_x + g_z*g_z)); 00161 } 00162 00163 void GurvIMU::init() 00164 { 00165 mpu.initialize(); 00166 mpu.setI2CMasterModeEnabled(0); 00167 mpu.setI2CBypassEnabled(0); 00168 mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_2000); 00169 getOffset(); 00170 wait(0.005); 00171 } 00172 00173 00174 float invSqrt(float number) 00175 { 00176 volatile long i; 00177 volatile float x, y; 00178 volatile const float f = 1.5F; 00179 00180 x = number * 0.5F; 00181 y = number; 00182 i = * ( long * ) &y; 00183 i = 0x5f375a86 - ( i >> 1 ); 00184 y = * ( float * ) &i; 00185 y = y * ( f - ( x * y * y ) ); 00186 return y; 00187 }
Generated on Wed Jul 13 2022 00:49:05 by
1.7.2