1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /*! \file orientation.h
10     \brief Functions to convert between various orientation representations
11 
12     Functions to convert between various orientation representations.  Also
13     includes functions for manipulating quaternions.
14 */
15 
16 #ifndef ORIENTATION_H
17 #define ORIENTATION_H
18 
19 /// quaternion structure definition
20 typedef struct Quaternion
21 {
22 	float q0;	        ///< scalar component
23 	float q1;	        ///< x vector component
24 	float q2;	        ///< y vector component
25 	float q3;	        ///< z vector component
26 } Quaternion;
27 
28 // function prototypes
29 /// Aerospace NED accelerometer 3DOF tilt function, computing rotation matrix fR
30 void f3DOFTiltNED(
31     float fR[][3],              ///< computed rotation matrix (output)
32     float fGc[]                 ///< calibrated accelerometer input vector
33 );
34 /// Android accelerometer 3DOF tilt function computing, rotation matrix fR
35 void f3DOFTiltAndroid(
36     float fR[][3],              ///< computed rotation matrix (output)
37     float fGc[]                 ///< calibrated accelerometer input vector
38 );
39 /// Windows 8 accelerometer 3DOF tilt function computing, rotation matrix fR
40 void f3DOFTiltWin8(
41     float fR[][3],              ///< computed rotation matrix (output)
42     float fGc[]                 ///< calibrated accelerometer input vector
43 );
44 /// Aerospace NED magnetometer 3DOF flat eCompass function, computing rotation matrix fR
45 void f3DOFMagnetometerMatrixNED(
46     float fR[][3],              ///< computed rotation matrix (output)
47     float fBc[]                 ///< calibrated magnetometer reading (input)
48 );
49 /// Android magnetometer 3DOF flat eCompass function, computing rotation matrix fR
50 void f3DOFMagnetometerMatrixAndroid(
51     float fR[][3],              ///< computed rotation matrix (output)
52     float fBc[]                 ///< calibrated magnetometer reading (input)
53 );
54 /// Windows 8 magnetometer 3DOF flat eCompass function, computing rotation matrix fR
55 void f3DOFMagnetometerMatrixWin8(
56     float fR[][3],              ///< computed rotation matrix (output)
57     float fBc[]                 ///< calibrated magnetometer reading (input)
58 );
59 /// NED: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelta
60 void feCompassNED(
61     float fR[][3],              ///< computed rotation matrix (output)
62     float *pfDelta,             ///< magnetic inclination angle (output)
63     float *pfsinDelta,          ///< sin of the inclination angle
64     float *pfcosDelta,          ///< cos of the inclination angle
65     float fBc[],                ///< calibrated magnetometer vector (input)
66     float fGc[],                ///< calibrated accelerometer input vector (input)
67     float *pfmodBc,             ///< modulus of the calibrated magnetic vector
68     float *pfmodGc              ///< modulus of the calibrated accelerometer vector
69 );
70 /// Android: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelta
71 void feCompassAndroid(
72     float fR[][3],              ///< computed rotation matrix (output)
73     float *pfDelta,             ///< magnetic inclination angle (output)
74     float *pfsinDelta,          ///< sin of the inclination angle
75     float *pfcosDelta,          ///< cos of the inclination angle
76     float fBc[],                ///< calibrated magnetometer reading (input)
77     float fGc[],                ///< calibrated accelerometer input vector (input)
78     float *pfmodBc,             ///< modulus of the calibrated magnetic vector
79     float *pfmodGc              ///< modulus of the calibrated accelerometer vector
80 );
81 /// Win8: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelta
82 void feCompassWin8(
83     float fR[][3],              ///< computed rotation matrix (output)
84     float *pfDelta,             ///< magnetic inclination angle (output)
85     float *pfsinDelta,          ///< sin of the inclination angle
86     float *pfcosDelta,          ///< cos of the inclination angle
87     float fBc[],                ///< calibrated magnetometer reading (input)
88     float fGc[],                ///< calibrated accelerometer input vector (input)
89     float *pfmodBc,             ///< modulus of the calibrated magnetic vector
90     float *pfmodGc              ///< modulus of the calibrated accelerometer vector
91 );
92 /// extract the NED angles in degrees from the NED rotation matrix
93 void fNEDAnglesDegFromRotationMatrix(
94     float R[][3],               ///< rotation matrix input
95     float *pfPhiDeg,            ///< output: the roll angle range -180.0 <= Phi < 180.0 deg
96     float *pfTheDeg,            ///< output: the pitch angle -90.0 <= Theta <= 90.0 deg
97     float *pfPsiDeg,            ///< output: the yaw (compass) angle 0.0 <= Psi < 360.0 deg
98     float *pfRhoDeg,            ///< output: For NED, the compass heading Rho equals the yaw angle Psi
99     float *pfChiDeg             ///< output: the tilt angle from vertical Chi (0 <= Chi <= 180 deg)
100 );
101 /// extract the Android angles in degrees from the Android rotation matrix
102 void fAndroidAnglesDegFromRotationMatrix(
103     float R[][3],               ///< rotation matrix input
104     float *pfPhiDeg,            ///< the roll angle -90.0 <= Phi <= 90.0 deg
105     float *pfTheDeg,            ///< the pitch angle -180.0 <= The < 180.0 deg
106     float *pfPsiDeg,            ///< yaw angle Psi with range 0.0 <= Psi < 360.0 deg
107     float *pfRhoDeg,            ///< the compass heading angle Rho equals the yaw angle Psi
108     float *pfChiDeg             ///< the tilt angle from vertical Chi (0 <= Chi <= 180 deg)
109 );
110 /// extract the Windows 8 angles in degrees from the Windows 8 rotation matrix
111 void fWin8AnglesDegFromRotationMatrix(
112     float R[][3],               ///< rotation matrix input
113     float *pfPhiDeg,            ///< the roll angle -90.0 <= Phi <= 90.0 deg
114     float *pfTheDeg,            ///< pitch angle Theta in the range -180.0 <= The < 180.0 deg
115     float *pfPsiDeg,            ///< yaw angle Psi in range 0.0 <= Psi < 360.0 deg
116     float *pfRhoDeg,            ///< the compass angle Rho = 360 - Psi
117     float *pfChiDeg             ///< tilt angle from vertical Chi (0 <= Chi <= 180 deg)
118 );
119 /// compute the orientation quaternion from a 3x3 rotation matrix
120 void fQuaternionFromRotationMatrix(
121     float R[][3],               ///< Rotation matrix (input)
122     Quaternion *pq              ///< Quaternion (output)
123 );
124 /// compute the rotation matrix from an orientation quaternion
125 void fRotationMatrixFromQuaternion(
126     float R[][3],               ///< Rotation matrix (output)
127     const Quaternion *pq        ///< Quaternion (input)
128 );
129 /// function compute the quaternion product qB * qC
130 void qAeqBxC(
131     Quaternion *pqA,
132     const Quaternion *pqB,
133     const Quaternion *pqC
134 );
135 /// function compute the quaternion product qA = qA * qB
136 void qAeqAxB(
137     Quaternion *pqA,
138     const Quaternion *pqB
139 );
140 /// function compute the quaternion product conjg(qA) * qB
141 Quaternion qconjgAxB(
142     const Quaternion *pqA,
143     const Quaternion *pqB
144 );
145 /// function normalizes a rotation quaternion and ensures q0 is non-negative
146 void fqAeqNormqA(
147     Quaternion *pqA
148 );
149 /// set a quaternion to the unit quaternion
150 void fqAeq1(
151     Quaternion *pqA
152 );
153 /// computes normalized rotation quaternion from a rotation vector (deg)
154 void fQuaternionFromRotationVectorDeg(
155     Quaternion *pq,             ///< quaternion (output)
156     const float rvecdeg[],      ///< rotation vector in degrees
157     float fscaling              ///< delta Time
158 );
159 /// computes rotation vector (deg) from rotation quaternion
160 void fRotationVectorDegFromQuaternion(
161     Quaternion *pq,             ///< quaternion (input)
162     float rvecdeg[]             ///< rotation vector in degrees (output)
163 );
164 /// function low pass filters an orientation quaternion and computes virtual gyro rotation rate
165 void fLPFOrientationQuaternion(
166     Quaternion *pq,
167     Quaternion *pLPq,
168     float flpf,
169     float fdeltat,
170     float fOmega[]
171 );
172 /// function computes the rotation quaternion that rotates unit vector u onto unit vector v as v=q*.u.q
173 /// using q = 1/sqrt(2) * {sqrt(1 + u.v) - u x v / sqrt(1 + u.v)}
174 void fveqconjgquq(
175   Quaternion *pfq,
176   float fu[],
177   float fv[]
178 );
179 
180 #endif   // #ifndef ORIENTATION_H
181