Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
testHomogeneousMatrix.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  * Test some vpHomogeneousMatrix functionalities.
32  */
33 
39 #include <visp3/core/vpConfig.h>
40 
41 #ifdef VISP_HAVE_CATCH2
42 #include <visp3/core/vpHomogeneousMatrix.h>
43 
44 #define CATCH_CONFIG_RUNNER
45 #include <catch.hpp>
46 
47 #ifdef ENABLE_VISP_NAMESPACE
48 using namespace VISP_NAMESPACE_NAME;
49 #endif
50 
51 bool test_matrix_equal(const vpHomogeneousMatrix &M1, const vpHomogeneousMatrix &M2, double epsilon = 1e-10)
52 {
53  for (unsigned int i = 0; i < 4; i++) {
54  for (unsigned int j = 0; j < 4; j++) {
55  if (!vpMath::equal(M1[i][j], M2[i][j], epsilon)) {
56  return false;
57  }
58  }
59  }
60  return true;
61 }
62 
63 TEST_CASE("vpHomogeneousMatrix re-orthogonalize rotation matrix", "[vpHomogeneousMatrix]")
64 {
65  CHECK_NOTHROW([]() {
66  vpHomogeneousMatrix M { 0.9835, -0.0581, 0.1716, 0.0072, -0.0489, -0.9972,
67  -0.0571, 0.0352, 0.1744, 0.0478, -0.9835, 0.9470 };
68  }());
69 
70  SECTION("check re-orthogonalize rotation part")
71  {
72  vpHomogeneousMatrix M1 { 0.9835, -0.0581, 0.1716, 0.0072, -0.0489, -0.9972,
73  -0.0571, 0.0352, 0.1744, 0.0478, -0.9835, 0.9470 };
74 
76  M2[0][0] = 0.9835;
77  M2[0][1] = -0.0581;
78  M2[0][2] = 0.1716;
79  M2[0][3] = 0.0072;
80  M2[1][0] = -0.0489;
81  M2[1][1] = -0.9972;
82  M2[1][2] = -0.0571;
83  M2[1][3] = 0.0352;
84  M2[2][0] = 0.1744;
85  M2[2][1] = 0.0478;
86  M2[2][2] = -0.9835;
87  M2[2][3] = 0.9470;
89 
90  for (unsigned int i = 0; i < 4; i++) {
91  for (unsigned int j = 0; j < 4; j++) {
92  CHECK(M1[i][j] == Approx(M2[i][j]).margin(std::numeric_limits<double>::epsilon()));
93  }
94  }
95  }
96 
97  CHECK_NOTHROW([]() {
98  vpHomogeneousMatrix M { 0.9835, -0.0581, 0.1716, 0.0072, -0.0937, -0.9738,
99  0.2072, 0.0481, 0.1551, -0.2199, -0.9631, 0.9583 };
100 
101  std::cout << "Original data:" << std::endl;
102  std::cout << "0.9835 -0.0581 0.1716 0.0072" << std::endl;
103  std::cout << " -0.0937 -0.9738 0.2072 0.0481" << std::endl;
104  std::cout << "0.1551 -0.2199 -0.9631 0.9583" << std::endl;
105  std::cout << "0 0 0 1" << std::endl;
106  std::cout << "M after rotation re-orthogonalization:\n" << M << std::endl;
107  }());
108 
109  CHECK_NOTHROW([]() {
110  vpHomogeneousMatrix M1 { 0.9835, -0.0581, 0.1716, 0.0072, -0.0937, -0.9738,
111  0.2072, 0.0481, 0.1551, -0.2199, -0.9631, 0.9583 };
112 
113  // following R init should not throw an exception
114  vpRotationMatrix R { M1[0][0], M1[0][1], M1[0][2], M1[1][0], M1[1][1], M1[1][2], M1[2][0], M1[2][1], M1[2][2] };
115  }());
116 
117  CHECK_THROWS([]() {
118  vpHomogeneousMatrix M { 0.983, -0.058, 0.171, 0.0072, -0.093, -0.973, 0.207, 0.0481, 0.155, -0.219, -0.963, 0.9583 };
119  }());
120 }
121 
122 TEST_CASE("vpRotationMatrix re-orthogonalize rotation matrix", "[vpRotationMatrix]")
123 {
124  CHECK_NOTHROW(
125  []() { vpRotationMatrix R { 0.9835, -0.0581, 0.1716, -0.0489, -0.9972, -0.0571, 0.1744, 0.0478, -0.9835 }; }());
126 
127  CHECK_NOTHROW([]() {
128  vpRotationMatrix R { 0.9835, -0.0581, 0.1716, -0.0937, -0.9738, 0.2072, 0.1551, -0.2199, -0.9631 };
129 
130  std::cout << "Original data:" << std::endl;
131  std::cout << "0.9835 -0.0581 0.1716" << std::endl;
132  std::cout << " -0.0937 -0.9738 0.2072" << std::endl;
133  std::cout << "0.1551 -0.2199 -0.9631" << std::endl;
134  std::cout << "R after rotation re-orthogonalization:\n" << R << std::endl;
135  }());
136 
137  CHECK_NOTHROW([]() {
138  vpRotationMatrix R {
139  0.46682, -0.74434, 0.47754, -0.83228, -0.55233, -0.04733, 0.29899, -0.37535, -0.87734,
140  };
141 
142  std::cout << "Original data:" << std::endl;
143  std::cout << "0.46682, -0.74434, 0.47754" << std::endl;
144  std::cout << "-0.83228, -0.55233, -0.04733" << std::endl;
145  std::cout << "0.29899, -0.37535, -0.87734" << std::endl;
146  std::cout << "R after rotation re-orthogonalization:\n" << R << std::endl;
147  }());
148 
149  CHECK_NOTHROW([]() {
151  R = {
152  0.46682, -0.74434, 0.47754, -0.83228, -0.55233, -0.04733, 0.29899, -0.37535, -0.87734,
153  };
154 
155  std::cout << "Original data:" << std::endl;
156  std::cout << "0.46682, -0.74434, 0.47754" << std::endl;
157  std::cout << "-0.83228, -0.55233, -0.04733" << std::endl;
158  std::cout << "0.29899, -0.37535, -0.87734" << std::endl;
159  std::cout << "R after rotation re-orthogonalization:\n" << R << std::endl;
160  }());
161 
162  CHECK_THROWS([]() { vpRotationMatrix R { 0.983, -0.058, 0.171, -0.093, -0.973, 0.207, 0.155, -0.219, -0.963 }; }());
163 }
164 
165 TEST_CASE("ENU to NED conversion", "[enu2ned]")
166 {
167  vpHomogeneousMatrix enu_M_flu { 0, -1, 0, 0.2, 1, 0, 0, 1., 0, 0, 1, 0.3 };
168  std::cout << "enu_M_flu:\n" << enu_M_flu << std::endl;
169 
170  vpHomogeneousMatrix enu_M_ned { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0 };
171  std::cout << "enu_M_ned:\n" << enu_M_ned << std::endl;
172 
173  vpHomogeneousMatrix flu_M_frd { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0 };
174  std::cout << "flu_M_frd:\n" << flu_M_frd << std::endl;
175 
176  vpHomogeneousMatrix enu_M_frd = enu_M_flu * flu_M_frd;
177 
178  // Test1
179  {
180  vpHomogeneousMatrix ned_M_frd = enu_M_ned.inverse() * enu_M_flu * flu_M_frd;
181  std::cout << "ned_M_frd:\n" << ned_M_frd << std::endl;
182 
183  vpHomogeneousMatrix ned_M_frd_est = vpMath::enu2ned(enu_M_frd);
184  std::cout << "ned_M_frd_est:\n" << ned_M_frd_est << std::endl;
185 
186  bool success = test_matrix_equal(ned_M_frd, ned_M_frd_est);
187  std::cout << "Test enu2ned 1 " << (success ? "succeed" : "failed") << std::endl;
188 
189  CHECK(success);
190  }
191  // Test2
192  {
193  vpHomogeneousMatrix ned_M_flu = enu_M_ned.inverse() * enu_M_flu;
194  std::cout << "ned_M_flu:\n" << ned_M_flu << std::endl;
195 
196  vpHomogeneousMatrix ned_M_flu_est = vpMath::enu2ned(enu_M_flu);
197  std::cout << "ned_M_flu_est:\n" << ned_M_flu_est << std::endl;
198 
199  bool success = test_matrix_equal(ned_M_flu, ned_M_flu_est);
200  std::cout << "Test enu2ned 2 " << (success ? "succeed" : "failed") << std::endl;
201 
202  CHECK(success);
203  }
204 }
205 
206 TEST_CASE("vpHomogenousMatrix * vpRotationMatrix", "[operator*]")
207 {
208  // Test rotation_matrix * homogeneous_matrix
209  vpHomogeneousMatrix _1_M_2_ {
210  0.9835, -0.0581, 0.1716, 0.0072,
211  -0.0489, -0.9972, -0.0571, 0.0352,
212  0.1744, 0.0478, -0.9835, 0.9470
213  };
214  vpHomogeneousMatrix _2_M_3_truth {
215  0.9835, -0.0581, 0.1716, 0,
216  -0.0489, -0.9972, -0.0571, 0,
217  0.1744, 0.0478, -0.9835, 0
218  };
219 
220  vpRotationMatrix _2_R_3_ = _2_M_3_truth.getRotationMatrix();
221  vpHomogeneousMatrix _1_M_3_(_1_M_2_* _2_R_3_);
222  vpHomogeneousMatrix _1_M_3_truth(_1_M_2_ * _2_M_3_truth);
223  bool success = test_matrix_equal(_1_M_3_, _1_M_3_truth);
224  std::cout << "Test vpHomogeneousMatrix vpHomogeneousMatrix::operator*(vpRotationMatrix) " << (success ? "succeed" : "failed") << std::endl;
225  CHECK(success);
226 }
227 
228 int main(int argc, char *argv[])
229 {
230  Catch::Session session; // There must be exactly one instance
231 
232  // Let Catch (using Clara) parse the command line
233  session.applyCommandLine(argc, argv);
234 
235  int numFailed = session.run();
236 
237  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
238  // This clamping has already been applied, so just return it here
239  // You can also do any post run clean-up here
240  return numFailed;
241 }
242 #else
243 #include <iostream>
244 
245 int main() { return EXIT_SUCCESS; }
246 #endif
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:458
static vpHomogeneousMatrix enu2ned(const vpHomogeneousMatrix &enu_M)
Definition: vpMath.cpp:763
Implementation of a rotation matrix and operations on such kind of matrices.