rotations.cpp
Go to the documentation of this file.
1 /**************************************************************************************************
2  Software License Agreement (BSD License)
3 
4  Copyright (c) 2011-2013, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without modification, are permitted
8  provided that the following conditions are met:
9 
10  *Redistributions of source code must retain the above copyright notice, this list of
11  conditions and the following disclaimer.
12  *Redistributions in binary form must reproduce the above copyright notice, this list of
13  conditions and the following disclaimer in the documentation and/or other materials provided
14  with the distribution.
15  *Neither the name of the University of Aveiro nor the names of its contributors may be used to
16  endorse or promote products derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ***************************************************************************************************/
33 #include <stdio.h>
34 #include <string.h>
35 #include <math.h>
36 #include <assert.h>
37 
38 #include "rotations.h"
39 
40 static inline int
41 feq (double a, double b) {
42  return fabs (a - b) < 1e-9;
43 }
44 
45 static inline int
46 qeq (double *q, double a, double b, double c, double d)
47 {
48  return feq(q[0],a) && feq(q[1],b) && feq(q[2],c) && feq(q[3],d);
49 }
50 
51 static inline int
52 rpyeq (double roll, double pitch, double yaw, double r, double p, double y)
53 {
54  return feq(roll,r) && feq(pitch,p) && feq(yaw,y);
55 }
56 
67 void
68 rot_quat_mult (double c[4], const double a[4], const double b[4])
69 {
70  c[0] = a[0]*b[0] - a[1]*b[1] - a[2]*b[2] - a[3]*b[3];
71  c[1] = a[0]*b[1] + a[1]*b[0] + a[2]*b[3] - a[3]*b[2];
72  c[2] = a[0]*b[2] - a[1]*b[3] + a[2]*b[0] + a[3]*b[1];
73  c[3] = a[0]*b[3] + a[1]*b[2] - a[2]*b[1] + a[3]*b[0];
74 }
75 
86 void
87 rot_quat_rotate (const double rot[4], double v[3])
88 {
89  double a[4], b[4], c[4];
90 
91  b[0] = 0;
92  memcpy (b+1, v, 3 * sizeof (double));
93 
94  rot_quat_mult (a, rot, b);
95  b[0] = rot[0];
96  b[1] = -rot[1];
97  b[2] = -rot[2];
98  b[3] = -rot[3];
99  rot_quat_mult (c, a, b);
100 
101  memcpy (v, c+1, 3 * sizeof (double));
102 }
103 
115 void
116 rot_quat_rotate_rev (const double rot[4], double v[3])
117 {
118  double a[4], b[4], c[4];
119 
120  b[0] = 0;
121  memcpy (b+1, v, 3 * sizeof (double));
122 
123  rot_quat_mult (a, b, rot);
124  b[0] = rot[0];
125  b[1] = -rot[1];
126  b[2] = -rot[2];
127  b[3] = -rot[3];
128  rot_quat_mult (c, b, a);
129 
130  memcpy (v, c+1, 3 * sizeof (double));
131 }
132 
133 void
134 rot_angle_axis_to_quat (double theta, const double axis[3], double q[4])
135 {
136  double x = axis[0], y = axis[1], z = axis[2];
137  double norm = sqrt (x*x + y*y + z*z);
138  if (0 == norm) {
139  q[0] = 1;
140  q[1] = q[2] = q[3] = 0;
141  return;
142  }
143 
144  double t = sin(theta/2) / norm;
145 
146  q[0] = cos(theta / 2);
147  q[1] = x * t;
148  q[2] = y * t;
149  q[3] = z * t;
150 }
151 
152 void
153 rot_quat_to_angle_axis (const double q[4], double *theta, double axis[3])
154 {
155  double halftheta = acos (q[0]);
156  *theta = halftheta * 2;
157  double sinhalftheta = sin (halftheta);
158  if (feq (halftheta, 0)) {
159  axis[0] = 0;
160  axis[0] = 0;
161  axis[1] = 1;
162  *theta = 0;
163  } else {
164  axis[0] = q[1] / sinhalftheta;
165  axis[1] = q[2] / sinhalftheta;
166  axis[2] = q[3] / sinhalftheta;
167  }
168 }
169 
170 void
171 rot_roll_pitch_yaw_to_quat (const double rpy[3], double q[4])
172 {
173  double roll = rpy[0], pitch = rpy[1], yaw = rpy[2];
174 
175  double halfroll = roll / 2;
176  double halfpitch = pitch / 2;
177  double halfyaw = yaw / 2;
178 
179  double sin_r2 = sin (halfroll);
180  double sin_p2 = sin (halfpitch);
181  double sin_y2 = sin (halfyaw);
182 
183  double cos_r2 = cos (halfroll);
184  double cos_p2 = cos (halfpitch);
185  double cos_y2 = cos (halfyaw);
186 
187  q[0] = cos_r2 * cos_p2 * cos_y2 + sin_r2 * sin_p2 * sin_y2;
188  q[1] = sin_r2 * cos_p2 * cos_y2 - cos_r2 * sin_p2 * sin_y2;
189  q[2] = cos_r2 * sin_p2 * cos_y2 + sin_r2 * cos_p2 * sin_y2;
190  q[3] = cos_r2 * cos_p2 * sin_y2 - sin_r2 * sin_p2 * cos_y2;
191 }
192 
193 void
194 rot_quat_to_roll_pitch_yaw (const double q[4], double rpy[3])
195 {
196  double roll_a = 2 * (q[0]*q[1] + q[2]*q[3]);
197  double roll_b = 1 - 2 * (q[1]*q[1] + q[2]*q[2]);
198  rpy[0] = atan2 (roll_a, roll_b);
199 
200  double pitch_sin = 2 * (q[0]*q[2] - q[3]*q[1]);
201  rpy[1] = asin (pitch_sin);
202 
203  double yaw_a = 2 * (q[0]*q[3] + q[1]*q[2]);
204  double yaw_b = 1 - 2 * (q[2]*q[2] + q[3]*q[3]);
205  rpy[2] = atan2 (yaw_a, yaw_b);
206 }
207 
208 void
209 rot_roll_pitch_yaw_to_angle_axis (const double rpy[3], double *theta,
210  double axis[3])
211 {
212  double q[4];
214  rot_quat_to_angle_axis (q, theta, axis);
215 }
216 
217 void
218 rot_angle_axis_to_roll_pitch_yaw (double theta, const double axis[3],
219  double rpy[3])
220 {
221  double q[4];
222  rot_angle_axis_to_quat (theta, axis, q);
224 }
225 
226 
227 int
228 rot_quat_to_matrix(const double quat[4], double rot[9])
229 {
230  double norm = quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] +
231  quat[3]*quat[3];
232  if (fabs(norm) < 1e-10)
233  return -1;
234 
235  norm = 1/norm;
236  double x = quat[1]*norm;
237  double y = quat[2]*norm;
238  double z = quat[3]*norm;
239  double w = quat[0]*norm;
240 
241  double x2 = x*x;
242  double y2 = y*y;
243  double z2 = z*z;
244  double w2 = w*w;
245  double xy = 2*x*y;
246  double xz = 2*x*z;
247  double yz = 2*y*z;
248  double wx = 2*w*x;
249  double wy = 2*w*y;
250  double wz = 2*w*z;
251 
252  rot[0] = w2+x2-y2-z2; rot[1] = xy-wz; rot[2] = xz+wy;
253  rot[3] = xy+wz; rot[4] = w2-x2+y2-z2; rot[5] = yz-wx;
254  rot[6] = xz-wy; rot[7] = yz+wx; rot[8] = w2-x2-y2+z2;
255 
256  return 0;
257 }
258 
259 int
260 rot_quat_pos_to_matrix(const double quat[4], const double pos[3], double mat[16])
261 {
262  double rot[9];
263  rot_quat_to_matrix(quat, rot);
264 
265  mat[0] = rot[0];
266  mat[1] = rot[1];
267  mat[2] = rot[2];
268  mat[3] = pos[0];
269 
270  mat[4] = rot[3];
271  mat[5] = rot[4];
272  mat[6] = rot[5];
273  mat[7] = pos[1];
274 
275  mat[8] = rot[6];
276  mat[9] = rot[7];
277  mat[10] = rot[8];
278  mat[11] = pos[2];
279 
280  mat[12] = 0;
281  mat[13] = 0;
282  mat[14] = 0;
283  mat[15] = 1;
284 
285  return 0;
286 }
287 
288 int
289 rot_matrix_to_quat(const double rot[9], double quat[4])
290 {
291  quat[0] = 0.5*sqrt(rot[0]+rot[4]+rot[8]+1);
292 
293  if (fabs(quat[0]) > 1e-8) {
294  double w4 = 1/4/quat[0];
295  quat[1] = (rot[7]-rot[5]) * w4;
296  quat[2] = (rot[2]-rot[6]) * w4;
297  quat[3] = (rot[3]-rot[1]) * w4;
298  }
299  else {
300  quat[1] = sqrt(fabs(-0.5*(rot[4]+rot[8])));
301  quat[2] = sqrt(fabs(-0.5*(rot[0]+rot[8])));
302  quat[3] = sqrt(fabs(-0.5*(rot[0]+rot[4])));
303  }
304 
305  double norm = quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] +
306  quat[3]*quat[3];
307  if (fabs(norm) < 1e-10)
308  return -1;
309 
310  norm = 1/norm;
311  quat[0] *= norm;
312  quat[1] *= norm;
313  quat[2] *= norm;
314  quat[3] *= norm;
315 
316  return 0;
317 }
318 
319 int
321 {
322 #define FAIL_TEST { fprintf(stderr, "rot_quaternion_test failed at line %d\n", \
323  __LINE__); return 0; }
324 
325  fprintf(stderr, "running quaternion test\n");
326  double theta = 0;
327  double rvec[] = { 0, 0, 1 };
328  double q[4];
329  double rpy[3];
330  double roll, pitch, yaw;
331 
332  rot_angle_axis_to_quat(theta, rvec, q);
333 
334  if (! qeq (q, 1, 0, 0, 0)) FAIL_TEST;
335 
337  roll = rpy[0]; pitch = rpy[1]; yaw = rpy[2];
338 
339  if (! rpyeq (roll,pitch,yaw, 0,0,0)) FAIL_TEST;
340 
341  // quat_from_angle_axis
342  theta = M_PI;
343  rot_angle_axis_to_quat(theta, rvec, q);
344 
345  fprintf(stderr,"<%.3f, %.3f, %.3f, %.3f>\n", q[0], q[1], q[2], q[3]);
346  if (! qeq (q, 0, 0, 0, 1)) FAIL_TEST;
347 
348  // rot_quat_to_angle_axis
349  rot_quat_to_angle_axis (q, &theta, rvec);
350  if (!feq (theta, M_PI)) FAIL_TEST;
351  if (!feq(rvec[0], 0) || !feq(rvec[1], 0) || !feq(rvec[2], 1)) FAIL_TEST;
352 
354 
355  if (! rpyeq (roll,pitch,yaw, 0,0,M_PI)) FAIL_TEST;
356 
357  double q2[4];
358  double q3[4];
359  double axis1[] = { 0, 1, 0 };
360  double axis2[] = { 0, 0, 1 };
361  rot_angle_axis_to_quat (M_PI/2, axis1, q);
362  rot_angle_axis_to_quat (M_PI/2, axis2, q);
363  rot_quat_mult (q3, q, q2);
364  rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
365  rot_quat_rotate (q, rvec);
366  fprintf(stderr, "by q: [ %.2f, %.2f, %.2f ]\n", rvec[0], rvec[1], rvec[2]);
367  rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
368  rot_quat_rotate (q2, rvec);
369  fprintf(stderr, "by q2: [ %.2f, %.2f, %.2f ]\n", rvec[0], rvec[1], rvec[2]);
370  rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
371  rot_quat_rotate (q3, rvec);
372  fprintf(stderr, "by q*q2: [ %.2f, %.2f, %.2f ]\n",
373  rvec[0], rvec[1], rvec[2]);
374  rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
375  rot_quat_mult (q3, q2, q);
376  rot_quat_rotate (q3, rvec);
377  fprintf(stderr, "by q2*q: [ %.2f, %.2f, %.2f ]\n",
378  rvec[0], rvec[1], rvec[2]);
379 
380  // TODO
381 
382 #undef FAIL_TEST
383 
384  fprintf(stderr, "rot_quaternion_test complete\n");
385  return 1;
386 }
void rot_angle_axis_to_roll_pitch_yaw(double theta, const double axis[3], double rpy[3])
Definition: rotations.cpp:218
int rot_quat_pos_to_matrix(const double quat[4], const double pos[3], double mat[16])
Definition: rotations.cpp:260
void rot_quat_mult(double c[4], const double a[4], const double b[4])
rot_quat_mult
Definition: rotations.cpp:68
void rot_roll_pitch_yaw_to_quat(const double rpy[3], double q[4])
Definition: rotations.cpp:171
#define FAIL_TEST
int rot_matrix_to_quat(const double rot[9], double quat[4])
Definition: rotations.cpp:289
void rot_roll_pitch_yaw_to_angle_axis(const double rpy[3], double *theta, double axis[3])
Definition: rotations.cpp:209
int rot_quaternion_test()
Definition: rotations.cpp:320
void rot_quat_rotate_rev(const double rot[4], double v[3])
rot_quat_rotate_rev
Definition: rotations.cpp:116
header file for rotations.cpp Transformation utilities
static int rpyeq(double roll, double pitch, double yaw, double r, double p, double y)
Definition: rotations.cpp:52
void rot_quat_to_roll_pitch_yaw(const double q[4], double rpy[3])
Definition: rotations.cpp:194
static int qeq(double *q, double a, double b, double c, double d)
Definition: rotations.cpp:46
void rot_quat_to_angle_axis(const double q[4], double *theta, double axis[3])
Definition: rotations.cpp:153
int rot_quat_to_matrix(const double quat[4], double rot[9])
Definition: rotations.cpp:228
void rot_quat_rotate(const double rot[4], double v[3])
rot_quat_rotate
Definition: rotations.cpp:87
static int feq(double a, double b)
Definition: rotations.cpp:41
void rot_angle_axis_to_quat(double theta, const double axis[3], double q[4])
Definition: rotations.cpp:134


mit_darpa_logs_player
Author(s): Miguel Oliveira
autogenerated on Mon Mar 2 2015 01:32:15