HSO4.hpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /********************************************************************************************/
  2. /* */
  3. /* HSO4.hpp header file */
  4. /* */
  5. /* This file is not currently part of the Boost library. It is simply an example of the use */
  6. /* quaternions can be put to. Hopefully it will be usefull too. */
  7. /* */
  8. /* This file provides tools to convert between quaternions and R^4 rotation matrices. */
  9. /* */
  10. /********************************************************************************************/
  11. // (C) Copyright Hubert Holin 2001.
  12. // Distributed under the Boost Software License, Version 1.0. (See
  13. // accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. #ifndef TEST_HSO4_HPP
  16. #define TEST_HSO4_HPP
  17. #include <utility>
  18. #include "HSO3.hpp"
  19. template<typename TYPE_FLOAT>
  20. struct R4_matrix
  21. {
  22. TYPE_FLOAT a11, a12, a13, a14;
  23. TYPE_FLOAT a21, a22, a23, a24;
  24. TYPE_FLOAT a31, a32, a33, a34;
  25. TYPE_FLOAT a41, a42, a43, a44;
  26. };
  27. // Note: the input quaternions need not be of norm 1 for the following function
  28. template<typename TYPE_FLOAT>
  29. R4_matrix<TYPE_FLOAT> quaternions_to_R4_rotation(::std::pair< ::boost::math::quaternion<TYPE_FLOAT> , ::boost::math::quaternion<TYPE_FLOAT> > const & pq)
  30. {
  31. using ::std::numeric_limits;
  32. TYPE_FLOAT a0 = pq.first.R_component_1();
  33. TYPE_FLOAT b0 = pq.first.R_component_2();
  34. TYPE_FLOAT c0 = pq.first.R_component_3();
  35. TYPE_FLOAT d0 = pq.first.R_component_4();
  36. TYPE_FLOAT norme_carre0 = a0*a0+b0*b0+c0*c0+d0*d0;
  37. if (norme_carre0 <= numeric_limits<TYPE_FLOAT>::epsilon())
  38. {
  39. ::std::string error_reporting("Argument to quaternions_to_R4_rotation is too small!");
  40. ::std::underflow_error bad_argument(error_reporting);
  41. throw(bad_argument);
  42. }
  43. TYPE_FLOAT a1 = pq.second.R_component_1();
  44. TYPE_FLOAT b1 = pq.second.R_component_2();
  45. TYPE_FLOAT c1 = pq.second.R_component_3();
  46. TYPE_FLOAT d1 = pq.second.R_component_4();
  47. TYPE_FLOAT norme_carre1 = a1*a1+b1*b1+c1*c1+d1*d1;
  48. if (norme_carre1 <= numeric_limits<TYPE_FLOAT>::epsilon())
  49. {
  50. ::std::string error_reporting("Argument to quaternions_to_R4_rotation is too small!");
  51. ::std::underflow_error bad_argument(error_reporting);
  52. throw(bad_argument);
  53. }
  54. TYPE_FLOAT prod_norm = norme_carre0*norme_carre1;
  55. TYPE_FLOAT a0a1 = a0*a1;
  56. TYPE_FLOAT a0b1 = a0*b1;
  57. TYPE_FLOAT a0c1 = a0*c1;
  58. TYPE_FLOAT a0d1 = a0*d1;
  59. TYPE_FLOAT b0a1 = b0*a1;
  60. TYPE_FLOAT b0b1 = b0*b1;
  61. TYPE_FLOAT b0c1 = b0*c1;
  62. TYPE_FLOAT b0d1 = b0*d1;
  63. TYPE_FLOAT c0a1 = c0*a1;
  64. TYPE_FLOAT c0b1 = c0*b1;
  65. TYPE_FLOAT c0c1 = c0*c1;
  66. TYPE_FLOAT c0d1 = c0*d1;
  67. TYPE_FLOAT d0a1 = d0*a1;
  68. TYPE_FLOAT d0b1 = d0*b1;
  69. TYPE_FLOAT d0c1 = d0*c1;
  70. TYPE_FLOAT d0d1 = d0*d1;
  71. R4_matrix<TYPE_FLOAT> out_matrix;
  72. out_matrix.a11 = (+a0a1+b0b1+c0c1+d0d1)/prod_norm;
  73. out_matrix.a12 = (+a0b1-b0a1-c0d1+d0c1)/prod_norm;
  74. out_matrix.a13 = (+a0c1+b0d1-c0a1-d0b1)/prod_norm;
  75. out_matrix.a14 = (+a0d1-b0c1+c0b1-d0a1)/prod_norm;
  76. out_matrix.a21 = (-a0b1+b0a1-c0d1+d0c1)/prod_norm;
  77. out_matrix.a22 = (+a0a1+b0b1-c0c1-d0d1)/prod_norm;
  78. out_matrix.a23 = (-a0d1+b0c1+c0b1-d0a1)/prod_norm;
  79. out_matrix.a24 = (+a0c1+b0d1+c0a1+d0b1)/prod_norm;
  80. out_matrix.a31 = (-a0c1+b0d1+c0a1-d0b1)/prod_norm;
  81. out_matrix.a32 = (+a0d1+b0c1+c0b1+d0a1)/prod_norm;
  82. out_matrix.a33 = (+a0a1-b0b1+c0c1-d0d1)/prod_norm;
  83. out_matrix.a34 = (-a0b1-b0a1+c0d1+d0c1)/prod_norm;
  84. out_matrix.a41 = (-a0d1-b0c1+c0b1+d0a1)/prod_norm;
  85. out_matrix.a42 = (-a0c1+b0d1-c0a1+d0b1)/prod_norm;
  86. out_matrix.a43 = (+a0b1+b0a1+c0d1+d0c1)/prod_norm;
  87. out_matrix.a44 = (+a0a1-b0b1-c0c1+d0d1)/prod_norm;
  88. return(out_matrix);
  89. }
  90. template<typename TYPE_FLOAT>
  91. inline bool is_R4_rotation_matrix(R4_matrix<TYPE_FLOAT> const & mat)
  92. {
  93. using ::std::abs;
  94. using ::std::numeric_limits;
  95. return (
  96. !(
  97. (abs(mat.a11*mat.a11+mat.a21*mat.a21+mat.a31*mat.a31+mat.a41*mat.a41 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  98. (abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32+mat.a41*mat.a42 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  99. (abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33+mat.a41*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  100. (abs(mat.a11*mat.a14+mat.a21*mat.a24+mat.a31*mat.a34+mat.a41*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  101. //(abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32+mat.a41*mat.a42 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  102. (abs(mat.a12*mat.a12+mat.a22*mat.a22+mat.a32*mat.a32+mat.a42*mat.a42 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  103. (abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33+mat.a42*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  104. (abs(mat.a12*mat.a14+mat.a22*mat.a24+mat.a32*mat.a34+mat.a42*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  105. //(abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33+mat.a41*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  106. //(abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33+mat.a42*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  107. (abs(mat.a13*mat.a13+mat.a23*mat.a23+mat.a33*mat.a33+mat.a43*mat.a43 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  108. (abs(mat.a13*mat.a14+mat.a23*mat.a24+mat.a33*mat.a34+mat.a43*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  109. //(abs(mat.a11*mat.a14+mat.a21*mat.a24+mat.a31*mat.a34+mat.a41*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  110. //(abs(mat.a12*mat.a14+mat.a22*mat.a24+mat.a32*mat.a34+mat.a42*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  111. //(abs(mat.a13*mat.a14+mat.a23*mat.a24+mat.a33*mat.a34+mat.a43*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
  112. (abs(mat.a14*mat.a14+mat.a24*mat.a24+mat.a34*mat.a34+mat.a44*mat.a44 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())
  113. )
  114. );
  115. }
  116. template<typename TYPE_FLOAT>
  117. ::std::pair< ::boost::math::quaternion<TYPE_FLOAT> , ::boost::math::quaternion<TYPE_FLOAT> > R4_rotation_to_quaternions( R4_matrix<TYPE_FLOAT> const & rot,
  118. ::std::pair< ::boost::math::quaternion<TYPE_FLOAT> , ::boost::math::quaternion<TYPE_FLOAT> > const * hint = 0)
  119. {
  120. if (!is_R4_rotation_matrix(rot))
  121. {
  122. ::std::string error_reporting("Argument to R4_rotation_to_quaternions is not an R^4 rotation matrix!");
  123. ::std::range_error bad_argument(error_reporting);
  124. throw(bad_argument);
  125. }
  126. R3_matrix<TYPE_FLOAT> mat;
  127. mat.a11 = -rot.a31*rot.a42+rot.a32*rot.a41+rot.a22*rot.a11-rot.a21*rot.a12;
  128. mat.a12 = -rot.a31*rot.a43+rot.a33*rot.a41+rot.a23*rot.a11-rot.a21*rot.a13;
  129. mat.a13 = -rot.a31*rot.a44+rot.a34*rot.a41+rot.a24*rot.a11-rot.a21*rot.a14;
  130. mat.a21 = -rot.a31*rot.a12-rot.a22*rot.a41+rot.a32*rot.a11+rot.a21*rot.a42;
  131. mat.a22 = -rot.a31*rot.a13-rot.a23*rot.a41+rot.a33*rot.a11+rot.a21*rot.a43;
  132. mat.a23 = -rot.a31*rot.a14-rot.a24*rot.a41+rot.a34*rot.a11+rot.a21*rot.a44;
  133. mat.a31 = +rot.a31*rot.a22-rot.a12*rot.a41+rot.a42*rot.a11-rot.a21*rot.a32;
  134. mat.a32 = +rot.a31*rot.a23-rot.a13*rot.a41+rot.a43*rot.a11-rot.a21*rot.a33;
  135. mat.a33 = +rot.a31*rot.a24-rot.a14*rot.a41+rot.a44*rot.a11-rot.a21*rot.a34;
  136. ::boost::math::quaternion<TYPE_FLOAT> q = R3_rotation_to_quaternion(mat);
  137. ::boost::math::quaternion<TYPE_FLOAT> p =
  138. ::boost::math::quaternion<TYPE_FLOAT>(rot.a11,rot.a12,rot.a13,rot.a14)*q;
  139. if ((hint != 0) && (abs(hint->second+q) < abs(hint->second-q)))
  140. {
  141. return(::std::make_pair(-p,-q));
  142. }
  143. return(::std::make_pair(p,q));
  144. }
  145. #endif /* TEST_HSO4_HPP */