/ARDroneLib/Soft/Lib/Maths/quaternions.c

https://github.com/zhengwy888/ARDrone-SDK_MF · C · 129 lines · 81 code · 23 blank · 25 comment · 3 complexity · 8a59cf8db8aa8a87a4a6bdeb98acc97b MD5 · raw file

  1. /**
  2. * \file quaternions.c
  3. * \brief Quaternions library used by Mykonos
  4. * \author Fran�ois Callou <francois.callou@parrot.com>
  5. * \version 1.0
  6. */
  7. #include <VP_Os/vp_os_assert.h>
  8. #include <Maths/quaternions.h>
  9. #include <Maths/maths.h>
  10. const quaternion_t quat_unitary = { 1.0f, {{{ 0.0f, 0.0f, 0.0f}}} };
  11. void mul_quat( quaternion_t* out, quaternion_t* q1, quaternion_t* q2)
  12. {
  13. vector31_t temp_v;
  14. /// You can't have output & input pointing to the same location
  15. VP_OS_ASSERT( out != q1 );
  16. VP_OS_ASSERT( out != q2 );
  17. // scalar result
  18. out->a = q1->a*q2->a - (q1->v.x*q2->v.x + q1->v.y*q2->v.y + q1->v.z*q2->v.z);
  19. // pure quaternion result
  20. cross_vec( &out->v , &q1->v, &q2->v );
  21. mulconst_vec( &temp_v, &q2->v, q1->a );
  22. add_vec( &out->v, &out->v, &temp_v);
  23. mulconst_vec( &temp_v, &q1->v, q2->a );
  24. add_vec( &out->v, &out->v, &temp_v);
  25. }
  26. void add_quat( quaternion_t* out, quaternion_t* q1, quaternion_t* q2 )
  27. {
  28. // scalar result
  29. out->a = q1->a + q2->a;
  30. // pure quaternion result
  31. add_vec( &out->v, &q1->v, &q2->v );
  32. }
  33. void mulconst_quat( quaternion_t* out, quaternion_t* q, float32_t k )
  34. {
  35. out->a = (q->a) * k;
  36. mulconst_vec( &out->v, &q->v, k );
  37. }
  38. void conjugate_quat( quaternion_t* out, quaternion_t* q )
  39. {
  40. out->a = q->a;
  41. out->v.x = -q->v.x;
  42. out->v.y = -q->v.y;
  43. out->v.z = -q->v.z;
  44. }
  45. float32_t norm_quat( quaternion_t *q )
  46. {
  47. return sqrtf( q->a*q->a + q->v.x * q->v.x + q->v.y * q->v.y + q->v.z * q->v.z );
  48. }
  49. bool_t normalize_quat( quaternion_t* q )
  50. {
  51. bool_t ret;
  52. float32_t norm;
  53. norm = norm_quat( q );
  54. if( f_is_zero( norm ) )
  55. {
  56. q->a = 0.0f;
  57. q->v.x = 0.0f;
  58. q->v.y = 0.0f;
  59. q->v.z = 0.0f;
  60. ret = FALSE;
  61. }
  62. else
  63. {
  64. q->a = f_zero( q->a / norm );
  65. q->v.x = f_zero( q->v.x / norm );
  66. q->v.y = f_zero( q->v.y / norm );
  67. q->v.z = f_zero( q->v.z / norm );
  68. ret = TRUE;
  69. }
  70. return ret;
  71. }
  72. void quat_to_euler_rot_mat(matrix33_t* m, quaternion_t* q)
  73. {
  74. //to use with normalised quaternion
  75. m->m11 = 1.0f - 2*q->v.y*q->v.y - 2*q->v.z*q->v.z;
  76. m->m12 = 2*q->v.x*q->v.y - 2*q->v.z*q->a;
  77. m->m13 = 2*q->v.z*q->v.x + 2*q->v.y*q->a;
  78. m->m21 = 2*q->v.x*q->v.y + 2*q->v.z*q->a;
  79. m->m22 = 1.0f - 2*q->v.x*q->v.x - 2*q->v.z*q->v.z;
  80. m->m23 = 2*q->v.z*q->v.y - 2*q->v.x*q->a;
  81. m->m31 = 2*q->v.z*q->v.x - 2*q->v.y*q->a;
  82. m->m32 = 2*q->v.z*q->v.y + 2*q->v.x*q->a;
  83. m->m33 = 1.0f - 2*q->v.x*q->v.x - 2*q->v.y*q->v.y;
  84. }
  85. void quat_to_euler_angles(angles_t* a, quaternion_t* q)
  86. {
  87. //to use with normalised quaternion
  88. float32_t sqvx = q->v.x*q->v.x;
  89. float32_t sqvy = q->v.y*q->v.y;
  90. float32_t sqvz = q->v.z*q->v.z;
  91. /* if ( f_is_zero(test -0.5) ) { // singularity at north pole
  92. a->psi = 2 * atan2(q->a,q->v.z);
  93. a->theta = PI/2;
  94. a->phi = 0;
  95. return;
  96. }
  97. if ( f_is_zero(test + 0.5) ) { // singularity at south pole
  98. a->psi = -2 * atan2(q->a,q->v.z);
  99. a->theta = - PI/2;
  100. a->phi = 0;
  101. return;
  102. }*/
  103. a->phi = atan2(2*q->v.y*q->v.z+2*q->a*q->v.x , 1 - 2*sqvx - 2*sqvy);
  104. a->theta = asin(2*(q->a*q->v.y - q->v.x*q->v.z ));
  105. a->psi = atan2(2*q->v.x*q->v.y+2*q->a*q->v.z , 1 - 2*sqvy - 2*sqvz);
  106. }