/*
smaller EKF for simpler estimation applications
Converted from Matlab to C++ by Paul Riseborough
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, see .
*/
#pragma once
#include
#include
//#include
#include
class SoloGimbalEKF
{
public:
typedef float ftype;
#if MATH_CHECK_INDEXES
typedef VectorN Vector13;
#else
typedef ftype Vector13[13];
#endif
// Constructor
SoloGimbalEKF();
// Run the EKF main loop once every time we receive sensor data
void RunEKF(float delta_time, const Vector3f &delta_angles, const Vector3f &delta_velocity, const Vector3f &joint_angles);
void reset();
// get gyro bias data
void getGyroBias(Vector3f &gyroBias) const;
// set gyro bias
void setGyroBias(const Vector3f &gyroBias);
// get quaternion data
void getQuat(Quaternion &quat) const;
// get filter alignment status - true is aligned
bool getStatus(void) const;
static const struct AP_Param::GroupInfo var_info[];
private:
// the states are available in two forms, either as a Vector13 or
// broken down as individual elements. Both are equivalent (same
// memory)
Vector13 states;
struct state_elements {
Vector3f angErr; // 0..2 rotation vector representing the growth in angle error since the last state correction (rad)
Vector3f velocity; // 3..5 NED velocity (m/s)
Vector3f delAngBias; // 6..8 estimated bias errors in the IMU delta angles
Quaternion quat; // 9..12 these states are used by the INS prediction only and are not used by the EKF state equations.
} &state;
// data from sensors
struct {
Vector3f delAng;
Vector3f delVel;
float gPhi;
float gPsi;
float gTheta;
} gSense;
float Cov[9][9]; // covariance matrix
Matrix3f Tsn; // Sensor to NED rotation matrix
float TiltCorrectionSquared; // Angle correction applied to tilt from last velocity fusion (rad)
bool newDataMag; // true when new magnetometer data is waiting to be used
uint32_t StartTime_ms; // time the EKF was started (msec)
bool FiltInit; // true when EKF is initialised
bool YawAligned; // true when EKF heading is initialised
float cosPhi;// = cosf(gSense.gPhi);
float cosTheta;// = cosf(gSense.gTheta);
float sinPhi;// = sinf(gSense.gPhi);
float sinTheta;// = sinf(gSense.gTheta);
float sinPsi;// = sinf(gSense.gPsi);
float cosPsi;// = cosf(gSense.gPsi);
uint32_t lastMagUpdate;
Vector3f magData;
uint32_t imuSampleTime_ms;
float dtIMU;
// States used for unwrapping of compass yaw error
float innovationIncrement;
float lastInnovation;
// state prediction
void predictStates();
// EKF covariance prediction
void predictCovariance();
// EKF velocity fusion
void fuseVelocity();
// read magnetometer data
void readMagData();
// EKF compass fusion
void fuseCompass();
// Perform an initial heading alignment using the magnetic field and assumed declination
void alignHeading();
// Calculate magnetic heading innovation
float calcMagHeadingInnov();
// Force symmmetry and non-negative diagonals on state covarinace matrix
void fixCovariance();
};