PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/m2q.c

https://github.com/mattbornski/spice
C | 632 lines | 74 code | 209 blank | 349 comment | 11 complexity | d659e81eabdea158fd545d9e1d2bd32f MD5 | raw file
  1. /* m2q.f -- translated by f2c (version 19980913).
  2. You must link the resulting object file with the libraries:
  3. -lf2c -lm (in that order)
  4. */
  5. #include "f2c.h"
  6. /* Table of constant values */
  7. static doublereal c_b2 = .1;
  8. /* $Procedure M2Q ( Matrix to quaternion ) */
  9. /* Subroutine */ int m2q_(doublereal *r__, doublereal *q)
  10. {
  11. /* Builtin functions */
  12. double sqrt(doublereal);
  13. /* Local variables */
  14. doublereal c__, s[3];
  15. extern /* Subroutine */ int chkin_(char *, ftnlen);
  16. doublereal trace, l2;
  17. extern logical isrot_(doublereal *, doublereal *, doublereal *);
  18. doublereal mtrace, factor, cc4;
  19. extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *,
  20. ftnlen);
  21. doublereal polish;
  22. extern /* Subroutine */ int setmsg_(char *, ftnlen);
  23. doublereal s114, s224, s334;
  24. /* $ Abstract */
  25. /* Find a unit quaternion corresponding to a specified rotation */
  26. /* matrix. */
  27. /* $ Disclaimer */
  28. /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
  29. /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
  30. /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
  31. /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
  32. /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
  33. /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
  34. /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
  35. /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
  36. /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
  37. /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
  38. /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
  39. /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
  40. /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
  41. /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
  42. /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
  43. /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
  44. /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
  45. /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
  46. /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
  47. /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
  48. /* $ Required_Reading */
  49. /* ROTATION */
  50. /* $ Keywords */
  51. /* MATH */
  52. /* MATRIX */
  53. /* ROTATION */
  54. /* $ Declarations */
  55. /* $ Brief_I/O */
  56. /* Variable I/O Description */
  57. /* -------- --- -------------------------------------------------- */
  58. /* R I A rotation matrix. */
  59. /* Q O A unit quaternion representing R. */
  60. /* $ Detailed_Input */
  61. /* R is a rotation matrix. */
  62. /* $ Detailed_Output */
  63. /* Q is a unit-length SPICE-style quaternion */
  64. /* representing R. See the discussion of quaternion */
  65. /* styles in Particulars below. */
  66. /* Q is a 4-dimensional vector. If R rotates vectors */
  67. /* in the counterclockwise sense by an angle of theta */
  68. /* radians about a unit vector A, where */
  69. /* 0 < theta < pi */
  70. /* - - */
  71. /* then letting h = theta/2, */
  72. /* Q = ( cos(h), sin(h)A , sin(h)A , sin(h)A ). */
  73. /* 1 2 3 */
  74. /* The restriction that theta must be in the range */
  75. /* [0, pi] determines the output quaternion Q */
  76. /* uniquely except when theta = pi; in this special */
  77. /* case, both of the quaternions */
  78. /* Q = ( 0, A , A , A ) */
  79. /* 1 2 3 */
  80. /* and */
  81. /* Q = ( 0, -A , -A , -A ) */
  82. /* 1 2 3 */
  83. /* are possible outputs. */
  84. /* $ Parameters */
  85. /* None. */
  86. /* $ Exceptions */
  87. /* 1) If R is not a rotation matrix, the error SPICE(NOTAROTATION) */
  88. /* is signaled. */
  89. /* $ Files */
  90. /* None. */
  91. /* $ Particulars */
  92. /* A unit quaternion is a 4-dimensional vector for which the sum of */
  93. /* the squares of the components is 1. Unit quaternions can be used */
  94. /* to represent rotations in the following way: given a rotation */
  95. /* angle theta, where */
  96. /* 0 < theta < pi */
  97. /* - - */
  98. /* and a unit vector A, we can represent the transformation that */
  99. /* rotates vectors in the counterclockwise sense by theta radians */
  100. /* about A using the quaternion Q, where */
  101. /* Q = */
  102. /* ( cos(theta/2), sin(theta/2)a , sin(theta/2)a , sin(theta/2)a ) */
  103. /* 1 2 3 */
  104. /* As mentioned in Detailed Output, our restriction on the range of */
  105. /* theta determines Q uniquely, except when theta = pi. */
  106. /* The SPICELIB routine Q2M is an one-sided inverse of this routine: */
  107. /* given any rotation matrix R, the calls */
  108. /* CALL M2Q ( R, Q ) */
  109. /* CALL Q2M ( Q, R ) */
  110. /* leave R unchanged, except for round-off error. However, the */
  111. /* calls */
  112. /* CALL Q2M ( Q, R ) */
  113. /* CALL M2Q ( R, Q ) */
  114. /* might preserve Q or convert Q to -Q. */
  115. /* Quaternion Styles */
  116. /* ----------------- */
  117. /* There are different "styles" of quaternions used in */
  118. /* science and engineering applications. Quaternion styles */
  119. /* are characterized by */
  120. /* - The order of quaternion elements */
  121. /* - The quaternion multiplication formula */
  122. /* - The convention for associating quaternions */
  123. /* with rotation matrices */
  124. /* Two of the commonly used styles are */
  125. /* - "SPICE" */
  126. /* > Invented by Sir William Rowan Hamilton */
  127. /* > Frequently used in mathematics and physics textbooks */
  128. /* - "Engineering" */
  129. /* > Widely used in aerospace engineering applications */
  130. /* SPICELIB subroutine interfaces ALWAYS use SPICE quaternions. */
  131. /* Quaternions of any other style must be converted to SPICE */
  132. /* quaternions before they are passed to SPICELIB routines. */
  133. /* Relationship between SPICE and Engineering Quaternions */
  134. /* ------------------------------------------------------ */
  135. /* Let M be a rotation matrix such that for any vector V, */
  136. /* M*V */
  137. /* is the result of rotating V by theta radians in the */
  138. /* counterclockwise direction about unit rotation axis vector A. */
  139. /* Then the SPICE quaternions representing M are */
  140. /* (+/-) ( cos(theta/2), */
  141. /* sin(theta/2) A(1), */
  142. /* sin(theta/2) A(2), */
  143. /* sin(theta/2) A(3) ) */
  144. /* while the engineering quaternions representing M are */
  145. /* (+/-) ( -sin(theta/2) A(1), */
  146. /* -sin(theta/2) A(2), */
  147. /* -sin(theta/2) A(3), */
  148. /* cos(theta/2) ) */
  149. /* For both styles of quaternions, if a quaternion q represents */
  150. /* a rotation matrix M, then -q represents M as well. */
  151. /* Given an engineering quaternion */
  152. /* QENG = ( q0, q1, q2, q3 ) */
  153. /* the equivalent SPICE quaternion is */
  154. /* QSPICE = ( q3, -q0, -q1, -q2 ) */
  155. /* Associating SPICE Quaternions with Rotation Matrices */
  156. /* ---------------------------------------------------- */
  157. /* Let FROM and TO be two right-handed reference frames, for */
  158. /* example, an inertial frame and a spacecraft-fixed frame. Let the */
  159. /* symbols */
  160. /* V , V */
  161. /* FROM TO */
  162. /* denote, respectively, an arbitrary vector expressed relative to */
  163. /* the FROM and TO frames. Let M denote the transformation matrix */
  164. /* that transforms vectors from frame FROM to frame TO; then */
  165. /* V = M * V */
  166. /* TO FROM */
  167. /* where the expression on the right hand side represents left */
  168. /* multiplication of the vector by the matrix. */
  169. /* Then if the unit-length SPICE quaternion q represents M, where */
  170. /* q = (q0, q1, q2, q3) */
  171. /* the elements of M are derived from the elements of q as follows: */
  172. /* +- -+ */
  173. /* | 2 2 | */
  174. /* | 1 - 2*( q2 + q3 ) 2*(q1*q2 - q0*q3) 2*(q1*q3 + q0*q2) | */
  175. /* | | */
  176. /* | | */
  177. /* | 2 2 | */
  178. /* M = | 2*(q1*q2 + q0*q3) 1 - 2*( q1 + q3 ) 2*(q2*q3 - q0*q1) | */
  179. /* | | */
  180. /* | | */
  181. /* | 2 2 | */
  182. /* | 2*(q1*q3 - q0*q2) 2*(q2*q3 + q0*q1) 1 - 2*( q1 + q2 ) | */
  183. /* | | */
  184. /* +- -+ */
  185. /* Note that substituting the elements of -q for those of q in the */
  186. /* right hand side leaves each element of M unchanged; this shows */
  187. /* that if a quaternion q represents a matrix M, then so does the */
  188. /* quaternion -q. */
  189. /* To map the rotation matrix M to a unit quaternion, we start by */
  190. /* decomposing the rotation matrix as a sum of symmetric */
  191. /* and skew-symmetric parts: */
  192. /* 2 */
  193. /* M = [ I + (1-cos(theta)) OMEGA ] + [ sin(theta) OMEGA ] */
  194. /* symmetric skew-symmetric */
  195. /* OMEGA is a skew-symmetric matrix of the form */
  196. /* +- -+ */
  197. /* | 0 -n3 n2 | */
  198. /* | | */
  199. /* OMEGA = | n3 0 -n1 | */
  200. /* | | */
  201. /* | -n2 n1 0 | */
  202. /* +- -+ */
  203. /* The vector N of matrix entries (n1, n2, n3) is the rotation axis */
  204. /* of M and theta is M's rotation angle. Note that N and theta */
  205. /* are not unique. */
  206. /* Let */
  207. /* C = cos(theta/2) */
  208. /* S = sin(theta/2) */
  209. /* Then the unit quaternions Q corresponding to M are */
  210. /* Q = +/- ( C, S*n1, S*n2, S*n3 ) */
  211. /* The mappings between quaternions and the corresponding rotations */
  212. /* are carried out by the SPICELIB routines */
  213. /* Q2M {quaternion to matrix} */
  214. /* M2Q {matrix to quaternion} */
  215. /* M2Q always returns a quaternion with scalar part greater than */
  216. /* or equal to zero. */
  217. /* SPICE Quaternion Multiplication Formula */
  218. /* --------------------------------------- */
  219. /* Given a SPICE quaternion */
  220. /* Q = ( q0, q1, q2, q3 ) */
  221. /* corresponding to rotation axis A and angle theta as above, we can */
  222. /* represent Q using "scalar + vector" notation as follows: */
  223. /* s = q0 = cos(theta/2) */
  224. /* v = ( q1, q2, q3 ) = sin(theta/2) * A */
  225. /* Q = s + v */
  226. /* Let Q1 and Q2 be SPICE quaternions with respective scalar */
  227. /* and vector parts s1, s2 and v1, v2: */
  228. /* Q1 = s1 + v1 */
  229. /* Q2 = s2 + v2 */
  230. /* We represent the dot product of v1 and v2 by */
  231. /* <v1, v2> */
  232. /* and the cross product of v1 and v2 by */
  233. /* v1 x v2 */
  234. /* Then the SPICE quaternion product is */
  235. /* Q1*Q2 = s1*s2 - <v1,v2> + s1*v2 + s2*v1 + (v1 x v2) */
  236. /* If Q1 and Q2 represent the rotation matrices M1 and M2 */
  237. /* respectively, then the quaternion product */
  238. /* Q1*Q2 */
  239. /* represents the matrix product */
  240. /* M1*M2 */
  241. /* $ Examples */
  242. /* 1) A case amenable to checking by hand calculation: */
  243. /* To convert the rotation matrix */
  244. /* +- -+ */
  245. /* | 0 1 0 | */
  246. /* | | */
  247. /* R = | -1 0 0 | */
  248. /* | | */
  249. /* | 0 0 1 | */
  250. /* +- -+ */
  251. /* also represented as */
  252. /* [ pi/2 ] */
  253. /* 3 */
  254. /* to a quaternion, we can use the code fragment */
  255. /* CALL ROTATE ( HALFPI(), 3, R ) */
  256. /* CALL M2Q ( R, Q ) */
  257. /* M2Q will return Q as */
  258. /* ( sqrt(2)/2, 0, 0, -sqrt(2)/2 ) */
  259. /* Why? Well, R is a reference frame transformation that */
  260. /* rotates vectors by -pi/2 radians about the axis vector */
  261. /* A = ( 0, 0, 1 ) */
  262. /* Equivalently, R rotates vectors by pi/2 radians in */
  263. /* the counterclockwise sense about the axis vector */
  264. /* -A = ( 0, 0, -1 ) */
  265. /* so our definition of Q, */
  266. /* h = theta/2 */
  267. /* Q = ( cos(h), sin(h)A , sin(h)A , sin(h)A ) */
  268. /* 1 2 3 */
  269. /* implies that in this case, */
  270. /* Q = ( cos(pi/4), 0, 0, -sin(pi/4) ) */
  271. /* = ( sqrt(2)/2, 0, 0, -sqrt(2)/2 ) */
  272. /* 2) Finding a quaternion that represents a rotation specified by */
  273. /* a set of Euler angles: */
  274. /* Suppose our original rotation R is the product */
  275. /* [ TAU ] [ pi/2 - DELTA ] [ ALPHA ] */
  276. /* 3 2 3 */
  277. /* The code fragment */
  278. /* CALL EUL2M ( TAU, HALFPI() - DELTA, ALPHA, */
  279. /* . 3, 2, 3, R ) */
  280. /* CALL M2Q ( R, Q ) */
  281. /* yields a quaternion Q that represents R. */
  282. /* $ Restrictions */
  283. /* None. */
  284. /* $ Literature_References */
  285. /* None. */
  286. /* $ Author_and_Institution */
  287. /* N.J. Bachman (JPL) */
  288. /* W.L. Taber (JPL) */
  289. /* $ Version */
  290. /* - SPICELIB Version 2.0.1, 27-FEB-2008 (NJB) */
  291. /* Updated header; added information about SPICE */
  292. /* quaternion conventions. Made various minor edits */
  293. /* throughout header. */
  294. /* - SPICELIB Version 2.0.0, 17-SEP-1999 (WLT) */
  295. /* The routine was re-implemented to sharpen the numerical */
  296. /* stability of the routine and eliminate calls to SIN */
  297. /* and COS functions. */
  298. /* - SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */
  299. /* Comment section for permuted index source lines was added */
  300. /* following the header. */
  301. /* - SPICELIB Version 1.0.0, 30-AUG-1990 (NJB) */
  302. /* -& */
  303. /* $ Index_Entries */
  304. /* matrix to quaternion */
  305. /* -& */
  306. /* SPICELIB functions */
  307. /* Local parameters */
  308. /* NTOL and DETOL are used to determine whether R is a rotation */
  309. /* matrix. */
  310. /* NTOL is the tolerance for the norms of the columns of R. */
  311. /* DTOL is the tolerance for the determinant of a matrix whose */
  312. /* columns are the unitized columns of R. */
  313. /* Local Variables */
  314. /* If R is not a rotation matrix, we can't proceed. */
  315. if (! isrot_(r__, &c_b2, &c_b2)) {
  316. chkin_("M2Q", (ftnlen)3);
  317. setmsg_("Input matrix was not a rotation.", (ftnlen)32);
  318. sigerr_("SPICE(NOTAROTATION)", (ftnlen)19);
  319. chkout_("M2Q", (ftnlen)3);
  320. return 0;
  321. }
  322. /* If our quaternion is C, S1, S2, S3 (the S's being the imaginary */
  323. /* part) and we let */
  324. /* CSi = C * Si */
  325. /* Sij = Si * Sj */
  326. /* then the rotation matrix corresponding to our quaternion is: */
  327. /* R(1,1) = 1.0D0 - 2*S22 - 2*S33 */
  328. /* R(2,1) = 2*S12 + 2*CS3 */
  329. /* R(3,1) = 2*S13 - 2*CS2 */
  330. /* R(1,2) = 2*S12 - 2*CS3 */
  331. /* R(2,2) = 1.0D0 - 2*S11 - 2*S33 */
  332. /* R(3,2) = 2*S23 + 2*CS1 */
  333. /* R(1,3) = 2*S13 + 2*CS2 */
  334. /* R(2,3) = 2*S23 - 2*CS1 */
  335. /* R(3,3) = 1.0D0 - 2*S11 - 2*S22 */
  336. /* From the above we can see that */
  337. /* TRACE = 3 - 4*(S11 + S22 + S33) */
  338. /* so that */
  339. /* 1.0D0 + TRACE = 4 - 4*(S11 + S22 + S33) */
  340. /* = 4*(CC + S11 + S22 + S33) */
  341. /* - 4*(S11 + S22 + S33) */
  342. /* = 4*CC */
  343. /* Thus up to sign */
  344. /* C = 0.5D0 * DSQRT( 1.0D0 + TRACE ) */
  345. /* But we also have */
  346. /* 1.0D0 + TRACE - 2.0D0*R(i,i) = 4.0D0 - 4.0D0(Sii + Sjj + Skk) */
  347. /* - 2.0D0 + 4.0D0(Sjj + Skk ) */
  348. /* = 2.0D0 - 4.0D0*Sii */
  349. /* So that */
  350. /* 1.0D0 - TRACE + 2.0D0*R(i,i) = 4.0D0*Sii */
  351. /* and so up to sign */
  352. /* Si = 0.5D0*DSQRT( 1.0D0 - TRACE + 2.0D0*R(i,i) ) */
  353. /* in addition to this observation, we note that all of the */
  354. /* product pairs can easily be computed */
  355. /* CS1 = (R(3,2) - R(2,3))/4.0D0 */
  356. /* CS2 = (R(1,3) - R(3,1))/4.0D0 */
  357. /* CS3 = (R(2,1) - R(1,2))/4.0D0 */
  358. /* S12 = (R(2,1) + R(1,2))/4.0D0 */
  359. /* S13 = (R(3,1) + R(1,3))/4.0D0 */
  360. /* S23 = (R(2,3) + R(3,2))/4.0D0 */
  361. /* But taking sums or differences of numbers that are nearly equal */
  362. /* or nearly opposite results in a loss of precision. As a result */
  363. /* we should take some care in which terms to select when computing */
  364. /* C, S1, S2, S3. However, by simply starting with one of the */
  365. /* large quantities cc, S11, S22, or S33 we can make sure that we */
  366. /* use the best of the 6 quantities above when computing the */
  367. /* remaining components of the quaternion. */
  368. trace = r__[0] + r__[4] + r__[8];
  369. mtrace = 1. - trace;
  370. cc4 = trace + 1.;
  371. s114 = mtrace + r__[0] * 2.;
  372. s224 = mtrace + r__[4] * 2.;
  373. s334 = mtrace + r__[8] * 2.;
  374. /* Note that if you simply add CC4 + S114 + S224 + S334 */
  375. /* you get four. Thus at least one of the 4 terms is greater than 1. */
  376. if (1. <= cc4) {
  377. c__ = sqrt(cc4 * .25);
  378. factor = 1. / (c__ * 4.);
  379. s[0] = (r__[5] - r__[7]) * factor;
  380. s[1] = (r__[6] - r__[2]) * factor;
  381. s[2] = (r__[1] - r__[3]) * factor;
  382. } else if (1. <= s114) {
  383. s[0] = sqrt(s114 * .25);
  384. factor = 1. / (s[0] * 4.);
  385. c__ = (r__[5] - r__[7]) * factor;
  386. s[1] = (r__[3] + r__[1]) * factor;
  387. s[2] = (r__[6] + r__[2]) * factor;
  388. } else if (1. <= s224) {
  389. s[1] = sqrt(s224 * .25);
  390. factor = 1. / (s[1] * 4.);
  391. c__ = (r__[6] - r__[2]) * factor;
  392. s[0] = (r__[3] + r__[1]) * factor;
  393. s[2] = (r__[7] + r__[5]) * factor;
  394. } else {
  395. s[2] = sqrt(s334 * .25);
  396. factor = 1. / (s[2] * 4.);
  397. c__ = (r__[1] - r__[3]) * factor;
  398. s[0] = (r__[6] + r__[2]) * factor;
  399. s[1] = (r__[7] + r__[5]) * factor;
  400. }
  401. /* If the magnitude of this quaternion is not one, we polish it */
  402. /* up a bit. */
  403. l2 = c__ * c__ + s[0] * s[0] + s[1] * s[1] + s[2] * s[2];
  404. if (l2 != 1.) {
  405. polish = 1. / sqrt(l2);
  406. c__ *= polish;
  407. s[0] *= polish;
  408. s[1] *= polish;
  409. s[2] *= polish;
  410. }
  411. if (c__ > 0.) {
  412. q[0] = c__;
  413. q[1] = s[0];
  414. q[2] = s[1];
  415. q[3] = s[2];
  416. } else {
  417. q[0] = -c__;
  418. q[1] = -s[0];
  419. q[2] = -s[1];
  420. q[3] = -s[2];
  421. }
  422. return 0;
  423. } /* m2q_ */