diff --git a/flight/AHRS/ahrs.c b/flight/AHRS/ahrs.c index fce7bb4b6..4ff83d09c 100644 --- a/flight/AHRS/ahrs.c +++ b/flight/AHRS/ahrs.c @@ -608,7 +608,10 @@ bool get_accel_gyro_data() * the fuselage, Y is along right the wing, and Z is down. */ void adc_callback(float * downsampled_data) -{ +{ + AHRSSettingsData settings; + AHRSSettingsGet(&settings); + float accel[3], gyro[3]; // Accel data is (y,x,z) in first third and fifth byte. Convert to m/s accel[0] = (downsampled_data[2] * accel_data.calibration.scale[0]) + accel_data.calibration.bias[0]; @@ -620,6 +623,19 @@ void adc_callback(float * downsampled_data) gyro[1] = (downsampled_data[3] * gyro_data.calibration.scale[1]) + gyro_data.calibration.bias[1]; gyro[2] = (downsampled_data[5] * gyro_data.calibration.scale[2]) + gyro_data.calibration.bias[2]; +#if 0 + static float gravity_tracking[3] = {0,0,0}; + const float tau = 0.9999; + gravity_tracking[0] = tau * gravity_tracking[0] + (1-tau) * accel[0]; + gravity_tracking[1] = tau * gravity_tracking[1] + (1-tau) * accel[1]; + gravity_tracking[2] = tau * gravity_tracking[2] + (1-tau) * (accel[2] + 9.81); + + if(settings.BiasCorrectedRaw == AHRSSETTINGS_BIASCORRECTEDRAW_TRUE) { + accel[0] -= gravity_tracking[0]; + accel[1] -= gravity_tracking[1]; + accel[2] -= gravity_tracking[2]; + } +#endif if(fifoBuf_getFree(&adc_fifo_buffer) >= (sizeof(accel) + sizeof(gyro))) { fifoBuf_putData(&adc_fifo_buffer, (uint8_t *) &accel[0], sizeof(accel)); fifoBuf_putData(&adc_fifo_buffer, (uint8_t *) &gyro[0], sizeof(gyro)); @@ -650,8 +666,6 @@ void adc_callback(float * downsampled_data) raw.magnetometers[1] = mag_data.scaled.axis[1]; raw.magnetometers[2] = mag_data.scaled.axis[2]; - AHRSSettingsData settings; - AHRSSettingsGet(&settings); if(settings.BiasCorrectedRaw == AHRSSETTINGS_BIASCORRECTEDRAW_TRUE) { raw.gyros_filtered[0] -= Nav.gyro_bias[0] * 180 / M_PI; raw.gyros_filtered[1] -= Nav.gyro_bias[1] * 180 / M_PI; diff --git a/flight/AHRS/inc/insgps13state.h b/flight/AHRS/inc/insgps13state.h new file mode 100644 index 000000000..b05d8b868 --- /dev/null +++ b/flight/AHRS/inc/insgps13state.h @@ -0,0 +1,90 @@ +/** + ****************************************************************************** + * @addtogroup AHRS + * @{ + * @addtogroup INSGPS + * @{ + * @brief INSGPS is a joint attitude and position estimation EKF + * + * @file insgps.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Include file of the INSGPS exposed functionality. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef INSGPS_H_ +#define INSGPS_H_ + +#include "stdint.h" + +/** + * @addtogroup Constants + * @{ + */ +#define POS_SENSORS 0x007 +#define HORIZ_SENSORS 0x018 +#define VERT_SENSORS 0x020 +#define MAG_SENSORS 0x1C0 +#define BARO_SENSOR 0x200 + +#define FULL_SENSORS 0x3FF + +/** + * @} + */ + +// Exposed Function Prototypes +void INSGPSInit(); +void INSStatePrediction(float gyro_data[3], float accel_data[3], float dT); +void INSCovariancePrediction(float dT); +void INSCorrection(float mag_data[3], float Pos[3], float Vel[3], float BaroAlt, uint16_t SensorsUsed); + +void INSResetP(float PDiag[13]); +void INSSetState(float pos[3], float vel[3], float q[4], float gyro_bias[3]); +void INSSetPosVelVar(float PosVar, float VelVar); +void INSSetGyroBias(float gyro_bias[3]); +void INSSetAccelVar(float accel_var[3]); +void INSSetGyroVar(float gyro_var[3]); +void INSSetMagNorth(float B[3]); +void INSSetMagVar(float scaled_mag_var[3]); +void INSPosVelReset(float pos[3], float vel[3]); + +void MagCorrection(float mag_data[3]); +void MagVelBaroCorrection(float mag_data[3], float Vel[3], float BaroAlt); +void FullCorrection(float mag_data[3], float Pos[3], float Vel[3], + float BaroAlt); +void GpsBaroCorrection(float Pos[3], float Vel[3], float BaroAlt); +void GpsMagCorrection(float mag_data[3], float Pos[3], float Vel[2]); +void VelBaroCorrection(float Vel[3], float BaroAlt); + +// Nav structure containing current solution +struct NavStruct { + float Pos[3]; // Position in meters and relative to a local NED frame + float Vel[3]; // Velocity in meters and in NED + float q[4]; // unit quaternion rotation relative to NED + float gyro_bias[3]; +} Nav; + +/** + * @} + * @} + */ + +#endif /* EKF_H_ */ diff --git a/flight/AHRS/insgps13state.c b/flight/AHRS/insgps13state.c new file mode 100644 index 000000000..e7cbb0a56 --- /dev/null +++ b/flight/AHRS/insgps13state.c @@ -0,0 +1,1637 @@ +/** + ****************************************************************************** + * @addtogroup AHRS + * @{ + * @addtogroup INSGPS + * @{ + * @brief INSGPS is a joint attitude and position estimation EKF + * + * @file insgps.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief An INS/GPS algorithm implemented with an EKF. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "insgps13state.h" +#include +#include + +// constants/macros/typdefs +#define NUMX 13 // number of states, X is the state vector +#define NUMW 9 // number of plant noise inputs, w is disturbance noise vector +#define NUMV 10 // number of measurements, v is the measurement noise vector +#define NUMU 6 // number of deterministic inputs, U is the input vector + +#if defined(GENERAL_COV) +// This might trick people so I have a note here. There is a slower but bigger version of the +// code here but won't fit when debugging disabled (requires -Os) +#define COVARIANCE_PREDICTION_GENERAL +#endif + +// Private functions +void CovariancePrediction(float F[NUMX][NUMX], float G[NUMX][NUMW], + float Q[NUMW], float dT, float P[NUMX][NUMX]); +void SerialUpdate(float H[NUMV][NUMX], float R[NUMV], float Z[NUMV], + float Y[NUMV], float P[NUMX][NUMX], float X[NUMX], + uint16_t SensorsUsed); +void RungeKutta(float X[NUMX], float U[NUMU], float dT); +void StateEq(float X[NUMX], float U[NUMU], float Xdot[NUMX]); +void LinearizeFG(float X[NUMX], float U[NUMU], float F[NUMX][NUMX], + float G[NUMX][NUMW]); +void MeasurementEq(float X[NUMX], float Be[3], float Y[NUMV]); +void LinearizeH(float X[NUMX], float Be[3], float H[NUMV][NUMX]); + +// Private variables +float F[NUMX][NUMX], G[NUMX][NUMW], H[NUMV][NUMX]; // linearized system matrices + // global to init to zero and maintain zero elements +float Be[3]; // local magnetic unit vector in NED frame +float P[NUMX][NUMX], X[NUMX]; // covariance matrix and state vector +float Q[NUMW], R[NUMV]; // input noise and measurement noise variances +float K[NUMX][NUMV]; // feedback gain matrix + +// ************* Exposed Functions **************** +// ************************************************* +void INSGPSInit() //pretty much just a place holder for now +{ + Be[0] = 1; + Be[1] = 0; + Be[2] = 0; // local magnetic unit vector + + for (int i = 0; i < NUMX; i++) { + for (int j = 0; j < NUMX; j++) { + P[i][j] = 0; // zero all terms + } + } + + P[0][0] = P[1][1] = P[2][2] = 25; // initial position variance (m^2) + P[3][3] = P[4][4] = P[5][5] = 5; // initial velocity variance (m/s)^2 + P[6][6] = P[7][7] = P[8][8] = P[9][9] = 1e-5; // initial quaternion variance + P[10][10] = P[11][11] = P[12][12] = 1e-5; // initial gyro bias variance (rad/s)^2 + + X[0] = X[1] = X[2] = X[3] = X[4] = X[5] = 0; // initial pos and vel (m) + X[6] = 1; + X[7] = X[8] = X[9] = 0; // initial quaternion (level and North) (m/s) + X[10] = X[11] = X[12] = 0; // initial gyro bias (rad/s) + + Q[0] = Q[1] = Q[2] = 50e-8; // gyro noise variance (rad/s)^2 + Q[3] = Q[4] = Q[5] = 0.01; // accelerometer noise variance (m/s^2)^2 + Q[6] = Q[7] = Q[8] = 2e-14; // gyro bias random walk variance (rad/s^2)^2 + + R[0] = R[1] = 0.004; // High freq GPS horizontal position noise variance (m^2) + R[2] = 0.036; // High freq GPS vertical position noise variance (m^2) + R[3] = R[4] = 0.004; // High freq GPS horizontal velocity noise variance (m/s)^2 + R[5] = 100; // High freq GPS vertical velocity noise variance (m/s)^2 + R[6] = R[7] = R[8] = 0.005; // magnetometer unit vector noise variance + R[9] = .05; // High freq altimeter noise variance (m^2) +} + +void INSResetP(float PDiag[NUMX]) +{ + uint8_t i,j; + + // if PDiag[i] nonzero then clear row and column and set diagonal element + for (i=0;i