#include "FastIMU.h" #include "Madgwick.h" #include //#define PRINT_ANGLES //#define PRINT_QUAT //#define PERFORM_CALIBRATION //Comment to disable startup calibration #define IMU_ADDRESS 0x68 //Change to the address of the IMU MPU6050 IMU; //Change to the name of any supported IMU! AccelData IMUAccel; //Sensor data GyroData IMUGyro; Madgwick filter; void setup_imu(){ // TODO: write my own kalman filter Wire.begin(); Wire.setClock(400000); //400khz clock calData calib; calib.accelBias[0]=-0.02; calib.accelBias[1]=-0.01; calib.accelBias[2]=0.16; calib.gyroBias[0] = -2.89; calib.gyroBias[1] = -3.59; calib.gyroBias[2] = -0.66; int err = IMU.init(calib, IMU_ADDRESS); if (err != 0) { Serial.print("Error initializing IMU: "); Serial.println(err); while (true) { ; } } if (err != 0) { Serial.print("Error Setting range: "); Serial.println(err); while (true) { ; } } #ifdef PERFORM_CALIBRATION Serial.println("Keep IMU level."); delay(5000); IMU.calibrateAccelGyro(&calib); Serial.println("Calibration done!"); Serial.println("Accel biases X/Y/Z: "); Serial.print(calib.accelBias[0]); Serial.print(", "); Serial.print(calib.accelBias[1]); Serial.print(", "); Serial.println(calib.accelBias[2]); Serial.println("Gyro biases X/Y/Z: "); Serial.print(calib.gyroBias[0]); Serial.print(", "); Serial.print(calib.gyroBias[1]); Serial.print(", "); Serial.println(calib.gyroBias[2]); delay(5000); IMU.init(calib, IMU_ADDRESS); #endif filter.begin(0.2f); Serial.println("IMU up"); } void update_imu(){ IMU.update(); IMU.getAccel(&IMUAccel); IMU.getGyro(&IMUGyro); // MPU6050 has no magnetometer filter.updateIMU(IMUGyro.gyroX, IMUGyro.gyroY, IMUGyro.gyroZ, IMUAccel.accelX, IMUAccel.accelY, IMUAccel.accelZ); float qw = filter.getQuatW(); float qx = filter.getQuatX(); float qy = filter.getQuatY(); float qz = filter.getQuatZ(); double heading{0}, bank{0}, attitude{0}; double sqw = qw*qw; double sqx = qx*qx; double sqy = qy*qy; double sqz = qz*qz; double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor double test = qx*qy + qz*qw; if (test > 0.499*unit) { // singularity at north pole heading = 2 * atan2(qx,qw); attitude = M_PI/2; bank = 0; return; } if (test < -0.499*unit) { // singularity at south pole heading = -2 * atan2(qx,qw); attitude = M_PI/2; bank = 0; return; } heading = atan2(2*qy*qw-2*qx*qz , sqx - sqy - sqz + sqw); attitude = asin(2*test/unit); bank = atan2(2*qx*qw-2*qy*qz , -sqx + sqy - sqz + sqw); pitch = heading; roll = bank; yaw = attitude; #ifdef PRINT_ANGLES Serial.print("Roll: "); Serial.print(roll, 5); Serial.print("\tPitch: "); Serial.print(pitch, 5); Serial.print("\tYaw: "); Serial.println(yaw, 5); #endif // PRINT_ANGLES #ifdef PRINT_QUAT Serial.print("QW: "); Serial.print(qw, 5); Serial.print("\tQX: "); Serial.print(qx, 5); Serial.print("\tQY: "); Serial.print(qy, 5); Serial.print("\tQZ: "); Serial.println(qz, 5); #endif // PRINT_QUAT }