Skip to content

Commit dba9b75

Browse files
authored
Merge pull request #9 from jonasBoss/master
Added function to initialize the Quaternions
2 parents bf3c639 + 4b64265 commit dba9b75

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

src/SensorFusion.cpp

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,95 @@ void SF::MadgwickUpdate(float gx, float gy, float gz, float ax, float ay, float
431431
anglesComputed = 0;
432432
}
433433

434+
435+
bool SF::initQuat(float ax, float ay, float az, float mx, float my, float mz){
436+
// Compute feedback only if accelerometer measurement valid
437+
// (avoids NaN in accelerometer normalisation)
438+
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
439+
float recipNorm;
440+
float N[3], D[3], E[3]; //Global vectors North, Down, East relative to sensor
441+
442+
// Down is negative accelerometer measurement
443+
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
444+
D[0] = - ax * recipNorm;
445+
D[1] = - ay * recipNorm;
446+
D[2] = - az * recipNorm;
447+
448+
// Magnetometer is not exatly perpendicular to Down, therefor not exatly North
449+
// we will calculate North later
450+
float m[3];
451+
recipNorm = invSqrt(mx * mx + my * my + mz * mz);
452+
m[0] = mx * recipNorm;
453+
m[1] = mx * recipNorm;
454+
m[2] = mx * recipNorm;
455+
456+
// Calculate East
457+
vectorCross(m, D, E);
458+
recipNorm = invSqrt(E[0] * E[0] + E[1] * E[1] + E[2] * E[2]);
459+
E[0] *= recipNorm;
460+
E[1] *= recipNorm;
461+
E[2] *= recipNorm;
462+
463+
// Calculate North
464+
vectorCross(D, E, N);
465+
466+
// Calculate Euler Parameter (quaternion) from the rotation matrix A=(N|D|E).
467+
// Using Shepperd algorithm (Woernle 2011)
468+
float Trace = N[0] + D[1] + E[2];
469+
float a[4] = {Trace, N[0], D[1], E[2]};
470+
float e[4];
471+
472+
//find index of Largest Euler parameter
473+
int k=0;
474+
for (int i=1; i<4; i++){
475+
if (a[i] > a[k])
476+
k = i;
477+
}
478+
//calculate that parameter
479+
e[k] = sqrt(1 + 2 * a[k] - Trace)/2;
480+
481+
switch (k){
482+
case 0:
483+
e[1] = (D[2] - E[1]) / (4 * e[0]);
484+
e[2] = (E[0] - N[2]) / (4 * e[0]);
485+
e[3] = (N[1] - D[0]) / (4 * e[0]);
486+
break;
487+
case 1:
488+
e[0] = (D[2] - E[1]) / (4 * e[1]);
489+
e[2] = (D[0] + N[1]) / (4 * e[1]);
490+
e[3] = (E[0] + N[2]) / (4 * e[1]);
491+
break;
492+
case 2:
493+
e[0] = (E[0] - N[2]) / (4 * e[2]);
494+
e[1] = (D[0] + N[1]) / (4 * e[2]);
495+
e[3] = (E[1] + D[2]) / (4 * e[2]);
496+
break;
497+
case 3:
498+
e[0] = (N[1] - D[0]) / (4 * e[3]);
499+
e[1] = (E[0] + N[2]) / (4 * e[3]);
500+
e[2] = (E[1] + D[2]) / (4 * e[3]);
501+
}
502+
503+
// invert the quaternion rotation
504+
// we calculated the rotation of Global NDE relative to the sensor
505+
// but we need the rotation of the Sensor relative to NDE
506+
q0 = e[0];
507+
q1 = -e[1];
508+
q2 = -e[2];
509+
q3 = -e[3];
510+
511+
return true;
512+
} else return false;
513+
}
514+
515+
void SF::vectorCross(float A[3], float B[3], float cross[3])
516+
{
517+
cross[0] = A[1] * B[2] - A[2] * B[1];
518+
cross[1] = A[2] * B[0] - A[0] * B[2];
519+
cross[2] = A[0] * B[1] - A[1] * B[0];
520+
}
521+
522+
434523
//============================================================================================
435524
// END OF CODE
436-
//============================================================================================
525+
//============================================================================================

src/SensorFusion.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class SF {
3535
void MadgwickUpdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz, float deltat);
3636
void MadgwickUpdate(float gx, float gy, float gz, float ax, float ay, float az, float deltat);
3737

38+
// find initial Quaternios
39+
// it is good practice to provide mean values from multiple measurements
40+
bool initQuat(float ax, float ay, float az, float mx, float my, float mz);
3841
//these values are already defined by arduino
3942
//const float DEG_TO_RAD = 0.0174532925199433f; //PI/180.0f;
4043
//const float RAD_TO_DEG = 57.29577951308233f; //180.0f/PI
@@ -83,6 +86,7 @@ class SF {
8386
float integralFBx, integralFBy, integralFBz; // integral error terms scaled by Ki
8487
bool anglesComputed;
8588
static float invSqrt(float x);
89+
void vectorCross(float A[3], float B[3], float cross[3]);
8690
void computeAngles();
8791
float roll, pitch, yaw;
8892
float Now,lastUpdate,deltat;

0 commit comments

Comments
 (0)