Visual Servoing Platform  version 3.6.1 under development (2024-05-26)
vpRotationMatrix.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Rotation matrix.
33  *
34 *****************************************************************************/
35 
42 #include <visp3/core/vpMath.h>
43 #include <visp3/core/vpMatrix.h>
44 
45 // Rotation classes
46 #include <visp3/core/vpRotationMatrix.h>
47 
48 // Exception
49 #include <visp3/core/vpException.h>
50 
51 // Debug trace
52 #include <math.h>
53 #include <visp3/core/vpDebug.h>
54 
61 {
62  for (unsigned int i = 0; i < 3; ++i) {
63  for (unsigned int j = 0; j < 3; ++j) {
64  if (i == j) {
65  (*this)[i][j] = 1.0;
66  }
67  else {
68  (*this)[i][j] = 0.0;
69  }
70  }
71  }
72 }
73 
84 {
85  for (unsigned int i = 0; i < 3; ++i) {
86  for (unsigned int j = 0; j < 3; ++j) {
87  rowPtrs[i][j] = R.rowPtrs[i][j];
88  }
89  }
90 
91  return *this;
92 }
93 
94 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
118 vpRotationMatrix &vpRotationMatrix::operator=(const std::initializer_list<double> &list)
119 {
120  if (dsize != static_cast<unsigned int>(list.size())) {
122  "Cannot set a 3-by-3 rotation matrix from a %d-elements list of doubles."));
123  }
124 
125  std::copy(list.begin(), list.end(), data);
126 
127  if (!isARotationMatrix()) {
128  if (isARotationMatrix(1e-3)) {
129  orthogonalize();
130  }
131  else {
132  throw(vpException(
134  "Rotation matrix initialization fails since its elements do not represent a valid rotation matrix"));
135  }
136  }
137 
138  return *this;
139 }
140 #endif
141 
159 {
160  if ((M.getCols() != 3) && (M.getRows() != 3)) {
161  throw(vpException(vpException::dimensionError, "Cannot set a (3x3) rotation matrix from a (%dx%d) matrix",
162  M.getRows(), M.getCols()));
163  }
164 
165  for (unsigned int i = 0; i < 3; ++i) {
166  for (unsigned int j = 0; j < 3; ++j) {
167  (*this)[i][j] = M[i][j];
168  }
169  }
170 
171  if (isARotationMatrix() == false) {
172  throw(vpException(vpException::fatalError, "Cannot set a rotation matrix "
173  "from a matrix that is not a "
174  "rotation matrix"));
175  }
176 
177  return *this;
178 }
179 
208 {
209  m_index = 0;
210  data[m_index] = val;
211  return *this;
212 }
213 
242 {
243  ++m_index;
244  if (m_index >= size()) {
246  "Cannot set rotation matrix out of bounds. It has only %d elements while you try to initialize "
247  "with %d elements",
248  size(), m_index + 1));
249  }
250  data[m_index] = val;
251  return *this;
252 }
253 
258 {
260 
261  for (unsigned int i = 0; i < 3; ++i) {
262  for (unsigned int j = 0; j < 3; ++j) {
263  double s = 0;
264  for (unsigned int k = 0; k < 3; ++k) {
265  s += rowPtrs[i][k] * R.rowPtrs[k][j];
266  }
267  p[i][j] = s;
268  }
269  }
270  return p;
271 }
272 
291 {
292  if ((M.getRows() != 3) || (M.getCols() != 3)) {
293  throw(vpException(vpException::dimensionError, "Cannot set a (3x3) rotation matrix from a (%dx%d) matrix",
294  M.getRows(), M.getCols()));
295  }
296  vpMatrix p(3, 3);
297 
298  for (unsigned int i = 0; i < 3; ++i) {
299  for (unsigned int j = 0; j < 3; ++j) {
300  double s = 0;
301  for (unsigned int k = 0; k < 3; ++k) {
302  s += (*this)[i][k] * M[k][j];
303  }
304  p[i][j] = s;
305  }
306  }
307  return p;
308 }
309 
325 {
326  return (vpHomogeneousMatrix(*this * M.getTranslationVector(), *this * M.getRotationMatrix()));
327 }
328 
359 {
360  if (v.getRows() != 3) {
362  "Cannot multiply a (3x3) rotation matrix by a %d "
363  "dimension column vector",
364  v.getRows()));
365  }
366  vpColVector v_out(3);
367 
368  for (unsigned int j = 0; j < colNum; ++j) {
369  double vj = v[j]; // optimization em 5/12/2006
370  for (unsigned int i = 0; i < rowNum; ++i) {
371  v_out[i] += rowPtrs[i][j] * vj;
372  }
373  }
374 
375  return v_out;
376 }
377 
383 {
385 
386  for (unsigned int j = 0; j < 3; ++j) {
387  p[j] = 0;
388  }
389 
390  for (unsigned int j = 0; j < 3; ++j) {
391  for (unsigned int i = 0; i < 3; ++i) {
392  p[i] += rowPtrs[i][j] * tv[j];
393  }
394  }
395 
396  return p;
397 }
398 
404 {
406 
407  for (unsigned int i = 0; i < rowNum; ++i) {
408  for (unsigned int j = 0; j < colNum; ++j) {
409  R[i][j] = rowPtrs[i][j] * x;
410  }
411  }
412 
413  return R;
414 }
415 
421 {
422  for (unsigned int i = 0; i < rowNum; ++i) {
423  for (unsigned int j = 0; j < colNum; ++j) {
424  rowPtrs[i][j] *= x;
425  }
426  }
427 
428  return *this;
429 }
430 
431 /*********************************************************************/
432 
439 bool vpRotationMatrix::isARotationMatrix(double threshold) const
440 {
441  bool isRotation = true;
442 
443  if ((getCols() != 3) || (getRows() != 3)) {
444  return false;
445  }
446 
447  // --comment: test R^TR = Id
448  vpRotationMatrix RtR = (*this).t() * (*this);
449  for (unsigned int i = 0; i < 3; ++i) {
450  for (unsigned int j = 0; j < 3; ++j) {
451  if (i == j) {
452  if (fabs(RtR[i][j] - 1) > threshold) {
453  isRotation = false;
454  }
455  }
456  else {
457  if (fabs(RtR[i][j]) > threshold) {
458  isRotation = false;
459  }
460  }
461  }
462  }
463  // test if it is a basis
464  // test || Ci || = 1
465  for (unsigned int i = 0; i < 3; ++i) {
466  if ((sqrt(vpMath::sqr(RtR[0][i]) + vpMath::sqr(RtR[1][i]) + vpMath::sqr(RtR[2][i])) - 1) > threshold) {
467  isRotation = false;
468  }
469  }
470 
471  // test || Ri || = 1
472  for (unsigned int i = 0; i < 3; ++i) {
473  if ((sqrt(vpMath::sqr(RtR[i][0]) + vpMath::sqr(RtR[i][1]) + vpMath::sqr(RtR[i][2])) - 1) > threshold) {
474  isRotation = false;
475  }
476  }
477 
478  // test if the basis is orthogonal
479  return isRotation;
480 }
481 
485 vpRotationMatrix::vpRotationMatrix() : vpArray2D<double>(3, 3), m_index(0) { eye(); }
486 
491 vpRotationMatrix::vpRotationMatrix(const vpRotationMatrix &M) : vpArray2D<double>(3, 3), m_index(0) { (*this) = M; }
492 
496 vpRotationMatrix::vpRotationMatrix(const vpHomogeneousMatrix &M) : vpArray2D<double>(3, 3), m_index(0) { build(M); }
497 
502 vpRotationMatrix::vpRotationMatrix(const vpThetaUVector &tu) : vpArray2D<double>(3, 3), m_index(0) { build(tu); }
503 
507 vpRotationMatrix::vpRotationMatrix(const vpPoseVector &p) : vpArray2D<double>(3, 3), m_index(0) { build(p); }
508 
513 vpRotationMatrix::vpRotationMatrix(const vpRzyzVector &euler) : vpArray2D<double>(3, 3), m_index(0)
514 {
515  build(euler);
516 }
517 
522 vpRotationMatrix::vpRotationMatrix(const vpRxyzVector &Rxyz) : vpArray2D<double>(3, 3), m_index(0) { build(Rxyz); }
523 
528 vpRotationMatrix::vpRotationMatrix(const vpRzyxVector &Rzyx) : vpArray2D<double>(3, 3), m_index(0) { build(Rzyx); }
529 
533 vpRotationMatrix::vpRotationMatrix(const vpMatrix &R) : vpArray2D<double>(3, 3), m_index(0) { *this = R; }
534 
539 vpRotationMatrix::vpRotationMatrix(double tux, double tuy, double tuz) : vpArray2D<double>(3, 3), m_index(0)
540 {
541  build(tux, tuy, tuz);
542 }
543 
547 vpRotationMatrix::vpRotationMatrix(const vpQuaternionVector &q) : vpArray2D<double>(3, 3), m_index(0) { build(q); }
548 
549 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
571 vpRotationMatrix::vpRotationMatrix(const std::initializer_list<double> &list)
572  : vpArray2D<double>(3, 3, list), m_index(0)
573 {
574  if (!isARotationMatrix()) {
575  if (isARotationMatrix(1e-3)) {
576  orthogonalize();
577  }
578  else {
579  throw(vpException(
581  "Rotation matrix initialization fails since its elements do not represent a valid rotation matrix"));
582  }
583  }
584 }
585 #endif
586 
594 {
595  vpRotationMatrix Rt;
596 
597  for (unsigned int i = 0; i < 3; ++i) {
598  for (unsigned int j = 0; j < 3; ++j) {
599  Rt[j][i] = (*this)[i][j];
600  }
601  }
602 
603  return Rt;
604 }
605 
613 {
614  vpRotationMatrix Ri = (*this).t();
615 
616  return Ri;
617 }
618 
637 
643 {
644  vpThetaUVector tu(*this);
645 
646  for (unsigned int i = 0; i < 3; ++i) {
647  std::cout << tu[i] << " ";
648  }
649 
650  std::cout << std::endl;
651 }
652 
653 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
665 {
666  build(v);
667  return *this;
668 }
669 
675 {
676  build(M);
677  return *this;
678 }
679 
687 {
688  return build(p);
689 }
690 
700 {
701  build(v);
702  return *this;
703 }
704 
714 {
715  build(v);
716  return *this;
717 }
718 
727 {
728  build(v);
729  return *this;
730 }
731 
737 vpRotationMatrix vpRotationMatrix::buildFrom(double tux, double tuy, double tuz)
738 {
739  build(tux, tuy, tuz);
740  return *this;
741 }
742 
748 {
749  build(q);
750  return *this;
751 }
752 #endif
753 
764 {
765  double theta, si, co, sinc, mcosc;
767 
768  theta = sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]));
769  si = sin(theta);
770  co = cos(theta);
771  sinc = vpMath::sinc(si, theta);
772  mcosc = vpMath::mcosc(co, theta);
773 
774  R[0][0] = co + (mcosc * v[0] * v[0]);
775  R[0][1] = (-sinc * v[2]) + (mcosc * v[0] * v[1]);
776  R[0][2] = (sinc * v[1]) + (mcosc * v[0] * v[2]);
777  R[1][0] = (sinc * v[2]) + (mcosc * v[1] * v[0]);
778  R[1][1] = co + (mcosc * v[1] * v[1]);
779  R[1][2] = (-sinc * v[0]) + (mcosc * v[1] * v[2]);
780  R[2][0] = (-sinc * v[1]) + (mcosc * v[2] * v[0]);
781  R[2][1] = (sinc * v[0]) + (mcosc * v[2] * v[1]);
782  R[2][2] = co + (mcosc * v[2] * v[2]);
783 
784  for (unsigned int i = 0; i < 3; ++i) {
785  for (unsigned int j = 0; j < 3; ++j) {
786  (*this)[i][j] = R[i][j];
787  }
788  }
789 
790  return *this;
791 }
792 
797 {
798  for (unsigned int i = 0; i < 3; ++i) {
799  for (unsigned int j = 0; j < 3; ++j) {
800  (*this)[i][j] = M[i][j];
801  }
802  }
803 
804  return *this;
805 }
806 
813 {
814  vpThetaUVector tu(p);
815  return build(tu);
816 }
817 
826 {
827  double c0, c1, c2, s0, s1, s2;
828 
829  c0 = cos(v[0]);
830  c1 = cos(v[1]);
831  c2 = cos(v[2]);
832  s0 = sin(v[0]);
833  s1 = sin(v[1]);
834  s2 = sin(v[2]);
835 
836  (*this)[0][0] = (c0 * c1 * c2) - (s0 * s2);
837  (*this)[0][1] = (-c0 * c1 * s2) - (s0 * c2);
838  (*this)[0][2] = c0 * s1;
839  (*this)[1][0] = (s0 * c1 * c2) + (c0 * s2);
840  (*this)[1][1] = (-s0 * c1 * s2) + (c0 * c2);
841  (*this)[1][2] = s0 * s1;
842  (*this)[2][0] = -s1 * c2;
843  (*this)[2][1] = s1 * s2;
844  (*this)[2][2] = c1;
845 
846  return *this;
847 }
848 
858 {
859  double c0, c1, c2, s0, s1, s2;
860 
861  c0 = cos(v[0]);
862  c1 = cos(v[1]);
863  c2 = cos(v[2]);
864  s0 = sin(v[0]);
865  s1 = sin(v[1]);
866  s2 = sin(v[2]);
867 
868  (*this)[0][0] = c1 * c2;
869  (*this)[0][1] = -c1 * s2;
870  (*this)[0][2] = s1;
871  (*this)[1][0] = (c0 * s2) + (s0 * s1 * c2);
872  (*this)[1][1] = (c0 * c2) - (s0 * s1 * s2);
873  (*this)[1][2] = -s0 * c1;
874  (*this)[2][0] = (-c0 * s1 * c2) + (s0 * s2);
875  (*this)[2][1] = (c0 * s1 * s2) + (c2 * s0);
876  (*this)[2][2] = c0 * c1;
877 
878  return *this;
879 }
880 
888 {
889  double c0, c1, c2, s0, s1, s2;
890 
891  c0 = cos(v[0]);
892  c1 = cos(v[1]);
893  c2 = cos(v[2]);
894  s0 = sin(v[0]);
895  s1 = sin(v[1]);
896  s2 = sin(v[2]);
897 
898  (*this)[0][0] = c0 * c1;
899  (*this)[0][1] = (c0 * s1 * s2) - (s0 * c2);
900  (*this)[0][2] = (c0 * s1 * c2) + (s0 * s2);
901 
902  (*this)[1][0] = s0 * c1;
903  (*this)[1][1] = (s0 * s1 * s2) + (c0 * c2);
904  (*this)[1][2] = (s0 * s1 * c2) - (c0 * s2);
905 
906  (*this)[2][0] = -s1;
907  (*this)[2][1] = c1 * s2;
908  (*this)[2][2] = c1 * c2;
909 
910  return *this;
911 }
912 
917 vpRotationMatrix &vpRotationMatrix::build(const double &tux, const double &tuy, const double &tuz)
918 {
919  vpThetaUVector tu(tux, tuy, tuz);
920  build(tu);
921  return *this;
922 }
923 
928 {
929  double a = q.w();
930  double b = q.x();
931  double c = q.y();
932  double d = q.z();
933  (*this)[0][0] = (((a * a) + (b * b)) - (c * c)) - (d * d);
934  (*this)[0][1] = (2 * b * c) - (2 * a * d);
935  (*this)[0][2] = (2 * a * c) + (2 * b * d);
936 
937  (*this)[1][0] = (2 * a * d) + (2 * b * c);
938  (*this)[1][1] = (((a * a) - (b * b)) + (c * c)) - (d * d);
939  (*this)[1][2] = (2 * c * d) - (2 * a * b);
940 
941  (*this)[2][0] = (2 * b * d) - (2 * a * c);
942  (*this)[2][1] = (2 * a * b) + (2 * c * d);
943  (*this)[2][2] = ((a * a) - (b * b) - (c * c)) + (d * d);
944  return *this;
945 }
946 
950 vpRotationMatrix operator*(const double &x, const vpRotationMatrix &R)
951 {
953 
954  unsigned int Rrow = R.getRows();
955  unsigned int Rcol = R.getCols();
956 
957  for (unsigned int i = 0; i < Rrow; ++i) {
958  for (unsigned int j = 0; j < Rcol; ++j) {
959  C[i][j] = R[i][j] * x;
960  }
961  }
962 
963  return C;
964 }
965 
971 {
972  vpThetaUVector tu;
973  tu.build(*this);
974  return tu;
975 }
976 
1005 {
1006  if (j >= getCols()) {
1007  throw(vpException(vpException::dimensionError, "Unable to extract a column vector from the homogeneous matrix"));
1008  }
1009  unsigned int nb_rows = getRows();
1010  vpColVector c(nb_rows);
1011  for (unsigned int i = 0; i < nb_rows; ++i) {
1012  c[i] = (*this)[i][j];
1013  }
1014  return c;
1015 }
1016 
1026 vpRotationMatrix vpRotationMatrix::mean(const std::vector<vpHomogeneousMatrix> &vec_M)
1027 {
1028  vpMatrix meanR(3, 3);
1029  vpRotationMatrix R;
1030  size_t vec_m_size = vec_M.size();
1031  for (size_t i = 0; i < vec_m_size; ++i) {
1032  R = vec_M[i].getRotationMatrix();
1033  meanR += (vpMatrix)R;
1034  }
1035  meanR /= static_cast<double>(vec_M.size());
1036 
1037  // Euclidean mean of the rotation matrix following Moakher's method (SIAM 2002)
1038  vpMatrix M, U, V;
1039  vpColVector sv;
1040  meanR.pseudoInverse(M, sv, 1e-6, U, V);
1041  double det = sv[0] * sv[1] * sv[2];
1042  if (det > 0) {
1043  meanR = U * V.t();
1044  }
1045  else {
1046  vpMatrix D(3, 3);
1047  D = 0.0;
1048  D[0][0] = 1.0;
1049  D[1][1] = 1.0;
1050  D[2][2] = -1;
1051  meanR = U * D * V.t();
1052  }
1053 
1054  R = meanR;
1055  return R;
1056 }
1057 
1066 vpRotationMatrix vpRotationMatrix::mean(const std::vector<vpRotationMatrix> &vec_R)
1067 {
1068  vpMatrix meanR(3, 3);
1069  vpRotationMatrix R;
1070  size_t vec_r_size = vec_R.size();
1071  for (size_t i = 0; i < vec_r_size; ++i) {
1072  meanR += (vpMatrix)vec_R[i];
1073  }
1074  meanR /= static_cast<double>(vec_R.size());
1075 
1076  // Euclidean mean of the rotation matrix following Moakher's method (SIAM 2002)
1077  vpMatrix M, U, V;
1078  vpColVector sv;
1079  meanR.pseudoInverse(M, sv, 1e-6, U, V);
1080  double det = sv[0] * sv[1] * sv[2];
1081  if (det > 0) {
1082  meanR = U * V.t();
1083  }
1084  else {
1085  vpMatrix D(3, 3);
1086  D = 0.0;
1087  D[0][0] = 1.0;
1088  D[1][1] = 1.0;
1089  D[2][2] = -1;
1090  meanR = U * D * V.t();
1091  }
1092 
1093  R = meanR;
1094  return R;
1095 }
1096 
1101 {
1102  vpMatrix U = *this;
1103  vpColVector w;
1104  vpMatrix V;
1105  U.svd(w, V);
1106  vpMatrix Vt = V.t();
1107  vpMatrix R = U * Vt;
1108 
1109  double det = R.det();
1110  if (det < 0) {
1111  Vt[2][0] *= -1;
1112  Vt[2][1] *= -1;
1113  Vt[2][2] *= -1;
1114 
1115  R = U * Vt;
1116  }
1117 
1118  data[0] = R[0][0];
1119  data[1] = R[0][1];
1120  data[2] = R[0][2];
1121  data[3] = R[1][0];
1122  data[4] = R[1][1];
1123  data[5] = R[1][2];
1124  data[6] = R[2][0];
1125  data[7] = R[2][1];
1126  data[8] = R[2][2];
1127 }
1128 
1129 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
1130 
1139 
1140 #endif //#if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:126
unsigned int getCols() const
Definition: vpArray2D.h:329
double * data
Address of the first element of the data array.
Definition: vpArray2D.h:139
double ** rowPtrs
Address of the first element of each rows.
Definition: vpArray2D.h:133
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:129
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:135
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:341
unsigned int getRows() const
Definition: vpArray2D.h:339
unsigned int colNum
Number of columns in the array.
Definition: vpArray2D.h:131
Implementation of column vector and the associated operations.
Definition: vpColVector.h:163
vpColVector operator*(const double &x, const vpColVector &v)
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ dimensionError
Bad dimension.
Definition: vpException.h:70
@ fatalError
Fatal error.
Definition: vpException.h:71
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
vpTranslationVector getTranslationVector() const
static double sinc(double x)
Definition: vpMath.cpp:269
static double sqr(double x)
Definition: vpMath.h:201
static double mcosc(double cosx, double x)
Definition: vpMath.cpp:234
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:146
void svd(vpColVector &w, vpMatrix &V)
Definition: vpMatrix.cpp:2132
vpMatrix t() const
Definition: vpMatrix.cpp:465
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition: vpMatrix.cpp:2343
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition: vpMatrix.cpp:6275
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:190
Implementation of a rotation vector as quaternion angle minimal representation.
const double & z() const
Returns the z-component of the quaternion.
const double & x() const
Returns the x-component of the quaternion.
const double & y() const
Returns the y-component of the quaternion.
const double & w() const
Returns the w-component of the quaternion.
Implementation of a rotation matrix and operations on such kind of matrices.
vp_deprecated void setIdentity()
vpRotationMatrix & build(const vpHomogeneousMatrix &M)
vpRotationMatrix & operator*=(double x)
bool isARotationMatrix(double threshold=1e-6) const
vpRotationMatrix & operator,(double val)
unsigned int m_index
vpColVector getCol(unsigned int j) const
vpThetaUVector getThetaUVector()
vpRotationMatrix & operator<<(double val)
vpRotationMatrix t() const
vp_deprecated vpRotationMatrix buildFrom(const vpHomogeneousMatrix &M)
vpRotationMatrix inverse() const
vpTranslationVector operator*(const vpTranslationVector &tv) const
static vpRotationMatrix mean(const std::vector< vpHomogeneousMatrix > &vec_M)
vpRotationMatrix & operator=(const vpRotationMatrix &R)
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRxyzVector.h:177
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRzyxVector.h:178
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRzyzVector.h:176
Implementation of a rotation vector as axis-angle minimal representation.
vpThetaUVector & build(const vpHomogeneousMatrix &M)
Class that consider the case of a translation vector.