MAV'RIC
quaternions.h
1 /*******************************************************************************
2  * Copyright (c) 2009-2014, MAV'RIC Development Team
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, 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 name of the copyright holder nor the names of its 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"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  ******************************************************************************/
31 
32 /*******************************************************************************
33  * \file quaternions.h
34  *
35  * \author MAV'RIC Team
36  * \author Felix Schill
37  * \author Geraud L'Eplattenier
38  *
39  * \brief Useful functions for quaternions
40  *
41  ******************************************************************************/
42 
43 
44 #ifndef QUATERNIONS_H_
45 #define QUATERNIONS_H_
46 
47 #ifdef __cplusplus
48 extern "C"
49 {
50 #endif
51 
52 #include <stdint.h>
53 #include "maths.h"
54 #include "vectors.h"
55 
56 
62 typedef struct
63 {
64  float s;
65  float v[3];
66 } quat_t;
67 
68 
76 #define QI(q, out) \
77  out.s = q.s;\
78  out.v[0] = -q.v[0];\
79  out.v[1] = -q.v[1];\
80  out.v[2] = -q.v[2];
81 
82 
92 #define QUAT(q, s, v0, v1, v2) \
93  q.s = s;\
94  q.v[0] = v0;\
95  q.v[1] = v1;\
96  q.v[2] = v2;
97 
98 
106 quat_t static inline quaternions_create_from_vector(float v[3])
107 {
108  quat_t q;
109  q.s = 0;
110  q.v[0] = v[0];
111  q.v[1] = v[1];
112  q.v[2] = v[2];
113  return q;
114 }
115 
116 
124 #define QMUL(q1,q2,out) \
125  tmp[0] = q1.v[1] * q2.v[2] - q1.v[2] * q2.v[1];\
126  tmp[1] = q1.v[2] * q2.v[0] - q1.v[0] * q2.v[2];\
127  tmp[2] = q1.v[0] * q2.v[1] - q1.v[1] * q2.v[0];\
128  out.v[0] = q2.s* q1.v[0] + q1.s * q2.v[0] + tmp[0];\
129  out.v[1] = q2.s* q1.v[1] + q1.s * q2.v[1] + tmp[1];\
130  out.v[2] = q2.s* q1.v[2] + q1.s * q2.v[2] + tmp[2];\
131  out.s= q1.s * q2.s - SCP(q1.v, q2.v);
132 
133 
142 quat_t static inline quaternions_multiply(const quat_t q1, const quat_t q2)
143 {
144  float tmp[3];
145  quat_t out;
146 
147  tmp[0] = q1.v[1] * q2.v[2] - q1.v[2] * q2.v[1];
148  tmp[1] = q1.v[2] * q2.v[0] - q1.v[0] * q2.v[2];
149  tmp[2] = q1.v[0] * q2.v[1] - q1.v[1] * q2.v[0];
150 
151  out.v[0] = q2.s * q1.v[0] + q1.s * q2.v[0] + tmp[0];
152  out.v[1] = q2.s * q1.v[1] + q1.s * q2.v[1] + tmp[1];
153  out.v[2] = q2.s * q1.v[2] + q1.s * q2.v[2] + tmp[2];
154  out.s = q1.s * q2.s - vectors_scalar_product(q1.v, q2.v);
155 
156  return out;
157 }
158 
159 
166 quat_t static inline quaternions_inverse(const quat_t q)
167 {
168  quat_t qinv;
169  qinv.s = q.s;
170 
171  for( int32_t i = 0; i < 3; i++)
172  {
173  qinv.v[i] = -q.v[i];
174  }
175 
176  return qinv;
177 }
178 
179 
190 quat_t static inline quaternions_global_to_local(const quat_t qe, const quat_t qvect)
191 {
192  quat_t qinv, qtmp;
193 
194  qinv = quaternions_inverse(qe);
195  qtmp = quaternions_multiply(qinv,qvect);
196  qtmp = quaternions_multiply(qtmp,qe);
197 
198  return qtmp;
199 }
200 
201 
212 quat_t static inline quaternions_local_to_global(const quat_t qe, const quat_t qvect)
213 {
214  quat_t qinv, qtmp;
215 
216  qinv = quaternions_inverse(qe);
217  qtmp = quaternions_multiply(qe, qvect);
218  qtmp = quaternions_multiply(qtmp, qinv);
219 
220  return qtmp;
221 }
222 
223 
235 void static inline quaternions_rotate_vector(const quat_t q, const float u[3], float v[3])
236 {
237  float tmp1[3], tmp2[3];
238 
239  vectors_cross_product(q.v, u, tmp1);
240  tmp1[0] = 2 * tmp1[0];
241  tmp1[1] = 2 * tmp1[1];
242  tmp1[2] = 2 * tmp1[2];
243 
244  vectors_cross_product(q.v, tmp1, tmp2);
245 
246  v[0] = u[0] + q.s * tmp1[0] + tmp2[0];
247  v[1] = u[1] + q.s * tmp1[1] + tmp2[1];
248  v[2] = u[2] + q.s * tmp1[2] + tmp2[2];
249 }
250 
251 
258 static inline quat_t quaternions_normalise(const quat_t q)
259 {
260  quat_t result;
261 
262  float snorm = SQR(q.s) + SQR(q.v[0]) + SQR(q.v[1]) + SQR(q.v[2]);
263 
264  if (snorm > 0.0000001f)
265  {
266  float norm = maths_fast_sqrt(snorm);
267  result.s = q.s / norm;
268  result.v[0] = q.v[0] / norm;
269  result.v[1] = q.v[1] / norm;
270  result.v[2] = q.v[2] / norm;
271  }
272  else
273  {
274  result.s = 1.0f;
275  result.v[0] = 0.0f;
276  result.v[1] = 0.0f;
277  result.v[2] = 0.0f;
278  }
279 
280  return result;
281 }
282 
283 
284 #ifdef __cplusplus
285 }
286 #endif
287 
288 #endif /* QUATERNIONS_H_ */
float s
Scalar component.
Definition: quaternions.h:64
Unit quaternion.
Definition: quaternions.h:62
float v[3]
Vector component.
Definition: quaternions.h:65