AHRS based on MatrixPilot DCM algorithm; ported from Pololu MinIMU-9 example code in turn based on ArduPilot 1.5

Revision:
0:62284d27d75e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DCM.h	Tue Jan 24 17:40:40 2012 +0000
@@ -0,0 +1,168 @@
+/*
+MinIMU-9-mbed-AHRS
+Pololu MinIMU-9 + mbed AHRS (Attitude and Heading Reference System)
+
+Modified and ported to mbed environment by Michael Shimniok
+http://www.bot-thoughts.com/
+
+Basedd on MinIMU-9-Arduino-AHRS
+Pololu MinIMU-9 + Arduino AHRS (Attitude and Heading Reference System)
+
+Copyright (c) 2011 Pololu Corporation.
+http://www.pololu.com/
+
+MinIMU-9-Arduino-AHRS is based on sf9domahrs by Doug Weibel and Jose Julio:
+http://code.google.com/p/sf9domahrs/
+
+sf9domahrs is based on ArduIMU v1.5 by Jordi Munoz and William Premerlani, Jose
+Julio and Doug Weibel:
+http://code.google.com/p/ardu-imu/
+
+MinIMU-9-Arduino-AHRS is free software: you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+MinIMU-9-Arduino-AHRS is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with MinIMU-9-Arduino-AHRS. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef __DCM_H
+#define __DCM_H
+
+#define GRAVITY 1024  //this equivalent to 1G in the raw data coming from the accelerometer 
+#define Accel_Scale(x) x*(GRAVITY/9.81)//Scaling the raw data of the accel to actual acceleration in meters for seconds square
+
+#define ToRad(x) ((x)*0.01745329252)  // *pi/180
+#define ToDeg(x) ((x)*57.2957795131)  // *180/pi
+
+//#define Kp_ROLLPITCH 0.02
+//#define Ki_ROLLPITCH 0.00002
+//#define Kp_YAW 1.2
+//#define Ki_YAW 0.00002
+#define Kp_ROLLPITCH 0.02
+#define Ki_ROLLPITCH 0.00002
+#define Kp_YAW 1.2
+#define Ki_YAW 0.00002
+
+#define OUTPUTMODE 1 // enable drift correction
+
+// TODO: move elsewhere
+// Gyro sensor hardware-specific stuff
+#define Gyro_Gain_X 0.07 //X axis Gyro gain
+#define Gyro_Gain_Y 0.07 //Y axis Gyro gain
+#define Gyro_Gain_Z 0.07 //Z axis Gyro gain
+#define Gyro_Scaled_X(x) ((x)*ToRad(Gyro_Gain_X)) //Return the scaled ADC raw data of the gyro in radians per second
+#define Gyro_Scaled_Y(x) ((x)*ToRad(Gyro_Gain_Y)) //Return the scaled ADC raw data of the gyro in radians per second
+#define Gyro_Scaled_Z(x) ((x)*ToRad(Gyro_Gain_Z)) //Return the scaled ADC raw data of the gyro in radians per second
+
+/** DCM AHRS algorithm ported to mbed from Pololu MinIMU-9 in turn ported from ArduPilot 1.5
+ * revised in a more OO style, though no done yet.
+ *
+ * Early version. There's more to do here but it's a start, at least.
+ *
+ * Warning: Interface will most likely change.
+ *
+ * Expects to see a Sensors.h in your project, as follows, with functions that read sensors and set the appropriate 
+ * "input" member variables below. Eventually I'll change this to a better encapsulated OOP approach. 
+ *
+ * This approach of an external Sensors.* is an abstraction layer that makes it much, much easier to
+ * swap in a different sensor suite versus the original code. You can use Serial, I2C, SPI, Analog,
+ * whatever you want, whatever it takes as long as you populate the gyro, accel, and mag vectors before
+ * calling Update_step()
+ *
+ * @code
+ * #ifndef __SENSORS_H
+ * #define __SENSORS_H
+ *
+ * void Gyro_Init(void);
+ * void Read_Gyro(void);
+ * void Accel_Init(void);
+ * void Read_Accel(void);
+ * void Compass_Init(void);
+ * void Read_Compass(void);
+ * void Calculate_Offsets(void);
+ * void Compass_Heading(void);
+ * 
+ * #endif
+ * @endcode
+ *
+ */
+class DCM {
+    public:
+        /** Output: Euler angle: roll */
+        float roll;
+        /** Output:  Euler angle: pitch */
+        float pitch;
+        /** Output:  Euler angle: yaw */
+        float yaw;
+        
+        /** Input gyro sensor reading X-axis */
+        int gyro_x;
+        /** Input gyro sensor reading Y-axis */
+        int gyro_y;
+        /** Input gyro sensor reading Z-axis */
+        int gyro_z;
+        /** Input accelerometer sensor reading X-axis */
+        int accel_x;
+        /** Input accelerometer sensor reading Y-axis */
+        int accel_y;
+        /** Input accelerometer sensor reading Z-axis */
+        int accel_z;
+        /*
+        int magnetom_x;
+        int magnetom_y;
+        int magnetom_z;
+        */
+        /** Input for the offset corrected & scaled magnetometer reading, X-axis */
+        float c_magnetom_x;
+        /** Input for the offset corrected & scaled magnetometer reading, Y-axis */
+        float c_magnetom_y;
+        /** Input for the offset corrected & scaled magnetometer reading, Z-axis */
+        float c_magnetom_z;
+        /** Input for the calculated magnetic heading */
+        float MAG_Heading;
+        /** Input for the speed (ie, the magnitude of the 3d velocity vector */
+        float speed_3d;
+        /** Input for the integration time (DCM algorithm) */
+        float G_Dt;
+
+        /** Creates a new DCM AHRS algorithm object
+         */
+        DCM(void);
+
+        /** A single update cycle for the algorithm; updates the matrix, normalizes it, corrects for gyro
+         * drift on 3 axes, (does not yet adjust for acceleration). Magnetometer update is run less often
+         * than gyro/accelerometer-based update
+         */
+        void Update_step(void);
+        
+    private:        
+        float Accel_Vector[3];  // Store the acceleration in a vector
+        float Gyro_Vector[3];   // Store the gyros turn rate in a vector
+        float dcm[3][3];        // The Direction Cosine Matrix
+        float errorRollPitch[3]; 
+        float errorYaw[3];
+        float Omega_Vector[3];  // Corrected Gyro_Vector data
+        float Omega_P[3];       // Omega Proportional correction
+        float Omega_I[3];       // Omega Integrator
+        float Omega[3];         // Omega
+        float Temporary_Matrix[3][3];
+        float Update_Matrix[3][3];
+        int update_count;   // call Update_mag() every update_count calls to Update_step()
+        float constrain(float x, float a, float b);
+        void Normalize(void);
+        void Drift_correction(void);
+        void Accel_adjust(void);
+        void Matrix_update(void);
+        void Euler_angles(void);
+        void Update_mag(void);
+        
+};
+
+#endif
\ No newline at end of file