Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
catchGenericTrackerDeterminist.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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
37
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
56using namespace VISP_NAMESPACE_NAME;
57#endif
58
59namespace
60{
61bool read_data(int cpt, vpImage<unsigned char> &I)
62{
63#if defined(VISP_HAVE_DATASET)
64#if VISP_HAVE_DATASET_VERSION >= 0x030600
65 std::string ext("png");
66#else
67 std::string ext("pgm");
68#endif
69#else
70 // We suppose that the user will download a recent dataset
71 std::string ext("png");
72#endif
73 const std::string env_ipath = vpIoTools::getViSPImagesDataPath();
74 const std::string ipath = vpIoTools::createFilePath(env_ipath, "mbt/cube/image%04d." + ext);
75 std::string image_filename = vpIoTools::formatString(ipath, cpt);
76
77 if (!vpIoTools::checkFilename(image_filename)) {
78 return false;
79 }
80
81 vpImageIo::read(I, image_filename);
82 return true;
83}
84
85void checkPoses(const vpHomogeneousMatrix &cMo1, const vpHomogeneousMatrix &cMo2)
86{
87 for (unsigned int i = 0; i < 3; i++) {
88 for (unsigned int j = 0; j < 4; j++) {
89 CHECK(cMo1[i][j] == Catch::Approx(cMo2[i][j]).epsilon(std::numeric_limits<double>::epsilon()));
90 }
91 }
92}
93
94void configureTracker(vpMbGenericTracker &tracker, vpCameraParameters &cam)
95{
96 const std::string env_ipath = vpIoTools::getViSPImagesDataPath();
97 const std::string configFile = vpIoTools::createFilePath(env_ipath, "mbt/cube.xml");
98 const std::string modelFile = vpIoTools::createFilePath(env_ipath, "mbt/cube_and_cylinder.cao");
99#if defined(VISP_HAVE_PUGIXML)
100 const bool verbose = false;
101 tracker.loadConfigFile(configFile, verbose);
102#else
103 // Corresponding parameters manually set to have an example code
104 // By setting the parameters:
105 cam.initPersProjWithoutDistortion(547, 542, 338, 234);
106
107 vpMe me;
108 me.setMaskSize(5);
109 me.setMaskNumber(180);
110 me.setRange(7);
112 me.setThreshold(5);
113 me.setMu1(0.5);
114 me.setMu2(0.5);
115 me.setSampleStep(4);
116
117 vpKltOpencv klt;
118 klt.setMaxFeatures(300);
119 klt.setWindowSize(5);
120 klt.setQuality(0.01);
121 klt.setMinDistance(5);
122 klt.setHarrisFreeParameter(0.01);
123 klt.setBlockSize(3);
124 klt.setPyramidLevels(3);
125
126 tracker.setCameraParameters(cam);
127 tracker.setMovingEdge(me);
128 tracker.setKltOpencv(klt);
129 tracker.setKltMaskBorder(5);
130 tracker.setAngleAppear(vpMath::rad(65));
131 tracker.setAngleDisappear(vpMath::rad(75));
132
133 // Specify the clipping to
134 tracker.setNearClippingDistance(0.01);
135 tracker.setFarClippingDistance(0.90);
136 tracker.setClipping(tracker.getClipping() | vpMbtPolygon::FOV_CLIPPING);
137 // tracker.setClipping(tracker.getClipping() | vpMbtPolygon::LEFT_CLIPPING |
138 // vpMbtPolygon::RIGHT_CLIPPING | vpMbtPolygon::UP_CLIPPING |
139 // vpMbtPolygon::DOWN_CLIPPING); // Equivalent to FOV_CLIPPING
140#endif
141 tracker.getCameraParameters(cam);
142 tracker.loadModel(modelFile);
143 tracker.setDisplayFeatures(true);
144
145 const vpPoseVector initPose(0.02231950571, 0.1071368004, 0.5071128378, 2.100485509, 1.146812236, -0.4560126437);
147 read_data(0, I);
148 tracker.initFromPose(I, vpHomogeneousMatrix(initPose));
149}
150} // anonymous namespace
151
152TEST_CASE("Check MBT determinism sequential", "[MBT_determinism]")
153{
154 // First tracker
155 vpMbGenericTracker tracker1;
157 configureTracker(tracker1, cam);
158
160 read_data(0, I);
161#ifdef DEBUG_DISPLAY
162 vpDisplayX d(I);
163#endif
164
166 for (int cpt = 0; read_data(cpt, I); cpt++) {
167 tracker1.track(I);
168 tracker1.getPose(cMo1);
169
170#ifdef DEBUG_DISPLAY
172 tracker1.display(I, cMo1, cam, vpColor::red, 3);
173 vpDisplay::displayFrame(I, cMo1, cam, 0.05, vpColor::none, 3);
175#endif
176 }
177 std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
178
179 // Second tracker
180 vpMbGenericTracker tracker2;
181 configureTracker(tracker2, cam);
183 for (int cpt = 0; read_data(cpt, I); cpt++) {
184 tracker2.track(I);
185 tracker2.getPose(cMo2);
186
187#ifdef DEBUG_DISPLAY
189 tracker2.display(I, cMo2, cam, vpColor::red, 3);
190 vpDisplay::displayFrame(I, cMo2, cam, 0.05, vpColor::none, 3);
192#endif
193 }
194 std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
195
196 // Check that both poses are identical
197 checkPoses(cMo1, cMo2);
198}
199
200TEST_CASE("Check MBT determinism parallel", "[MBT_determinism]")
201{
202 // First tracker
203 std::future<vpHomogeneousMatrix> res_cMo1 = std::async(std::launch::async, []() {
204 vpMbGenericTracker tracker1;
206 configureTracker(tracker1, cam);
207
210 for (int cpt = 0; read_data(cpt, I); cpt++) {
211 tracker1.track(I);
212 tracker1.getPose(cMo1);
213 }
214 return cMo1;
215 });
216
217 // Second tracker
218 std::future<vpHomogeneousMatrix> res_cMo2 = std::async(std::launch::async, []() {
219 vpMbGenericTracker tracker2;
221 configureTracker(tracker2, cam);
222
225 for (int cpt = 0; read_data(cpt, I); cpt++) {
226 tracker2.track(I);
227 tracker2.getPose(cMo2);
228 }
229 return cMo2;
230 });
231
232 vpHomogeneousMatrix cMo1 = res_cMo1.get();
233 vpHomogeneousMatrix cMo2 = res_cMo2.get();
234 std::cout << "Run both trackers in separate threads" << std::endl;
235 std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
236 std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
237
238 // Check that both poses are identical
239 checkPoses(cMo1, cMo2);
240}
241
242TEST_CASE("Check Stereo MBT determinism parallel", "[MBT_determinism]")
243{
244 // First tracker
245 std::future<vpHomogeneousMatrix> res_cMo1 = std::async(std::launch::async, []() {
246 vpMbGenericTracker tracker1(2);
248 configureTracker(tracker1, cam);
249
252 for (int cpt = 0; read_data(cpt, I); cpt++) {
253 tracker1.track(I, I);
254 tracker1.getPose(cMo1);
255 }
256 return cMo1;
257 });
258
259 // Second tracker
260 std::future<vpHomogeneousMatrix> res_cMo2 = std::async(std::launch::async, []() {
261 vpMbGenericTracker tracker2(2);
263 configureTracker(tracker2, cam);
264
267 for (int cpt = 0; read_data(cpt, I); cpt++) {
268 tracker2.track(I, I);
269 tracker2.getPose(cMo2);
270 }
271 return cMo2;
272 });
273
274 vpHomogeneousMatrix cMo1 = res_cMo1.get();
275 vpHomogeneousMatrix cMo2 = res_cMo2.get();
276 std::cout << "Run both stereo trackers in separate threads" << std::endl;
277 std::cout << "First tracker, final cMo:\n" << cMo1 << std::endl;
278 std::cout << "Second tracker, final cMo:\n" << cMo2 << std::endl;
279
280 // Check that both poses are identical
281 checkPoses(cMo1, cMo2);
282}
283
284int main(int argc, char *argv[])
285{
286 Catch::Session session;
287 session.applyCommandLine(argc, argv);
288 int numFailed = session.run();
289 return numFailed;
290}
291
292#else
293#include <iostream>
294
295int main() { return EXIT_SUCCESS; }
296#endif
Generic class defining intrinsic camera parameters.
static const vpColor red
Definition vpColor.h:198
static const vpColor none
Definition vpColor.h:210
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition vpDisplayX.h:135
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 of the vpImage class member functions.
Definition vpImage.h:131
static std::string getViSPImagesDataPath()
static bool checkFilename(const std::string &filename)
static std::string formatString(const std::string &name, unsigned int val)
static std::string createFilePath(const std::string &parent, const std::string &child)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition vpKltOpencv.h:83
void setBlockSize(int blockSize)
void setQuality(double qualityLevel)
void setHarrisFreeParameter(double harris_k)
void setMaxFeatures(int maxCount)
void setMinDistance(double minDistance)
void setWindowSize(int winSize)
void setPyramidLevels(int pyrMaxLevel)
static double rad(double deg)
Definition vpMath.h:129
Real-time 6D object pose tracking using its CAD model.
virtual void getPose(vpHomogeneousMatrix &cMo) const VP_OVERRIDE
virtual void track(const vpImage< unsigned char > &I) 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
Definition vpMe.h:143
void setMu1(const double &mu_1)
Definition vpMe.h:408
void setRange(const unsigned int &range)
Definition vpMe.h:438
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition vpMe.h:531
void setMaskNumber(const unsigned int &mask_number)
Definition vpMe.cpp:555
void setThreshold(const double &threshold)
Definition vpMe.h:489
void setSampleStep(const double &sample_step)
Definition vpMe.h:445
void setMaskSize(const unsigned int &mask_size)
Definition vpMe.cpp:563
void setMu2(const double &mu_2)
Definition vpMe.h:415
@ NORMALIZED_THRESHOLD
Definition vpMe.h:154
Implementation of a pose vector and operations on poses.
read_data(CameraParameters|None cam_depth, ImageGray I, rs.pipeline pipe)