Visual Servoing Platform  version 3.6.1 under development (2025-02-01)
vpThetaUVector.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  * Theta U parameterization for the rotation.
32  */
33 
39 #include <cmath> // std::fabs
40 #include <limits> // numeric_limits
41 
42 #include <visp3/core/vpThetaUVector.h>
43 
44 BEGIN_VISP_NAMESPACE
45 
46 const double vpThetaUVector::minimum = 0.0001;
47 const unsigned int vpThetaUVector::constr_val_3 = 3;
48 
67 
84 
105 vpThetaUVector::vpThetaUVector(double tux, double tuy, double tuz) : vpRotationVector(constr_val_3) { buildFrom(tux, tuy, tuz); }
106 
110 vpThetaUVector::vpThetaUVector(const std::vector<double> &tu) : vpRotationVector(constr_val_3) { buildFrom(tu); }
111 
116 {
118 
119  M.extract(R);
120  buildFrom(R);
121 
122  return *this;
123 }
129 {
130  const unsigned int val_3 = 3;
131  const unsigned int index_3 = 3;
132  for (unsigned int i = 0; i < val_3; ++i) {
133  data[i] = p[i + index_3];
134  }
135 
136  return *this;
137 }
138 
143 {
144  double s, c, theta;
145  const unsigned int index_0 = 0;
146  const unsigned int index_1 = 1;
147  const unsigned int index_2 = 2;
148 
149  s = ((R[1][0] - R[0][1]) * (R[1][0] - R[0][1])) + ((R[index_2][0] - R[0][index_2]) * (R[index_2][0] - R[0][index_2])) +
150  ((R[index_2][index_1] - R[index_1][index_2]) * (R[index_2][index_1] - R[index_1][index_2]));
151  s = sqrt(s) / 2.0;
152  c = ((R[index_0][index_0] + R[index_1][index_1] + R[index_2][index_2]) - 1.0) / 2.0;
153  theta = atan2(s, c); /* theta in [0, PI] since s > 0 */
154 
155  // General case when theta != pi. If theta=pi, c=-1
156  if ((1 + c) > minimum) // Since -1 <= c <= 1, no fabs(1+c) is required
157  {
158  double sinc = vpMath::sinc(s, theta);
159 
160  data[index_0] = (R[index_2][index_1] - R[index_1][index_2]) / (2.0 * sinc);
161  data[index_1] = (R[index_0][index_2] - R[index_2][index_0]) / (2.0 * sinc);
162  data[index_2] = (R[index_1][index_0] - R[index_0][index_1]) / (2.0 * sinc);
163  }
164  else /* theta near PI */
165  {
166  double x = 0;
167  if ((R[0][0] - c) > std::numeric_limits<double>::epsilon()) {
168  x = sqrt((R[0][0] - c) / (1 - c));
169  }
170 
171  double y = 0;
172  if ((R[1][1] - c) > std::numeric_limits<double>::epsilon()) {
173  y = sqrt((R[1][1] - c) / (1 - c));
174  }
175 
176  double z = 0;
177  if ((R[index_2][index_2] - c) > std::numeric_limits<double>::epsilon()) {
178  z = sqrt((R[index_2][index_2] - c) / (1 - c));
179  }
180 
181  if ((x > y) && (x > z)) {
182  if ((R[index_2][index_1] - R[index_1][index_2]) < 0) {
183  x = -x;
184  }
185  if ((vpMath::sign(x) * vpMath::sign(y)) != (vpMath::sign(R[0][1] + R[1][0]))) {
186  y = -y;
187  }
188  if ((vpMath::sign(x) * vpMath::sign(z)) != (vpMath::sign(R[index_0][index_2] + R[index_2][index_0]))) {
189  z = -z;
190  }
191  }
192  else if (y > z) {
193  if ((R[index_0][index_2] - R[index_2][index_0]) < 0) {
194  y = -y;
195  }
196  if ((vpMath::sign(y) * vpMath::sign(x)) != (vpMath::sign(R[index_1][index_0] + R[index_0][index_1]))) {
197  x = -x;
198  }
199  if ((vpMath::sign(y) * vpMath::sign(z)) != (vpMath::sign(R[index_1][index_2] + R[index_2][index_1]))) {
200  z = -z;
201  }
202  }
203  else {
204  if ((R[1][0] - R[0][1]) < 0) {
205  z = -z;
206  }
207  if ((vpMath::sign(z) * vpMath::sign(x)) != (vpMath::sign(R[index_2][index_0] + R[index_0][index_2]))) {
208  x = -x;
209  }
210  if ((vpMath::sign(z) * vpMath::sign(y)) != (vpMath::sign(R[index_2][index_1] + R[index_1][index_2]))) {
211  y = -y;
212  }
213  }
214  data[index_0] = theta * x;
215  data[index_1] = theta * y;
216  data[index_2] = theta * z;
217  }
218 
219  return *this;
220 }
225 {
226  vpRotationMatrix R(rzyx);
227 
228  buildFrom(R);
229  return *this;
230 }
235 {
236  vpRotationMatrix R(rzyz);
237 
238  buildFrom(R);
239  return *this;
240 }
245 {
246  vpRotationMatrix R(rxyz);
247 
248  buildFrom(R);
249  return *this;
250 }
251 
256 {
257  vpRotationMatrix R(q);
258 
259  buildFrom(R);
260  return *this;
261 }
262 
266 vpThetaUVector &vpThetaUVector::buildFrom(const std::vector<double> &tu)
267 {
268  const unsigned int val_3 = 3;
269  if (tu.size() != val_3) {
270  throw(vpException(vpException::dimensionError, "Cannot construct a theta-u vector from a %d-dimension std::vector",
271  tu.size()));
272  }
273  for (unsigned int i = 0; i < val_3; ++i) {
274  data[i] = tu[i];
275  }
276 
277  return *this;
278 }
279 
284 {
285  const unsigned int val_3 = 3;
286  if (tu.size() != val_3) {
287  throw(vpException(vpException::dimensionError, "Cannot construct a theta-u vector from a %d-dimension std::vector",
288  tu.size()));
289  }
290  for (unsigned int i = 0; i < val_3; ++i) {
291  data[i] = tu[i];
292  }
293 
294  return *this;
295 }
296 
300 vpThetaUVector &vpThetaUVector::buildFrom(const double &tux, const double &tuy, const double &tuz)
301 {
302  const unsigned int index_0 = 0;
303  const unsigned int index_1 = 1;
304  const unsigned int index_2 = 2;
305  data[index_0] = tux;
306  data[index_1] = tuy;
307  data[index_2] = tuz;
308  return *this;
309 }
310 
336 {
337  for (unsigned int i = 0; i < dsize; ++i) {
338  data[i] = v;
339  }
340 
341  return *this;
342 }
343 
371 {
372  if (tu.size() != size()) {
373  throw(vpException(vpException::dimensionError, "Cannot set a theta-u vector from a %d-dimension col vector",
374  tu.size()));
375  }
376 
377  unsigned int l_size = size();
378  for (unsigned int i = 0; i < l_size; ++i) {
379  data[i] = tu[i];
380  }
381 
382  return *this;
383 }
384 
417 void vpThetaUVector::extract(double &theta, vpColVector &u) const
418 {
419  const unsigned int val_3 = 3;
420  u.resize(val_3);
421 
422  theta = getTheta();
423  // --comment: if theta equals 0
424  if (std::fabs(theta) <= std::numeric_limits<double>::epsilon()) {
425  u = 0;
426  return;
427  }
428  for (unsigned int i = 0; i < val_3; ++i) {
429  u[i] = data[i] / theta;
430  }
431 }
432 
460 {
461  const unsigned int index_0 = 0;
462  const unsigned int index_1 = 1;
463  const unsigned int index_2 = 2;
464  return sqrt((data[index_0] * data[index_0]) + (data[index_1] * data[index_1]) + (data[index_2] * data[index_2]));
465 }
466 
495 {
496  vpColVector u(3);
497 
498  double theta = getTheta();
499  // --comment: if theta equals 0
500  if (std::fabs(theta) <= std::numeric_limits<double>::epsilon()) {
501  u = 0;
502  return u;
503  }
504  const unsigned int val_3 = 3;
505  for (unsigned int i = 0; i < val_3; ++i) {
506  u[i] = data[i] / theta;
507  }
508  return u;
509 }
510 
516 {
517  double a_2 = getTheta() / 2;
518  vpColVector a_hat = getU();
519  double b_2 = tu_b.getTheta() / 2;
520  vpColVector b_hat = tu_b.getU();
521 
522  vpColVector a_hat_sin_2 = a_hat * std::sin(a_2);
523  vpColVector b_hat_sin_2 = b_hat * std::sin(b_2);
524  double c = 2 * std::acos((std::cos(a_2) * std::cos(b_2)) - (vpColVector::dotProd(a_hat_sin_2, b_hat_sin_2)));
525  vpColVector d = ((std::sin(a_2) * std::cos(b_2) * a_hat) + (std::cos(a_2) * std::sin(b_2) * b_hat)) +
526  (std::sin(a_2) * std::sin(b_2) * vpColVector::crossProd(a_hat, b_hat));
527  d = (c * d) / std::sin(c / 2.0);
528 
529  return vpThetaUVector(d);
530 }
531 
532 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
554 vpThetaUVector &vpThetaUVector::operator=(const std::initializer_list<double> &list)
555 {
556  if (list.size() > size()) {
557  throw(vpException(
559  "Cannot set theta u vector out of bounds. It has only %d values while you try to initialize with %d values",
560  size(), list.size()));
561  }
562  std::copy(list.begin(), list.end(), data);
563  return *this;
564 }
565 #endif
566 END_VISP_NAMESPACE
double * data
Address of the first element of the data array.
Definition: vpArray2D.h:148
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:1107
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static double dotProd(const vpColVector &a, const vpColVector &b)
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
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.
void extract(vpRotationMatrix &R) const
static double sinc(double x)
Definition: vpMath.cpp:268
static int sign(double x)
Definition: vpMath.h:429
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:203
Implementation of a rotation vector as quaternion angle minimal representation.
Implementation of a rotation matrix and operations on such kind of matrices.
Implementation of a generic rotation vector.
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRxyzVector.h:183
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRzyxVector.h:184
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRzyzVector.h:182
Implementation of a rotation vector as axis-angle minimal representation.
vpThetaUVector operator*(const vpThetaUVector &tu_b) const
vpColVector getU() const
void extract(double &theta, vpColVector &u) const
vpThetaUVector & buildFrom(const vpHomogeneousMatrix &M)
vpThetaUVector & operator=(const vpColVector &tu)
double getTheta() const