Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
catchGenericTrackerDeterminist.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  * Check that MBT is deterministic.
32  */
33 
38 #include <visp3/core/vpConfig.h>
39 
40 #if defined(VISP_HAVE_CATCH2) && defined(VISP_HAVE_THREADS)
41 
42 #include <catch_amalgamated.hpp>
43 
44 #include <future>
45 #include <thread>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/io/vpImageIo.h>
48 #include <visp3/mbt/vpMbGenericTracker.h>
49 
50 // #define DEBUG_DISPLAY // uncomment to check that the tracking is correct
51 #ifdef DEBUG_DISPLAY
52 #include <visp3/gui/vpDisplayX.h>
53 #endif
54 
55 #ifdef ENABLE_VISP_NAMESPACE
56 using namespace VISP_NAMESPACE_NAME;
57 #endif
58 
59 namespace
60 {
61 bool read_data(int cpt, vpImage<unsigned char> &I)
62 {
63 #if VISP_HAVE_DATASET_VERSION >= 0x030600
64  std::string ext("png");
65 #else
66  std::string ext("pgm");
67 #endif
68  const std::string env_ipath = vpIoTools::getViSPImagesDataPath();
69  const std::string ipath = vpIoTools::createFilePath(env_ipath, "mbt/cube/image%04d." + ext);
70 
71  char buffer[FILENAME_MAX];
72  snprintf(buffer, FILENAME_MAX, ipath.c_str(), cpt);
73  std::string image_filename = buffer;
74 
75  if (!vpIoTools::checkFilename(image_filename)) {
76  return false;
77  }
78 
79  vpImageIo::read(I, image_filename);
80  return true;
81 }
82 
83 void checkPoses(const vpHomogeneousMatrix &cMo1, const vpHomogeneousMatrix &cMo2)
84 {
85  for (unsigned int i = 0; i < 3; i++) {
86  for (unsigned int j = 0; j < 4; j++) {
87  CHECK(cMo1[i][j] == Catch::Approx(cMo2[i][j]).epsilon(std::numeric_limits<double>::epsilon()));
88  }
89  }
90 }
91 
92 void configureTracker(vpMbGenericTracker &tracker, vpCameraParameters &cam)
93 {
94  const std::string env_ipath = vpIoTools::getViSPImagesDataPath();
95  const std::string configFile = vpIoTools::createFilePath(env_ipath, "mbt/cube.xml");
96  const std::string modelFile = vpIoTools::createFilePath(env_ipath, "mbt/cube_and_cylinder.cao");
97 #if defined(VISP_HAVE_PUGIXML)
98  const bool verbose = false;
99  tracker.loadConfigFile(configFile, verbose);
100 #else
101  // Corresponding parameters manually set to have an example code
102  // By setting the parameters:
103  cam.initPersProjWithoutDistortion(547, 542, 338, 234);
104 
105  vpMe me;
106  me.setMaskSize(5);
107  me.setMaskNumber(180);
108  me.setRange(7);
110  me.setThreshold(5);
111  me.setMu1(0.5);
112  me.setMu2(0.5);
113  me.setSampleStep(4);
114 
115  vpKltOpencv klt;
116  klt.setMaxFeatures(300);
117  klt.setWindowSize(5);
118  klt.setQuality(0.01);
119  klt.setMinDistance(5);
120  klt.setHarrisFreeParameter(0.01);
121  klt.setBlockSize(3);
122  klt.setPyramidLevels(3);
123 
124  tracker.setCameraParameters(cam);
125  tracker.setMovingEdge(me);
126  tracker.setKltOpencv(klt);
127  tracker.setKltMaskBorder(5);
128  tracker.setAngleAppear(vpMath::rad(65));
129  tracker.setAngleDisappear(vpMath::rad(75));
130 
131  // Specify the clipping to
132  tracker.setNearClippingDistance(0.01);
133  tracker.setFarClippingDistance(0.90);
135  // tracker.setClipping(tracker.getClipping() | vpMbtPolygon::LEFT_CLIPPING |
136  // vpMbtPolygon::RIGHT_CLIPPING | vpMbtPolygon::UP_CLIPPING |
137  // vpMbtPolygon::DOWN_CLIPPING); // Equivalent to FOV_CLIPPING
138 #endif
139  tracker.getCameraParameters(cam);
140  tracker.loadModel(modelFile);
141  tracker.setDisplayFeatures(true);
142 
143  const vpPoseVector initPose(0.02231950571, 0.1071368004, 0.5071128378, 2.100485509, 1.146812236, -0.4560126437);
145  read_data(0, I);
146  tracker.initFromPose(I, vpHomogeneousMatrix(initPose));
147 }
148 } // anonymous namespace
149 
150 TEST_CASE("Check MBT determinism sequential", "[MBT_determinism]")
151 {
152  // First tracker
153  vpMbGenericTracker tracker1;
154  vpCameraParameters cam;
155  configureTracker(tracker1, cam);
156 
158  read_data(0, I);
159 #ifdef DEBUG_DISPLAY
160  vpDisplayX d(I);
161 #endif
162 
163  vpHomogeneousMatrix cMo1;
164  for (int cpt = 0; read_data(cpt, I); cpt++) {
165  tracker1.track(I);
166  tracker1.getPose(cMo1);
167 
168 #ifdef DEBUG_DISPLAY
170  tracker1.display(I, cMo1, cam, vpColor::red, 3);
171  vpDisplay::displayFrame(I, cMo1, cam, 0.05, vpColor::none, 3);
172  vpDisplay::flush(I);
173 #endif
174  }
175  std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
176 
177  // Second tracker
178  vpMbGenericTracker tracker2;
179  configureTracker(tracker2, cam);
180  vpHomogeneousMatrix cMo2;
181  for (int cpt = 0; read_data(cpt, I); cpt++) {
182  tracker2.track(I);
183  tracker2.getPose(cMo2);
184 
185 #ifdef DEBUG_DISPLAY
187  tracker2.display(I, cMo2, cam, vpColor::red, 3);
188  vpDisplay::displayFrame(I, cMo2, cam, 0.05, vpColor::none, 3);
189  vpDisplay::flush(I);
190 #endif
191  }
192  std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
193 
194  // Check that both poses are identical
195  checkPoses(cMo1, cMo2);
196 }
197 
198 TEST_CASE("Check MBT determinism parallel", "[MBT_determinism]")
199 {
200  // First tracker
201  std::future<vpHomogeneousMatrix> res_cMo1 = std::async(std::launch::async, []() {
202  vpMbGenericTracker tracker1;
203  vpCameraParameters cam;
204  configureTracker(tracker1, cam);
205 
207  vpHomogeneousMatrix cMo1;
208  for (int cpt = 0; read_data(cpt, I); cpt++) {
209  tracker1.track(I);
210  tracker1.getPose(cMo1);
211  }
212  return cMo1;
213  });
214 
215  // Second tracker
216  std::future<vpHomogeneousMatrix> res_cMo2 = std::async(std::launch::async, []() {
217  vpMbGenericTracker tracker2;
218  vpCameraParameters cam;
219  configureTracker(tracker2, cam);
220 
222  vpHomogeneousMatrix cMo2;
223  for (int cpt = 0; read_data(cpt, I); cpt++) {
224  tracker2.track(I);
225  tracker2.getPose(cMo2);
226  }
227  return cMo2;
228  });
229 
230  vpHomogeneousMatrix cMo1 = res_cMo1.get();
231  vpHomogeneousMatrix cMo2 = res_cMo2.get();
232  std::cout << "Run both trackers in separate threads" << std::endl;
233  std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
234  std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
235 
236  // Check that both poses are identical
237  checkPoses(cMo1, cMo2);
238 }
239 
240 TEST_CASE("Check Stereo MBT determinism parallel", "[MBT_determinism]")
241 {
242  // First tracker
243  std::future<vpHomogeneousMatrix> res_cMo1 = std::async(std::launch::async, []() {
244  vpMbGenericTracker tracker1(2);
245  vpCameraParameters cam;
246  configureTracker(tracker1, cam);
247 
249  vpHomogeneousMatrix cMo1;
250  for (int cpt = 0; read_data(cpt, I); cpt++) {
251  tracker1.track(I, I);
252  tracker1.getPose(cMo1);
253  }
254  return cMo1;
255  });
256 
257  // Second tracker
258  std::future<vpHomogeneousMatrix> res_cMo2 = std::async(std::launch::async, []() {
259  vpMbGenericTracker tracker2(2);
260  vpCameraParameters cam;
261  configureTracker(tracker2, cam);
262 
264  vpHomogeneousMatrix cMo2;
265  for (int cpt = 0; read_data(cpt, I); cpt++) {
266  tracker2.track(I, I);
267  tracker2.getPose(cMo2);
268  }
269  return cMo2;
270  });
271 
272  vpHomogeneousMatrix cMo1 = res_cMo1.get();
273  vpHomogeneousMatrix cMo2 = res_cMo2.get();
274  std::cout << "Run both stereo trackers in separate threads" << std::endl;
275  std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
276  std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
277 
278  // Check that both poses are identical
279  checkPoses(cMo1, cMo2);
280 }
281 
282 int main(int argc, char *argv[])
283 {
284  Catch::Session session;
285  session.applyCommandLine(argc, argv);
286  int numFailed = session.run();
287  return numFailed;
288 }
289 
290 #else
291 #include <iostream>
292 
293 int main() { return EXIT_SUCCESS; }
294 #endif
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
static const vpColor red
Definition: vpColor.h:217
static const vpColor none
Definition: vpColor.h:229
static void display(const vpImage< unsigned char > &I)
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0), const std::string &frameName="", const vpColor &textColor=vpColor::black, const vpImagePoint &textOffset=vpImagePoint(15, 15))
static void flush(const vpImage< unsigned char > &I)
Implementation of an homogeneous matrix and operations on such kind of matrices.
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:147
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1053
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:786
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1427
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition: vpKltOpencv.h:74
void setBlockSize(int blockSize)
Definition: vpKltOpencv.h:267
void setQuality(double qualityLevel)
Definition: vpKltOpencv.h:356
void setHarrisFreeParameter(double harris_k)
Definition: vpKltOpencv.h:275
void setMaxFeatures(int maxCount)
Definition: vpKltOpencv.h:315
void setMinDistance(double minDistance)
Definition: vpKltOpencv.h:324
void setWindowSize(int winSize)
Definition: vpKltOpencv.h:377
void setPyramidLevels(int pyrMaxLevel)
Definition: vpKltOpencv.h:343
static double rad(double deg)
Definition: vpMath.h:129
Real-time 6D object pose tracking using its CAD model.
virtual void setCameraParameters(const vpCameraParameters &camera) VP_OVERRIDE
virtual void setDisplayFeatures(bool displayF) VP_OVERRIDE
virtual void getCameraParameters(vpCameraParameters &camera) const VP_OVERRIDE
virtual void initFromPose(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo) VP_OVERRIDE
virtual void getPose(vpHomogeneousMatrix &cMo) const VP_OVERRIDE
virtual void setMovingEdge(const vpMe &me)
virtual void setAngleDisappear(const double &a) VP_OVERRIDE
virtual void track(const vpImage< unsigned char > &I) VP_OVERRIDE
virtual void loadModel(const std::string &modelFile, bool verbose=false, const vpHomogeneousMatrix &T=vpHomogeneousMatrix()) VP_OVERRIDE
virtual void getClipping(unsigned int &clippingFlag1, unsigned int &clippingFlag2) const
virtual void setClipping(const unsigned int &flags) VP_OVERRIDE
virtual void setNearClippingDistance(const double &dist) VP_OVERRIDE
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, unsigned int thickness=1, bool displayFullModel=false) VP_OVERRIDE
virtual void loadConfigFile(const std::string &configFile, bool verbose=true) VP_OVERRIDE
virtual void setAngleAppear(const double &a) VP_OVERRIDE
virtual void setFarClippingDistance(const double &dist) VP_OVERRIDE
Definition: vpMe.h:134
void setMu1(const double &mu_1)
Definition: vpMe.h:385
void setRange(const unsigned int &range)
Definition: vpMe.h:415
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition: vpMe.h:505
void setMaskNumber(const unsigned int &mask_number)
Definition: vpMe.cpp:552
void setThreshold(const double &threshold)
Definition: vpMe.h:466
void setSampleStep(const double &sample_step)
Definition: vpMe.h:422
void setMaskSize(const unsigned int &mask_size)
Definition: vpMe.cpp:560
void setMu2(const double &mu_2)
Definition: vpMe.h:392
@ NORMALIZED_THRESHOLD
Definition: vpMe.h:145
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:203