Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpVelocityTwistMatrix.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Velocity twist transformation matrix.
32  *
33 *****************************************************************************/
34 
43 #include <assert.h>
44 #include <sstream>
45 
46 #include <visp3/core/vpException.h>
47 #include <visp3/core/vpVelocityTwistMatrix.h>
48 
56 {
57  for (int i = 0; i < 6; ++i) {
58  for (int j = 0; j < 6; ++j) {
59  rowPtrs[i][j] = V.rowPtrs[i][j];
60  }
61  }
62 
63  return *this;
64 }
65 
70 {
71  const unsigned int nparam = 6;
72  for (unsigned int i = 0; i < nparam; ++i) {
73  for (unsigned int j = 0; j < nparam; ++j) {
74  if (i == j) {
75  (*this)[i][j] = 1.0;
76  }
77  else {
78  (*this)[i][j] = 0.0;
79  }
80  }
81  }
82 }
83 
88 
96 
116 {
117  if (full) {
118  build(M);
119  }
120  else {
122  }
123 }
124 
140  : vpArray2D<double>(6, 6)
141 {
142  build(t, thetau);
143 }
144 
158 {
159  build(thetau);
160 }
161 
176  : vpArray2D<double>(6, 6)
177 {
178  build(t, R);
179 }
180 
193 
209 vpVelocityTwistMatrix::vpVelocityTwistMatrix(double tx, double ty, double tz, double tux, double tuy, double tuz)
210  : vpArray2D<double>(6, 6)
211 {
212  vpTranslationVector t(tx, ty, tz);
213  vpThetaUVector tu(tux, tuy, tuz);
214  build(t, tu);
215 }
216 
224 {
226  const unsigned int nparam = 6;
227  for (unsigned int i = 0; i < nparam; ++i) {
228  for (unsigned int j = 0; j < nparam; ++j) {
229  double s = 0;
230  for (unsigned int k = 0; k < nparam; ++k) {
231  s += rowPtrs[i][k] * V.rowPtrs[k][j];
232  }
233  p[i][j] = s;
234  }
235  }
236  return p;
237 }
238 
283 {
284  const unsigned int nparam = 6;
285  if (nparam != M.getRows()) {
286  throw(vpException(vpException::dimensionError, "Cannot multiply a (6x6) velocity twist matrix by a (%dx%d) matrix",
287  M.getRows(), M.getCols()));
288  }
289 
290  vpMatrix p(nparam, M.getCols());
291  unsigned int m_col = M.getCols();
292  for (unsigned int i = 0; i < nparam; ++i) {
293  for (unsigned int j = 0; j < m_col; ++j) {
294  double s = 0;
295  for (unsigned int k = 0; k < nparam; ++k) {
296  s += rowPtrs[i][k] * M[k][j];
297  }
298  p[i][j] = s;
299  }
300  }
301  return p;
302 }
303 
316 {
317  const unsigned int nparam = 6;
318  vpColVector c(nparam);
319 
320  if (nparam != v.getRows()) {
322  "Cannot multiply a (6x6) velocity twist matrix by a "
323  "(%d) column vector",
324  v.getRows()));
325  }
326 
327  c = 0.0;
328 
329  for (unsigned int i = 0; i < nparam; ++i) {
330  for (unsigned int j = 0; j < nparam; ++j) {
331  c[i] += rowPtrs[i][j] * v[j];
332  }
333  }
334 
335  return c;
336 }
337 
338 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
351 {
352  build(R);
353  return *this;
354 }
355 
371 {
372  build(t, R);
373  return *this;
374 }
375 
392 {
393  build(t, thetau);
394  return *this;
395 }
396 
410 {
411  build(thetau);
412  return *this;
413 }
414 
434 {
435  build(M, full);
436  return *this;
437 }
438 #endif
439 
452 {
453  const unsigned int val_3 = 3;
454  for (unsigned int i = 0; i < val_3; ++i) {
455  for (unsigned int j = 0; j < val_3; ++j) {
456  (*this)[i][j] = R[i][j];
457  (*this)[i + 3][j + 3] = R[i][j];
458  (*this)[i][j + 3] = 0;
459  }
460  }
461  return *this;
462 }
463 
479 {
480  vpMatrix skewaR = t.skew(t) * R;
481 
482  const unsigned int val_3 = 3;
483  for (unsigned int i = 0; i < val_3; ++i) {
484  for (unsigned int j = 0; j < val_3; ++j) {
485  (*this)[i][j] = R[i][j];
486  (*this)[i + 3][j + 3] = R[i][j];
487  (*this)[i][j + 3] = skewaR[i][j];
488  }
489  }
490 
491  return *this;
492 }
493 
510 {
511  build(t, vpRotationMatrix(thetau));
512  return *this;
513 }
514 
528 {
529  build(vpRotationMatrix(thetau));
530  return *this;
531 }
532 
552 {
553  if (full) {
555  }
556  else {
558  }
559 
560  return *this;
561 }
562 
565 {
568  extract(R);
570  extract(T);
572  RtT = -(R.t() * T);
573 
574  Wi.build(RtT, R.t());
575 
576  return Wi;
577 }
578 
581 
584 {
585  const unsigned int val_3 = 3;
586  for (unsigned int i = 0; i < val_3; ++i) {
587  for (unsigned int j = 0; j < val_3; ++j) {
588  R[i][j] = (*this)[i][j];
589  }
590  }
591 }
592 
595 {
597  extract(R);
598  vpMatrix skTR(3, 3);
599  const unsigned int val_3 = 3;
600  for (unsigned int i = 0; i < val_3; ++i) {
601  for (unsigned int j = 0; j < val_3; ++j) {
602  skTR[i][j] = (*this)[i][j + val_3];
603  }
604  }
605 
606  vpMatrix skT = skTR * R.t();
607  const unsigned int index_0 = 0;
608  const unsigned int index_1 = 1;
609  const unsigned int index_2 = 2;
610  tv[index_0] = skT[index_2][index_1];
611  tv[index_1] = skT[index_0][index_2];
612  tv[index_2] = skT[index_1][index_0];
613 }
614 
634 int vpVelocityTwistMatrix::print(std::ostream &s, unsigned int length, char const *intro) const
635 {
636  typedef std::string::size_type size_type;
637 
638  unsigned int m = getRows();
639  unsigned int n = getCols();
640 
641  std::vector<std::string> values(m * n);
642  std::ostringstream oss;
643  std::ostringstream ossFixed;
644  std::ios_base::fmtflags original_flags = oss.flags();
645 
646  // --comment: could be used ossFixed << std::fixed
647  ossFixed.setf(std::ios::fixed, std::ios::floatfield);
648 
649  size_type maxBefore = 0; // the length of the integral part
650  size_type maxAfter = 0; // number of decimals plus
651  // one place for the decimal point
652  for (unsigned int i = 0; i < m; ++i) {
653  for (unsigned int j = 0; j < n; ++j) {
654  oss.str("");
655  oss << (*this)[i][j];
656  if (oss.str().find("e") != std::string::npos) {
657  ossFixed.str("");
658  ossFixed << (*this)[i][j];
659  oss.str(ossFixed.str());
660  }
661 
662  values[(i * n) + j] = oss.str();
663  size_type thislen = values[(i * n) + j].size();
664  size_type p = values[(i * n) + j].find('.');
665 
666  if (p == std::string::npos) {
667  maxBefore = vpMath::maximum(maxBefore, thislen);
668  // maxAfter remains the same
669  }
670  else {
671  maxBefore = vpMath::maximum(maxBefore, p);
672  maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
673  }
674  }
675  }
676 
677  size_type totalLength = length;
678  // increase totalLength according to maxBefore
679  totalLength = vpMath::maximum(totalLength, maxBefore);
680  // decrease maxAfter according to totalLength
681  maxAfter = std::min<size_type>(maxAfter, totalLength - maxBefore);
682  if (maxAfter == 1) {
683  maxAfter = 0;
684  }
685 
686  // the following line is useful for debugging
687  // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
688 
689  if (intro) {
690  s << intro;
691  }
692  s << "[" << m << "," << n << "]=\n";
693 
694  for (unsigned int i = 0; i < m; ++i) {
695  s << " ";
696  for (unsigned int j = 0; j < n; ++j) {
697  size_type p = values[(i * n) + j].find('.');
698  s.setf(std::ios::right, std::ios::adjustfield);
699  s.width(static_cast<std::streamsize>(maxBefore));
700  s << values[(i * n) + j].substr(0, p).c_str();
701 
702  if (maxAfter > 0) {
703  s.setf(std::ios::left, std::ios::adjustfield);
704  if (p != std::string::npos) {
705  s.width(static_cast<std::streamsize>(maxAfter));
706  s << values[(i * n) + j].substr(p, maxAfter).c_str();
707  }
708  else {
709  assert(maxAfter > 1);
710  s.width(static_cast<std::streamsize>(maxAfter));
711  s << ".0";
712  }
713  }
714 
715  s << ' ';
716  }
717  s << std::endl;
718  }
719 
720  s.flags(original_flags); // restore s to standard state
721 
722  return static_cast<int>(maxBefore + maxAfter);
723 }
724 
725 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
726 
734 
735 #endif // #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
736 END_VISP_NAMESPACE
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:145
unsigned int getCols() const
Definition: vpArray2D.h:337
double ** rowPtrs
Address of the first element of each rows.
Definition: vpArray2D.h:1102
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
vpArray2D< double > t() const
Compute the transpose of the array.
Definition: vpArray2D.h:1163
unsigned int getRows() const
Definition: vpArray2D.h:347
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ dimensionError
Bad dimension.
Definition: vpException.h:71
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
vpTranslationVector getTranslationVector() const
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:254
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
Implementation of a rotation matrix and operations on such kind of matrices.
vpRotationMatrix t() const
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.
vpVelocityTwistMatrix & build(const vpTranslationVector &t, const vpRotationMatrix &R)
vpVelocityTwistMatrix operator*(const vpVelocityTwistMatrix &V) const
void extract(vpRotationMatrix &R) const
Extract the rotation matrix from the velocity twist matrix.
vpVelocityTwistMatrix inverse() const
Invert the velocity twist matrix.
int print(std::ostream &s, unsigned int length, char const *intro=0) const
VP_DEPRECATED vpVelocityTwistMatrix buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
VP_DEPRECATED void setIdentity()
vpVelocityTwistMatrix & operator=(const vpVelocityTwistMatrix &V)