SPI slave program to enable communication between the FPGA and the STM32L432 board.

Dependencies:   mbed

Quaternions.cpp

Committer:
Zbyszek
Date:
2019-05-15
Revision:
15:791f35b0f220
Parent:
13:c7e8e277f884

File content as of revision 15:791f35b0f220:

#include "Quaternions.h"
#include "CustomDatatypes.h"
#include <math.h>


//----------------------------------------------------------------------------------------------------------------//
/*
 *Takes the angular rate in roll, pitch, yaw form and converts it into quaternion notation
*/
Quaternion toQuaternionNotation(vector AngularRate, double dt) {
//--------------Variables--------------//
    Quaternion q;
//--------------Variables--------------//
    
    
    double l = sqrt(pow(AngularRate.x, 2) + pow(AngularRate.y, 2) + pow(AngularRate.z, 2));      //Normalise the quaternion such that it a unit quaternion between 0 and 1.
    double theta = (dt * l) / 2;                                                //Get Theta in quaternions
    
    //double thetaRad = theta * 0.01745; // 0.01745 = pi/180
                                                                                //Convert each component of rotation
    q.w = cosf(theta);                                                          //* Magnitude 
    q.x = sinf(theta) * (AngularRate.x / l);                                    //*
    q.y = sinf(theta) * (AngularRate.y / l);                                    //*
    q.z = sinf(theta) * (AngularRate.z / l);                                    //*
                                                                                //Convert each component of rotation
    return q;
}
//----------------------------------------------------------------------------------------------------------------//


Quaternion toQuaternionNotation123(vector AngularRate, double dt) {
//--------------Variables--------------//
    Quaternion Q;
    float Sin_Mag;
//--------------Variables--------------//
    
    Q.x  = AngularRate.x * dt;
    Q.y  = AngularRate.y * dt;
    Q.z  = AngularRate.z * dt;
    Q.w  = 1.0f - 0.5f * (Q.x * Q.x +Q.y * Q.y + Q.z * Q.z);
    
    
    
    double l = sqrt(pow(AngularRate.x, 2) + pow(AngularRate.y, 2) + pow(AngularRate.z, 2));      //Normalise the quaternion such that it a unit quaternion between 0 and 1.
    double theta = l / 2;                                                //Get Theta in quaternions
    
    //double thetaRad = theta * 0.01745; // 0.01745 = pi/180
    
    Sin_Mag = sin(theta) / l;  
                                                                                //Convert each component of rotation
    Q.x = AngularRate.x * Sin_Mag;
    Q.y = AngularRate.y * Sin_Mag;
    Q.z = AngularRate.z * Sin_Mag;
    Q.w = cos(theta);                                                                            
                                                                                
    return Q;
}
//----------------------------------------------------------------------------------------------------------------//






//----------------------------------------------------------------------------------------------------------------//
/*
 *This function updates the old orientation by rotating the reference frame by
 *the change in angle. All this is done in quaternion form.
 */
Quaternion getQuaternionProduct(Quaternion Q1, Quaternion Q2) {
//--------------Variables--------------//
    Quaternion currentQ;
//--------------Variables--------------//    
    
    
    // Piecewise matrix multiplication
    currentQ.w = (Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z);
    currentQ.x = (Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y);
    currentQ.y = (Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x);
    currentQ.z = (Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w);
    
    return currentQ;

}
//----------------------------------------------------------------------------------------------------------------//



//----------------------------------------------------------------------------------------------------------------//
/*
 *This function updates the old orientation by rotating the reference frame by
 *the change in angle. All this is done in quaternion form.
 */
Quaternion getQVproduct(Quaternion Q, vector v) {
//--------------Variables--------------//
    Quaternion currentQ;
//--------------Variables--------------//    
    
    
    // Piecewise matrix multiplication
    currentQ.x = (Q.w*v.x + Q.z*v.y - Q.y*v.z);
    currentQ.y = (Q.w*v.y + Q.x*v.z - Q.z*v.x);
    currentQ.z = (Q.y*v.x - Q.x*v.y + Q.w*v.z);
    currentQ.w = (-Q.x*v.x - Q.y*v.y - Q.z*v.z);
    
    return currentQ;

}
//----------------------------------------------------------------------------------------------------------------//







//----------------------------------------------------------------------------------------------------------------//
Quaternion quaternionConjugate(Quaternion Q) {
//--------------Variables--------------//
    Quaternion localQ;
//--------------Variables--------------//   
    
    localQ.w = Q.w;
    localQ.x = -Q.x;
    localQ.y = -Q.y;
    localQ.z = -Q.z;
    
    return localQ;
    
}
//----------------------------------------------------------------------------------------------------------------//

//----------------------------------------------------------------------------------------------------------------//
Quaternion sumQuaternion(Quaternion Q1, Quaternion Q2) {
//--------------Variables--------------//
    Quaternion localQ;
//--------------Variables--------------//   
    
    localQ.w = Q1.w + Q2.w;
    localQ.x = Q1.x + Q2.x;
    localQ.y = Q1.y + Q2.y;
    localQ.z = Q1.z + Q2.z;
    
    return localQ;
    
}
//----------------------------------------------------------------------------------------------------------------//


//----------------------------------------------------------------------------------------------------------------//
vector sumVector(vector v1, vector v2) {
//--------------Variables--------------//
    vector localv;
//--------------Variables--------------//   
    
    localv.x = v1.x + v2.x;
    localv.y = v1.y + v2.y;
    localv.z = v1.z + v2.z;
    
    return localv;
    
}
//----------------------------------------------------------------------------------------------------------------//







//----------------------------------------------------------------------------------------------------------------//
vector rotateVector(Quaternion Q, vector v) {
//--------------Variables--------------//
Quaternion vectorQ;
Quaternion Qconjugate;
Quaternion rotationQ;
vector localv;
vector rotatedVector;
//--------------Variables--------------// 

    localv = v;  
    vectorQ = vector2Quaternion(localv);
    Qconjugate = quaternionConjugate(Q);
    
    //q*p*q*. Our point is our rotation axis therefore q*v*q*
    rotationQ = getQuaternionProduct(Q, vectorQ);
    rotationQ = getQuaternionProduct(rotationQ, Qconjugate);
    rotatedVector = quaternion2Vector(rotationQ);
    
    return rotatedVector;
    
}
//----------------------------------------------------------------------------------------------------------------//








//----------------------------------------------------------------------------------------------------------------//
Quaternion vector2Quaternion(vector v) {
//--------------Variables--------------//
Quaternion localQ;
//--------------Variables--------------//   
    
    localQ.w = 0;
    localQ.x = v.x;
    localQ.y = v.y;
    localQ.z = v.z;

    return localQ; 
}
//----------------------------------------------------------------------------------------------------------------//








//----------------------------------------------------------------------------------------------------------------//
vector quaternion2Vector(Quaternion Q) {
//--------------Variables--------------//
vector localv;
//--------------Variables--------------//   
    
    localv.x = Q.x;
    localv.y = Q.y;
    localv.z = Q.z;

    return localv; 
}
//----------------------------------------------------------------------------------------------------------------//






//----------------------------------------------------------------------------------------------------------------//
Quaternion normaliseQuaternion(Quaternion Q) {
//--------------Variables--------------//
Quaternion localQ;
double l;
//--------------Variables--------------// 
    localQ = Q;  
    l = getQuaternionNorm(localQ);
    
    localQ.w = localQ.w / l;
    localQ.x = localQ.x / l;
    localQ.y = localQ.y / l;
    localQ.z = localQ.z / l;

    return localQ; 
}
//----------------------------------------------------------------------------------------------------------------//








//----------------------------------------------------------------------------------------------------------------//
double getQuaternionNorm(Quaternion Q) {
//--------------Variables--------------//
double l;
//--------------Variables--------------//   
    
    l = sqrt(pow(Q.w, 2) + pow(Q.x, 2) + pow(Q.y, 2) + pow(Q.z, 2));      //Normalise the quaternion such that it a unit quaternion between 0 and 1.

    return l; 
}
//----------------------------------------------------------------------------------------------------------------//



//----------------------------------------------------------------------------------------------------------------//
Quaternion getQaDelta(Quaternion Q) {
//--------------Variables--------------//
Quaternion localQ;
//--------------Variables--------------//   
    
    localQ.w = sqrt((Q.z+1)/2);
    localQ.x = -(Q.y/sqrt(2*(Q.z +1 )));
    localQ.y = Q.x/sqrt(2*(Q.z +1 ));
    localQ.z = 0;

    return localQ; 
}
//----------------------------------------------------------------------------------------------------------------//




//----------------------------------------------------------------------------------------------------------------//
vector crossProduct(vector v1, vector v2) {
//--------------Variables--------------//
vector localv;
//--------------Variables--------------//   
    
    
    localv.x = v1.y * v2.z - v1.z * v2.y;
    localv.y = v1.z * v2.x - v1.x * v2.z;
    localv.z = v1.x * v2.y - v1.y * v2.x;
    
    return localv; 
}
//----------------------------------------------------------------------------------------------------------------//

//----------------------------------------------------------------------------------------------------------------//
vector rotateGlobal(vector v1, Quaternion Q) {
//--------------Variables--------------//
vector localv;
Quaternion localQ1;
Quaternion localQ2;
Quaternion localQconjugate;
vector r;
//--------------Variables--------------//   
    
    localQconjugate = quaternionConjugate(Q);
    localQ1 = getQVproduct(Q, v1);
    localQ2 = getQuaternionProduct(localQ1, localQconjugate);
    localv = quaternion2Vector(localQ2);
    
    return localv;
    
    //r.x = -Q.x;
    //r.y = -Q.y;
    //r.z = -Q.z;
    //return sumVector(v1, crossProduct(sumVector(r, r), sumVector(crossProduct(r, v1), mul(Q.w, v1))));
}
//----------------------------------------------------------------------------------------------------------------//

vector mul(float b, vector a) {
    
    
    
    a.x *= b;
    a.y *= b;
    a.z *= b;
    
    return a;
}    


//----------------------------------------------------------------------------------------------------------------//
vector rotateLocal(vector v1, Quaternion Q) {
//--------------Variables--------------//
vector localv;
Quaternion localQ1;
Quaternion localQ2;
Quaternion localQconjugate;
vector r;
//--------------Variables--------------//   
    
    localQconjugate = quaternionConjugate(Q);
    localQ1 = getQVproduct(localQconjugate, v1);
    localQ2 = getQuaternionProduct(localQ1, Q);
    localv = quaternion2Vector(localQ2);
    
    return localv;
    
    
    //r.x = Q.x;
    //r.y = Q.y;
    //r.z = Q.z;
    
    //return sumVector(v1, crossProduct(sumVector(r, r), sumVector(crossProduct(r, v1), mul(Q.w, v1))));
}
//----------------------------------------------------------------------------------------------------------------//




//----------------------------------------------------------------------------------------------------------------//
Quaternion updateQuaternion(Quaternion Qprevious, vector angularRate, double deltaTime)
{
    vector AngularRates;
    Quaternion localQ, Qprime;
    
    //The angular rates will be sent from each IMU object in form a structure and not an array and therefroe the angularRate[] will have to be chnaged
    AngularRates.x = angularRate.x;
    AngularRates.y = angularRate.y;
    AngularRates.z = angularRate.z;
    
    //Need to add variable delta_t when I add the function that gets me the time between samples
    localQ = toQuaternionNotation(AngularRates, deltaTime);
    Qprime = getQuaternionProduct(Qprevious, localQ); // Perform the rotation on the old quaternion
    
    return Qprime;
}
//----------------------------------------------------------------------------------------------------------------//



//----------------------------------------------------------------------------------------------------------------//
vector eulerA(Quaternion Q)
{
    vector EulerAngles;
    

    
    EulerAngles.x = atan2((2*(Q.w*Q.x + Q.y*Q.z)), (pow(Q.w,2)-pow(Q.x,2)-pow(Q.y,2)+pow(Q.z,2))) * (180.0f/3.141592654f); //atan2 returns the angle between -π and π radians (equivalent to -180 and 180 degrees)
    EulerAngles.y = -asin(2*(Q.x*Q.z - Q.w*Q.y)) * (180.0f/3.141592654f); //asin returns the angle between -π/2 and π/2 radians (equivalent to -90 and 90 degrees) 
    EulerAngles.z = atan2((2*(Q.w*Q.z + Q.x*Q.y)), (pow(Q.w,2)+pow(Q.x,2)-pow(Q.y,2)-pow(Q.z,2))) * (180.0f/3.141592654f);
   
    return EulerAngles;
}
//----------------------------------------------------------------------------------------------------------------//



//----------------------------------------------------------------------------------------------------------------//
Quaternion euler2Quaternion(Quaternion Q)
{
    
    

    // Abbreviations for the various angular functions
    double cy = cosf(Q.z * 0.5f);
    double sy = sinf(Q.z * 0.5f);
    double cp = cosf(Q.y * 0.5f);
    double sp = sinf(Q.y * 0.5f);
    double cr = cosf(Q.x * 0.5f);
    double sr = sinf(Q.x * 0.5f);

    Quaternion q;
    q.w = cy * cp * cr + sy * sp * sr;
    q.x = cy * cp * sr - sy * sp * cr;
    q.y = sy * cp * sr + cy * sp * cr;
    q.z = sy * cp * cr - cy * sp * sr;
    
    return q;

}
//----------------------------------------------------------------------------------------------------------------//