Rotation.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
3  *
4  * Copyright 2007-2012 VTT Technical Research Centre of Finland
5  *
6  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
7  * <http://www.vtt.fi/multimedia/alvar.html>
8  *
9  * ALVAR is free software; you can redistribute it and/or modify it under the
10  * terms of the GNU Lesser General Public License as published by the Free
11  * Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with ALVAR; if not, see
21  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
22  */
23 
24 #include "ar_track_alvar/Alvar.h"
26 
27 using namespace std;
28 
29 namespace alvar {
30 using namespace std;
31 
32 Rotation::Rotation()
33 {
34  cvInitMatHeader(&quaternion_mat, 4, 1, CV_64F, quaternion);
35  Reset();
36 }
37 
38 Rotation::Rotation(const Rotation& r) {
39  cvInitMatHeader(&quaternion_mat, 4, 1, CV_64F, quaternion);
40  cvCopy(&r.quaternion_mat, &quaternion_mat);
41 }
42 
43 Rotation::Rotation(CvMat *data, RotationType t)
44 {
45  cvInitMatHeader(&quaternion_mat, 4, 1, CV_64F, quaternion);
46 
47  Reset();
48 
49  switch (t)
50  {
51  case QUAT :
52  SetQuaternion(data);
53  break;
54  case MAT :
55  SetMatrix(data);
56  break;
57  case EUL :
58  SetEuler(data);
59  break;
60  case ROD :
61  SetRodriques(data);
62  break;
63  }
64 }
65 
66 void Rotation::Transpose()
67 {
68  double tmp[9];
69  CvMat tmp_mat = cvMat(3, 3, CV_64F, tmp);
70  GetMatrix(&tmp_mat);
71  cvTranspose(&tmp_mat, &tmp_mat);
72  SetMatrix(&tmp_mat);
73 }
74 
75 void Rotation::MirrorMat(CvMat *mat, bool x, bool y, bool z) {
76  CvMat *mat_mul = cvCloneMat(mat);
77  cvSetIdentity(mat_mul);
78  if (x) cvmSet(mat_mul, 0, 0, -1);
79  if (y) cvmSet(mat_mul, 1, 1, -1);
80  if (z) cvmSet(mat_mul, 2, 2, -1);
81  cvMatMul(mat_mul, mat, mat);
82  cvReleaseMat(&mat_mul);
83 }
84 
85 void Rotation::Mirror(bool x, bool y, bool z)
86 {
87  double tmp[9];
88  CvMat tmp_mat = cvMat(3, 3, CV_64F, tmp);
89  GetMatrix(&tmp_mat);
90  MirrorMat(&tmp_mat, x, y, z);
91  SetMatrix(&tmp_mat);
92 }
93 
94 void Rotation::Reset()
95 {
96  cvZero(&quaternion_mat); cvmSet(&quaternion_mat, 0, 0, 1);
97 }
98 
99 void Rotation::Mat9ToRod(double *mat, double *rod)
100 {
101  CvMat mat_m, rod_m;
102  cvInitMatHeader(&mat_m, 3, 3, CV_64F, mat);
103  cvInitMatHeader(&rod_m, 3, 1, CV_64F, rod);
104  cvRodrigues2(&mat_m, &rod_m);
105 }
106 
107 void Rotation::RodToMat9(double *rod, double *mat)
108 {
109  CvMat mat_m, rod_m;
110  cvInitMatHeader(&mat_m, 3, 3, CV_64F, mat);
111  cvInitMatHeader(&rod_m, 3, 1, CV_64F, rod);
112  cvRodrigues2(&rod_m, &mat_m, 0);
113 }
114 
115 void Rotation::QuatInv(const double *q, double *qi)
116 {
117  qi[0] = q[0];
118  qi[1] = -1*q[1];
119  qi[2] = -1*q[2];
120  qi[3] = -1*q[3];
121 }
122 
123 void Rotation::QuatNorm(double *q)
124 {
125  double l = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3] );
126 
127  if(l != 0)
128  for(unsigned i = 0; i < 4; ++i)
129  q[i] = q[i] / l;
130 }
131 
132 void Rotation::QuatMul(const double *q1, const double *q2, double *q3)
133 {
134  double w1 = q1[0];
135  double x1 = q1[1];
136  double y1 = q1[2];
137  double z1 = q1[3];
138 
139  double w2 = q2[0];
140  double x2 = q2[1];
141  double y2 = q2[2];
142  double z2 = q2[3];
143 
144  q3[0] = w1*w2 - x1*x2 - y1*y2 - z1*z2;
145  q3[1] = w1*x2 + x1*w2 + y1*z2 - z1*y2;
146  q3[2] = w1*y2 + y1*w2 + z1*x2 - x1*z2;
147  q3[3] = w1*z2 + z1*w2 + x1*y2 - y1*x2;
148 
149  QuatNorm(q3);
150 }
151 
152 void Rotation::QuatToMat9(const double *quat, double *mat)
153 {
154  double W = quat[0];
155  double X = quat[1];
156  double Y = quat[2];
157  double Z = quat[3];
158 
159  double xx = X * X;
160  double xy = X * Y;
161  double xz = X * Z;
162  double xw = X * W;
163 
164  double yy = Y * Y;
165  double yz = Y * Z;
166  double yw = Y * W;
167 
168  double zz = Z * Z;
169  double zw = Z * W;
170 
171  mat[0] = 1 - 2 * ( yy + zz ); //(0,0)
172  mat[1] = 2 * ( xy - zw ); //(0,1)
173  mat[2] = 2 * ( xz + yw ); //(0,2)
174 
175  mat[3] = 2 * ( xy + zw ); //(1,0)
176  mat[4] = 1 - 2 * ( xx + zz ); //(1,1)
177  mat[5] = 2 * ( yz - xw ); //(1,2)
178 
179  mat[6] = 2 * ( xz - yw ); //(2,0)
180  mat[7] = 2 * ( yz + xw ); //(2,1)
181  mat[8] = 1 - 2 * ( xx + yy ); //(2,2)
182 }
183 
184 // TODO: Now we don't want to eliminate the translation part from the matrix here. Did this change break something???
185 void Rotation::QuatToMat16(const double *quat, double *mat)
186 {
187  //memset(mat, 0, 16*sizeof(double));
188 
189  double W = quat[0];
190  double X = quat[1];
191  double Y = quat[2];
192  double Z = quat[3];
193 
194  double xx = X * X;
195  double xy = X * Y;
196  double xz = X * Z;
197  double xw = X * W;
198 
199  double yy = Y * Y;
200  double yz = Y * Z;
201  double yw = Y * W;
202 
203  double zz = Z * Z;
204  double zw = Z * W;
205 
206  mat[0] = 1 - 2 * ( yy + zz ); //(0,0)
207  mat[1] = 2 * ( xy - zw ); //(0,1)
208  mat[2] = 2 * ( xz + yw ); //(0,2)
209 
210  mat[4] = 2 * ( xy + zw ); //(1,0)
211  mat[5] = 1 - 2 * ( xx + zz ); //(1,1)
212  mat[6] = 2 * ( yz - xw ); //(1,2)
213 
214  mat[8] = 2 * ( xz - yw ); //(2,0)
215  mat[9] = 2 * ( yz + xw ); //(2,1)
216  mat[10] = 1 - 2 * ( xx + yy ); //(2,2)
217 
218  //mat[15] = 1;
219 }
220 
221 void Rotation::QuatToEul(const double *q, double *eul)
222 {
223  double qw = q[0];
224  double qx = q[1];
225  double qy = q[2];
226  double qz = q[3];
227 
228  double heading = 0, bank = 0, attitude = 0;
229 
230  if ((2*qx*qy + 2*qz*qw) == 1.0)
231  {
232  heading = 2 * atan2(qx,qw);
233  bank = 0;
234  }
235  else if ((2*qx*qy + 2*qz*qw) == -1.0)
236  {
237  heading = -2 * atan2(qx,qw);
238  bank = 0;
239  }
240  else
241  {
242  heading = atan2(2*qy*qw-2*qx*qz , 1 - 2*qy*qy - 2*qz*qz);
243  bank = atan2(2*qx*qw-2*qy*qz , 1 - 2*qx*qx - 2*qz*qz);
244  }
245 
246  attitude = asin(2*qx*qy + 2*qz*qw);
247 
248  heading = 180.0 * heading / PI;
249  attitude = 180.0 * attitude / PI;
250  bank = 180.0 * bank / PI;
251 
252  eul[0] = heading;
253  eul[1] = attitude;
254  eul[2] = bank;
255 }
256 
257 void Rotation::Mat9ToQuat(const double *mat, double *quat)
258 {
259  quat[0] = sqrt(max(0., 1 + mat[0] + mat[4] + mat[8])) / 2.0; // w
260  quat[1] = sqrt(max(0., 1 + mat[0] - mat[4] - mat[8])) / 2.0; // x
261  quat[2] = sqrt(max(0., 1 - mat[0] + mat[4] - mat[8])) / 2.0; // y
262  quat[3] = sqrt(max(0., 1 - mat[0] - mat[4] + mat[8])) / 2.0; // z
263 
264  quat[1] = quat[1]*Sign(mat[7] - mat[5]); // x
265  quat[2] = quat[2]*Sign(mat[2] - mat[6]); // y
266  quat[3] = quat[3]*Sign(mat[3] - mat[1]); // z
267 
268  QuatNorm(quat);
269 }
270 
271 void Rotation::EulToQuat(const double *eul, double *quat)
272 {
273  double heading = PI*eul[0]/180.0;
274  double attitude = PI*eul[1]/180.0;
275  double bank = PI*eul[2]/180.0;
276 
277  double c1 = cos(heading/2.0);
278  double s1 = sin(heading/2.0);
279  double c2 = cos(attitude/2.0);
280  double s2 = sin(attitude/2.0);
281  double c3 = cos(bank/2.0);
282  double s3 = sin(bank/2.0);
283  double c1c2 = c1*c2;
284  double s1s2 = s1*s2;
285 
286  quat[0] = c1c2*c3 - s1s2*s3;
287  quat[1] = c1c2*s3 + s1s2*c3;
288  quat[2] = s1*c2*c3 + c1*s2*s3;
289  quat[3] = c1*s2*c3 - s1*c2*s3;
290 
291  QuatNorm(quat);
292 }
293 
294 void Rotation::SetQuaternion(CvMat *mat)
295 {
296  cvCopy(mat, &quaternion_mat);
297  QuatNorm(quaternion);
298 }
299 
300 void Rotation::SetQuaternion(const double *quat)
301 {
302  quaternion[0] = quat[0];
303  quaternion[1] = quat[1];
304  quaternion[2] = quat[2];
305  quaternion[3] = quat[3];
306  QuatNorm(quaternion);
307 }
308 
309 void Rotation::SetEuler(const CvMat *mat)
310 {
311  EulToQuat(mat->data.db, quaternion);
312 }
313 
314 void Rotation::SetRodriques(const CvMat *mat)
315 {
316  double tmp[9];
317  RodToMat9(mat->data.db, tmp);
318  Mat9ToQuat(tmp, quaternion);
319 }
320 
321 void Rotation::SetMatrix(const CvMat *mat)
322 {
323  double tmp[9];
324  for(int i = 0; i < 3; ++i)
325  for(int j = 0; j < 3; ++j)
326  tmp[i*3+j] = cvmGet(mat, i, j);
327 
328  Mat9ToQuat(tmp, quaternion);
329 }
330 
331 void Rotation::GetMatrix(CvMat *mat) const
332 {
333  if (mat->width == 3) {
334  QuatToMat9(quaternion, mat->data.db);
335  } else if (mat->width == 4) {
336  cvSetIdentity(mat);
337  QuatToMat16(quaternion, mat->data.db);
338  }
339 }
340 
341 void Rotation::GetRodriques(CvMat *mat) const
342 {
343  double tmp[9];
344  QuatToMat9(quaternion, tmp);
345  Mat9ToRod(tmp, mat->data.db);
346 }
347 
348 void Rotation::GetEuler(CvMat *mat) const
349 {
350  QuatToEul(quaternion, mat->data.db);
351 }
352 
353 void Rotation::GetQuaternion(CvMat *mat) const
354 {
355  cvCopy(&quaternion_mat, mat);
356 }
357 
358 // TODO: This is not needed???
359 inline Rotation& Rotation::operator = (const Rotation& r)
360 {
361  memcpy(quaternion, r.quaternion, 4*sizeof(double));
362  return *this;
363 }
364 
365 inline Rotation& Rotation::operator += (const Rotation& r)
366 {
367  Rotation res;
368  QuatMul(quaternion, r.quaternion, res.quaternion);
369  memcpy(quaternion, res.quaternion, 4*sizeof(double));
370  //x += v.x;
371  //y += v.y;
372  //z += v.z;
373 
374  return *this;
375 }
376 
377 inline Rotation operator + (const Rotation& r1, const Rotation& r2)
378 {
379  Rotation ret = r1;
380  ret += r2;
381 
382  return ret;
383 }
384 
385 } // namespace alvar
Main ALVAR namespace.
Definition: Alvar.h:174
CvMat quaternion_mat
Definition: Rotation.h:47
RotationType
Rotation can be represented in four ways: quaternion (QUAT), matrix (MAT), euler angles (EUL) and exp...
Definition: Rotation.h:53
This file implements a parametrized rotation.
int ALVAR_EXPORT Sign(const C &v)
Returns the sign of a number.
Definition: Util.h:54
Rotation operator+(const Rotation &r1, const Rotation &r2)
Definition: Rotation.cpp:377
const double PI
Definition: Util.h:48
double quaternion[4]
Definition: Rotation.h:48
const int res
Rotation structure and transformations between different parameterizations.
Definition: Rotation.h:43
This file defines library export definitions, version numbers and build information.


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Mon Jun 10 2019 12:47:04