Visual Servoing Platform  version 3.6.1 under development (2025-03-13)
servoSimu4Points.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  * Demonstration of the wireframe simulator with a simple visual servoing
33  *
34 *****************************************************************************/
35 
42 #include <stdlib.h>
43 
44 #include <visp3/core/vpConfig.h>
45 #include <visp3/core/vpCameraParameters.h>
46 #include <visp3/core/vpHomogeneousMatrix.h>
47 #include <visp3/core/vpImage.h>
48 #include <visp3/core/vpIoTools.h>
49 #include <visp3/core/vpMath.h>
50 #include <visp3/core/vpTime.h>
51 #include <visp3/core/vpVelocityTwistMatrix.h>
52 #include <visp3/gui/vpDisplayFactory.h>
53 #include <visp3/gui/vpPlot.h>
54 #include <visp3/io/vpImageIo.h>
55 #include <visp3/io/vpParseArgv.h>
56 #include <visp3/robot/vpSimulatorCamera.h>
57 #include <visp3/robot/vpWireFrameSimulator.h>
58 #include <visp3/visual_features/vpFeatureBuilder.h>
59 #include <visp3/visual_features/vpFeaturePoint.h>
60 #include <visp3/vs/vpServo.h>
61 
62 #define GETOPTARGS "dhp"
63 
64 #if defined(VISP_HAVE_DISPLAY) && (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
65 
66 #if defined(ENABLE_VISP_NAMESPACE)
67 using namespace VISP_NAMESPACE_NAME;
68 #endif
69 
78 void usage(const char *name, const char *badparam)
79 {
80  fprintf(stdout, "\n\
81 Demonstration of the wireframe simulator with a simple visual servoing.\n\
82  \n\
83 The visual servoing consists in bringing the camera at a desired \n\
84 position from the object.\n\
85  \n\
86 The visual features used to compute the pose of the camera and \n\
87 thus the control law are four points.\n\
88  \n\
89 This demonstration explains also how to move the object around a world\n\
90 reference frame. Here, the movement is a rotation around the x and y axis\n\
91 at a given distance from the world frame. In fact the object trajectory\n\
92 is on a sphere whose center is the origin of the world frame.\n\
93  \n\
94 SYNOPSIS\n\
95  %s [-d] [-p] [-h]\n",
96  name);
97 
98  fprintf(stdout, "\n\
99 OPTIONS: Default\n\
100  -d \n\
101  Turn off the display.\n\
102  \n\
103  -p \n\
104  Turn off the plotter.\n\
105  \n\
106  -h\n\
107  Print the help.\n");
108 
109  if (badparam)
110  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
111 }
112 
125 bool getOptions(int argc, const char **argv, bool &display, bool &plot)
126 {
127  const char *optarg_;
128  int c;
129  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
130 
131  switch (c) {
132  case 'd':
133  display = false;
134  break;
135  case 'p':
136  plot = false;
137  break;
138  case 'h':
139  usage(argv[0], nullptr);
140  return false;
141 
142  default:
143  usage(argv[0], optarg_);
144  return false;
145  }
146  }
147 
148  if ((c == 1) || (c == -1)) {
149  // standalone param or error
150  usage(argv[0], nullptr);
151  std::cerr << "ERROR: " << std::endl;
152  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
153  return false;
154  }
155 
156  return true;
157 }
158 
159 int main(int argc, const char **argv)
160 {
161  const unsigned int NB_DISPLAYS = 3;
162 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
163  std::shared_ptr<vpDisplay> display[NB_DISPLAYS];
164  for (unsigned int i = 0; i < NB_DISPLAYS; ++i) {
165  display[i] = vpDisplayFactory::createDisplay();
166  }
167 #else
168  vpDisplay *display[NB_DISPLAYS];
169  for (unsigned int i = 0; i < NB_DISPLAYS; ++i) {
170  display[i] = vpDisplayFactory::allocateDisplay();
171  }
172 #endif
173  unsigned int exit_status = EXIT_SUCCESS;
174  try {
175  bool opt_display = true;
176  bool opt_plot = true;
177  std::string filename = vpIoTools::getParent(argv[0]) + "/mire.png";
178  std::cout << "Read " << filename << std::endl;
179 
180  // Read the command line options
181  if (getOptions(argc, argv, opt_display, opt_plot) == false) {
182  return EXIT_FAILURE;
183  }
184 
185  vpImage<vpRGBa> Iint(480, 640, vpRGBa(255));
186  vpImage<vpRGBa> Iext1(480, 640, vpRGBa(255));
187  vpImage<vpRGBa> Iext2(480, 640, vpRGBa(255));
188 
189  if (opt_display) {
190  // Display size is automatically defined by the image (I) size
191  display[0]->init(Iint, 100, 100, "The internal view");
192  display[1]->init(Iext1, 100, 100, "The first external view");
193  display[2]->init(Iext2, 100, 100, "The second external view");
194  vpDisplay::setWindowPosition(Iint, 0, 0);
195  vpDisplay::setWindowPosition(Iext1, 750, 0);
196  vpDisplay::setWindowPosition(Iext2, 0, 550);
197  vpDisplay::display(Iint);
198  vpDisplay::flush(Iint);
199  vpDisplay::display(Iext1);
200  vpDisplay::flush(Iext1);
201  vpDisplay::display(Iext2);
202  vpDisplay::flush(Iext2);
203  }
204 
205  vpPlot *plotter = nullptr;
206 
207  if (opt_plot) {
208  plotter = new vpPlot(2, 480, 640, 750, 550, "Real time curves plotter");
209  plotter->setTitle(0, "Visual features error");
210  plotter->setTitle(1, "Camera velocities");
211  plotter->initGraph(0, 8);
212  plotter->initGraph(1, 6);
213  plotter->setLegend(0, 0, "error_feat_p1_x");
214  plotter->setLegend(0, 1, "error_feat_p1_y");
215  plotter->setLegend(0, 2, "error_feat_p2_x");
216  plotter->setLegend(0, 3, "error_feat_p2_y");
217  plotter->setLegend(0, 4, "error_feat_p3_x");
218  plotter->setLegend(0, 5, "error_feat_p3_y");
219  plotter->setLegend(0, 6, "error_feat_p4_x");
220  plotter->setLegend(0, 7, "error_feat_p4_y");
221  plotter->setLegend(1, 0, "vc_x");
222  plotter->setLegend(1, 1, "vc_y");
223  plotter->setLegend(1, 2, "vc_z");
224  plotter->setLegend(1, 3, "wc_x");
225  plotter->setLegend(1, 4, "wc_y");
226  plotter->setLegend(1, 5, "wc_z");
227  }
228 
229  vpServo task;
230  vpSimulatorCamera robot;
231  float sampling_time = 0.020f; // Sampling period in second
232  robot.setSamplingTime(sampling_time);
233 
234  // Since the task gain lambda is very high, we need to increase default
235  // max velocities
236  robot.setMaxTranslationVelocity(10);
238 
239  // Set initial position of the object in the camera frame
240  vpHomogeneousMatrix cMo(0, 0.1, 2.0, vpMath::rad(35), vpMath::rad(25), 0);
241  // Set desired position of the object in the camera frame
242  vpHomogeneousMatrix cdMo(0.0, 0.0, 1.0, vpMath::rad(0), vpMath::rad(0), vpMath::rad(0));
243  // Set initial position of the object in the world frame
244  vpHomogeneousMatrix wMo(0.0, 0.0, 0.2, 0, 0, 0);
245  // Position of the camera in the world frame
247  wMc = wMo * cMo.inverse();
248 
249  // The four point used as visual features
250  vpPoint point[4];
251  point[0].setWorldCoordinates(-0.1, -0.1, 0);
252  point[3].setWorldCoordinates(-0.1, 0.1, 0);
253  point[2].setWorldCoordinates(0.1, 0.1, 0);
254  point[1].setWorldCoordinates(0.1, -0.1, 0);
255 
256  // Projection of the points
257  for (int i = 0; i < 4; i++)
258  point[i].track(cMo);
259 
260  // Set the current visual feature
261  vpFeaturePoint p[4];
262  for (int i = 0; i < 4; i++)
263  vpFeatureBuilder::create(p[i], point[i]);
264 
265  // Projection of the points
266  for (int i = 0; i < 4; i++)
267  point[i].track(cdMo);
268 
269  vpFeaturePoint pd[4];
270  for (int i = 0; i < 4; i++)
271  vpFeatureBuilder::create(pd[i], point[i]);
272 
275 
276  vpHomogeneousMatrix cMe; // Identity
277  vpVelocityTwistMatrix cVe(cMe);
278  task.set_cVe(cVe);
279 
280  vpMatrix eJe;
281  robot.get_eJe(eJe);
282  task.set_eJe(eJe);
283 
284  for (int i = 0; i < 4; i++)
285  task.addFeature(p[i], pd[i]);
286 
287  task.setLambda(10);
288 
289  std::list<vpImageSimulator> list;
290  vpImageSimulator imsim;
291 
292  vpColVector X[4];
293  for (int i = 0; i < 4; i++)
294  X[i].resize(3);
295  X[0][0] = -0.2;
296  X[0][1] = -0.2;
297  X[0][2] = 0;
298 
299  X[1][0] = 0.2;
300  X[1][1] = -0.2;
301  X[1][2] = 0;
302 
303  X[2][0] = 0.2;
304  X[2][1] = 0.2;
305  X[2][2] = 0;
306 
307  X[3][0] = -0.2;
308  X[3][1] = 0.2;
309  X[3][2] = 0;
310 
311  imsim.init(filename.c_str(), X);
312 
313  list.push_back(imsim);
314 
316 
317  // Set the scene
319 
320  // Initialize simulator frames
321  sim.set_fMo(wMo); // Position of the object in the world reference frame
322  sim.setCameraPositionRelObj(cMo); // Initial position of the object in the camera frame
323  sim.setDesiredCameraPosition(cdMo); // Desired position of the object in the camera frame
324 
325  // Set the External camera position
326  vpHomogeneousMatrix camMf(vpHomogeneousMatrix(0.0, 0, 3.5, vpMath::rad(0), vpMath::rad(30), 0));
327  sim.setExternalCameraPosition(camMf);
328 
329  // Computes the position of a camera which is fixed in the object frame
330  vpHomogeneousMatrix camoMf(0, 0.0, 1.5, 0, vpMath::rad(140), 0);
331  camoMf = camoMf * (sim.get_fMo().inverse());
332 
333  // Set the parameters of the cameras (internal and external)
334  vpCameraParameters camera(1000, 1000, 320, 240);
335  sim.setInternalCameraParameters(camera);
336  sim.setExternalCameraParameters(camera);
337 
338  int max_iter = 10;
339 
340  if (opt_display) {
341  max_iter = 2500;
342 
343  // Get the internal and external views
344  sim.getInternalImage(Iint);
345  sim.getExternalImage(Iext1);
346  sim.getExternalImage(Iext2, camoMf);
347 
348  // Display the object frame (current and desired position)
349  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
350  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
351 
352  // Display the object frame the world reference frame and the camera
353  // frame
354  vpDisplay::displayFrame(Iext1, camMf * sim.get_fMo() * cMo.inverse(), camera, 0.2, vpColor::none);
355  vpDisplay::displayFrame(Iext1, camMf * sim.get_fMo(), camera, 0.2, vpColor::none);
356  vpDisplay::displayFrame(Iext1, camMf, camera, 0.2, vpColor::none);
357 
358  // Display the world reference frame and the object frame
359  vpDisplay::displayFrame(Iext2, camoMf, camera, 0.2, vpColor::none);
360  vpDisplay::displayFrame(Iext2, camoMf * sim.get_fMo(), camera, 0.05, vpColor::none);
361 
362  vpDisplay::displayText(Iint, 20, 20, "Click to start visual servo", vpColor::red);
363 
364  vpDisplay::flush(Iint);
365  vpDisplay::flush(Iext1);
366  vpDisplay::flush(Iext2);
367 
368  std::cout << "Click on a display" << std::endl;
369 
370  while (!vpDisplay::getClick(Iint, false) && !vpDisplay::getClick(Iext1, false) &&
371  !vpDisplay::getClick(Iext2, false)) {
372  };
373  }
374 
375  robot.setPosition(wMc);
376  // Print the task
377  task.print();
378 
379  int iter = 0;
380  bool stop = false;
381  vpColVector v;
382 
383  double t_prev, t = vpTime::measureTimeMs();
384 
385  while (iter++ < max_iter && !stop) {
386  t_prev = t;
387  t = vpTime::measureTimeMs();
388 
389  if (opt_display) {
390  vpDisplay::display(Iint);
391  vpDisplay::display(Iext1);
392  vpDisplay::display(Iext2);
393  }
394 
395  robot.get_eJe(eJe);
396  task.set_eJe(eJe);
397 
398  wMc = robot.getPosition();
399  cMo = wMc.inverse() * wMo;
400  for (int i = 0; i < 4; i++) {
401  point[i].track(cMo);
402  vpFeatureBuilder::create(p[i], point[i]);
403  }
404 
405  v = task.computeControlLaw();
407 
408  // Compute the movement of the object around the world reference frame.
409  vpHomogeneousMatrix a(0, 0, 0.2, 0, 0, 0);
410  vpHomogeneousMatrix b(0, 0, 0, vpMath::rad(1.5 * iter), 0, 0);
411  vpHomogeneousMatrix c(0, 0, 0, 0, vpMath::rad(2.5 * iter), 0);
412 
413  // Move the object in the world frame
414  wMo = b * c * a;
415 
416  sim.set_fMo(wMo); // Move the object in the simulator
417  sim.setCameraPositionRelObj(cMo);
418 
419  // Compute the position of the external view which is fixed in the
420  // object frame
421  camoMf.buildFrom(0, 0.0, 1.5, 0, vpMath::rad(150), 0);
422  camoMf = camoMf * (sim.get_fMo().inverse());
423 
424  if (opt_plot) {
425  plotter->plot(0, iter, task.getError());
426  plotter->plot(1, iter, v);
427  }
428 
429  if (opt_display) {
430  // Get the internal and external views
431  sim.getInternalImage(Iint);
432  sim.getExternalImage(Iext1);
433  sim.getExternalImage(Iext2, camoMf);
434 
435  // Display the object frame (current and desired position)
436  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
437  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
438 
439  // Display the camera frame, the object frame the world reference
440  // frame
441  vpDisplay::displayFrame(Iext1, sim.getExternalCameraPosition() * sim.get_fMo() * cMo.inverse(), camera, 0.2,
442  vpColor::none);
443  vpDisplay::displayFrame(Iext1, sim.getExternalCameraPosition() * sim.get_fMo(), camera, 0.2, vpColor::none);
445 
446  // Display the world reference frame and the object frame
447  vpDisplay::displayFrame(Iext2, camoMf, camera, 0.2, vpColor::none);
448  vpDisplay::displayFrame(Iext2, camoMf * sim.get_fMo(), camera, 0.05, vpColor::none);
449 
450  vpDisplay::displayText(Iint, 20, 20, "Click to stop visual servo", vpColor::red);
451 
452  std::stringstream ss;
453  ss << "Loop time: " << t - t_prev << " ms";
454  vpDisplay::displayText(Iint, 40, 20, ss.str(), vpColor::red);
455 
456  if (vpDisplay::getClick(Iint, false)) {
457  stop = true;
458  }
459  vpDisplay::flush(Iint);
460  vpDisplay::flush(Iext1);
461  vpDisplay::flush(Iext2);
462 
463  vpTime::wait(t, sampling_time * 1000); // Wait ms
464  }
465 
466  std::cout << "|| s - s* || = " << (task.getError()).sumSquare() << std::endl;
467  }
468 
469  if (opt_plot && plotter != nullptr) {
470  vpDisplay::display(Iint);
471  sim.getInternalImage(Iint);
472  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
473  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
474  vpDisplay::displayText(Iint, 20, 20, "Click to quit", vpColor::red);
475  if (vpDisplay::getClick(Iint)) {
476  stop = true;
477  }
478  vpDisplay::flush(Iint);
479 
480  delete plotter;
481  }
482 
483  task.print();
484 
485  exit_status = EXIT_SUCCESS;
486  }
487  catch (const vpException &e) {
488  std::cout << "Catch an exception: " << e << std::endl;
489  exit_status = EXIT_FAILURE;
490  }
491 #if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
492  for (unsigned int i = 0; i < NB_DISPLAYS; ++i) {
493  delete display[i];
494  }
495 #endif
496  return exit_status;
497 }
498 #elif !(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
499 int main()
500 {
501  std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
502  return EXIT_SUCCESS;
503 }
504 #else
505 int main()
506 {
507  std::cout << "You do not have X11, or GDI (Graphical Device Interface), or GTK functionalities to display images..."
508  << std::endl;
509  std::cout << "Tip if you are on a unix-like system:" << std::endl;
510  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
511  std::cout << "Tip if you are on a windows-like system:" << std::endl;
512  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
513  return EXIT_SUCCESS;
514 }
515 
516 #endif
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static const vpColor red
Definition: vpColor.h:198
static const vpColor none
Definition: vpColor.h:210
Class that defines generic functionalities for display.
Definition: vpDisplay.h:178
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
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)
static void setWindowPosition(const vpImage< unsigned char > &I, int winx, int winy)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
void track(const vpHomogeneousMatrix &cMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
Class which enables to project an image in the 3D space and get the view of a virtual camera.
void init(const vpImage< unsigned char > &I, vpColVector *X)
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1326
static double rad(double deg)
Definition: vpMath.h:129
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
Definition: vpPlot.h:112
void initGraph(unsigned int graphNum, unsigned int curveNbr)
Definition: vpPlot.cpp:203
void setLegend(unsigned int graphNum, unsigned int curveNum, const std::string &legend)
Definition: vpPlot.cpp:552
void plot(unsigned int graphNum, unsigned int curveNum, double x, double y)
Definition: vpPlot.cpp:270
void setTitle(unsigned int graphNum, const std::string &title)
Definition: vpPlot.cpp:510
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:79
void setWorldCoordinates(double oX, double oY, double oZ)
Definition: vpPoint.cpp:113
Definition: vpRGBa.h:70
void get_eJe(vpMatrix &eJe) VP_OVERRIDE
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel) VP_OVERRIDE
@ CAMERA_FRAME
Definition: vpRobot.h:84
void setMaxRotationVelocity(double maxVr)
Definition: vpRobot.cpp:261
void setMaxTranslationVelocity(double maxVt)
Definition: vpRobot.cpp:240
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:380
@ EYEINHAND_L_cVe_eJe
Definition: vpServo.h:168
void addFeature(vpBasicFeature &s_cur, vpBasicFeature &s_star, unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:331
void set_cVe(const vpVelocityTwistMatrix &cVe_)
Definition: vpServo.h:1043
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:171
void setLambda(double c)
Definition: vpServo.h:991
void set_eJe(const vpMatrix &eJe_)
Definition: vpServo.h:1106
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:134
vpColVector getError() const
Definition: vpServo.h:515
vpColVector computeControlLaw()
Definition: vpServo.cpp:705
@ DESIRED
Definition: vpServo.h:208
Class that defines the simplest robot: a free flying camera.
Implementation of a wire frame simulator. Compared to the vpSimulator class, it does not require thir...
vpHomogeneousMatrix getExternalCameraPosition() const
void setCameraPositionRelObj(const vpHomogeneousMatrix &cMo_)
void getInternalImage(vpImage< unsigned char > &I)
void initScene(const vpSceneObject &obj, const vpSceneDesiredObject &desiredObject)
void setExternalCameraPosition(const vpHomogeneousMatrix &cam_Mf)
void set_fMo(const vpHomogeneousMatrix &fMo_)
vpHomogeneousMatrix get_fMo() const
void setDesiredCameraPosition(const vpHomogeneousMatrix &cdMo_)
void setInternalCameraParameters(const vpCameraParameters &cam)
void setExternalCameraParameters(const vpCameraParameters &cam)
void getExternalImage(vpImage< unsigned char > &I)
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMs()