ViSP  2.8.0
vpRotationMatrix.cpp
1 /****************************************************************************
2  *
3  * $Id: vpRotationMatrix.cpp 4056 2013-01-05 13:04:42Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Rotation matrix.
36  *
37  * Authors:
38  * Eric Marchand
39  *
40  *****************************************************************************/
41 
49 #include <visp/vpMath.h>
50 #include <visp/vpMatrix.h>
51 
52 // Rotation classes
53 #include <visp/vpRotationMatrix.h>
54 
55 
56 // Exception
57 #include <visp/vpException.h>
58 #include <visp/vpMatrixException.h>
59 
60 // Debug trace
61 #include <visp/vpDebug.h>
62 #include <math.h>
63 const double vpRotationMatrix::threshold = 1e-6;
64 const double vpRotationMatrix::minimum = 0.00001;
65 
66 #define vpDEBUG_LEVEL1 0
67 
68 
72 void
74 {
75  unsigned int i,j ;
76 
77  try {
78  resize(3,3) ;
79  }
80  catch(vpException me)
81  {
82  vpERROR_TRACE("Error caught") ;
83  throw ;
84  }
85  for (i=0 ; i < 3 ; i++)
86  for (j=0 ; j < 3; j++)
87  if (i==j)
88  (*this)[i][j] = 1.0 ;
89  else
90  (*this)[i][j] = 0.0;
91 
92 }
93 
99 void
101 {
102  init() ;
103 }
109 void
111 {
112  init() ;
113 }
114 
122 {
123  for (unsigned int i=0; i<3; i++)
124  {
125  for (unsigned int j=0; j<3; j++)
126  {
127  rowPtrs[i][j] = m.rowPtrs[i][j];
128  }
129  }
130 
131  return *this;
132 }
133 
141 {
142 
143  if ((m.getCols() !=3) &&(m.getRows() !=3))
144  {
145  vpERROR_TRACE("m is not a rotation matrix !!!!! ") ;
147  "m is not a rotation matrix !!!!!"));
148  }
149 
150  for (unsigned int i=0; i<3; i++)
151  {
152  for (unsigned int j=0; j<3; j++)
153  {
154  (*this)[i][j] = m[i][j];
155  }
156  }
157 
158  if (isARotationMatrix() == false)
159  {
160  vpERROR_TRACE("m is not a rotation matrix !!!!! ") ;
162  "m is not a rotation matrix !!!!!"));
163  }
164 
165  return *this;
166 }
167 
171 {
172  vpRotationMatrix p ;
173 
174  for (unsigned int i=0;i<3;i++)
175  for (unsigned int j=0;j<3;j++)
176  {
177  double s =0 ;
178  for (unsigned int k=0;k<3;k++)
179  s +=rowPtrs[i][k] * B.rowPtrs[k][j];
180  p[i][j] = s ;
181  }
182  return p;
183 }
198 vpMatrix
200 {
201  if (B.getRows() != 3 || B.getCols() != 3) {
202  vpERROR_TRACE("The matrix is not a 3 by 3 dimension matrix") ;
204  "The matrix is not a 3 by 3 dimension matrix"));
205  }
206  vpRotationMatrix p ;
207 
208  for (unsigned int i=0;i<3;i++)
209  for (unsigned int j=0;j<3;j++)
210  {
211  double s =0 ;
212  for (unsigned int k=0;k<3;k++)
213  s +=(*this)[i][k] * B[k][j];
214  p[i][j] = s ;
215  }
216  return p;
217 }
218 
250 {
251  if (v.getRows() != 3) {
252  vpERROR_TRACE("The column vector is not a 3 dimension vector") ;
254  "The column vector is not a 3 dimension vector"));
255  }
256  vpColVector c;
257  vpMatrix::multMatrixVector(*this, v, c);
258  return c;
259 }
260 
261 
270 {
271  vpERROR_TRACE("Cannot add two rotation matrices !!!!! ") ;
273  "Cannot add two rotation matrices !!!!!"));
274 }
275 
284 {
285  vpERROR_TRACE("Cannot substract two rotation matrices !!!!! ") ;
287  "Cannot substract two rotation matrices !!!!!"));
288 }
289 
293 {
295 
296  for (unsigned int j=0;j<3;j++)p[j]=0 ;
297 
298  for (unsigned int j=0;j<3;j++) {
299  for (unsigned int i=0;i<3;i++) {
300  p[i]+=rowPtrs[i][j] * mat[j];
301  }
302  }
303 
304  return p;
305 }
306 
307 /*********************************************************************/
308 
313 bool
315 {
316  unsigned int i,j ;
317  bool isRotation = true ;
318 
319  // test R^TR = Id ;
320  vpRotationMatrix RtR = (*this).t()*(*this) ;
321  for (i=0 ; i < 3 ; i++)
322  for (j=0 ; j < 3 ; j++)
323  if (i==j)
324  {
325  if (fabs(RtR[i][j]-1) > threshold) isRotation = false ;
326  }
327  else
328  {
329  if (fabs(RtR[i][j]) > threshold) isRotation = false ;
330  }
331 
332  // test if it is a basis
333  // test || Ci || = 1
334  for (i=0 ; i < 3 ; i++)
335  if ((sqrt(vpMath::sqr(RtR[0][i]) +
336  vpMath::sqr(RtR[1][i]) +
337  vpMath::sqr(RtR[2][i])) - 1) > threshold) isRotation = false ;
338 
339  // test || Ri || = 1
340  for (i=0 ; i < 3 ; i++)
341  if ((sqrt(vpMath::sqr(RtR[i][0]) +
342  vpMath::sqr(RtR[i][1]) +
343  vpMath::sqr(RtR[i][2])) - 1) > threshold) isRotation = false ;
344 
345  // test if the basis is orthogonal
346  return isRotation ;
347 }
348 
349 
354 {
355  init() ;
356 }
357 
358 
364 {
365  init() ;
366  (*this) = M ;
367 }
368 
371 {
372  init() ;
373  buildFrom(tu) ;
374 }
375 
376 
379 {
380  init() ;
381  buildFrom(euler) ;
382 }
383 
384 
385 
388 {
389  init() ;
390  buildFrom(Rxyz) ;
391 }
392 
395 {
396  init() ;
397  buildFrom(Rzyx) ;
398 }
399 
402  const double tuy,
403  const double tuz) : vpMatrix()
404 {
405  init() ;
406  buildFrom(tux, tuy, tuz) ;
407 }
408 
411  init();
412  buildFrom(q);
413 }
414 
415 
422 {
423  vpRotationMatrix Rt ;
424 
425  unsigned int i,j;
426  for (i=0;i<3;i++)
427  for (j=0;j<3;j++)
428  Rt[j][i] = (*this)[i][j];
429 
430  return Rt;
431 
432 }
433 
440 {
441  vpRotationMatrix Ri = (*this).t() ;
442 
443  return Ri ;
444 }
445 
451 void
453 {
454  M = inverse() ;
455 }
456 
457 
459 std::ostream &operator <<(std::ostream &s,const vpRotationMatrix &R)
460 {
461  for (unsigned int i=0; i<3; i++)
462  {
463  for (unsigned int j=0; j<3; j++)
464  std::cout << R[i][j] << " " ;
465  std::cout << std::endl ;
466  }
467 
468  return (s);
469 }
470 
472 void
474 {
475  vpThetaUVector tu(*this) ;
476 
477  for (unsigned int i=0; i<3; i++)
478  std::cout << tu[i] << " " ;
479 
480  std::cout << std::endl ;
481 }
482 
483 
484 /*
485  \relates vpRotationMatrix
486  Transform a vector vpThetaUVector into a rotation matrix.
487 
488  Representation theta u (angle and axes of the rotation) is considered for
489  the rotation vector.
490 
491  The rotation is computed using :
492  \f[
493  R = \cos{ \theta} \; {I}_{3} + (1 - \cos{ \theta}) \; v v^{T} + \sin{ \theta} \; [v]_\times
494  \f]
495 */
498 {
499  unsigned int i,j;
500  double theta, si, co, sinc, mcosc;
502 
503  theta = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
504  si = sin(theta);
505  co = cos(theta);
506  sinc = vpMath::sinc(si,theta);
507  mcosc = vpMath::mcosc(co,theta);
508 
509  R[0][0] = co + mcosc*v[0]*v[0];
510  R[0][1] = -sinc*v[2] + mcosc*v[0]*v[1];
511  R[0][2] = sinc*v[1] + mcosc*v[0]*v[2];
512  R[1][0] = sinc*v[2] + mcosc*v[1]*v[0];
513  R[1][1] = co + mcosc*v[1]*v[1];
514  R[1][2] = -sinc*v[0] + mcosc*v[1]*v[2];
515  R[2][0] = -sinc*v[1] + mcosc*v[2]*v[0];
516  R[2][1] = sinc*v[0] + mcosc*v[2]*v[1];
517  R[2][2] = co + mcosc*v[2]*v[2];
518 
519  for (i=0;i<3;i++) for (j=0;j<3;j++) (*this)[i][j] = R[i][j];
520 
521 #if (vpDEBUG_LEVEL1) // test new version wrt old version
522  {
523  // old version
524  vpRotationMatrix R_old; // has to be replaced by (*this) if good version
525  double sinu,cosi,mcosi,u[3],ang;
526 
527  ang = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
528  if (ang > minimum)
529  {
530  for (i=0;i<3;i++) u[i] = v[i]/ang;
531  sinu = sin(ang);
532  cosi = cos(ang);
533  mcosi = 1-cosi;
534  R_old[0][0] = cosi + mcosi*u[0]*u[0];
535  R_old[0][1] = -sinu*u[2] + mcosi*u[0]*u[1];
536  R_old[0][2] = sinu*u[1] + mcosi*u[0]*u[2];
537  R_old[1][0] = sinu*u[2] + mcosi*u[1]*u[0];
538  R_old[1][1] = cosi + mcosi*u[1]*u[1];
539  R_old[1][2] = -sinu*u[0] + mcosi*u[1]*u[2];
540  R_old[2][0] = -sinu*u[1] + mcosi*u[2]*u[0];
541  R_old[2][1] = sinu*u[0] + mcosi*u[2]*u[1];
542  R_old[2][2] = cosi + mcosi*u[2]*u[2];
543  }
544  else
545  {
546  for (i=0;i<3;i++)
547  {
548  for(j=0;j<3;j++) R_old[i][j] = 0.0;
549  R_old[i][i] = 1.0;
550  }
551  }
552  // end old version
553  // test the new version
554 
555  unsigned int pb = 0;
556  for (i=0;i<3;i++)
557  {
558  for(j=0;j<3;j++)
559  if (fabs(R_old[i][j] - R[i][j]) > 1.e-4) pb = 1;
560  }
561  if (pb == 1)
562  {
563  printf("vpRotationMatrix::buildFrom(const vpThetaUVector &v)\n");
564  std::cout << " theta " << theta << std::endl;
565  std::cout << " R : " << std::endl << R << std::endl;
566  std::cout << " R_old : " << std::endl << R_old << std::endl;
567  }
568 
569  }
570  // end test
571 #endif
572 
573  return *this ;
574 }
575 
584 {
585  double c0,c1,c2,s0,s1,s2;
586 
587  c0 = cos(v[0]);
588  c1 = cos(v[1]);
589  c2 = cos(v[2]);
590  s0 = sin(v[0]);
591  s1 = sin(v[1]);
592  s2 = sin(v[2]);
593 
594  (*this)[0][0] = c0*c1*c2 - s0*s2;
595  (*this)[0][1] = -c0*c1*s2 - s0*c2;
596  (*this)[0][2] = c0*s1;
597  (*this)[1][0] = s0*c1*c2+c0*s2 ;
598  (*this)[1][1] = -s0*c1*s2 + c0*c2 ;
599  (*this)[1][2] = s0*s1;
600  (*this)[2][0] = -s1*c2;
601  (*this)[2][1] = s1*s2;
602  (*this)[2][2] = c1;
603 
604  return (*this) ;
605 }
606 
607 
619 {
620  double c0,c1,c2,s0,s1,s2;
621 
622  c0 = cos(v[0]);
623  c1 = cos(v[1]);
624  c2 = cos(v[2]);
625  s0 = sin(v[0]);
626  s1 = sin(v[1]);
627  s2 = sin(v[2]);
628 
629  (*this)[0][0] = c1*c2;
630  (*this)[0][1] = -c1*s2;
631  (*this)[0][2] = s1;
632  (*this)[1][0] = c0*s2+s0*s1*c2;
633  (*this)[1][1] = c0*c2-s0*s1*s2;
634  (*this)[1][2] = -s0*c1;
635  (*this)[2][0] = -c0*s1*c2+s0*s2;
636  (*this)[2][1] = c0*s1*s2+c2*s0;
637  (*this)[2][2] = c0*c1;
638 
639  return (*this) ;
640 }
641 
642 
643 
653 {
654  double c0,c1,c2,s0,s1,s2;
655 
656  c0 = cos(v[0]);
657  c1 = cos(v[1]);
658  c2 = cos(v[2]);
659  s0 = sin(v[0]);
660  s1 = sin(v[1]);
661  s2 = sin(v[2]);
662 
663  (*this)[0][0] = c0*c1 ;
664  (*this)[0][1] = c0*s1*s2 - s0*c2 ;
665  (*this)[0][2] = c0*s1*c2 + s0*s2 ;
666 
667  (*this)[1][0] = s0*c1 ;
668  (*this)[1][1] = s0*s1*s2 + c0*c2 ;
669  (*this)[1][2] = s0*s1*c2 - c0*s2 ;
670 
671  (*this)[2][0] = -s1 ;
672  (*this)[2][1] = c1*s2 ;
673  (*this)[2][2] = c1*c2 ;
674 
675  return (*this) ;
676 }
677 
678 
679 
683  const double tuy,
684  const double tuz)
685 {
686  vpThetaUVector tu(tux, tuy, tuz) ;
687  buildFrom(tu) ;
688  return *this ;
689 }
690 
691 
695  double a = q.w();
696  double b = q.x();
697  double c = q.y();
698  double d = q.z();
699  (*this)[0][0] = a*a+b*b-c*c-d*d;
700  (*this)[0][1] = 2*b*c-2*a*d;
701  (*this)[0][2] = 2*a*c+2*b*d;
702 
703  (*this)[1][0] = 2*a*d+2*b*c;
704  (*this)[1][1] = a*a-b*b+c*c-d*d;
705  (*this)[1][2] = 2*c*d-2*a*b;
706 
707  (*this)[2][0] = 2*b*d-2*a*c;
708  (*this)[2][1] = 2*a*b+2*c*d;
709  (*this)[2][2] = a*a-b*b-c*c+d*d;
710  return *this;
711 }
712 #undef vpDEBUG_LEVEL1
713 
714 /*
715  * Local variables:
716  * c-basic-offset: 2
717  * End:
718  */
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:174
vpRotationMatrix inverse() const
invert the rotation matrix
#define vpERROR_TRACE
Definition: vpDebug.h:379
error that can be emited by ViSP classes.
Definition: vpException.h:75
double y() const
Returns y-component of the quaternion.
vpRotationMatrix t() const
transpose
Class that consider the case of the Euler angle using the z-y-x convention, where are respectively ...
Definition: vpRzyxVector.h:151
void setIdentity()
Basic initialisation (identity)
vpRotationMatrix operator+(const vpRotationMatrix &B) const
overload + operator (to say it forbidden operation, throw exception)
vpRotationMatrix & operator=(const vpRotationMatrix &R)
copy operator from vpRotationMatrix
static double sinc(double x)
Definition: vpMath.h:301
void init()
Basic initialisation (identity)
bool isARotationMatrix() const
test if the matrix is an rotation matrix
The vpRotationMatrix considers the particular case of a rotation matrix.
vpRotationMatrix buildFrom(const vpThetaUVector &v)
Transform a vector vpThetaUVector into an rotation matrix.
double w() const
Returns w-component of the quaternion.
double ** rowPtrs
address of the first element of each rows
Definition: vpMatrix.h:119
static void multMatrixVector(const vpMatrix &A, const vpColVector &b, vpColVector &c)
Definition: vpMatrix.cpp:811
static double mcosc(double cosx, double x)
Definition: vpMath.h:331
static double sqr(double x)
Definition: vpMath.h:106
double z() const
Returns z-component of the quaternion.
double x() const
Returns x-component of the quaternion.
Defines a quaternion and its basic operations.
VISP_EXPORT std::ostream & operator<<(std::ostream &os, const vpImagePoint &ip)
Definition: vpImagePoint.h:529
void printVector()
Print the matrix as a vector [T thetaU].
vpRotationMatrix()
basic constructor
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
unsigned int getCols() const
Return the number of columns of the matrix.
Definition: vpMatrix.h:159
vpTranslationVector operator*(const vpTranslationVector &mat) const
operation c = A * b (A is unchanged)
error that can be emited by the vpMatrix class and its derivates
Class that consider the case of the Euler angle using the x-y-z convention, where are respectively ...
Definition: vpRxyzVector.h:152
vpMatrix operator-() const
Definition: vpMatrix.cpp:751
Class that consider the case of the Euler angles using the z-y-z convention, where are respectively...
Definition: vpRzyzVector.h:150
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:157
Class that consider the case of a translation vector.
Class that consider the case of the parameterization for the rotation.