Visual Servoing Platform  version 3.1.0
testRotation.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Tests transformation from various representations of rotation.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 
45 #include <visp3/core/vpMath.h>
46 #include <visp3/core/vpQuaternionVector.h>
47 #include <visp3/core/vpRotationMatrix.h>
48 #include <visp3/io/vpParseArgv.h>
49 
50 #include <cassert>
51 #include <limits>
52 #include <stdio.h>
53 #include <stdlib.h>
54 
55 static unsigned int cpt = 0;
56 
57 bool test(const std::string &s, const vpArray2D<double> &v, const std::vector<double> &bench)
58 {
59  std::cout << "** Test " << ++cpt << std::endl;
60  std::cout << s << "(" << v.getRows() << "," << v.getCols() << ") = [" << v << "]" << std::endl;
61  if (bench.size() != v.size()) {
62  std::cout << "Test fails: bad size wrt bench" << std::endl;
63  return false;
64  }
65  for (unsigned int i = 0; i < v.size(); i++) {
66  if (std::fabs(v.data[i] - bench[i]) > std::fabs(v.data[i]) * std::numeric_limits<double>::epsilon()) {
67  std::cout << "Test fails: bad content" << std::endl;
68  return false;
69  }
70  }
71 
72  return true;
73 }
74 
75 bool test(const std::string &s, const vpRotationVector &v, const double &bench)
76 {
77  std::cout << "** Test " << ++cpt << std::endl;
78  std::cout << s << "(" << v.getRows() << "," << v.getCols() << ") = [" << v << "]" << std::endl;
79  for (unsigned int i = 0; i < v.size(); i++) {
80  if (std::fabs(v[i] - bench) > std::fabs(v[i]) * std::numeric_limits<double>::epsilon()) {
81  std::cout << "Test fails: bad content" << std::endl;
82  return false;
83  }
84  }
85 
86  return true;
87 }
88 
89 int main()
90 {
91  try {
92  {
94  std::vector<double> bench1(3, vpMath::rad(10));
95  if (test("r1", r1, bench1) == false)
96  return EXIT_FAILURE;
97 
98  vpThetaUVector r2 = r1;
99  if (test("r2", r2, bench1) == false)
100  return EXIT_FAILURE;
101 
102  if (test("r2", r2, vpMath::rad(10)) == false)
103  return EXIT_FAILURE;
104 
105  vpThetaUVector r3;
106  r3 = vpMath::rad(10);
107  if (test("r3", r3, bench1) == false)
108  return EXIT_FAILURE;
109 
110  std::cout << "** Test " << ++cpt << std::endl;
111  for (unsigned int i = 0; i < r3.size(); i++) {
112  if (std::fabs(r3[i] - bench1[i]) > std::fabs(r3[i]) * std::numeric_limits<double>::epsilon()) {
113  std::cout << "Test fails: bad content" << std::endl;
114  return EXIT_FAILURE;
115  }
116  }
117 
118  vpColVector r4 = 0.5 * r1;
119  std::vector<double> bench2(3, vpMath::rad(5));
120  if (test("r4", r4, bench2) == false)
121  return EXIT_FAILURE;
122 
123  vpThetaUVector r5(r3);
124  if (test("r5", r5, bench1) == false)
125  return EXIT_FAILURE;
126  }
127  {
129  std::vector<double> bench1(3, vpMath::rad(10));
130  if (test("r1", r1, bench1) == false)
131  return EXIT_FAILURE;
132 
133  vpRxyzVector r2 = r1;
134  if (test("r2", r2, bench1) == false)
135  return EXIT_FAILURE;
136 
137  if (test("r2", r2, vpMath::rad(10)) == false)
138  return EXIT_FAILURE;
139 
140  vpRxyzVector r3;
141  r3 = vpMath::rad(10);
142  if (test("r3", r3, bench1) == false)
143  return EXIT_FAILURE;
144 
145  std::cout << "** Test " << ++cpt << std::endl;
146  for (unsigned int i = 0; i < r3.size(); i++) {
147  if (std::fabs(r3[i] - bench1[i]) > std::fabs(r3[i]) * std::numeric_limits<double>::epsilon()) {
148  std::cout << "Test fails: bad content" << std::endl;
149  return EXIT_FAILURE;
150  }
151  }
152 
153  vpColVector r4 = 0.5 * r1;
154  std::vector<double> bench2(3, vpMath::rad(5));
155  if (test("r4", r4, bench2) == false)
156  return EXIT_FAILURE;
157 
158  vpRxyzVector r5(r3);
159  if (test("r5", r5, bench1) == false)
160  return EXIT_FAILURE;
161  }
162  {
164  std::vector<double> bench1(3, vpMath::rad(10));
165  if (test("r1", r1, bench1) == false)
166  return EXIT_FAILURE;
167 
168  vpRzyxVector r2 = r1;
169  if (test("r2", r2, bench1) == false)
170  return EXIT_FAILURE;
171 
172  if (test("r2", r2, vpMath::rad(10)) == false)
173  return EXIT_FAILURE;
174 
175  vpRzyxVector r3;
176  r3 = vpMath::rad(10);
177  if (test("r3", r3, bench1) == false)
178  return EXIT_FAILURE;
179 
180  std::cout << "** Test " << ++cpt << std::endl;
181  for (unsigned int i = 0; i < r3.size(); i++) {
182  if (std::fabs(r3[i] - bench1[i]) > std::fabs(r3[i]) * std::numeric_limits<double>::epsilon()) {
183  std::cout << "Test fails: bad content" << std::endl;
184  return EXIT_FAILURE;
185  }
186  }
187 
188  vpColVector r4 = 0.5 * r1;
189  std::vector<double> bench2(3, vpMath::rad(5));
190  if (test("r4", r4, bench2) == false)
191  return EXIT_FAILURE;
192 
193  vpRzyxVector r5(r3);
194  if (test("r5", r5, bench1) == false)
195  return EXIT_FAILURE;
196  }
197  {
199  std::vector<double> bench1(3, vpMath::rad(10));
200  if (test("r1", r1, bench1) == false)
201  return EXIT_FAILURE;
202 
203  vpRzyzVector r2 = r1;
204  if (test("r2", r2, bench1) == false)
205  return EXIT_FAILURE;
206 
207  if (test("r2", r2, vpMath::rad(10)) == false)
208  return EXIT_FAILURE;
209 
210  vpRzyzVector r3;
211  r3 = vpMath::rad(10);
212  if (test("r3", r3, bench1) == false)
213  return EXIT_FAILURE;
214 
215  std::cout << "** Test " << ++cpt << std::endl;
216  for (unsigned int i = 0; i < r3.size(); i++) {
217  if (std::fabs(r3[i] - bench1[i]) > std::fabs(r3[i]) * std::numeric_limits<double>::epsilon()) {
218  std::cout << "Test fails: bad content" << std::endl;
219  return EXIT_FAILURE;
220  }
221  }
222 
223  vpColVector r4 = 0.5 * r1;
224  std::vector<double> bench2(3, vpMath::rad(5));
225  if (test("r4", r4, bench2) == false)
226  return EXIT_FAILURE;
227 
228  vpRzyzVector r5(r3);
229  if (test("r5", r5, bench1) == false)
230  return EXIT_FAILURE;
231  }
232  {
234  std::vector<double> bench1(4, vpMath::rad(10));
235  if (test("r1", r1, bench1) == false)
236  return EXIT_FAILURE;
237 
238  vpQuaternionVector r2 = r1;
239  if (test("r2", r2, bench1) == false)
240  return EXIT_FAILURE;
241 
242  if (test("r2", r2, vpMath::rad(10)) == false)
243  return EXIT_FAILURE;
244 
246  r3.set(vpMath::rad(10), vpMath::rad(10), vpMath::rad(10), vpMath::rad(10));
247  if (test("r3", r3, bench1) == false)
248  return EXIT_FAILURE;
249 
250  std::cout << "** Test " << ++cpt << std::endl;
251  for (unsigned int i = 0; i < r3.size(); i++) {
252  if (std::fabs(r3[i] - bench1[i]) > std::fabs(r3[i]) * std::numeric_limits<double>::epsilon()) {
253  std::cout << "Test fails: bad content" << std::endl;
254  return EXIT_FAILURE;
255  }
256  }
257 
258  vpColVector r4 = 0.5 * r1;
259  std::vector<double> bench2(4, vpMath::rad(5));
260  if (test("r4", r4, bench2) == false)
261  return EXIT_FAILURE;
262 
263  vpQuaternionVector r5(r3);
264  if (test("r5", r5, bench1) == false)
265  return EXIT_FAILURE;
266  }
267  {
269  for (int i = -10; i < 10; i++) {
270  for (int j = -10; j < 10; j++) {
271  vpThetaUVector tu(vpMath::rad(90 + i), vpMath::rad(170 + j), vpMath::rad(45));
272  tu.buildFrom(vpRotationMatrix(tu)); // put some coherence into rotation convention
273 
274  std::cout << "Initialization " << std::endl;
275 
276  double theta;
277  vpColVector u;
278  tu.extract(theta, u);
279 
280  std::cout << "theta=" << vpMath::deg(theta) << std::endl;
281  std::cout << "u=" << u << std::endl;
282 
283  std::cout << "From vpThetaUVector to vpRotationMatrix " << std::endl;
284  R.buildFrom(tu);
285 
286  std::cout << "Matrix R";
287  if (R.isARotationMatrix() == 1)
288  std::cout << " is a rotation matrix " << std::endl;
289  else
290  std::cout << " is not a rotation matrix " << std::endl;
291 
292  std::cout << R << std::endl;
293 
294  std::cout << "From vpRotationMatrix to vpQuaternionVector " << std::endl;
295  vpQuaternionVector q(R);
296  std::cout << q << std::endl;
297 
298  R.buildFrom(q);
299  std::cout << "From vpQuaternionVector to vpRotationMatrix " << std::endl;
300 
301  std::cout << "From vpRotationMatrix to vpRxyzVector " << std::endl;
302  vpRxyzVector RxyzBuildFromR(R);
303  std::cout << RxyzBuildFromR << std::endl;
304 
305  std::cout << "From vpRxyzVector to vpThetaUVector " << std::endl;
306  std::cout << " use From vpRxyzVector to vpRotationMatrix " << std::endl;
307  std::cout << " use From vpRotationMatrix to vpThetaUVector " << std::endl;
308 
309  vpThetaUVector tuBuildFromEu;
310  tuBuildFromEu.buildFrom(R);
311 
312  std::cout << std::endl;
313  std::cout << "result : should equivalent to the first one " << std::endl;
314 
315  double theta2;
316  vpColVector u2;
317 
318  tuBuildFromEu.extract(theta2, u2);
319  std::cout << "theta=" << vpMath::deg(theta2) << std::endl;
320  std::cout << "u=" << u2 << std::endl;
321 
322  assert(vpMath::abs(theta2 - theta) < std::numeric_limits<double>::epsilon() * 1e10);
323  assert(vpMath::abs(u[0] - u2[0]) < std::numeric_limits<double>::epsilon() * 1e10);
324  assert(vpMath::abs(u[1] - u2[1]) < std::numeric_limits<double>::epsilon() * 1e10);
325  assert(vpMath::abs(u[2] - u2[2]) < std::numeric_limits<double>::epsilon() * 1e10);
326  }
327  vpRzyzVector rzyz(vpMath::rad(180), vpMath::rad(120), vpMath::rad(45));
328  std::cout << "Initialization vpRzyzVector " << std::endl;
329  std::cout << rzyz << std::endl;
330  std::cout << "From vpRzyzVector to vpRotationMatrix " << std::endl;
331  R.buildFrom(rzyz);
332  std::cout << "From vpRotationMatrix to vpRzyzVector " << std::endl;
333  vpRzyzVector rzyz_final;
334  rzyz_final.buildFrom(R);
335  std::cout << rzyz_final << std::endl;
336 
337  vpRzyxVector rzyx(vpMath::rad(180), vpMath::rad(120), vpMath::rad(45));
338  std::cout << "Initialization vpRzyxVector " << std::endl;
339  std::cout << rzyx << std::endl;
340  std::cout << "From vpRzyxVector to vpRotationMatrix " << std::endl;
341  R.buildFrom(rzyx);
342  std::cout << R << std::endl;
343  std::cout << "From vpRotationMatrix to vpRzyxVector " << std::endl;
344  vpRzyxVector rzyx_final;
345  rzyx_final.buildFrom(R);
346  std::cout << rzyx_final << std::endl;
347  }
348  }
349  std::cout << "All tests succeed" << std::endl;
350  return EXIT_SUCCESS;
351  } catch (vpException &e) {
352  std::cout << "Catch an exception: " << e << std::endl;
353  return EXIT_FAILURE;
354  }
355 }
Implementation of a generic rotation vector.
void set(const double x, const double y, const double z, const double w)
void extract(double &theta, vpColVector &u) const
vpColVector extract(unsigned int r, unsigned int colsize) const
Definition: vpColVector.h:158
vpRzyzVector buildFrom(const vpRotationMatrix &R)
error that can be emited by ViSP classes.
Definition: vpException.h:71
unsigned int getRows() const
Definition: vpArray2D.h:156
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:158
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRzyxVector.h:158
vpThetaUVector buildFrom(const vpHomogeneousMatrix &M)
static Type abs(const Type &x)
Definition: vpMath.h:152
Implementation of a rotation matrix and operations on such kind of matrices.
unsigned int getCols() const
Definition: vpArray2D.h:146
vpRotationMatrix buildFrom(const vpHomogeneousMatrix &M)
Implementation of a rotation vector as quaternion angle minimal representation.
vpRzyxVector buildFrom(const vpRotationMatrix &R)
static double rad(double deg)
Definition: vpMath.h:102
static double deg(double rad)
Definition: vpMath.h:95
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRxyzVector.h:156
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRzyzVector.h:154
Implementation of a rotation vector as axis-angle minimal representation.
bool isARotationMatrix() const