ISPose.c
Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright (c) 2014-2020 Inertial Sense, Inc. - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #define _MATH_DEFINES_DEFINED
14 #include <math.h>
15 
16 // #include "misc/debug.h"
17 #include "ISConstants.h"
18 #include "ISPose.h"
19 #include "ISEarth.h"
20 
21 //_____ M A C R O S ________________________________________________________
22 
23 //_____ D E F I N I T I O N S ______________________________________________
24 
25 //_____ G L O B A L S ______________________________________________________
26 
27 //_____ L O C A L P R O T O T Y P E S ____________________________________
28 
29 //_____ F U N C T I O N S __________________________________________________
30 
31 /*
32  * Initialize Quaternion q = [w, x, y, z]
33  */
35 {
36 #if 1
37  q[0] = 1.0;
38  q[1] = q[2] = q[3] = 0.0;
39 #else
40  Euler_t theta = { 0, 0, 0 };
41  euler2quat(theta, q);
42 #endif
43 }
44 
45 
46 /* Quaternion Conjugate: q* = [ w, -x, -y, -z ] of quaterion q = [ w, x, y, z ]
47  * Rotation in opposite direction.
48  */
49 void quatConj(Quat_t result, const Quat_t q)
50 {
51  result[0] = q[0];
52  result[1] = -q[1];
53  result[2] = -q[2];
54  result[3] = -q[3];
55 }
56 
57 
58 /*
59  * Product of two Quaternions. Order of q1 and q2 matters (same as applying two successive DCMs)!!!
60  * Combines two quaternion rotations into one rotation.
61  * result = q1 * q2
62  * Reference: http://www.mathworks.com/help/aeroblks/quaternionmultiplication.html
63  */
64 void mul_Quat_Quat(Quat_t result, const Quat_t q1, const Quat_t q2)
65 {
66  result[0] = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3];
67  result[1] = q1[0]*q2[1] + q1[1]*q2[0] - q1[2]*q2[3] + q1[3]*q2[2];
68  result[2] = q1[0]*q2[2] + q1[1]*q2[3] + q1[2]*q2[0] - q1[3]*q2[1];
69  result[3] = q1[0]*q2[3] - q1[1]*q2[2] + q1[2]*q2[1] + q1[3]*q2[0];
70 }
71 
72 /*
73 * Product of two Quaternions. Order of q1 and q2 matters (same as applying two successive DCMs)!!!
74 * Combines two quaternion rotations into one rotation.
75 * result = quatConj(q1) * q2
76 * Reference: http://www.mathworks.com/help/aeroblks/quaternionmultiplication.html
77 */
78 void mul_ConjQuat_Quat(Quat_t result, const Quat_t qc, const Quat_t q2)
79 {
80  result[0] = qc[0]*q2[0] + qc[1]*q2[1] + qc[2]*q2[2] + qc[3]*q2[3];
81  result[1] = qc[0]*q2[1] - qc[1]*q2[0] + qc[2]*q2[3] - qc[3]*q2[2];
82  result[2] = qc[0]*q2[2] - qc[1]*q2[3] - qc[2]*q2[0] + qc[3]*q2[1];
83  result[3] = qc[0]*q2[3] + qc[1]*q2[2] - qc[2]*q2[1] - qc[3]*q2[0];
84 }
85 
86 /*
87 * Product of two Quaternions. Order of q1 and q2 matters (same as applying two successive DCMs)!!!
88 * Combines two quaternion rotations into one rotation.
89 * result = q1 * quatConj(q2)
90 * Reference: http://www.mathworks.com/help/aeroblks/quaternionmultiplication.html
91 */
92 void mul_Quat_ConjQuat(Quat_t result, const Quat_t q1, const Quat_t qc)
93 {
94  result[0] = q1[0]*qc[0] + q1[1]*qc[1] + q1[2]*qc[2] + q1[3]*qc[3];
95  result[1] = -q1[0]*qc[1] + q1[1]*qc[0] + q1[2]*qc[3] - q1[3]*qc[2];
96  result[2] = -q1[0]*qc[2] - q1[1]*qc[3] + q1[2]*qc[0] + q1[3]*qc[1];
97  result[3] = -q1[0]*qc[3] + q1[1]*qc[2] - q1[2]*qc[1] + q1[3]*qc[0];
98 }
99 
100 /*
101  * Division of two Quaternions. Order matters!!!
102  * result = q1 / q2.
103  * Reference: http://www.mathworks.com/help/aeroblks/quaterniondivision.html
104  */
105 void div_Quat_Quat(Quat_t result, const Quat_t q1, const Quat_t q2)
106 {
107  q_t d = (q_t)1.0 / (q1[0] * q1[0] + q1[1] * q1[1] + q1[2] * q1[2] + q1[3] * q1[3]);
108 
109  result[0] = (q1[0]*q2[0] + q1[1]*q2[1] + q1[2]*q2[2] + q1[3]*q2[3]) * d;
110  result[1] = (q1[0]*q2[1] - q1[1]*q2[0] - q1[2]*q2[3] + q1[3]*q2[2]) * d;
111  result[2] = (q1[0]*q2[2] + q1[1]*q2[3] - q1[2]*q2[0] - q1[3]*q2[1]) * d;
112  result[3] = (q1[0]*q2[3] - q1[1]*q2[2] + q1[2]*q2[1] - q1[3]*q2[0]) * d;
113 }
114 
115 
116 /* Quaternion rotation from vector v1 to vector v2.
117  */
118 void quat_Vec3_Vec3(Quat_t result, const Vector3_t v1, const Vector3_t v2)
119 {
120  Vector3_t w1, w2;
121 
122  // Normalize input vectors
123  mul_Vec3_X( w1, v1, recipNorm_Vec3(v1) );
124  mul_Vec3_X( w2, v2, recipNorm_Vec3(v2) );
125 
126  // q[1:3]
127  cross_Vec3( &result[1], w1, w2 );
128 
129  // q[0]
130  result[0] = (q_t)(_SQRT( dot_Vec3(w1) * dot_Vec3(w1) ) + dot_Vec3_Vec3(w1, w2));
131 
132  // Normalize quaternion
133  div_Vec4_X( result, result, mag_Vec4(result) );
134 }
135 
136 
137 /* Computationally simple means to apply quaternion rotation to a vector.
138  * Requires quaternion be normalized first.
139  * If quaternion describes current attitude, then rotation is body -> inertial frame.
140  * Equivalent to a DCM.T * vector multiply.
141  */
142 void quatRot(Vector3_t result, const Quat_t q, const Vector3_t v)
143 {
144  Vector3_t t;
145  cross_Vec3( t, &q[1], v );
146  mul_Vec3_X( t, t, (f_t)2.0 );
147 
148  cross_Vec3( result, &q[1], t );
149  mul_Vec3_X( t, t, q[0] );
150  add_Vec3_Vec3( result, result, t );
151  add_Vec3_Vec3( result, result, v );
152 }
153 
154 
155 /* Computationally simple means to apply quaternion conjugate (opposite) rotation to a vector
156  * (18 multiplies, 6 subtracts, 6 adds). Using a DCM uses (27 multiplies, 12 adds, 6 subtracts).
157  * Requires quaternion be normalized first.
158  * If quaternion describes current attitude, then rotation is inertial -> body frame.
159  * Equivalent to a DCM * vector multiply.
160  */
161 void quatConjRot(Vector3_t result, const Quat_t q, const Vector3_t v)
162 {
163  Quat_t qC;
164  Vector3_t t;
165 
166  // Rotation in opposite direction
167  quatConj( qC, q );
168 
169  cross_Vec3( t, &qC[1], v );
170  mul_Vec3_X( t, t, (f_t)2.0 );
171 
172  cross_Vec3( result, &qC[1], t );
173  mul_Vec3_X( t, t, qC[0] );
174  add_Vec3_Vec3( result, result, t );
175  add_Vec3_Vec3( result, result, v );
176 }
177 
178 
179 /*
180  * This will convert from quaternions to euler angles
181  * q(W,X,Y,Z) -> euler(phi,theta,psi) (rad)
182  *
183  * Reference: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
184  */
185 void quat2euler(const Quat_t q, Euler_t theta)
186 {
187  float sinang = 2 * (q[0] * q[2] - q[3] * q[1]);
188  if (sinang > 1.0f) { sinang = 1.0f; }
189  if (sinang < -1.0f) { sinang = -1.0f; }
190 
191  theta[0] = _ATAN2(2 * (q[0]*q[1] + q[2]*q[3]), 1 - 2 * (q[1]*q[1] + q[2]*q[2]));
192  theta[1] = _ASIN (sinang);
193  theta[2] = _ATAN2(2 * (q[0]*q[3] + q[1]*q[2]), 1 - 2 * (q[2]*q[2] + q[3]*q[3]));
194 }
195 void quat2phiTheta(const Quat_t q, f_t *phi, f_t *theta)
196 {
197  float sinang = 2 * (q[0] * q[2] - q[3] * q[1]);
198  if (sinang > 1.0f) { sinang = 1.0f; }
199  if (sinang < -1.0f) { sinang = -1.0f; }
200 
201  *phi = _ATAN2( 2 * (q[0] * q[1] + q[2] * q[3]), 1 - 2 * (q[1] * q[1] + q[2] * q[2]) );
202  *theta = _ASIN (sinang);
203 }
204 void quat2psi(const Quat_t q, f_t *psi)
205 {
206  float sinang = 2 * (q[0] * q[2] - q[3] * q[1]);
207  if (sinang > 1.0f) { sinang = 1.0f; }
208  if (sinang < -1.0f) { sinang = -1.0f; }
209 
210  *psi = _ATAN2(2 * (q[0]*q[3] + q[1]*q[2]), 1 - 2 * (q[2]*q[2] + q[3]*q[3]));
211 }
212 
213 
214 /*
215  * This will convert from euler angles to quaternion vector
216  * euler(phi,theta,psi) (rad) -> q(W,X,Y,Z)
217  */
218 void euler2quat(const Euler_t euler, Quat_t q)
219 {
220  f_t hphi = euler[0] * (f_t)0.5;
221  f_t hthe = euler[1] * (f_t)0.5;
222  f_t hpsi = euler[2] * (f_t)0.5;
223 
224  f_t shphi = _SIN(hphi);
225  f_t chphi = _COS(hphi);
226 
227  f_t shthe = _SIN(hthe);
228  f_t chthe = _COS(hthe);
229 
230  f_t shpsi = _SIN(hpsi);
231  f_t chpsi = _COS(hpsi);
232 
233  q[0] = chphi * chthe * chpsi + shphi * shthe * shpsi;
234  q[1] = shphi * chthe * chpsi - chphi * shthe * shpsi;
235  q[2] = chphi * shthe * chpsi + shphi * chthe * shpsi;
236  q[3] = chphi * chthe * shpsi - shphi * shthe * chpsi;
237 }
238 
239 
240 /*
241 * Quaternion rotation to NED with respect to ECEF at specified LLA
242 */
243 // void quatEcef2Ned(Vector4 Qe2n, const Vector3d lla)
244 // {
245 // Vector3 Ee2nLL;
246 // Vector4 Qe2n0LL, Qe2nLL;
247 //
248 // //Qe2n0LL is reference attitude [NED w/r/t ECEF] at zero latitude and longitude (elsewhere qned0)
249 // Qe2n0LL[0] = cosf(-C_PIDIV4_F);
250 // Qe2n0LL[1] = 0.0f;
251 // Qe2n0LL[2] = sinf(-C_PIDIV4_F);
252 // Qe2n0LL[3] = 0.0f;
253 //
254 // //Qe2nLL is delta reference attitude [NED w/r/t ECEF] accounting for latitude and longitude (elsewhere qned)
255 // Ee2nLL[0] = 0.0f;
256 // Ee2nLL[1] = (float)(-lla[0]);
257 // Ee2nLL[2] = (float)(lla[1]);
258 //
259 // euler2quat(Ee2nLL, Qe2nLL);
260 //
261 // //Qe2b=Qe2n*Qn2b is vehicle attitude [BOD w/r/t ECEF]
262 // mul_Quat_Quat(Qe2n, Qe2n0LL, Qe2nLL);
263 // }
264 
265 
266 /* Attitude quaternion for NED frame in ECEF */
267 void quat_ecef2ned(float lat, float lon, float *qe2n)
268 {
269  float eul[3];
270 
271  eul[0] = 0.0f;
272  eul[1] = -lat - 0.5f * C_PI_F;
273  eul[2] = lon;
274  euler2quat(eul, qe2n);
275 }
276 
277 
278 /*
279 * Convert ECEF quaternion to NED euler at specified ECEF
280 */
281 void qe2b2EulerNedEcef(Vector3 eul, const Vector4 qe2b, const Vector3d ecef)
282 {
283  Vector3d lla;
284 
285 // ecef2lla_d(ecef, lla);
286  ecef2lla(ecef, lla, 5);
287  qe2b2EulerNedLLA(eul, qe2b, lla);
288 }
289 
290 
291 /*
292 * Convert ECEF quaternion to NED euler at specified LLA (rad)
293 */
294 void qe2b2EulerNedLLA(Vector3 eul, const Vector4 qe2b, const Vector3d lla)
295 {
296  Vector3 eulned;
297  Vector4 qe2n;
298  Vector4 qn2b;
299 
300  eulned[0] = 0.0f;
301  eulned[1] = ((float)-lla[0]) - 0.5f * C_PI_F;
302  eulned[2] = (float)lla[1];
303  euler2quat(eulned, qe2n);
304  mul_Quat_ConjQuat(qn2b, qe2b, qe2n);
305  quat2euler(qn2b, eul);
306 }
307 
308 
309 /*
310  * This will construct a direction cosine matrix from
311  * the psi angle - rotates from NE to body frame
312  *
313  * body = tBL(2,2)*NE
314  *
315  */
316 void psiDCM(const f_t psi, Matrix2_t m)
317 {
318  f_t cpsi = _COS(psi); // cos(psi)
319  f_t spsi = _SIN(psi); // sin(psi)
320 
321  // Row 1
322  m[0] = cpsi;
323  m[1] = spsi;
324  // Row 2
325  m[2] = -spsi;
326  m[3] = cpsi;
327 }
328 
329 
330 /*
331 * This will extract the psi euler angle from a direction cosine matrix in the
332 * standard rotation sequence, for either a 2x2 or 3x3 DCM matrix.
333 * [phi][theta][psi] from NED to body frame
334 *
335 * body = tBL(2,2)*NE
336 * body = tBL(3,3)*NED
337 *
338 * reference: http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
339 */
340 f_t DCMpsi(const f_t *m )
341 {
342  return _ATAN2( m[1], m[0] );
343 }
344 
345 
346 /*
347  * This will construct a direction cosine matrix from
348  * euler angles in the standard rotation sequence
349  * [phi][theta][psi] from NED to body frame
350  *
351  * body = tBL(3,3)*NED
352  *
353  * reference: http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
354  */
355 void eulerDCM(const Euler_t euler, Matrix3_t m)
356 {
357  f_t cphi = _COS(euler[0]); // cos(phi)
358  f_t cthe = _COS(euler[1]); // cos(theta)
359  f_t cpsi = _COS(euler[2]); // cos(psi)
360 
361  f_t sphi = _SIN(euler[0]); // sin(phi)
362  f_t sthe = _SIN(euler[1]); // sin(theta)
363  f_t spsi = _SIN(euler[2]); // sin(psi)
364 
365  // Row 1
366  m[0] = cpsi*cthe;
367  m[1] = spsi*cthe;
368  m[2] = -sthe;
369  // Row 2
370  m[3] = -spsi*cphi + cpsi*sthe*sphi;
371  m[4] = cpsi*cphi + spsi*sthe*sphi;
372  m[5] = cthe*sphi;
373  // Row 3
374  m[6] = spsi*sphi + cpsi*sthe*cphi;
375  m[7] = -cpsi*sphi + spsi*sthe*cphi;
376  m[8] = cthe*cphi;
377 }
378 
379 
380 void phiThetaDCM(const Euler_t euler, Matrix3_t m )
381 {
382  f_t cphi = _COS( euler[0] ); // cos(phi)
383  f_t cthe = _COS( euler[1] ); // cos(theta)
384 
385  f_t sphi = _SIN( euler[0] ); // sin(phi)
386  f_t sthe = _SIN( euler[1] ); // sin(theta)
387 
388  // Row 1
389  m[0] = cthe;
390  m[1] = 0.0f;
391  m[2] = -sthe;
392  // Row 2
393  m[3] = sthe*sphi;
394  m[4] = cphi;
395  m[5] = cthe*sphi;
396  // Row 3
397  m[6] = sthe*cphi;
398  m[7] = -sphi;
399  m[8] = cthe*cphi;
400 }
401 
402 
403 /*
404 * This will construct the transpose matrix of
405 * the direction cosine matrix from
406 * euler angles in the standard rotation sequence
407 * [phi][theta][psi] from NED to body frame
408 *
409 * body = tBL(3,3)*NED
410 *
411 * reference: http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
412 */
413 void eulerDCM_Trans(const Euler_t euler, Matrix3_t m )
414 {
415  f_t cphi = _COS( euler[0] ); // cos(phi)
416  f_t cthe = _COS( euler[1] ); // cos(theta)
417  f_t cpsi = _COS( euler[2] ); // cos(psi)
418 
419  f_t sphi = _SIN( euler[0] ); // sin(phi)
420  f_t sthe = _SIN( euler[1] ); // sin(theta)
421  f_t spsi = _SIN( euler[2] ); // sin(psi)
422 
423  // Col 1
424  m[0] = cpsi*cthe;
425  m[3] = spsi*cthe;
426  m[6] = -sthe;
427  // Col 2
428  m[1] = -spsi*cphi + cpsi*sthe*sphi;
429  m[4] = cpsi*cphi + spsi*sthe*sphi;
430  m[7] = cthe*sphi;
431  // Col 3
432  m[2] = spsi*sphi + cpsi*sthe*cphi;
433  m[5] = -cpsi*sphi + spsi*sthe*cphi;
434  m[8] = cthe*cphi;
435 }
436 
437 
438 /*
439  * This will extract euler angles from a direction cosine matrix in the
440  * standard rotation sequence.
441  * [phi][theta][psi] from NED to body frame
442  *
443  * body = tBL(3,3)*NED
444  *
445  * reference: http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
446  */
447 void DCMeuler(const Matrix3_t m, Euler_t euler)
448 {
449  euler[0] = _ATAN2( m[5], m[8] ); // phi
450  euler[1] = _ASIN( -m[2] ); // theta
451  euler[2] = _ATAN2( m[1], m[0] ); // psi
452 }
453 
454 
455 /*
456  * This will construct a direction cosine matrix from
457  * quaternions in the standard rotation sequence
458  * [phi][theta][psi] from NED to body frame
459  * (18 multiplies, 6 adds, 6 subtracts)
460  *
461  * body = tBL(3,3)*NED
462  * q(4,1)
463  *
464  * Reference: http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
465  */
466 void quatDCM(const Quat_t q, Matrix3_t mat)
467 {
468  f_t q0q1 = q[0]*q[1];
469  f_t q0q2 = q[0]*q[2];
470  f_t q0q3 = q[0]*q[3];
471  f_t q1q1 = q[1]*q[1];
472  f_t q1q2 = q[1]*q[2];
473  f_t q1q3 = q[1]*q[3];
474  f_t q2q2 = q[2]*q[2];
475  f_t q2q3 = q[2]*q[3];
476  f_t q3q3 = q[3]*q[3];
477 
478  // Row 1
479  mat[0] = (f_t)1.0 - (f_t)2 * (q2q2 + q3q3);
480  mat[1] = (f_t)2 * (q1q2 + q0q3);
481  mat[2] = (f_t)2 * (q1q3 - q0q2);
482  // Row 2
483  mat[3] = (f_t)2 * (q1q2 - q0q3);
484  mat[4] = (f_t)1.0 - (f_t)2 * (q1q1 + q3q3);
485  mat[5] = (f_t)2 * (q2q3 + q0q1);
486  // Row 3
487  mat[6] = (f_t)2 * (q1q3 + q0q2);
488  mat[7] = (f_t)2 * (q2q3 - q0q1);
489  mat[8] = (f_t)1.0 - (f_t)2 * (q1q1 + q2q2);
490 }
491 void quatdDCM(const Vector4d q, Matrix3_t mat )
492 {
493  f_t q0q1 = (f_t)(q[0] * q[1]);
494  f_t q0q2 = (f_t)(q[0] * q[2]);
495  f_t q0q3 = (f_t)(q[0] * q[3]);
496  f_t q1q1 = (f_t)(q[1] * q[1]);
497  f_t q1q2 = (f_t)(q[1] * q[2]);
498  f_t q1q3 = (f_t)(q[1] * q[3]);
499  f_t q2q2 = (f_t)(q[2] * q[2]);
500  f_t q2q3 = (f_t)(q[2] * q[3]);
501  f_t q3q3 = (f_t)(q[3] * q[3]);
502 
503  // Row 1
504  mat[0] = (f_t)1.0 - (f_t)2.0 * (q2q2 + q3q3);
505  mat[1] = (f_t)2.0 * (q1q2 + q0q3);
506  mat[2] = (f_t)2.0 * (q1q3 - q0q2);
507  // Row 2
508  mat[3] = (f_t)2.0 * (q1q2 - q0q3);
509  mat[4] = (f_t)1.0 - (f_t)2.0 * (q1q1 + q3q3);
510  mat[5] = (f_t)2.0 * (q2q3 + q0q1);
511  // Row 3
512  mat[6] = (f_t)2.0 * (q1q3 + q0q2);
513  mat[7] = (f_t)2.0 * (q2q3 - q0q1);
514  mat[8] = (f_t)1.0 - (f_t)2.0 * (q1q1 + q2q2);
515 }
516 
517 /*
518  * This will construct quaternions from a direction cosine
519  * matrix in the standard rotation sequence.
520  * [phi][theta][psi] from NED to body frame
521  *
522  * body = tBL(3,3)*NED
523  * q(4,1)
524  *
525  * Reference: http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
526  */
527 void DCMquat(const Matrix3_t mat, Quat_t q)
528 {
529  f_t d;
530 
531  q[0] = (f_t)0.5 * _SQRT((f_t)1.0 + mat[0] + mat[4] + mat[8]);
532 
533  d = (f_t)1.0 / ((f_t)4.0 * q[0]);
534 
535  q[1] = d * (mat[5] - mat[7]);
536  q[2] = d * (mat[6] - mat[2]);
537  q[3] = d * (mat[1] - mat[3]);
538 }
539 
540 /*
541  * This will construct the euler omega-cross matrix
542  * wx(3,3)
543  * p, q, r (rad/sec)
544  */
545 void eulerWx(const Euler_t euler, Matrix3_t mat)
546 {
547  f_t p = euler[0];
548  f_t q = euler[1];
549  f_t r = euler[2];
550 
551  // Row 1
552  mat[0] = 0;
553  mat[1] = -r;
554  mat[2] = q;
555  // Row 2
556  mat[3] = r;
557  mat[4] = 0;
558  mat[5] = -p;
559  // Row 3
560  mat[6] = -q;
561  mat[7] = p;
562  mat[8] = 0;
563 }
564 
565 /*
566  * This will construct the quaternion omega matrix
567  * W(4,4)
568  * p, q, r (rad/sec)
569  */
570 void quatW(const Euler_t euler, Matrix4_t mat)
571 {
572  f_t p = euler[0] * (f_t)0.5;
573  f_t q = euler[1] * (f_t)0.5;
574  f_t r = euler[2] * (f_t)0.5;
575 
576  // Row 1
577  mat[0] = 0;
578  mat[1] = -p;
579  mat[2] = -q;
580  mat[3] = -r;
581  // Row 2
582  mat[4] = p;
583  mat[5] = 0;
584  mat[6] = r;
585  mat[7] = -q;
586  // Row 3
587  mat[8] = q;
588  mat[9] = -r;
589  mat[10] = 0;
590  mat[11] = p;
591  // Row 4
592  mat[12] = r;
593  mat[13] = q;
594  mat[14] = -p;
595  mat[15] = 0;
596 }
597 
598 
599 /*
600 * Convert quaternion to rotation axis (and angle). Quaternion must be normalized.
601 */
602 void quatRotAxis(const Quat_t q, Vector3_t pqr)
603 {
604  // Normalize quaternion
605 // mul_Vec4_X( q, q, 1/mag_Vec4(q) );
606 
607 // f_t theta = _ACOS( q[0] ) * (f_t)2.0;
608  f_t sin_a, d;
609 
610  sin_a = _SQRT( (f_t)1.0 - q[0] * q[0] );
611 
612  if ( _FABS( sin_a ) < (f_t)0.0005 )
613  sin_a = (f_t)1.0;
614 
615  d = (f_t)1.0 / sin_a;
616 
617  pqr[0] = q[1] * d;
618  pqr[1] = q[2] * d;
619  pqr[2] = q[3] * d;
620 }
621 
622 
623 /*
624  * Compute the derivative of the Euler_t angle psi with respect
625  * to the quaternion Q. The result is a row vector
626  *
627  * d(psi)/d(q0)
628  * d(psi)/d(q1)
629  * d(psi)/d(q2)
630  * d(psi)/d(q3)
631  */
632 void dpsi_dq(const Quat_t q, Quat_t dq)
633 {
634  f_t t1 = 1 - 2 * (q[2]*q[2] + q[3]*q[2]);
635  f_t t2 = 2 * (q[1]*q[2] + q[0]*q[3]);
636  f_t err = 2 / ( t1*t1 + t2*t2 );
637 
638  dq[0] = err * (q[3]*t1);
639  dq[1] = err * (q[2]*t1);
640  dq[2] = err * (q[1]*t1 + 2 * q[2]*t2);
641  dq[3] = err * (q[0]*t1 + 2 * q[3]*t2);
642 }
643 
644 
645 /*
646  * NED to Euler_t
647  */
648 void nedEuler(const Vector3_t ned, Euler_t e)
649 {
650  e[0] = 0;
651  e[1] = _ATAN2( -ned[2], _SQRT( ned[0] * ned[0] + ned[1] * ned[1] ) );
652  e[2] = _ATAN2( ned[1], ned[0] );
653 }
654 
655 
656 /*
657  * Euler_t to NED
658  */
659 void eulerNed(const Euler_t e, Vector3_t ned)
660 {
661  Vector3_t v = { 1, 0, 0};
662 
663  vectorBodyToReference( v, e, ned );
664 }
665 
666 
667 /*
668  * Rotate eulers from body to inertial frame by ins eulers, in order: phi, theta, psi
669  */
670 void eulerBodyToReference(const Euler_t e, const Euler_t rot, Euler_t result)
671 {
672  Matrix3_t Ai, At, AiAt;
673  // Create DCMs (rotation matrices)
674  eulerDCM(rot, Ai);
675  eulerDCM(e, At);
676 
677  // Apply INS Rotation to Desired Target vector
678  mul_Mat3x3_Mat3x3(AiAt, At, Ai); // Apply rotation
679  DCMeuler(AiAt, result); // Pull out new eulers
680 }
681 
682 
683 /*
684  * Rotate eulers from inertial to body frame by ins eulers, in order: psi, theta, phi
685  */
686 void eulerReferenceToBody(const Euler_t e, const Euler_t rot, Euler_t result)
687 {
688  Matrix3_t Ai, At, AiAt;
689  // Create DCMs (rotation matrices)
690  eulerDCM(rot, Ai);
691  eulerDCM(e, At);
692 
693  // Apply INS Rotation to Desired Target vector
694  mul_Mat3x3_Mat3x3_Trans(AiAt, At, Ai); // Apply rotation
695  DCMeuler(AiAt, result); // Pull out new eulers
696 }
697 
698 
699 /*
700  * Rotate vector from body to inertial frame by euler angles, in order: phi, theta, psi
701  */
702 void vectorBodyToReference(const Vector3_t v, const Euler_t rot, Vector3_t result)
703 {
704  Matrix3_t DCM;
705 
706  // Create DCM (rotation matrix)
707  eulerDCM(rot, DCM);
708 
709  // Apply rotation to vector
710  mul_Mat3x3_Trans_Vec3x1( result, DCM, v );
711 }
712 
713 
714 /*
715  * Rotate vector from inertial to body frame by euler angles, in order: psi, theta, phi
716  */
717 void vectorReferenceToBody(const Vector3_t v, const Euler_t rot, Vector3_t result)
718 {
719  Matrix3_t DCM;
720 
721  // Create DCM (rotation matrix)
722  eulerDCM(rot, DCM);
723 
724  // Apply rotation to vector
725  mul_Mat3x3_Vec3x1( result, DCM, v );
726 }
727 
728 
729 
d
void quatDCM(const Quat_t q, Matrix3_t mat)
Definition: ISPose.c:466
void DCMquat(const Matrix3_t mat, Quat_t q)
Definition: ISPose.c:527
void quat2euler(const Quat_t q, Euler_t theta)
Definition: ISPose.c:185
float f_t
Definition: ISConstants.h:786
void vectorReferenceToBody(const Vector3_t v, const Euler_t rot, Vector3_t result)
Definition: ISPose.c:717
void DCMeuler(const Matrix3_t m, Euler_t euler)
Definition: ISPose.c:447
f
void quatConj(Quat_t result, const Quat_t q)
Definition: ISPose.c:49
void eulerBodyToReference(const Euler_t e, const Euler_t rot, Euler_t result)
Definition: ISPose.c:670
void cross_Vec3(Vector3 result, const Vector3 v1, const Vector3 v2)
Definition: ISMatrix.c:594
void quat2psi(const Quat_t q, f_t *psi)
Definition: ISPose.c:204
void psiDCM(const f_t psi, Matrix2_t m)
Definition: ISPose.c:316
void mul_Mat3x3_Trans_Vec3x1(Vector3 result, const Matrix3 m, const Vector3 v)
Definition: ISMatrix.c:437
void quatConjRot(Vector3_t result, const Quat_t q, const Vector3_t v)
Definition: ISPose.c:161
void quatRotAxis(const Quat_t q, Vector3_t pqr)
Definition: ISPose.c:602
void div_Quat_Quat(Quat_t result, const Quat_t q1, const Quat_t q2)
Definition: ISPose.c:105
#define _ATAN2
Definition: ISConstants.h:775
#define dot_Vec3(v)
Definition: ISMatrix.h:29
void quat_ecef2ned(float lat, float lon, float *qe2n)
Definition: ISPose.c:267
f_t dot_Vec3_Vec3(const Vector3 v1, const Vector3 v2)
Definition: ISMatrix.c:570
f_t q_t
Definition: ISPose.h:37
Matrix3 Matrix3_t
Definition: ISPose.h:39
Matrix4 Matrix4_t
Definition: ISPose.h:40
void mul_Mat3x3_Mat3x3(Matrix3 result, const Matrix3 m1, const Matrix3 m2)
Definition: ISMatrix.c:322
void eulerNed(const Euler_t e, Vector3_t ned)
Definition: ISPose.c:659
void quat_init(Quat_t q)
Definition: ISPose.c:34
void quatW(const Euler_t euler, Matrix4_t mat)
Definition: ISPose.c:570
void quat2phiTheta(const Quat_t q, f_t *phi, f_t *theta)
Definition: ISPose.c:195
#define _ASIN
Definition: ISConstants.h:773
#define _SQRT
Definition: ISConstants.h:776
void mul_Quat_ConjQuat(Quat_t result, const Quat_t q1, const Quat_t qc)
Definition: ISPose.c:92
f_t Vector4[4]
Definition: ISConstants.h:793
#define _SIN
Definition: ISConstants.h:770
void mul_Mat3x3_Vec3x1(Vector3 result, const Matrix3 m, const Vector3 v)
Definition: ISMatrix.c:430
#define C_PI_F
Definition: ISConstants.h:554
Vector4_t Quat_t
Definition: ISPose.h:36
void euler2quat(const Euler_t euler, Quat_t q)
Definition: ISPose.c:218
void quatdDCM(const Vector4d q, Matrix3_t mat)
Definition: ISPose.c:491
void eulerReferenceToBody(const Euler_t e, const Euler_t rot, Euler_t result)
Definition: ISPose.c:686
Matrix2 Matrix2_t
Definition: ISPose.h:38
void quat_Vec3_Vec3(Quat_t result, const Vector3_t v1, const Vector3_t v2)
Definition: ISPose.c:118
void eulerDCM(const Euler_t euler, Matrix3_t m)
Definition: ISPose.c:355
void eulerWx(const Euler_t euler, Matrix3_t mat)
Definition: ISPose.c:545
#define mag_Vec4(v)
Definition: ISMatrix.h:35
void qe2b2EulerNedEcef(Vector3 eul, const Vector4 qe2b, const Vector3d ecef)
Definition: ISPose.c:281
void add_Vec3_Vec3(Vector3 result, const Vector3 v1, const Vector3 v2)
Definition: ISMatrix.c:675
double Vector3d[3]
Definition: ISConstants.h:790
#define recipNorm_Vec3(v)
Definition: ISMatrix.h:42
void qe2b2EulerNedLLA(Vector3 eul, const Vector4 qe2b, const Vector3d lla)
Definition: ISPose.c:294
void ecef2lla(const double *Pe, double *LLA, const int Niter)
Definition: ISEarth.c:54
void mul_Quat_Quat(Quat_t result, const Quat_t q1, const Quat_t q2)
Definition: ISPose.c:64
void mul_Vec3_X(Vector3 result, const Vector3 v, const f_t x)
Definition: ISMatrix.c:620
void nedEuler(const Vector3_t ned, Euler_t e)
Definition: ISPose.c:648
void dpsi_dq(const Quat_t q, Quat_t dq)
Definition: ISPose.c:632
void eulerDCM_Trans(const Euler_t euler, Matrix3_t m)
Definition: ISPose.c:413
void mul_Mat3x3_Mat3x3_Trans(Matrix3 result, const Matrix3 m1, const Matrix3 m2)
Definition: ISMatrix.c:386
void mul_ConjQuat_Quat(Quat_t result, const Quat_t qc, const Quat_t q2)
Definition: ISPose.c:78
void quatRot(Vector3_t result, const Quat_t q, const Vector3_t v)
Definition: ISPose.c:142
void vectorBodyToReference(const Vector3_t v, const Euler_t rot, Vector3_t result)
Definition: ISPose.c:702
#define _COS
Definition: ISConstants.h:771
void div_Vec4_X(Vector4 result, const Vector4 v, const f_t x)
Definition: ISMatrix.c:658
f_t DCMpsi(const f_t *m)
Definition: ISPose.c:340
#define _FABS
Definition: ISConstants.h:777
void phiThetaDCM(const Euler_t euler, Matrix3_t m)
Definition: ISPose.c:380
double Vector4d[4]
Definition: ISConstants.h:792


inertial_sense_ros
Author(s):
autogenerated on Sat Sep 19 2020 03:19:04