Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
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
38
39#include <cmath> // std::fabs
40#include <limits> // numeric_limits
41
42#include <visp3/core/vpThetaUVector.h>
43
45
46const double vpThetaUVector::minimum = 0.0001;
47const unsigned int vpThetaUVector::constr_val_3 = 3;
48
65
82
103vpThetaUVector::vpThetaUVector(double tux, double tuy, double tuz) : vpRotationVector(constr_val_3) { buildFrom(tux, tuy, tuz); }
104
108vpThetaUVector::vpThetaUVector(const std::vector<double> &tu) : vpRotationVector(constr_val_3) { buildFrom(tu); }
109
114{
116
117 M.extract(R);
118 buildFrom(R);
119
120 return *this;
121}
122
127{
128 const unsigned int val_3 = 3;
129 const unsigned int index_3 = 3;
130 for (unsigned int i = 0; i < val_3; ++i) {
131 data[i] = p[i + index_3];
132 }
133
134 return *this;
135}
136
141{
142 double s, c, theta;
143 const unsigned int index_0 = 0;
144 const unsigned int index_1 = 1;
145 const unsigned int index_2 = 2;
146
147 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])) +
148 ((R[index_2][index_1] - R[index_1][index_2]) * (R[index_2][index_1] - R[index_1][index_2]));
149 s = sqrt(s) / 2.0;
150 c = ((R[index_0][index_0] + R[index_1][index_1] + R[index_2][index_2]) - 1.0) / 2.0;
151 theta = atan2(s, c); /* theta in [0, PI] since s > 0 */
152
153 // General case when theta != pi. If theta=pi, c=-1
154 if ((1 + c) > minimum) // Since -1 <= c <= 1, no fabs(1+c) is required
155 {
156 double sinc = vpMath::sinc(s, theta);
157
158 data[index_0] = (R[index_2][index_1] - R[index_1][index_2]) / (2.0 * sinc);
159 data[index_1] = (R[index_0][index_2] - R[index_2][index_0]) / (2.0 * sinc);
160 data[index_2] = (R[index_1][index_0] - R[index_0][index_1]) / (2.0 * sinc);
161 }
162 else /* theta near PI */
163 {
164 double x = 0;
165 if ((R[0][0] - c) > std::numeric_limits<double>::epsilon()) {
166 x = sqrt((R[0][0] - c) / (1 - c));
167 }
168
169 double y = 0;
170 if ((R[1][1] - c) > std::numeric_limits<double>::epsilon()) {
171 y = sqrt((R[1][1] - c) / (1 - c));
172 }
173
174 double z = 0;
175 if ((R[index_2][index_2] - c) > std::numeric_limits<double>::epsilon()) {
176 z = sqrt((R[index_2][index_2] - c) / (1 - c));
177 }
178
179 if ((x > y) && (x > z)) {
180 if ((R[index_2][index_1] - R[index_1][index_2]) < 0) {
181 x = -x;
182 }
183 if ((vpMath::sign(x) * vpMath::sign(y)) != (vpMath::sign(R[0][1] + R[1][0]))) {
184 y = -y;
185 }
186 if ((vpMath::sign(x) * vpMath::sign(z)) != (vpMath::sign(R[index_0][index_2] + R[index_2][index_0]))) {
187 z = -z;
188 }
189 }
190 else if (y > z) {
191 if ((R[index_0][index_2] - R[index_2][index_0]) < 0) {
192 y = -y;
193 }
194 if ((vpMath::sign(y) * vpMath::sign(x)) != (vpMath::sign(R[index_1][index_0] + R[index_0][index_1]))) {
195 x = -x;
196 }
197 if ((vpMath::sign(y) * vpMath::sign(z)) != (vpMath::sign(R[index_1][index_2] + R[index_2][index_1]))) {
198 z = -z;
199 }
200 }
201 else {
202 if ((R[1][0] - R[0][1]) < 0) {
203 z = -z;
204 }
205 if ((vpMath::sign(z) * vpMath::sign(x)) != (vpMath::sign(R[index_2][index_0] + R[index_0][index_2]))) {
206 x = -x;
207 }
208 if ((vpMath::sign(z) * vpMath::sign(y)) != (vpMath::sign(R[index_2][index_1] + R[index_1][index_2]))) {
209 y = -y;
210 }
211 }
212 data[index_0] = theta * x;
213 data[index_1] = theta * y;
214 data[index_2] = theta * z;
215 }
216
217 return *this;
218}
219
223{
224 vpRotationMatrix R(rzyx);
225
226 buildFrom(R);
227 return *this;
228}
229
233{
234 vpRotationMatrix R(rzyz);
235
236 buildFrom(R);
237 return *this;
238}
239
243{
244 vpRotationMatrix R(rxyz);
245
246 buildFrom(R);
247 return *this;
248}
249
254{
255 vpRotationMatrix R(q);
256
257 buildFrom(R);
258 return *this;
259}
260
264vpThetaUVector &vpThetaUVector::buildFrom(const std::vector<double> &tu)
265{
266 const unsigned int val_3 = 3;
267 if (tu.size() != val_3) {
268 throw(vpException(vpException::dimensionError, "Cannot construct a theta-u vector from a %d-dimension std::vector",
269 tu.size()));
270 }
271 for (unsigned int i = 0; i < val_3; ++i) {
272 data[i] = tu[i];
273 }
274
275 return *this;
276}
277
282{
283 const unsigned int val_3 = 3;
284 if (tu.size() != val_3) {
285 throw(vpException(vpException::dimensionError, "Cannot construct a theta-u vector from a %d-dimension std::vector",
286 tu.size()));
287 }
288 for (unsigned int i = 0; i < val_3; ++i) {
289 data[i] = tu[i];
290 }
291
292 return *this;
293}
294
298vpThetaUVector &vpThetaUVector::buildFrom(const double &tux, const double &tuy, const double &tuz)
299{
300 const unsigned int index_0 = 0;
301 const unsigned int index_1 = 1;
302 const unsigned int index_2 = 2;
303 data[index_0] = tux;
304 data[index_1] = tuy;
305 data[index_2] = tuz;
306 return *this;
307}
308
334{
335 for (unsigned int i = 0; i < dsize; ++i) {
336 data[i] = v;
337 }
338
339 return *this;
340}
341
369{
370 if (tu.size() != size()) {
371 throw(vpException(vpException::dimensionError, "Cannot set a theta-u vector from a %d-dimension col vector",
372 tu.size()));
373 }
374
375 unsigned int l_size = size();
376 for (unsigned int i = 0; i < l_size; ++i) {
377 data[i] = tu[i];
378 }
379
380 return *this;
381}
382
415void vpThetaUVector::extract(double &theta, vpColVector &u) const
416{
417 const unsigned int val_3 = 3;
418 u.resize(val_3);
419
420 theta = getTheta();
421 // --comment: if theta equals 0
422 if (std::fabs(theta) <= std::numeric_limits<double>::epsilon()) {
423 u = 0;
424 return;
425 }
426 for (unsigned int i = 0; i < val_3; ++i) {
427 u[i] = data[i] / theta;
428 }
429}
430
458{
459 const unsigned int index_0 = 0;
460 const unsigned int index_1 = 1;
461 const unsigned int index_2 = 2;
462 return sqrt((data[index_0] * data[index_0]) + (data[index_1] * data[index_1]) + (data[index_2] * data[index_2]));
463}
464
493{
494 vpColVector u(3);
495
496 double theta = getTheta();
497 // --comment: if theta equals 0
498 if (std::fabs(theta) <= std::numeric_limits<double>::epsilon()) {
499 u = 0;
500 return u;
501 }
502 const unsigned int val_3 = 3;
503 for (unsigned int i = 0; i < val_3; ++i) {
504 u[i] = data[i] / theta;
505 }
506 return u;
507}
508
514{
515 double a_2 = getTheta() / 2;
516 vpColVector a_hat = getU();
517 double b_2 = tu_b.getTheta() / 2;
518 vpColVector b_hat = tu_b.getU();
519
520 vpColVector a_hat_sin_2 = a_hat * std::sin(a_2);
521 vpColVector b_hat_sin_2 = b_hat * std::sin(b_2);
522 double c = 2 * std::acos((std::cos(a_2) * std::cos(b_2)) - (vpColVector::dotProd(a_hat_sin_2, b_hat_sin_2)));
523 vpColVector d = ((std::sin(a_2) * std::cos(b_2) * a_hat) + (std::cos(a_2) * std::sin(b_2) * b_hat)) +
524 (std::sin(a_2) * std::sin(b_2) * vpColVector::crossProd(a_hat, b_hat));
525 d = (c * d) / std::sin(c / 2.0);
526
527 return vpThetaUVector(d);
528}
529
530#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
552vpThetaUVector &vpThetaUVector::operator=(const std::initializer_list<double> &list)
553{
554 if (list.size() > size()) {
555 throw(vpException(
557 "Cannot set theta u vector out of bounds. It has only %d values while you try to initialize with %d values",
558 size(), list.size()));
559 }
560 std::copy(list.begin(), list.end(), data);
561 return *this;
562}
563#endif
564END_VISP_NAMESPACE
unsigned int dsize
Definition vpArray2D.h:1207
unsigned int size() const
Definition vpArray2D.h:435
Implementation of column vector and the associated operations.
static double dotProd(const vpColVector &a, const vpColVector &b)
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
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:289
static int sign(double x)
Definition vpMath.h:432
Implementation of a pose vector and operations on poses.
Implementation of a rotation vector as quaternion angle minimal representation.
Implementation of a rotation matrix and operations on such kind of matrices.
vpRotationVector()
Constructor that constructs a 0-size rotation vector.
Implementation of a rotation vector as Euler angle minimal representation.
Implementation of a rotation vector as Euler angle minimal representation.
Implementation of a rotation vector as Euler 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