Visual Servoing Platform  version 3.6.1 under development (2024-05-18)
testGenericTrackerDeterminist.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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  * Check that MBT is deterministic.
33  *
34 *****************************************************************************/
35 
36 #include <visp3/core/vpConfig.h>
37 
38 #if defined(VISP_HAVE_CATCH2) && defined(VISP_HAVE_THREADS)
39 #define CATCH_CONFIG_ENABLE_BENCHMARKING
40 #define CATCH_CONFIG_RUNNER
41 #include <catch.hpp>
42 
43 #include <future>
44 #include <thread>
45 #include <visp3/core/vpIoTools.h>
46 #include <visp3/io/vpImageIo.h>
47 #include <visp3/mbt/vpMbGenericTracker.h>
48 
49 // #define DEBUG_DISPLAY // uncomment to check that the tracking is correct
50 #ifdef DEBUG_DISPLAY
51 #include <visp3/gui/vpDisplayX.h>
52 #endif
53 
54 namespace
55 {
56 bool read_data(int cpt, vpImage<unsigned char> &I)
57 {
58 #if VISP_HAVE_DATASET_VERSION >= 0x030600
59  std::string ext("png");
60 #else
61  std::string ext("pgm");
62 #endif
63  const std::string env_ipath = vpIoTools::getViSPImagesDataPath();
64  const std::string ipath = vpIoTools::createFilePath(env_ipath, "mbt/cube/image%04d." + ext);
65 
66  char buffer[FILENAME_MAX];
67  snprintf(buffer, FILENAME_MAX, ipath.c_str(), cpt);
68  std::string image_filename = buffer;
69 
70  if (!vpIoTools::checkFilename(image_filename)) {
71  return false;
72  }
73 
74  vpImageIo::read(I, image_filename);
75  return true;
76 }
77 
78 void checkPoses(const vpHomogeneousMatrix &cMo1, const vpHomogeneousMatrix &cMo2)
79 {
80  for (unsigned int i = 0; i < 3; i++) {
81  for (unsigned int j = 0; j < 4; j++) {
82  CHECK(cMo1[i][j] == Approx(cMo2[i][j]).epsilon(std::numeric_limits<double>::epsilon()));
83  }
84  }
85 }
86 
87 void configureTracker(vpMbGenericTracker &tracker, vpCameraParameters &cam)
88 {
89  const std::string env_ipath = vpIoTools::getViSPImagesDataPath();
90  const std::string configFile = vpIoTools::createFilePath(env_ipath, "mbt/cube.xml");
91  const std::string modelFile = vpIoTools::createFilePath(env_ipath, "mbt/cube_and_cylinder.cao");
92 #if defined(VISP_HAVE_PUGIXML)
93  const bool verbose = false;
94  tracker.loadConfigFile(configFile, verbose);
95 #else
96  // Corresponding parameters manually set to have an example code
97  // By setting the parameters:
98  cam.initPersProjWithoutDistortion(547, 542, 338, 234);
99 
100  vpMe me;
101  me.setMaskSize(5);
102  me.setMaskNumber(180);
103  me.setRange(7);
105  me.setThreshold(5);
106  me.setMu1(0.5);
107  me.setMu2(0.5);
108  me.setSampleStep(4);
109 
110  vpKltOpencv klt;
111  klt.setMaxFeatures(300);
112  klt.setWindowSize(5);
113  klt.setQuality(0.01);
114  klt.setMinDistance(5);
115  klt.setHarrisFreeParameter(0.01);
116  klt.setBlockSize(3);
117  klt.setPyramidLevels(3);
118 
119  tracker.setCameraParameters(cam);
120  tracker.setMovingEdge(me);
121  tracker.setKltOpencv(klt);
122  tracker.setKltMaskBorder(5);
123  tracker.setAngleAppear(vpMath::rad(65));
124  tracker.setAngleDisappear(vpMath::rad(75));
125 
126  // Specify the clipping to
127  tracker.setNearClippingDistance(0.01);
128  tracker.setFarClippingDistance(0.90);
130  // tracker.setClipping(tracker.getClipping() | vpMbtPolygon::LEFT_CLIPPING |
131  // vpMbtPolygon::RIGHT_CLIPPING | vpMbtPolygon::UP_CLIPPING |
132  // vpMbtPolygon::DOWN_CLIPPING); // Equivalent to FOV_CLIPPING
133 #endif
134  tracker.getCameraParameters(cam);
135  tracker.loadModel(modelFile);
136  tracker.setDisplayFeatures(true);
137 
138  const vpPoseVector initPose(0.02231950571, 0.1071368004, 0.5071128378, 2.100485509, 1.146812236, -0.4560126437);
140  read_data(0, I);
141  tracker.initFromPose(I, vpHomogeneousMatrix(initPose));
142 }
143 } // anonymous namespace
144 
145 TEST_CASE("Check MBT determinism sequential", "[MBT_determinism]")
146 {
147  // First tracker
148  vpMbGenericTracker tracker1;
149  vpCameraParameters cam;
150  configureTracker(tracker1, cam);
151 
153  read_data(0, I);
154 #ifdef DEBUG_DISPLAY
155  vpDisplayX d(I);
156 #endif
157 
158  vpHomogeneousMatrix cMo1;
159  for (int cpt = 0; read_data(cpt, I); cpt++) {
160  tracker1.track(I);
161  tracker1.getPose(cMo1);
162 
163 #ifdef DEBUG_DISPLAY
165  tracker1.display(I, cMo1, cam, vpColor::red, 3);
166  vpDisplay::displayFrame(I, cMo1, cam, 0.05, vpColor::none, 3);
167  vpDisplay::flush(I);
168 #endif
169  }
170  std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
171 
172  // Second tracker
173  vpMbGenericTracker tracker2;
174  configureTracker(tracker2, cam);
175  vpHomogeneousMatrix cMo2;
176  for (int cpt = 0; read_data(cpt, I); cpt++) {
177  tracker2.track(I);
178  tracker2.getPose(cMo2);
179 
180 #ifdef DEBUG_DISPLAY
182  tracker2.display(I, cMo2, cam, vpColor::red, 3);
183  vpDisplay::displayFrame(I, cMo2, cam, 0.05, vpColor::none, 3);
184  vpDisplay::flush(I);
185 #endif
186  }
187  std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
188 
189  // Check that both poses are identical
190  checkPoses(cMo1, cMo2);
191 }
192 
193 TEST_CASE("Check MBT determinism parallel", "[MBT_determinism]")
194 {
195  // First tracker
196  std::future<vpHomogeneousMatrix> res_cMo1 = std::async(std::launch::async, []() {
197  vpMbGenericTracker tracker1;
198  vpCameraParameters cam;
199  configureTracker(tracker1, cam);
200 
202  vpHomogeneousMatrix cMo1;
203  for (int cpt = 0; read_data(cpt, I); cpt++) {
204  tracker1.track(I);
205  tracker1.getPose(cMo1);
206  }
207  return cMo1;
208  });
209 
210  // Second tracker
211  std::future<vpHomogeneousMatrix> res_cMo2 = std::async(std::launch::async, []() {
212  vpMbGenericTracker tracker2;
213  vpCameraParameters cam;
214  configureTracker(tracker2, cam);
215 
217  vpHomogeneousMatrix cMo2;
218  for (int cpt = 0; read_data(cpt, I); cpt++) {
219  tracker2.track(I);
220  tracker2.getPose(cMo2);
221  }
222  return cMo2;
223  });
224 
225  vpHomogeneousMatrix cMo1 = res_cMo1.get();
226  vpHomogeneousMatrix cMo2 = res_cMo2.get();
227  std::cout << "Run both trackers in separate threads" << std::endl;
228  std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
229  std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
230 
231  // Check that both poses are identical
232  checkPoses(cMo1, cMo2);
233 }
234 
235 TEST_CASE("Check Stereo MBT determinism parallel", "[MBT_determinism]")
236 {
237  // First tracker
238  std::future<vpHomogeneousMatrix> res_cMo1 = std::async(std::launch::async, []() {
239  vpMbGenericTracker tracker1(2);
240  vpCameraParameters cam;
241  configureTracker(tracker1, cam);
242 
244  vpHomogeneousMatrix cMo1;
245  for (int cpt = 0; read_data(cpt, I); cpt++) {
246  tracker1.track(I, I);
247  tracker1.getPose(cMo1);
248  }
249  return cMo1;
250  });
251 
252  // Second tracker
253  std::future<vpHomogeneousMatrix> res_cMo2 = std::async(std::launch::async, []() {
254  vpMbGenericTracker tracker2(2);
255  vpCameraParameters cam;
256  configureTracker(tracker2, cam);
257 
259  vpHomogeneousMatrix cMo2;
260  for (int cpt = 0; read_data(cpt, I); cpt++) {
261  tracker2.track(I, I);
262  tracker2.getPose(cMo2);
263  }
264  return cMo2;
265  });
266 
267  vpHomogeneousMatrix cMo1 = res_cMo1.get();
268  vpHomogeneousMatrix cMo2 = res_cMo2.get();
269  std::cout << "Run both stereo trackers in separate threads" << std::endl;
270  std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
271  std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
272 
273  // Check that both poses are identical
274  checkPoses(cMo1, cMo2);
275 }
276 
277 int main(int argc, char *argv[])
278 {
279  Catch::Session session; // There must be exactly one instance
280 
281  // Let Catch (using Clara) parse the command line
282  session.applyCommandLine(argc, argv);
283 
284  int numFailed = session.run();
285 
286  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
287  // This clamping has already been applied, so just return it here
288  // You can also do any post run clean-up here
289  return numFailed;
290 }
291 #else
292 #include <iostream>
293 
294 int main() { return EXIT_SUCCESS; }
295 #endif
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
static const vpColor red
Definition: vpColor.h:211
static const vpColor none
Definition: vpColor.h:223
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:128
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:143
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1834
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:1215
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:2197
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition: vpKltOpencv.h:73
void setBlockSize(int blockSize)
Definition: vpKltOpencv.h:266
void setQuality(double qualityLevel)
Definition: vpKltOpencv.h:355
void setHarrisFreeParameter(double harris_k)
Definition: vpKltOpencv.h:274
void setMaxFeatures(int maxCount)
Definition: vpKltOpencv.h:314
void setMinDistance(double minDistance)
Definition: vpKltOpencv.h:323
void setWindowSize(int winSize)
Definition: vpKltOpencv.h:376
void setPyramidLevels(int pyrMaxLevel)
Definition: vpKltOpencv.h:342
static double rad(double deg)
Definition: vpMath.h:127
Real-time 6D object pose tracking using its CAD model.
virtual void initFromPose(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo) vp_override
virtual void setKltMaskBorder(const unsigned int &e)
virtual void loadConfigFile(const std::string &configFile, bool verbose=true) vp_override
virtual void setAngleDisappear(const double &a) vp_override
virtual void getPose(vpHomogeneousMatrix &cMo) const 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 getCameraParameters(vpCameraParameters &camera) const vp_override
virtual void setMovingEdge(const vpMe &me)
virtual void setAngleAppear(const double &a) vp_override
virtual void loadModel(const std::string &modelFile, bool verbose=false, const vpHomogeneousMatrix &T=vpHomogeneousMatrix()) vp_override
virtual void setKltOpencv(const vpKltOpencv &t)
virtual void setFarClippingDistance(const double &dist) vp_override
virtual void setNearClippingDistance(const double &dist) vp_override
virtual void getClipping(unsigned int &clippingFlag1, unsigned int &clippingFlag2) const
virtual void setCameraParameters(const vpCameraParameters &camera) vp_override
virtual void setClipping(const unsigned int &flags) vp_override
virtual void setDisplayFeatures(bool displayF) vp_override
virtual void track(const vpImage< unsigned char > &I) vp_override
Definition: vpMe.h:124
void setMu1(const double &mu_1)
Definition: vpMe.h:399
void setRange(const unsigned int &range)
Definition: vpMe.h:429
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition: vpMe.h:519
void setMaskNumber(const unsigned int &mask_number)
Definition: vpMe.cpp:488
void setThreshold(const double &threshold)
Definition: vpMe.h:480
void setSampleStep(const double &sample_step)
Definition: vpMe.h:436
void setMaskSize(const unsigned int &mask_size)
Definition: vpMe.cpp:496
void setMu2(const double &mu_2)
Definition: vpMe.h:406
@ NORMALIZED_THRESHOLD
Definition: vpMe.h:135
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:189