@@ -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+ // ============================================================================================
0 commit comments