Cubli library

AttitudeEstimator/AttitudeEstimator.cpp

Committer:
fbob
Date:
2019-02-25
Revision:
2:dc7840a67f77
Parent:
1:085840a3d767

File content as of revision 2:dc7840a67f77:

#include "mbed.h"
#include "AttitudeEstimator.h"

// Class constructor
AttitudeEstimator::AttitudeEstimator() : imu(A4,A5)
{
}

// Initialize class
void AttitudeEstimator::init()
{
    // Initialize IMU sensor object
    imu.init();

    dt = 0.005;
    dt_half = dt/2.0;
    
    x = eye(4,1);
    A = eye(4);
    P = eye(4);
    Q = 0.001*eye(4);
    R = 10.0*eye(4);
    H = eye(4);
    I = eye(4);
    
    g = zeros(3,1);
    a = zeros(3,1);
    m = zeros(3,1);
    
    q = zeros(4,1);
    
    BN = eye(3);

}

// Estimate euler angles (rad) and angular velocity (rad/s)
void AttitudeEstimator::estimate()
{
    // Read IMU sensor data
    read();
    get_output();
    
    float omega_x = g(1,1)*dt_half;
    float omega_y = g(2,1)*dt_half;
    float omega_z = g(3,1)*dt_half;
    
    /*A(1,1) = 1.0;
    A(1,2) = -g(1,1)*dt/2.0;
    A(1,3) = -g(2,1)*dt/2.0;
    A(1,4) = -g(3,1)*dt/2.0;
    A(2,1) = g(1,1)*dt/2.0;
    A(2,2) = 1.0;
    A(2,3) = g(3,1)*dt/2.0;
    A(2,4) = -g(2,1)*dt/2.0;
    A(3,1) = g(2,1)*dt/2.0;
    A(3,2) = -g(3,1)*dt/2.0;
    A(3,3) = 1.0;
    A(3,4) = g(1,1)*dt/2.0;
    A(4,1) = g(3,1)*dt/2.0;
    A(4,2) = g(2,1)*dt/2.0;
    A(4,3) = -g(1,1)*dt/2.0;
    A(4,4) = 1.0;*/
    
    A(1,2) = -omega_x;
    A(1,3) = -omega_y;
    A(1,4) = -omega_z;
    A(2,1) = omega_x;
    A(2,3) = omega_z;
    A(2,4) = -omega_y;
    A(3,1) = omega_y;
    A(3,2) = -omega_z;
    A(3,4) = omega_x;
    A(4,1) = omega_z;
    A(4,2) = omega_y;
    A(4,3) = -omega_x;

    x = A*x;
    x = x/norm(x);

    P = A*P*transpose(A)+Q;

    //K = P*transpose(H)*inverse(H*P*transpose(H)+R);
    K = P*inverse(P+R);

    //x = x+K*(q-H*x);
    x = x+K*(q-x);
    x = x/norm(x);
    //P = P-K*H*P;
    P = P-K*P;
    //P = P*(I-K*H);
    //P = P-K*(H*P*transpose(H)+R)*transpose(K);
    //P = (eye(4)-K*H)*P*transpose(eye(4)-K*H)+K*R*transpose(K);
}

void AttitudeEstimator::read()
{
    imu.read();
    g(1,1) = imu.gx-0.0099;
    g(2,1) = imu.gy+0.0693;
    g(3,1) = imu.gz-0.0339;
    a(1,1) = 1.0077*(imu.ax-0.0975);
    a(2,1) = 1.0061*(imu.ay-0.0600);
    a(3,1) = 0.9926*(imu.az-0.5156);
    m(1,1) = 0.8838*(imu.mx+21.0631);
    m(2,1) = 1.1537*(imu.my+8.9233);
    m(3,1) = 0.9982*(imu.mz-11.8958);
}

void AttitudeEstimator::get_output()
{
    a = a/norm(a);
    m = m/norm(m);

    Matrix t1(3,1), t2(3,1), t3(3,1);
    t1 = a;
    //t2 = cross(a,m)/norm(cross(a,m));
    t2 = cross(a,m);
    t2 = t2/norm(t2);
    t3 = cross(t1,t2);

    /*Matrix BT(3,3), NT(3,3);
    BT(1,1) = t1(1,1);
    BT(2,1) = t1(2,1);
    BT(3,1) = t1(3,1);
    BT(1,2) = t2(1,1);
    BT(2,2) = t2(2,1);
    BT(3,2) = t2(3,1);
    BT(1,3) = t3(1,1);
    BT(2,3) = t3(2,1);
    BT(3,3) = t3(3,1);

    NT(1,2) = -0.3666;
    NT(1,3) = -0.9304;
    NT(2,2) = -0.9304;
    NT(2,3) = 0.3666;
    NT(3,1) = -1.0;

    BN = BT*transpose(NT);*/
    
    
    BN(1,1) = -t3(1,1);
    BN(2,1) = -t3(2,1);
    BN(3,1) = -t3(3,1);
    BN(1,2) = -t2(1,1);
    BN(2,2) = -t2(2,1);
    BN(3,2) = -t2(3,1);
    BN(1,3) = -t1(1,1);
    BN(2,3) = -t1(2,1);
    BN(3,3) = -t1(3,1);

    /*q(4,1) =  0.0;

    float tr = trace(BN);
    if (tr > 0.0) {
        float sqtrp1 = sqrt( tr + 1.0);
        q(1,1) = 0.5*sqtrp1;
        q(2,1) = (BN(2,3) - BN(3,2))/(2.0*sqtrp1);
        q(3,1) = (BN(3,1) - BN(1,3))/(2.0*sqtrp1);
        q(4,1) = (BN(1,2) - BN(2,1))/(2.0*sqtrp1);
    } else {
        if ((BN(2,2) > BN(1,1)) && (BN(2,2) > BN(3,3))) {
            float sqdip1 = sqrt(BN(2,2) - BN(1,1) - BN(3,3) + 1.0 );
            q(3,1) = 0.5*sqdip1;
            if ( sqdip1 != 0 ) {
                sqdip1 = 0.5/sqdip1;
            }
            q(1,1) = (BN(3,1) - BN(1,3))*sqdip1;
            q(2,1) = (BN(1,2) + BN(2,1))*sqdip1;
            q(4,1) = (BN(2,3) + BN(3,2))*sqdip1;
        } else if (BN(3,3) > BN(1,1)) {
            float sqdip1 = sqrt(BN(3,3) - BN(1,1) - BN(2,2) + 1.0 );
            q(4,1) = 0.5*sqdip1;
            if ( sqdip1 != 0 ) {
                sqdip1 = 0.5/sqdip1;
            }
            q(1,1) = (BN(1,2) - BN(2,1))*sqdip1;
            q(2,1) = (BN(3,1) + BN(1,3))*sqdip1;
            q(3,1) = (BN(2,3) + BN(3,2))*sqdip1;
        } else {
            float sqdip1 = sqrt(BN(1,1) - BN(2,2) - BN(3,3) + 1.0 );
            q(2,1) = 0.5*sqdip1;
            if ( sqdip1 != 0 ) {
                sqdip1 = 0.5/sqdip1;
            }
            q(1,1) = (BN(2,3) - BN(3,2))*sqdip1;
            q(3,1) = (BN(1,2) + BN(2,1))*sqdip1;
            q(4,1) = (BN(3,1) + BN(1,3))*sqdip1;
        }
    }*/
    
    q = dcm2quat(BN);

    if((abs(x(1,1)) > abs(x(2,1))) && (abs(x(1,1)) > abs(x(3,1))) && (abs(x(1,1)) > abs(x(4,1)))) {
        if (((x(1,1) > 0) && (q(1,1) < 0)) || ((x(1,1) < 0) && (q(1,1) > 0))) {
            q = -q;
        }
    } else if ((abs(x(2,1)) > abs(x(3,1))) && (abs(x(2,1)) > abs(x(4,1)))) {
        if (((x(2,1) > 0) && (q(2,1) < 0)) || ((x(2,1) < 0) && (q(2,1) > 0))) {
            q = -q;
        }
    } else if ((abs(x(3,1)) > abs(x(4,1)))) {
        if (((x(3,1) > 0) && (q(3,1) < 0)) || ((x(3,1) < 0) && (q(3,1) > 0))) {
            q = -q;
        }
    } else {
        if (((x(4,1) > 0) && (q(4,1) < 0)) || ((x(4,1) < 0) && (q(4,1) > 0))) {
            q = -q;
        }
    }
}