39 #include <visp3/core/vpConfig.h>
41 #if defined(VISP_HAVE_CATCH2)
43 #include <visp3/core/vpThetaUVector.h>
44 #include <visp3/core/vpUniRand.h>
46 #include <catch_amalgamated.hpp>
48 #ifdef ENABLE_VISP_NAMESPACE
64 const double ctheta = std::cos(angle);
65 const double stheta = std::sin(angle);
66 const double ax = rng.
uniform(-1.0, 1.0);
67 const double ay = rng.
uniform(-1.0, 1.0);
68 const double az = rng.
uniform(-1.0, 1.0);
74 bool test(
const std::string &s,
const vpArray2D<double> &v,
const std::vector<double> &bench)
76 std::cout << s <<
"(" << v.
getRows() <<
"," << v.
getCols() <<
") = [" << v <<
"]" << std::endl;
77 if (bench.size() != v.
size()) {
78 std::cout <<
"Test fails: bad size wrt bench" << std::endl;
81 for (
unsigned int i = 0; i < v.
size(); i++) {
82 if (std::fabs(v.
data[i] - bench[i]) > std::fabs(v.
data[i]) * std::numeric_limits<double>::epsilon()) {
83 std::cout <<
"Test fails: bad content" << std::endl;
93 std::cout << s <<
"(" << v.
getRows() <<
"," << v.
getCols() <<
") = [" << v <<
"]" << std::endl;
95 std::cout <<
"Test fails: bad size wrt bench" << std::endl;
98 for (
unsigned int i = 0; i < v.
size(); i++) {
99 if (std::fabs(v.
data[i] - bench[i]) > std::fabs(v.
data[i]) * std::numeric_limits<double>::epsilon()) {
100 std::cout <<
"Test fails: bad content" << std::endl;
108 bool test(
const std::string &s,
const vpRotationVector &v,
const double &bench)
110 std::cout << s <<
"(" << v.
getRows() <<
"," << v.
getCols() <<
") = [" << v <<
"]" << std::endl;
111 for (
unsigned int i = 0; i < v.
size(); i++) {
112 if (std::fabs(v[i] - bench) > std::fabs(v[i]) * std::numeric_limits<double>::epsilon()) {
113 std::cout <<
"Test fails: bad content" << std::endl;
123 for (
unsigned int i = 0; i < 4; i++) {
124 for (
unsigned int j = 0; j < 4; j++) {
133 TEST_CASE(
"Common rotation operations",
"[rotation]")
135 SECTION(
"Theta u initialization")
140 CHECK(test(
"r1", r1, bench1));
143 bench1 = r1.toStdVector();
144 CHECK(test(
"r1", r1, bench1));
146 r1.buildFrom(bench3);
147 CHECK(test(
"r1", r1, bench3));
150 CHECK(test(
"r2", r2, bench1));
151 CHECK(r2.
data != r1.data);
157 CHECK(test(
"r3", r3, bench1));
159 for (
unsigned int i = 0; i < r3.
size(); i++) {
160 CHECK(std::fabs(r3[i] - bench1[i]) < std::fabs(r3[i]) * std::numeric_limits<double>::epsilon());
165 CHECK(test(
"r4", r4, bench2));
168 CHECK(test(
"r5", r5, bench1));
170 SECTION(
"Rxyz initialization")
175 CHECK(test(
"r1", r1, bench1));
178 bench1 = r1.toStdVector();
179 CHECK(test(
"r1", r1, bench1));
181 r1.buildFrom(bench3);
182 CHECK(test(
"r1", r1, bench3));
185 CHECK(test(
"r2", r2, bench1));
191 CHECK(test(
"r3", r3, bench1));
193 for (
unsigned int i = 0; i < r3.
size(); i++) {
194 CHECK(std::fabs(r3[i] - bench1[i]) <= std::fabs(r3[i]) * std::numeric_limits<double>::epsilon());
199 CHECK(test(
"r4", r4, bench2));
202 CHECK(test(
"r5", r5, bench1));
204 SECTION(
"rzyx initialization")
209 CHECK(test(
"r1", r1, bench1));
212 bench1 = r1.toStdVector();
213 CHECK(test(
"r1", r1, bench1));
215 r1.buildFrom(bench3);
216 CHECK(test(
"r1", r1, bench3));
219 CHECK(test(
"r2", r2, bench1));
225 CHECK(test(
"r3", r3, bench1));
227 for (
unsigned int i = 0; i < r3.
size(); i++) {
228 CHECK(std::fabs(r3[i] - bench1[i]) <= std::fabs(r3[i]) * std::numeric_limits<double>::epsilon());
233 CHECK(test(
"r4", r4, bench2));
236 CHECK(test(
"r5", r5, bench1));
238 SECTION(
"rzyz initialiation")
243 CHECK(test(
"r1", r1, bench1));
246 bench1 = r1.toStdVector();
247 CHECK(test(
"r1", r1, bench1));
249 r1.buildFrom(bench3);
250 CHECK(test(
"r1", r1, bench3));
253 CHECK(test(
"r2", r2, bench1));
259 CHECK(test(
"r3", r3, bench1));
261 for (
unsigned int i = 0; i < r3.
size(); i++) {
262 CHECK(std::fabs(r3[i] - bench1[i]) <= std::fabs(r3[i]) * std::numeric_limits<double>::epsilon());
267 CHECK(test(
"r4", r4, bench2));
270 CHECK(test(
"r5", r5, bench1));
272 SECTION(
"Test quaternion initialization",
"[quaternion]")
277 CHECK(test(
"r1", r1, bench1));
280 bench1 = r1.toStdVector();
281 CHECK(test(
"r1", r1, bench1));
283 r1.buildFrom(bench3);
284 CHECK(test(
"r1", r1, bench3));
287 CHECK(test(
"r2", r2, bench1));
293 CHECK(test(
"r3", r3, bench1));
295 for (
unsigned int i = 0; i < r3.
size(); i++) {
296 CHECK(std::fabs(r3[i] - bench1[i]) <= std::fabs(r3[i]) * std::numeric_limits<double>::epsilon());
301 CHECK(test(
"r4", r4, bench2));
304 CHECK(test(
"r5", r5, bench1));
306 SECTION(
"Conversions")
309 for (
int i = -10; i < 10; i++) {
310 for (
int j = -10; j < 10; j++) {
314 std::cout <<
"Initialization " << std::endl;
320 std::cout <<
"theta=" <<
vpMath::deg(theta) << std::endl;
321 std::cout <<
"u=" << u << std::endl;
323 std::cout <<
"From vpThetaUVector to vpRotationMatrix " << std::endl;
326 std::cout <<
"Matrix R";
329 std::cout << R << std::endl;
331 std::cout <<
"From vpRotationMatrix to vpQuaternionVector " << std::endl;
333 CHECK(q.magnitude() == Catch::Approx(1.0).margin(1e-4));
334 std::cout << q << std::endl;
338 std::cout <<
"From vpQuaternionVector to vpRotationMatrix " << std::endl;
340 std::cout <<
"From vpRotationMatrix to vpRxyzVector " << std::endl;
342 std::cout << RxyzbuildR << std::endl;
344 std::cout <<
"From vpRxyzVector to vpThetaUVector " << std::endl;
345 std::cout <<
" use From vpRxyzVector to vpRotationMatrix " << std::endl;
346 std::cout <<
" use From vpRotationMatrix to vpThetaUVector " << std::endl;
351 std::cout << std::endl;
352 std::cout <<
"result : should equivalent to the first one " << std::endl;
358 std::cout <<
"theta=" <<
vpMath::deg(theta2) << std::endl;
359 std::cout <<
"u=" << u2 << std::endl;
361 CHECK(
vpMath::abs(theta2 - theta) < std::numeric_limits<double>::epsilon() * 1e10);
362 CHECK(
vpMath::abs(u[0] - u2[0]) < std::numeric_limits<double>::epsilon() * 1e10);
363 CHECK(
vpMath::abs(u[1] - u2[1]) < std::numeric_limits<double>::epsilon() * 1e10);
364 CHECK(
vpMath::abs(u[2] - u2[2]) < std::numeric_limits<double>::epsilon() * 1e10);
367 SECTION(
"Conversion from and to rzyz vector")
370 std::cout <<
"Initialization vpRzyzVector " << std::endl;
371 std::cout << rzyz << std::endl;
372 std::cout <<
"From vpRzyzVector to vpRotationMatrix " << std::endl;
375 std::cout <<
"From vpRotationMatrix to vpRzyzVector " << std::endl;
378 CHECK(test(
"rzyz", rzyz_final,
vpColVector(rzyz)));
379 std::cout << rzyz_final << std::endl;
381 SECTION(
"Conversion from and to rzyx vector")
384 std::cout <<
"Initialization vpRzyxVector " << std::endl;
385 std::cout << rzyx << std::endl;
386 std::cout <<
"From vpRzyxVector to vpRotationMatrix " << std::endl;
389 std::cout << R << std::endl;
390 std::cout <<
"From vpRotationMatrix to vpRzyxVector " << std::endl;
393 bool ret = test(
"rzyx", rzyx_final,
vpColVector(rzyx));
396 std::cout <<
"Rzyx vector differ. Test rotation matrix..." << std::endl;
399 std::cout <<
"Rzyx vector differ but rotation matrix is valid" << std::endl;
404 std::cout << rzyx_final << std::endl;
407 SECTION(
"Rotation matrix extraction from homogeneous matrix and multiplication")
411 _1_M_2_truth[0][0] = 0.9835;
412 _1_M_2_truth[0][1] = -0.0581;
413 _1_M_2_truth[0][2] = 0.1716;
414 _1_M_2_truth[0][3] = 0;
415 _1_M_2_truth[1][0] = -0.0489;
416 _1_M_2_truth[1][1] = -0.9972;
417 _1_M_2_truth[1][2] = -0.0571;
418 _1_M_2_truth[1][3] = 0;
419 _1_M_2_truth[2][0] = 0.1744;
420 _1_M_2_truth[2][1] = 0.0478;
421 _1_M_2_truth[2][2] = -0.9835;
422 _1_M_2_truth[2][3] = 0;
424 _2_M_3_[0][0] = 0.9835;
425 _2_M_3_[0][1] = -0.0581;
426 _2_M_3_[0][2] = 0.1716;
427 _2_M_3_[0][3] = 0.0072;
428 _2_M_3_[1][0] = -0.0489;
429 _2_M_3_[1][1] = -0.9972;
430 _2_M_3_[1][2] = -0.0571;
431 _2_M_3_[1][3] = 0.0352;
432 _2_M_3_[2][0] = 0.1744;
433 _2_M_3_[2][1] = 0.0478;
434 _2_M_3_[2][2] = -0.9835;
435 _2_M_3_[2][3] = 0.9470;
440 CHECK(test_matrix_equal(_1_M_3_, _1_M_3_truth));
444 TEST_CASE(
"Theta u multiplication",
"[theta.u]")
446 const int nTrials = 100;
447 const uint64_t seed = 0x123456789;
449 for (
int iter = 0; iter < nTrials; iter++) {
461 const double tolerance = 1e-9;
462 for (
unsigned int i = 0; i < 3; i++) {
463 for (
unsigned int j = 0; j < 3; j++) {
464 CHECK(c1Rc3_ref[i][j] == Catch::Approx(c1Rc3[i][j]).epsilon(0).margin(tolerance));
470 TEST_CASE(
"Quaternion multiplication",
"[quaternion]")
472 const int nTrials = 100;
473 const uint64_t seed = 0x123456789;
475 for (
int iter = 0; iter < nTrials; iter++) {
488 const double tolerance = 1e-9;
489 for (
unsigned int i = 0; i < 3; i++) {
490 for (
unsigned int j = 0; j < 3; j++) {
491 CHECK(c1Rc3_ref[i][j] == Catch::Approx(c1Rc3[i][j]).epsilon(0).margin(tolerance));
497 int main(
int argc,
char *argv[])
499 Catch::Session session;
500 session.applyCommandLine(argc, argv);
501 int numFailed = session.run();
507 int main() {
return EXIT_SUCCESS; }
unsigned int getCols() const
Type * data
Address of the first element of the data array.
unsigned int size() const
Return the number of elements of the 2D array.
unsigned int getRows() const
Implementation of column vector and the associated operations.
vpColVector extract(unsigned int r, unsigned int colsize) const
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
static double rad(double deg)
static Type abs(const Type &x)
static bool equal(double x, double y, double threshold=0.001)
static double deg(double rad)
Implementation of a rotation vector as quaternion angle minimal representation.
void set(double x, double y, double z, double w)
Implementation of a rotation matrix and operations on such kind of matrices.
bool isARotationMatrix(double threshold=1e-6) const
vpRotationMatrix & buildFrom(const vpHomogeneousMatrix &M)
Implementation of a generic rotation vector.
Implementation of a rotation vector as Euler angle minimal representation.
Implementation of a rotation vector as Euler angle minimal representation.
vpRzyxVector & buildFrom(const vpRotationMatrix &R)
Implementation of a rotation vector as Euler angle minimal representation.
vpRzyzVector & buildFrom(const vpRotationMatrix &R)
Implementation of a rotation vector as axis-angle minimal representation.
void extract(double &theta, vpColVector &u) const
vpThetaUVector & buildFrom(const vpHomogeneousMatrix &M)
Class for generating random numbers with uniform probability density.
int uniform(int a, int b)