Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
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
40
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
50
51const unsigned int vpPoseVector::constr_value_6 = 6;
62vpPoseVector::vpPoseVector() : vpArray2D<double>(constr_value_6, 1) { }
63
79vpPoseVector::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
107vpPoseVector::vpPoseVector(const vpTranslationVector &tv, const vpThetaUVector &tu) : vpArray2D<double>(constr_value_6, 1)
108{
109 buildFrom(tv, tu);
110}
111
124vpPoseVector::vpPoseVector(const vpTranslationVector &tv, const vpRotationMatrix &R) : vpArray2D<double>(constr_value_6, 1)
125{
126 buildFrom(tv, R);
127}
128
139vpPoseVector::vpPoseVector(const vpHomogeneousMatrix &M) : vpArray2D<double>(constr_value_6, 1) { buildFrom(M); }
140
158void vpPoseVector::set(double tx, double ty, double tz, double tux, double tuy, double tuz)
159{
160 const unsigned int index_0 = 0;
161 const unsigned int index_1 = 1;
162 const unsigned int index_2 = 2;
163 const unsigned int index_3 = 3;
164 const unsigned int index_4 = 4;
165 const unsigned int index_5 = 5;
166 (*this)[index_0] = tx;
167 (*this)[index_1] = ty;
168 (*this)[index_2] = tz;
169
170 (*this)[index_3] = tux;
171 (*this)[index_4] = tuy;
172 (*this)[index_5] = tuz;
173}
174
193vpPoseVector &vpPoseVector::buildFrom(const double &tx, const double &ty, const double &tz, const double &tux, const double &tuy, const double &tuz)
194{
195 const unsigned int index_0 = 0;
196 const unsigned int index_1 = 1;
197 const unsigned int index_2 = 2;
198 const unsigned int index_3 = 3;
199 const unsigned int index_4 = 4;
200 const unsigned int index_5 = 5;
201 (*this)[index_0] = tx;
202 (*this)[index_1] = ty;
203 (*this)[index_2] = tz;
204
205 (*this)[index_3] = tux;
206 (*this)[index_4] = tuy;
207 (*this)[index_5] = tuz;
208 return *this;
209}
210
223{
225 M.extract(R);
227 M.extract(tv);
228 buildFrom(tv, R);
229 return *this;
230}
231
244{
245 const unsigned int val_3 = 3;
246 const unsigned int index_3 = 3;
247 for (unsigned int i = 0; i < val_3; ++i) {
248 (*this)[i] = tv[i];
249 (*this)[i + index_3] = tu[i];
250 }
251 return *this;
252}
253
268{
270 tu.buildFrom(R);
271
272 buildFrom(tv, tu);
273 return *this;
274}
275
280{
281 const unsigned int index_0 = 0;
282 const unsigned int index_1 = 1;
283 const unsigned int index_2 = 2;
284 tv[index_0] = (*this)[index_0];
285 tv[index_1] = (*this)[index_1];
286 tv[index_2] = (*this)[index_2];
287}
288
293{
294 const unsigned int index_0 = 0;
295 const unsigned int index_1 = 1;
296 const unsigned int index_2 = 2;
297 const unsigned int index_3 = 3;
298 const unsigned int index_4 = 4;
299 const unsigned int index_5 = 5;
300 tu[index_0] = (*this)[index_3];
301 tu[index_1] = (*this)[index_4];
302 tu[index_2] = (*this)[index_5];
303}
304
308{
309 vpRotationMatrix R((*this)[3], (*this)[4], (*this)[5]);
310 q.buildFrom(R);
311}
312
316{
317 const unsigned int index_3 = 3;
318 const unsigned int index_4 = 4;
319 const unsigned int index_5 = 5;
320 R.buildFrom((*this)[index_3], (*this)[index_4], (*this)[index_5]);
321}
322
327{
328 const unsigned int index_0 = 0;
329 const unsigned int index_1 = 1;
330 const unsigned int index_2 = 2;
331 vpTranslationVector tr((*this)[index_0], (*this)[index_1], (*this)[index_2]);
332 return tr;
333}
334
340{
341 vpRotationMatrix R((*this)[3], (*this)[4], (*this)[5]);
342 return R;
343}
344
350{
351 vpThetaUVector tu((*this)[3], (*this)[4], (*this)[5]);
352 return tu;
353}
354
377{
378 const unsigned int nparam = 6;
379 const unsigned int nparam_t = 3;
380 for (unsigned int i = 0; i < nparam; ++i) {
381 if (i < nparam_t) {
382 std::cout << (*this)[i] << " ";
383 }
384 else {
385 std::cout << vpMath::deg((*this)[i]) << " ";
386 }
387 }
388 std::cout << std::endl;
389}
390
402void vpPoseVector::save(std::ofstream &f) const
403{
404 if (!f.fail()) {
405 f << *this;
406 }
407 else {
408 throw(vpException(vpException::ioError, "Cannot save the pose vector: ofstream not opened"));
409 }
410}
411
422void vpPoseVector::load(std::ifstream &f)
423{
424 if (!f.fail()) {
425 const unsigned int nparam = 6;
426 for (unsigned int i = 0; i < nparam; ++i) {
427 f >> (*this)[i];
428 }
429 }
430 else {
431 throw(vpException(vpException::ioError, "Cannot read pose vector: ifstream not opened"));
432 }
433}
434
435/*
436 Transpose the pose vector. The resulting vector becomes a row vector.
437
438*/
440{
442 memcpy(v.data, data, rowNum * sizeof(double));
443 return v;
444}
445
465int vpPoseVector::print(std::ostream &s, unsigned int length, char const *intro) const
466{
467 typedef std::string::size_type size_type;
468
469 unsigned int m = getRows();
470 unsigned int n = 1;
471
472 std::vector<std::string> values(m * n);
473 std::ostringstream oss;
474 std::ostringstream ossFixed;
475 std::ios_base::fmtflags original_flags = oss.flags();
476
477 // --comment: ossFixed less less std fixed
478 ossFixed.setf(std::ios::fixed, std::ios::floatfield);
479
480 size_type maxBefore = 0; // the length of the integral part
481 size_type maxAfter = 0; // number of decimals plus
482 // one place for the decimal point
483 for (unsigned int i = 0; i < m; ++i) {
484 oss.str("");
485 oss << (*this)[i];
486 if (oss.str().find("e") != std::string::npos) {
487 ossFixed.str("");
488 ossFixed << (*this)[i];
489 oss.str(ossFixed.str());
490 }
491
492 values[i] = oss.str();
493 size_type thislen = values[i].size();
494 size_type p = values[i].find('.');
495
496 if (p == std::string::npos) {
497 maxBefore = vpMath::maximum(maxBefore, thislen);
498 // maxAfter remains the same
499 }
500 else {
501 maxBefore = vpMath::maximum(maxBefore, p);
502 maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
503 }
504 }
505
506 size_type totalLength = length;
507 // increase totalLength according to maxBefore
508 totalLength = vpMath::maximum(totalLength, maxBefore);
509 // decrease maxAfter according to totalLength
510 maxAfter = std::min<size_type>(maxAfter, totalLength - maxBefore);
511 if (maxAfter == 1) {
512 maxAfter = 0;
513 }
514
515 // the following line is useful for debugging
516 // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
517
518 if (intro) {
519 s << intro;
520 }
521 s << "[" << m << "," << n << "]=\n";
522
523 for (unsigned int i = 0; i < m; ++i) {
524 s << " ";
525 size_type p = values[i].find('.');
526 s.setf(std::ios::right, std::ios::adjustfield);
527 s.width(static_cast<std::streamsize>(maxBefore));
528 s << values[i].substr(0, p).c_str();
529
530 if (maxAfter > 0) {
531 s.setf(std::ios::left, std::ios::adjustfield);
532 if (p != std::string::npos) {
533 s.width(static_cast<std::streamsize>(maxAfter));
534 s << values[i].substr(p, maxAfter).c_str();
535 }
536 else {
537 assert(maxAfter > 1);
538 s.width(static_cast<std::streamsize>(maxAfter));
539 s << ".0";
540 }
541 }
542
543 s << ' ';
544
545 s << std::endl;
546 }
547
548 s.flags(original_flags); // restore s to standard state
549
550 return static_cast<int>(maxBefore + maxAfter);
551}
552
557std::vector<double> vpPoseVector::toStdVector() const
558{
559 std::vector<double> v(this->size());
560
561 unsigned int this_size = this->size();
562 for (unsigned int i = 0; i < this_size; ++i) {
563 v[i] = data[i];
564 }
565 return v;
566}
567
568#ifdef VISP_HAVE_NLOHMANN_JSON
569#include <visp3/core/vpJsonParsing.h>
570VP_ATTRIBUTE_NO_DESTROY const std::string vpPoseVector::jsonTypeName = "vpPoseVector";
571void vpPoseVector::convert_to_json(nlohmann::json &j) const
572{
573 const vpArray2D<double> *asArray = (vpArray2D<double>*) this;
574 to_json(j, *asArray);
575 j["type"] = vpPoseVector::jsonTypeName;
576}
577void vpPoseVector::parse_json(const nlohmann::json &j)
578{
579#ifdef ENABLE_VISP_NAMESPACE
580 using namespace VISP_NAMESPACE_NAME;
581#endif
582 vpArray2D<double> *asArray = (vpArray2D<double>*) this;
583 if (j.is_object() && j.contains("type")) { // Specific conversions
584 const bool converted = convertFromTypeAndBuildFrom<vpPoseVector, vpHomogeneousMatrix>(j, *this);
585 if (!converted) {
586 from_json(j, *asArray);
587 }
588 }
589 else { // Generic 2D array conversion
590 from_json(j, *asArray);
591 }
592
593 if ((getCols() != 1) && (getRows() != 6)) {
594 throw vpException(vpException::badValue, "From JSON, tried to read something that is not a 6D pose vector");
595 }
596}
597#endif
598END_VISP_NAMESPACE
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition vpArray2D.h:146
unsigned int getCols() const
Definition vpArray2D.h:423
unsigned int rowNum
Definition vpArray2D.h:1201
unsigned int size() const
Definition vpArray2D.h:435
unsigned int getRows() const
Definition vpArray2D.h:433
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:257
static double deg(double rad)
Definition vpMath.h:119
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)
static const std::string jsonTypeName
vpRowVector t() const
friend void to_json(nlohmann::json &j, const vpPoseVector &cam)
void extract(vpRotationMatrix &R) const
void set(double tx, double ty, double tz, double tux, double tuy, double tuz)
vpThetaUVector getThetaUVector() const
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.
Implementation of row vector and the associated operations.
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.