xsquaternion.c
Go to the documentation of this file.
1 
2 // Copyright (c) 2003-2021 Xsens Technologies B.V. or subsidiaries worldwide.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions, and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions, and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the names of the copyright holders nor the names of their contributors
16 // may be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
26 // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE LAWS OF THE NETHERLANDS
28 // SHALL BE EXCLUSIVELY APPLICABLE AND ANY DISPUTES SHALL BE FINALLY SETTLED UNDER THE RULES
29 // OF ARBITRATION OF THE INTERNATIONAL CHAMBER OF COMMERCE IN THE HAGUE BY ONE OR MORE
30 // ARBITRATORS APPOINTED IN ACCORDANCE WITH SAID RULES.
31 //
32 
33 
34 // Copyright (c) 2003-2021 Xsens Technologies B.V. or subsidiaries worldwide.
35 // All rights reserved.
36 //
37 // Redistribution and use in source and binary forms, with or without modification,
38 // are permitted provided that the following conditions are met:
39 //
40 // 1. Redistributions of source code must retain the above copyright notice,
41 // this list of conditions, and the following disclaimer.
42 //
43 // 2. Redistributions in binary form must reproduce the above copyright notice,
44 // this list of conditions, and the following disclaimer in the documentation
45 // and/or other materials provided with the distribution.
46 //
47 // 3. Neither the names of the copyright holders nor the names of their contributors
48 // may be used to endorse or promote products derived from this software without
49 // specific prior written permission.
50 //
51 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
52 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
53 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
54 // THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 // SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
56 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
58 // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE LAWS OF THE NETHERLANDS
60 // SHALL BE EXCLUSIVELY APPLICABLE AND ANY DISPUTES SHALL BE FINALLY SETTLED UNDER THE RULES
61 // OF ARBITRATION OF THE INTERNATIONAL CHAMBER OF COMMERCE IN THE HAGUE BY ONE OR MORE
62 // ARBITRATORS APPOINTED IN ACCORDANCE WITH SAID RULES.
63 //
64 
65 #include "xsquaternion.h"
66 #include "xseuler.h"
67 #include "xsmatrix.h"
68 #include "xsvector.h"
69 #include <math.h>
70 #include "xsfloatmath.h"
71 
72 
86 {
87  thisPtr->m_w = XsMath_zero;
88  thisPtr->m_x = XsMath_zero;
89  thisPtr->m_y = XsMath_zero;
90  thisPtr->m_z = XsMath_zero;
91 }
92 
94 int XsQuaternion_empty(const XsQuaternion* thisPtr)
95 {
96  return thisPtr->m_w == XsMath_zero && thisPtr->m_x == XsMath_zero && thisPtr->m_y == XsMath_zero && thisPtr->m_z == XsMath_zero;
97 }
98 
104 {
105  XsQuaternion_inverse(thisPtr, thisPtr);
106 }
107 
113 void XsQuaternion_inverse(const XsQuaternion* thisPtr, XsQuaternion* dest)
114 {
115  dest->m_w = thisPtr->m_w;
116  dest->m_x = -thisPtr->m_x;
117  dest->m_y = -thisPtr->m_y;
118  dest->m_z = -thisPtr->m_z;
119 }
120 
124 {
125  XsReal divisor, length = sqrt(thisPtr->m_w * thisPtr->m_w + thisPtr->m_x * thisPtr->m_x + thisPtr->m_y * thisPtr->m_y + thisPtr->m_z * thisPtr->m_z);
126  divisor = XsMath_one / length;
127  if (thisPtr->m_w < 0)
128  divisor = -divisor;
129 
130  dest->m_w = thisPtr->m_w * divisor;
131  dest->m_x = thisPtr->m_x * divisor;
132  dest->m_y = thisPtr->m_y * divisor;
133  dest->m_z = thisPtr->m_z * divisor;
134 
135  return length;
136 }
137 
141 {
142  return XsQuaternion_normalized(thisPtr, thisPtr);
143 }
144 
147 {
148  XsReal cosX, sinX, cosY, sinY, cosZ, sinZ;
149 
150  if (XsEuler_empty(src))
151  {
152  *thisPtr = *XsQuaternion_identity();
153  return;
154  }
155 
156  cosX = cos(XsMath_pt5 * XsMath_deg2rad(src->m_x));
157  sinX = sin(XsMath_pt5 * XsMath_deg2rad(src->m_x));
158  cosY = cos(XsMath_pt5 * XsMath_deg2rad(src->m_y));
159  sinY = sin(XsMath_pt5 * XsMath_deg2rad(src->m_y));
160  cosZ = cos(XsMath_pt5 * XsMath_deg2rad(src->m_z));
161  sinZ = sin(XsMath_pt5 * XsMath_deg2rad(src->m_z));
162 
163  thisPtr->m_w = cosX * cosY * cosZ + sinX * sinY * sinZ;
164  thisPtr->m_x = sinX * cosY * cosZ - cosX * sinY * sinZ;
165  thisPtr->m_y = cosX * sinY * cosZ + sinX * cosY * sinZ;
166  thisPtr->m_z = cosX * cosY * sinZ - sinX * sinY * cosZ;
167 }
168 
177 {
178  XsReal trace; // Trace of matrix
179  XsReal s;
180 
181  if (!XsMatrix_dimensionsMatch(ori, 3, 3))
182  {
183  XsQuaternion_destruct(thisPtr);
184  return;
185  }
186 
187  // XsQuaternion result;
188 
189  // Calculate trace of matrix
190  // T = 4 - 4x^2 - 4y^2 - 4z^2
191  // = 4 ( 1 - x^2 - y^2 - z^2)
192  // = 1 + fRgs[0][0] + fRgs[1][1] + fRgs[2][2] (= 4q0^2)
193 
194  trace = XsMatrix_value(ori, 0, 0) + XsMatrix_value(ori, 1, 1) + XsMatrix_value(ori, 2, 2) + XsMath_one;
195 
196  // If the trace of the matrix is greater than zero,
197  // then perform an "instant" calculation.
198  // Important note wrt. rounding errors:
199  // Test if (T > 0.0000001) to avoid large distortions!
200  // If the trace of the matrix is equal to zero, then identify
201  // which major diagonal element has the greatest value
202  if (trace * trace >= XsMath_tinyValue)
203  {
204  s = XsMath_two * sqrt(trace);
205  thisPtr->m_w = XsMath_pt25 * s;
206 
207  s = XsMath_one / s;
208  thisPtr->m_x = (XsMatrix_value(ori, 1, 2) - XsMatrix_value(ori, 2, 1)) * s;
209  thisPtr->m_y = (XsMatrix_value(ori, 2, 0) - XsMatrix_value(ori, 0, 2)) * s;
210  thisPtr->m_z = (XsMatrix_value(ori, 0, 1) - XsMatrix_value(ori, 1, 0)) * s;
211  }
212  else if ((XsMatrix_value(ori, 0, 0) > XsMatrix_value(ori, 1, 1)) && (XsMatrix_value(ori, 0, 0) > XsMatrix_value(ori, 2, 2)))
213  {
214  trace = XsMath_one + XsMatrix_value(ori, 0, 0) - XsMatrix_value(ori, 1, 1) - XsMatrix_value(ori, 2, 2);
215  s = XsMath_two * sqrt(trace);
216  thisPtr->m_x = XsMath_pt25 * s;
217 
218  s = XsMath_one / s;
219  thisPtr->m_w = (XsMatrix_value(ori, 1, 2) - XsMatrix_value(ori, 2, 1)) * s;
220  thisPtr->m_y = (XsMatrix_value(ori, 0, 1) + XsMatrix_value(ori, 1, 0)) * s;
221  thisPtr->m_z = (XsMatrix_value(ori, 2, 0) + XsMatrix_value(ori, 0, 2)) * s;
222  }
223  else if (XsMatrix_value(ori, 1, 1) > XsMatrix_value(ori, 2, 2))
224  {
225  trace = XsMath_one + XsMatrix_value(ori, 1, 1) - XsMatrix_value(ori, 0, 0) - XsMatrix_value(ori, 2, 2);
226  s = XsMath_two * sqrt(trace);
227  thisPtr->m_y = XsMath_pt25 * s;
228 
229  s = XsMath_one / s;
230  thisPtr->m_w = (XsMatrix_value(ori, 2, 0) - XsMatrix_value(ori, 0, 2)) * s;
231  thisPtr->m_x = (XsMatrix_value(ori, 0, 1) + XsMatrix_value(ori, 1, 0)) * s;
232  thisPtr->m_z = (XsMatrix_value(ori, 1, 2) + XsMatrix_value(ori, 2, 1)) * s;
233  }
234  else
235  {
236  trace = XsMath_one + XsMatrix_value(ori, 2, 2) - XsMatrix_value(ori, 0, 0) - XsMatrix_value(ori, 1, 1);
237  s = XsMath_two * sqrt(trace);
238  thisPtr->m_z = XsMath_pt25 * s;
239 
240  s = XsMath_one / s;
241  thisPtr->m_w = (XsMatrix_value(ori, 0, 1) - XsMatrix_value(ori, 1, 0)) * s;
242  thisPtr->m_x = (XsMatrix_value(ori, 2, 0) + XsMatrix_value(ori, 0, 2)) * s;
243  thisPtr->m_y = (XsMatrix_value(ori, 1, 2) + XsMatrix_value(ori, 2, 1)) * s;
244  }
245 
246  XsQuaternion_inverse(thisPtr, thisPtr);
247 }
248 
251 {
252  static const XsQuaternion sIdentity = { { { 1, 0, 0, 0 } } };
253  return &sIdentity;
254 }
255 
257 void XsQuaternion_multiply(const XsQuaternion* left, const XsQuaternion* right, XsQuaternion* dest)
258 {
259  XsReal qa0 = left->m_w;
260  XsReal qa1 = left->m_x;
261  XsReal qa2 = left->m_y;
262  XsReal qa3 = left->m_z;
263 
264  XsReal qb0 = right->m_w;
265  XsReal qb1 = right->m_x;
266  XsReal qb2 = right->m_y;
267  XsReal qb3 = right->m_z;
268 
269  dest->m_w = qa0 * qb0 - qa1 * qb1 - qa2 * qb2 - qa3 * qb3;
270  dest->m_x = qa1 * qb0 + qa0 * qb1 - qa3 * qb2 + qa2 * qb3;
271  dest->m_y = qa2 * qb0 + qa3 * qb1 + qa0 * qb2 - qa1 * qb3;
272  dest->m_z = qa3 * qb0 - qa2 * qb1 + qa1 * qb2 + qa0 * qb3;
273 }
274 
278 {
279  XsReal t;
280  int i;
281  for (i = 0; i < 4; ++i)
282  {
283  t = a->m_data[i];
284  a->m_data[i] = b->m_data[i];
285  b->m_data[i] = t;
286  }
287 }
288 
292 {
293  copy->m_w = src->m_w;
294  copy->m_x = src->m_x;
295  copy->m_y = src->m_y;
296  copy->m_z = src->m_z;
297 }
298 
302 {
303  return (a->m_w == b->m_w &&
304  a->m_x == b->m_x &&
305  a->m_y == b->m_y &&
306  a->m_z == b->m_z);
307 }
308 
315 static int fuzzyIsEqual(double a, double b, double tolerance)
316 {
317  return fabs(a - b) <= tolerance;
318 }
319 
323 int XsQuaternion_compare(XsQuaternion const* thisPtr, XsQuaternion const* other, XsReal tolerance)
324 {
325  if (thisPtr == other)
326  return 1;
327 
328  if (fuzzyIsEqual(thisPtr->m_data[0], other->m_data[0], tolerance) &&
329  fuzzyIsEqual(thisPtr->m_data[1], other->m_data[1], tolerance) &&
330  fuzzyIsEqual(thisPtr->m_data[2], other->m_data[2], tolerance) &&
331  fuzzyIsEqual(thisPtr->m_data[3], other->m_data[3], tolerance))
332  return 1;
333  // add extra check for q == -q (negative-definite vs positive-definite comparison)
334  return (fuzzyIsEqual(thisPtr->m_data[0], -other->m_data[0], tolerance) &&
335  fuzzyIsEqual(thisPtr->m_data[1], -other->m_data[1], tolerance) &&
336  fuzzyIsEqual(thisPtr->m_data[2], -other->m_data[2], tolerance) &&
337  fuzzyIsEqual(thisPtr->m_data[3], -other->m_data[3], tolerance));
338 }
339 
344 {
345  return (thisPtr->m_w * other->m_w) +
346  (thisPtr->m_x * other->m_x) +
347  (thisPtr->m_y * other->m_y) +
348  (thisPtr->m_z * other->m_z);
349 }
350 
XsQuaternion::XsQuaternion_fromRotationMatrix
void XsQuaternion_fromRotationMatrix(XsQuaternion *thisPtr, const XsMatrix *ori)
Create a quaternion representation of orientation matrix ori.
Definition: xsquaternion.c:176
XsMatrix
A class that represents a matrix of real numbers.
Definition: xsmatrix.h:107
XsQuaternion::XsQuaternion_invert
void XsQuaternion_invert(XsQuaternion *thisPtr)
Invert this quaternion.
Definition: xsquaternion.c:103
XsMath_one
XSMATHCONST XsReal XsMath_one
1.0
Definition: xsmath.h:158
XsMatrix::XsMatrix_value
XsReal XsMatrix_value(const XsMatrix *thisPtr, XsSize row, XsSize column)
Returns the data value at row and column.
Definition: xsmatrix.c:299
xsquaternion.h
s
XmlRpcServer s
XsEuler::m_x
XsReal m_x
Stores the x component of the euler triplet.
Definition: xseuler.h:213
xsvector.h
XsQuaternion::XsQuaternion_normalized
XsReal XsQuaternion_normalized(const XsQuaternion *thisPtr, XsQuaternion *dest)
Create a normalized version of this quaternion.
Definition: xsquaternion.c:123
XsQuaternion::XsQuaternion_copy
void XsQuaternion_copy(XsQuaternion *copy, XsQuaternion const *src)
Copies the contents of thisPtr into copy.
Definition: xsquaternion.c:291
xsfloatmath.h
XsMath_tinyValue
XSMATHCONST XsReal XsMath_tinyValue
A really small value.
Definition: xsmath.h:120
XsMatrix::XsMatrix_dimensionsMatch
int XsMatrix_dimensionsMatch(const XsMatrix *thisPtr, XsSize rows, XsSize columns)
Returns not zero if the dimensions of the XsMatrix are equal to rows and columns.
Definition: xsmatrix.c:312
XsQuaternion
A class that implements a quaternion.
Definition: xsquaternion.h:102
xsmatrix.h
XsQuaternion::XsQuaternion_inverse
void XsQuaternion_inverse(const XsQuaternion *thisPtr, XsQuaternion *dest)
Compute the inverse/conjugate of this quaternion.
Definition: xsquaternion.c:113
fuzzyIsEqual
static int fuzzyIsEqual(double a, double b, double tolerance)
Checks whether a and b are equal with tolerance tolerance.
Definition: xsquaternion.c:315
XsQuaternion::XsQuaternion_empty
int XsQuaternion_empty(const XsQuaternion *thisPtr)
Test if this is a null object.
Definition: xsquaternion.c:94
XsMath_pt5
XSMATHCONST XsReal XsMath_pt5
0.5
Definition: xsmath.h:154
XsQuaternion::XsQuaternion_dotProduct
XsReal XsQuaternion_dotProduct(XsQuaternion const *thisPtr, XsQuaternion const *other)
Returns the dot product of the thisPtr with other.
Definition: xsquaternion.c:343
XsReal
double XsReal
Defines the floating point type used by the Xsens libraries.
Definition: xstypedefs.h:73
XsQuaternion::XsQuaternion_equal
int XsQuaternion_equal(XsQuaternion const *a, XsQuaternion const *b)
returns non-zero if a and b are numerically equal
Definition: xsquaternion.c:301
XsMath_pt25
XSMATHCONST XsReal XsMath_pt25
0.25
Definition: xsmath.h:152
XsQuaternion::XsQuaternion_multiply
void XsQuaternion_multiply(const XsQuaternion *left, const XsQuaternion *right, XsQuaternion *dest)
Multiply left quaternion with right quaternion and put the result in dest. The parameters may point t...
Definition: xsquaternion.c:257
XsQuaternion::XsQuaternion_identity
const XsQuaternion * XsQuaternion_identity(void)
Returns an XsQuaternion that represents the identity quaternion.
Definition: xsquaternion.c:250
XsQuaternion::m_x
XsReal m_x
Stores the x component of the quaternion.
Definition: xsquaternion.h:110
XsQuaternion::m_data
XsReal m_data[4]
Stores the quaternion in an array of four elements.
Definition: xsquaternion.h:114
XsEuler::m_z
XsReal m_z
Stores the z component of the euler triplet.
Definition: xseuler.h:215
XsMath_two
XSMATHCONST XsReal XsMath_two
2
Definition: xsmath.h:162
XsMath_zero
XSMATHCONST XsReal XsMath_zero
0
Definition: xsmath.h:150
XsQuaternion::XsQuaternion_swap
void XsQuaternion_swap(XsQuaternion *a, XsQuaternion *b)
Swap the contents of a and b.
Definition: xsquaternion.c:277
xseuler.h
XsEuler
Contains Euler Angle data and conversion from Quaternion.
Definition: xseuler.h:92
length
TF2SIMD_FORCE_INLINE tf2Scalar length(const Quaternion &q)
XsQuaternion::m_y
XsReal m_y
Stores the y component of the quaternion.
Definition: xsquaternion.h:111
XsMath_deg2rad
XSMATHINLINE XsReal XsMath_deg2rad(XsReal degrees)
Convert degrees to radians.
Definition: xsmath.h:203
XsQuaternion::XsQuaternion_destruct
void XsQuaternion_destruct(XsQuaternion *thisPtr)
Sets the contents to 0, which is an invalid XsQuaternion.
Definition: xsquaternion.c:85
XsEuler::m_y
XsReal m_y
Stores the y component of the euler triplet.
Definition: xseuler.h:214
XsQuaternion::m_w
XsReal m_w
Stores the w component of the quaternion.
Definition: xsquaternion.h:109
XsQuaternion::XsQuaternion_compare
int XsQuaternion_compare(XsQuaternion const *thisPtr, XsQuaternion const *other, XsReal tolerance)
Returns non-zero if the values at thisPtr and other are within tolerance of each other.
Definition: xsquaternion.c:323
XsQuaternion::m_z
XsReal m_z
Stores the z component of the quaternion.
Definition: xsquaternion.h:112
XsEuler::XsEuler_empty
int XsEuler_empty(const XsEuler *thisPtr)
Returns true if all angles in this object are zero.
Definition: xseuler.c:95
XsQuaternion::XsQuaternion_fromEulerAngles
void XsQuaternion_fromEulerAngles(XsQuaternion *thisPtr, const XsEuler *src)
Create a quaternion representation from euler angles.
Definition: xsquaternion.c:146
XsQuaternion::XsQuaternion_normalize
XsReal XsQuaternion_normalize(XsQuaternion *thisPtr)
Normalize this quaternion.
Definition: xsquaternion.c:140


xsens_mti_driver
Author(s):
autogenerated on Sun Sep 3 2023 02:43:20