Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpPoseVector.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  * Pose object. A pose is a size 6 vector [t, tu]^T where tu is
32  * a rotation vector (theta u representation) and t is a translation vector.
33  */
34 
41 #include <assert.h>
42 #include <sstream>
43 
44 #include <visp3/core/vpException.h>
45 #include <visp3/core/vpMath.h>
46 #include <visp3/core/vpMatrixException.h>
47 #include <visp3/core/vpPoseVector.h>
48 
49 BEGIN_VISP_NAMESPACE
50 
51 const unsigned int vpPoseVector::constr_value_6 = 6;
62 vpPoseVector::vpPoseVector() : vpArray2D<double>(constr_value_6, 1) { }
63 
79 vpPoseVector::vpPoseVector(double tx, double ty, double tz, double tux, double tuy, double tuz)
80  : vpArray2D<double>(constr_value_6, 1)
81 {
82  const unsigned int index_0 = 0;
83  const unsigned int index_1 = 1;
84  const unsigned int index_2 = 2;
85  const unsigned int index_3 = 3;
86  const unsigned int index_4 = 4;
87  const unsigned int index_5 = 5;
88  (*this)[index_0] = tx;
89  (*this)[index_1] = ty;
90  (*this)[index_2] = tz;
91 
92  (*this)[index_3] = tux;
93  (*this)[index_4] = tuy;
94  (*this)[index_5] = tuz;
95 }
96 
107 vpPoseVector::vpPoseVector(const vpTranslationVector &tv, const vpThetaUVector &tu) : vpArray2D<double>(constr_value_6, 1)
108 {
109  buildFrom(tv, tu);
110 }
111 
124 vpPoseVector::vpPoseVector(const vpTranslationVector &tv, const vpRotationMatrix &R) : vpArray2D<double>(constr_value_6, 1)
125 {
126  buildFrom(tv, R);
127 }
128 
139 vpPoseVector::vpPoseVector(const vpHomogeneousMatrix &M) : vpArray2D<double>(constr_value_6, 1) { buildFrom(M); }
140 
156 void vpPoseVector::set(double tx, double ty, double tz, double tux, double tuy, double tuz)
157 {
158  const unsigned int index_0 = 0;
159  const unsigned int index_1 = 1;
160  const unsigned int index_2 = 2;
161  const unsigned int index_3 = 3;
162  const unsigned int index_4 = 4;
163  const unsigned int index_5 = 5;
164  (*this)[index_0] = tx;
165  (*this)[index_1] = ty;
166  (*this)[index_2] = tz;
167 
168  (*this)[index_3] = tux;
169  (*this)[index_4] = tuy;
170  (*this)[index_5] = tuz;
171 }
172 
189 vpPoseVector &vpPoseVector::buildFrom(const double &tx, const double &ty, const double &tz, const double &tux, const double &tuy, const double &tuz)
190 {
191  const unsigned int index_0 = 0;
192  const unsigned int index_1 = 1;
193  const unsigned int index_2 = 2;
194  const unsigned int index_3 = 3;
195  const unsigned int index_4 = 4;
196  const unsigned int index_5 = 5;
197  (*this)[index_0] = tx;
198  (*this)[index_1] = ty;
199  (*this)[index_2] = tz;
200 
201  (*this)[index_3] = tux;
202  (*this)[index_4] = tuy;
203  (*this)[index_5] = tuz;
204  return *this;
205 }
206 
219 {
221  M.extract(R);
223  M.extract(tv);
224  buildFrom(tv, R);
225  return *this;
226 }
227 
240 {
241  const unsigned int val_3 = 3;
242  const unsigned int index_3 = 3;
243  for (unsigned int i = 0; i < val_3; ++i) {
244  (*this)[i] = tv[i];
245  (*this)[i + index_3] = tu[i];
246  }
247  return *this;
248 }
249 
264 {
265  vpThetaUVector tu;
266  tu.buildFrom(R);
267 
268  buildFrom(tv, tu);
269  return *this;
270 }
271 
276 {
277  const unsigned int index_0 = 0;
278  const unsigned int index_1 = 1;
279  const unsigned int index_2 = 2;
280  tv[index_0] = (*this)[index_0];
281  tv[index_1] = (*this)[index_1];
282  tv[index_2] = (*this)[index_2];
283 }
284 
289 {
290  const unsigned int index_0 = 0;
291  const unsigned int index_1 = 1;
292  const unsigned int index_2 = 2;
293  const unsigned int index_3 = 3;
294  const unsigned int index_4 = 4;
295  const unsigned int index_5 = 5;
296  tu[index_0] = (*this)[index_3];
297  tu[index_1] = (*this)[index_4];
298  tu[index_2] = (*this)[index_5];
299 }
304 {
305  vpRotationMatrix R((*this)[3], (*this)[4], (*this)[5]);
306  q.buildFrom(R);
307 }
312 {
313  const unsigned int index_3 = 3;
314  const unsigned int index_4 = 4;
315  const unsigned int index_5 = 5;
316  R.buildFrom((*this)[index_3], (*this)[index_4], (*this)[index_5]);
317 }
323 {
324  const unsigned int index_0 = 0;
325  const unsigned int index_1 = 1;
326  const unsigned int index_2 = 2;
327  vpTranslationVector tr((*this)[index_0], (*this)[index_1], (*this)[index_2]);
328  return tr;
329 }
330 
336 {
337  vpRotationMatrix R((*this)[3], (*this)[4], (*this)[5]);
338  return R;
339 }
340 
346 {
347  vpThetaUVector tu((*this)[3], (*this)[4], (*this)[5]);
348  return tu;
349 }
350 
373 {
374  const unsigned int nparam = 6;
375  const unsigned int nparam_t = 3;
376  for (unsigned int i = 0; i < nparam; ++i) {
377  if (i < nparam_t) {
378  std::cout << (*this)[i] << " ";
379  }
380  else {
381  std::cout << vpMath::deg((*this)[i]) << " ";
382  }
383  }
384  std::cout << std::endl;
385 }
386 
398 void vpPoseVector::save(std::ofstream &f) const
399 {
400  if (!f.fail()) {
401  f << *this;
402  }
403  else {
404  throw(vpException(vpException::ioError, "Cannot save the pose vector: ofstream not opened"));
405  }
406 }
407 
418 void vpPoseVector::load(std::ifstream &f)
419 {
420  if (!f.fail()) {
421  const unsigned int nparam = 6;
422  for (unsigned int i = 0; i < nparam; ++i) {
423  f >> (*this)[i];
424  }
425  }
426  else {
427  throw(vpException(vpException::ioError, "Cannot read pose vector: ifstream not opened"));
428  }
429 }
430 
431 /*
432  Transpose the pose vector. The resulting vector becomes a row vector.
433 
434 */
436 {
437  vpRowVector v(rowNum);
438  memcpy(v.data, data, rowNum * sizeof(double));
439  return v;
440 }
441 
461 int vpPoseVector::print(std::ostream &s, unsigned int length, char const *intro) const
462 {
463  typedef std::string::size_type size_type;
464 
465  unsigned int m = getRows();
466  unsigned int n = 1;
467 
468  std::vector<std::string> values(m * n);
469  std::ostringstream oss;
470  std::ostringstream ossFixed;
471  std::ios_base::fmtflags original_flags = oss.flags();
472 
473  // --comment: ossFixed less less std fixed
474  ossFixed.setf(std::ios::fixed, std::ios::floatfield);
475 
476  size_type maxBefore = 0; // the length of the integral part
477  size_type maxAfter = 0; // number of decimals plus
478  // one place for the decimal point
479  for (unsigned int i = 0; i < m; ++i) {
480  oss.str("");
481  oss << (*this)[i];
482  if (oss.str().find("e") != std::string::npos) {
483  ossFixed.str("");
484  ossFixed << (*this)[i];
485  oss.str(ossFixed.str());
486  }
487 
488  values[i] = oss.str();
489  size_type thislen = values[i].size();
490  size_type p = values[i].find('.');
491 
492  if (p == std::string::npos) {
493  maxBefore = vpMath::maximum(maxBefore, thislen);
494  // maxAfter remains the same
495  }
496  else {
497  maxBefore = vpMath::maximum(maxBefore, p);
498  maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
499  }
500  }
501 
502  size_type totalLength = length;
503  // increase totalLength according to maxBefore
504  totalLength = vpMath::maximum(totalLength, maxBefore);
505  // decrease maxAfter according to totalLength
506  maxAfter = std::min<size_type>(maxAfter, totalLength - maxBefore);
507  if (maxAfter == 1) {
508  maxAfter = 0;
509  }
510 
511  // the following line is useful for debugging
512  // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
513 
514  if (intro) {
515  s << intro;
516  }
517  s << "[" << m << "," << n << "]=\n";
518 
519  for (unsigned int i = 0; i < m; ++i) {
520  s << " ";
521  size_type p = values[i].find('.');
522  s.setf(std::ios::right, std::ios::adjustfield);
523  s.width(static_cast<std::streamsize>(maxBefore));
524  s << values[i].substr(0, p).c_str();
525 
526  if (maxAfter > 0) {
527  s.setf(std::ios::left, std::ios::adjustfield);
528  if (p != std::string::npos) {
529  s.width(static_cast<std::streamsize>(maxAfter));
530  s << values[i].substr(p, maxAfter).c_str();
531  }
532  else {
533  assert(maxAfter > 1);
534  s.width(static_cast<std::streamsize>(maxAfter));
535  s << ".0";
536  }
537  }
538 
539  s << ' ';
540 
541  s << std::endl;
542  }
543 
544  s.flags(original_flags); // restore s to standard state
545 
546  return static_cast<int>(maxBefore + maxAfter);
547 }
548 
553 std::vector<double> vpPoseVector::toStdVector() const
554 {
555  std::vector<double> v(this->size());
556 
557  unsigned int this_size = this->size();
558  for (unsigned int i = 0; i < this_size; ++i) {
559  v[i] = data[i];
560  }
561  return v;
562 }
563 
564 #ifdef VISP_HAVE_NLOHMANN_JSON
565 #include <visp3/core/vpJsonParsing.h>
566 const std::string vpPoseVector::jsonTypeName = "vpPoseVector";
567 void vpPoseVector::convert_to_json(nlohmann::json &j) const
568 {
569  const vpArray2D<double> *asArray = (vpArray2D<double>*) this;
570  to_json(j, *asArray);
571  j["type"] = vpPoseVector::jsonTypeName;
572 }
573 void vpPoseVector::parse_json(const nlohmann::json &j)
574 {
575 #ifdef ENABLE_VISP_NAMESPACE
576  using namespace VISP_NAMESPACE_NAME;
577 #endif
578  vpArray2D<double> *asArray = (vpArray2D<double>*) this;
579  if (j.is_object() && j.contains("type")) { // Specific conversions
580  const bool converted = convertFromTypeAndBuildFrom<vpPoseVector, vpHomogeneousMatrix>(j, *this);
581  if (!converted) {
582  from_json(j, *asArray);
583  }
584  }
585  else { // Generic 2D array conversion
586  from_json(j, *asArray);
587  }
588 
589  if ((getCols() != 1) && (getRows() != 6)) {
590  throw vpException(vpException::badValue, "From JSON, tried to read something that is not a 6D pose vector");
591  }
592 }
593 #endif
594 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
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:148
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:1101
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
unsigned int getRows() const
Definition: vpArray2D.h:347
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ ioError
I/O error.
Definition: vpException.h:67
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
Implementation of an homogeneous matrix and operations on such kind of matrices.
void extract(vpRotationMatrix &R) const
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:254
static double deg(double rad)
Definition: vpMath.h:119
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:203
vpTranslationVector getTranslationVector() const
std::vector< double > toStdVector() const
void load(std::ifstream &f)
void save(std::ofstream &f) const
friend void from_json(const nlohmann::json &j, vpPoseVector &cam)
Definition: vpPoseVector.h:342
vpRowVector t() const
friend void to_json(nlohmann::json &j, const vpPoseVector &cam)
Definition: vpPoseVector.h:337
void extract(vpRotationMatrix &R) const
void set(double tx, double ty, double tz, double tux, double tuy, double tuz)
vpThetaUVector getThetaUVector() const
static const std::string jsonTypeName
Definition: vpPoseVector.h:309
vpPoseVector & buildFrom(const double &tx, const double &ty, const double &tz, const double &tux, const double &tuy, const double &tuz)
void print() const
vpRotationMatrix getRotationMatrix() const
Implementation of a rotation vector as quaternion angle minimal representation.
vpQuaternionVector & buildFrom(const double &qx, const double &qy, const double &qz, const double &qw)
Implementation of a rotation matrix and operations on such kind of matrices.
vpRotationMatrix & buildFrom(const vpHomogeneousMatrix &M)
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:124
Implementation of a rotation vector as axis-angle minimal representation.
vpThetaUVector & buildFrom(const vpHomogeneousMatrix &M)
Class that consider the case of a translation vector.