Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
servoSimu4Points.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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 http://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  * Authors:
35  * Nicolas Melchior
36  *
37  *****************************************************************************/
38 
45 #include <stdlib.h>
46 
47 #include <visp3/core/vpCameraParameters.h>
48 #include <visp3/core/vpHomogeneousMatrix.h>
49 #include <visp3/core/vpImage.h>
50 #include <visp3/core/vpIoTools.h>
51 #include <visp3/core/vpMath.h>
52 #include <visp3/core/vpTime.h>
53 #include <visp3/core/vpVelocityTwistMatrix.h>
54 #include <visp3/gui/vpDisplayD3D.h>
55 #include <visp3/gui/vpDisplayGDI.h>
56 #include <visp3/gui/vpDisplayGTK.h>
57 #include <visp3/gui/vpDisplayOpenCV.h>
58 #include <visp3/gui/vpDisplayX.h>
59 #include <visp3/io/vpImageIo.h>
60 #include <visp3/io/vpParseArgv.h>
61 #include <visp3/robot/vpSimulatorCamera.h>
62 #include <visp3/robot/vpWireFrameSimulator.h>
63 #include <visp3/visual_features/vpFeatureBuilder.h>
64 #include <visp3/visual_features/vpFeaturePoint.h>
65 #include <visp3/vs/vpServo.h>
66 
67 #define GETOPTARGS "dh"
68 
69 #ifdef VISP_HAVE_DISPLAY
70 
71 void usage(const char *name, std::string ipath, const char *badparam);
72 bool getOptions(int argc, const char **argv, std::string &ipath, bool &display);
73 
83 void usage(const char *name, std::string ipath, const char *badparam)
84 {
85  fprintf(stdout, "\n\
86 Demonstration of the wireframe simulator with a simple visual servoing.\n\
87  \n\
88 The visual servoing consists in bringing the camera at a desired \n\
89 position from the object.\n\
90  \n\
91 The visual features used to compute the pose of the camera and \n\
92 thus the control law are four points.\n\
93  \n\
94 This demonstration explains also how to move the object around a world\n\
95 reference frame. Here, the movement is a rotation around the x and y axis\n\
96 at a given distance from the world frame. In fact the object trajectory\n\
97 is on a sphere whose center is the origin of the world frame.\n\
98  \n\
99 SYNOPSIS\n\
100  %s [-d] [-h]\n", name);
101 
102  fprintf(stdout, "\n\
103 OPTIONS: Default\n\
104  -i <input image path> %s\n\
105  Set mire.pgm image input path.\n\
106  From this path read \"mire/mire.pgm\" image.\n\
107  Setting the VISP_INPUT_IMAGE_PATH environment variable \n\
108  produces the same behaviour than using this option.\n\
109  \n\
110  -d \n\
111  Turn off the display.\n\
112  \n\
113  -h\n\
114  Print the help.\n", ipath.c_str());
115 
116  if (badparam)
117  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
118 }
119 
132 bool getOptions(int argc, const char **argv, std::string &ipath, bool &display)
133 {
134  const char *optarg_;
135  int c;
136  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
137 
138  switch (c) {
139  case 'i':
140  ipath = optarg_;
141  break;
142  case 'd':
143  display = false;
144  break;
145  case 'h':
146  usage(argv[0], ipath, NULL);
147  return false;
148  break;
149 
150  default:
151  usage(argv[0], ipath, optarg_);
152  return false;
153  break;
154  }
155  }
156 
157  if ((c == 1) || (c == -1)) {
158  // standalone param or error
159  usage(argv[0], ipath, NULL);
160  std::cerr << "ERROR: " << std::endl;
161  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
162  return false;
163  }
164 
165  return true;
166 }
167 
168 int main(int argc, const char **argv)
169 {
170  try {
171  bool opt_display = true;
172  std::string opt_ipath;
173  std::string env_ipath;
174  std::string ipath;
175  std::string filename;
176 
177  // Read the command line options
178  if (getOptions(argc, argv, opt_ipath, opt_display) == false) {
179  exit(-1);
180  }
181 
182  vpImage<vpRGBa> Iint(480, 640, 255);
183  vpImage<vpRGBa> Iext1(480, 640, 255);
184  vpImage<vpRGBa> Iext2(480, 640, 255);
185 
186 #if defined VISP_HAVE_X11
187  vpDisplayX display[3];
188 #elif defined VISP_HAVE_OPENCV
189  vpDisplayOpenCV display[3];
190 #elif defined VISP_HAVE_GDI
191  vpDisplayGDI display[3];
192 #elif defined VISP_HAVE_D3D9
193  vpDisplayD3D display[3];
194 #elif defined VISP_HAVE_GTK
195  vpDisplayGTK display[3];
196 #endif
197 
198  if (opt_display) {
199  // Display size is automatically defined by the image (I) size
200  display[0].init(Iint, 100, 100, "The internal view");
201  display[1].init(Iext1, 100, 100, "The first external view");
202  display[2].init(Iext2, 100, 100, "The second external view");
203  vpDisplay::setWindowPosition(Iint, 0, 0);
204  vpDisplay::setWindowPosition(Iext1, 700, 0);
205  vpDisplay::setWindowPosition(Iext2, 0, 550);
206  vpDisplay::display(Iint);
207  vpDisplay::flush(Iint);
208  vpDisplay::display(Iext1);
209  vpDisplay::flush(Iext1);
210  vpDisplay::display(Iext2);
211  vpDisplay::flush(Iext2);
212  }
213 
214  vpServo task;
215  vpSimulatorCamera robot;
216  float sampling_time = 0.040f; // Sampling period in second
217  robot.setSamplingTime(sampling_time);
218 
219  // Since the task gain lambda is very high, we need to increase default
220  // max velocities
221  robot.setMaxTranslationVelocity(10);
223 
224  // Set initial position of the object in the camera frame
225  vpHomogeneousMatrix cMo(0, 0.1, 2.0, vpMath::rad(35), vpMath::rad(25), 0);
226  // Set desired position of the object in the camera frame
227  vpHomogeneousMatrix cdMo(0.0, 0.0, 1.0, vpMath::rad(0), vpMath::rad(0), vpMath::rad(0));
228  // Set initial position of the object in the world frame
229  vpHomogeneousMatrix wMo(0.0, 0.0, 0.2, 0, 0, 0);
230  // Position of the camera in the world frame
232  wMc = wMo * cMo.inverse();
233 
234  // The four point used as visual features
235  vpPoint point[4];
236  point[0].setWorldCoordinates(-0.1, -0.1, 0);
237  point[3].setWorldCoordinates(-0.1, 0.1, 0);
238  point[2].setWorldCoordinates(0.1, 0.1, 0);
239  point[1].setWorldCoordinates(0.1, -0.1, 0);
240 
241  // Projection of the points
242  for (int i = 0; i < 4; i++)
243  point[i].track(cMo);
244 
245  // Set the current visual feature
246  vpFeaturePoint p[4];
247  for (int i = 0; i < 4; i++)
248  vpFeatureBuilder::create(p[i], point[i]);
249 
250  // Projection of the points
251  for (int i = 0; i < 4; i++)
252  point[i].track(cdMo);
253 
254  vpFeaturePoint pd[4];
255  for (int i = 0; i < 4; i++)
256  vpFeatureBuilder::create(pd[i], point[i]);
257 
260 
261  vpHomogeneousMatrix cMe; // Identity
262  vpVelocityTwistMatrix cVe(cMe);
263  task.set_cVe(cVe);
264 
265  vpMatrix eJe;
266  robot.get_eJe(eJe);
267  task.set_eJe(eJe);
268 
269  for (int i = 0; i < 4; i++)
270  task.addFeature(p[i], pd[i]);
271 
272  task.setLambda(10);
273 
274  std::list<vpImageSimulator> list;
275  vpImageSimulator imsim;
276 
277  vpColVector X[4];
278  for (int i = 0; i < 4; i++)
279  X[i].resize(3);
280  X[0][0] = -0.2;
281  X[0][1] = -0.2;
282  X[0][2] = 0;
283 
284  X[1][0] = 0.2;
285  X[1][1] = -0.2;
286  X[1][2] = 0;
287 
288  X[2][0] = 0.2;
289  X[2][1] = 0.2;
290  X[2][2] = 0;
291 
292  X[3][0] = -0.2;
293  X[3][1] = 0.2;
294  X[3][2] = 0;
295 
296  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
297  // environment variable value
298  env_ipath = vpIoTools::getViSPImagesDataPath();
299 
300  if (!env_ipath.empty())
301  ipath = env_ipath;
302 
303  if (!opt_ipath.empty())
304  ipath = opt_ipath;
305 
306  filename = vpIoTools::createFilePath(ipath, "mire/mire.pgm");
307 
308  imsim.init(filename.c_str(), X);
309 
310  list.push_back(imsim);
311 
313 
314  // Set the scene
316 
317  // Initialize simulator frames
318  sim.set_fMo(wMo); // Position of the object in the world reference frame
319  sim.setCameraPositionRelObj(cMo); // Initial position of the object in the camera frame
320  sim.setDesiredCameraPosition(cdMo); // Desired position of the object in the camera frame
321 
322  // Set the External camera position
323  vpHomogeneousMatrix camMf(vpHomogeneousMatrix(0.0, 0, 3.5, vpMath::rad(0), vpMath::rad(30), 0));
324  sim.setExternalCameraPosition(camMf);
325 
326  // Computes the position of a camera which is fixed in the object frame
327  vpHomogeneousMatrix camoMf(0, 0.0, 1.5, 0, vpMath::rad(140), 0);
328  camoMf = camoMf * (sim.get_fMo().inverse());
329 
330  // Set the parameters of the cameras (internal and external)
331  vpCameraParameters camera(1000, 1000, 320, 240);
332  sim.setInternalCameraParameters(camera);
333  sim.setExternalCameraParameters(camera);
334 
335  int stop = 10;
336 
337  if (opt_display) {
338  stop = 2500;
339 
340  // Get the internal and external views
341  sim.getInternalImage(Iint);
342  sim.getExternalImage(Iext1);
343  sim.getExternalImage(Iext2, camoMf);
344 
345  // Display the object frame (current and desired position)
346  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
347  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
348 
349  // Display the object frame the world reference frame and the camera
350  // frame
351  vpDisplay::displayFrame(Iext1, camMf * sim.get_fMo() * cMo.inverse(), camera, 0.2, vpColor::none);
352  vpDisplay::displayFrame(Iext1, camMf * sim.get_fMo(), camera, 0.2, vpColor::none);
353  vpDisplay::displayFrame(Iext1, camMf, camera, 0.2, vpColor::none);
354 
355  // Display the world reference frame and the object frame
356  vpDisplay::displayFrame(Iext2, camoMf, camera, 0.2, vpColor::none);
357  vpDisplay::displayFrame(Iext2, camoMf * sim.get_fMo(), camera, 0.05, vpColor::none);
358 
359  vpDisplay::flush(Iint);
360  vpDisplay::flush(Iext1);
361  vpDisplay::flush(Iext2);
362 
363  std::cout << "Click on a display" << std::endl;
364  while (!vpDisplay::getClick(Iint, false) && !vpDisplay::getClick(Iext1, false) &&
365  !vpDisplay::getClick(Iext2, false)) {
366  };
367  }
368 
369  robot.setPosition(wMc);
370  // Print the task
371  task.print();
372 
373  int iter = 0;
374  vpColVector v;
375 
376  while (iter++ < stop) {
377  if (opt_display) {
378  vpDisplay::display(Iint);
379  vpDisplay::display(Iext1);
380  vpDisplay::display(Iext2);
381  }
382 
383  double t = vpTime::measureTimeMs();
384 
385  robot.get_eJe(eJe);
386  task.set_eJe(eJe);
387 
388  wMc = robot.getPosition();
389  cMo = wMc.inverse() * wMo;
390  for (int i = 0; i < 4; i++) {
391  point[i].track(cMo);
392  vpFeatureBuilder::create(p[i], point[i]);
393  }
394 
395  v = task.computeControlLaw();
397 
398  // Compute the movement of the object around the world reference frame.
399  vpHomogeneousMatrix a(0, 0, 0.2, 0, 0, 0);
400  vpHomogeneousMatrix b(0, 0, 0, vpMath::rad(1.5 * iter), 0, 0);
401  vpHomogeneousMatrix c(0, 0, 0, 0, vpMath::rad(2.5 * iter), 0);
402 
403  // Move the object in the world frame
404  wMo = b * c * a;
405 
406  sim.set_fMo(wMo); // Move the object in the simulator
407  sim.setCameraPositionRelObj(cMo);
408 
409  // Compute the position of the external view which is fixed in the
410  // object frame
411  camoMf.buildFrom(0, 0.0, 1.5, 0, vpMath::rad(150), 0);
412  camoMf = camoMf * (sim.get_fMo().inverse());
413 
414  if (opt_display) {
415  // Get the internal and external views
416  sim.getInternalImage(Iint);
417  sim.getExternalImage(Iext1);
418  sim.getExternalImage(Iext2, camoMf);
419 
420  // Display the object frame (current and desired position)
421  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
422  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
423 
424  // Display the camera frame, the object frame the world reference
425  // frame
426  vpDisplay::displayFrame(Iext1, sim.getExternalCameraPosition() * sim.get_fMo() * cMo.inverse(), camera, 0.2,
427  vpColor::none);
428  vpDisplay::displayFrame(Iext1, sim.getExternalCameraPosition() * sim.get_fMo(), camera, 0.2, vpColor::none);
430 
431  // Display the world reference frame and the object frame
432  vpDisplay::displayFrame(Iext2, camoMf, camera, 0.2, vpColor::none);
433  vpDisplay::displayFrame(Iext2, camoMf * sim.get_fMo(), camera, 0.05, vpColor::none);
434 
435  vpDisplay::flush(Iint);
436  vpDisplay::flush(Iext1);
437  vpDisplay::flush(Iext2);
438  }
439 
440  vpTime::wait(t, sampling_time * 1000); // Wait 40 ms
441 
442  std::cout << "|| s - s* || = " << (task.getError()).sumSquare() << std::endl;
443  }
444 
445  task.print();
446  task.kill();
447 
448  return EXIT_SUCCESS;
449  } catch (const vpException &e) {
450  std::cout << "Catch an exception: " << e << std::endl;
451  return EXIT_FAILURE;
452  }
453 }
454 #else
455 int main()
456 {
457  std::cout << "You do not have X11, or GDI (Graphical Device Interface), or GTK functionalities to display images..." << std::endl;
458  std::cout << "Tip if you are on a unix-like system:" << std::endl;
459  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
460  std::cout << "Tip if you are on a windows-like system:" << std::endl;
461  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
462  return EXIT_SUCCESS;
463 }
464 
465 #endif
void setPosition(const vpHomogeneousMatrix &wMc)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:164
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:173
void init(const vpImage< unsigned char > &I, vpColVector *X)
void setWorldCoordinates(double oX, double oY, double oZ)
Definition: vpPoint.cpp:113
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1292
Implementation of an homogeneous matrix and operations on such kind of matrices.
Class that defines the simplest robot: a free flying camera.
vpHomogeneousMatrix get_fMo() const
void addFeature(vpBasicFeature &s, vpBasicFeature &s_star, unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:497
void set_fMo(const vpHomogeneousMatrix &fMo_)
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
void set_eJe(const vpMatrix &eJe_)
Definition: vpServo.h:508
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:150
static const vpColor none
Definition: vpColor.h:191
error that can be emited by ViSP classes.
Definition: vpException.h:71
void track(const vpHomogeneousMatrix &cMo)
vpHomogeneousMatrix inverse() const
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
void setExternalCameraPosition(const vpHomogeneousMatrix &cam_Mf)
vpHomogeneousMatrix getPosition() const
void setDesiredCameraPosition(const vpHomogeneousMatrix &cdMo_)
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:126
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
void setMaxRotationVelocity(double maxVr)
Definition: vpRobot.cpp:260
Class that defines what is a point.
Definition: vpPoint.h:58
virtual void setSamplingTime(const double &delta_t)
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed...
Definition: vpDisplayD3D.h:106
void kill()
Definition: vpServo.cpp:192
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1537
vpColVector computeControlLaw()
Definition: vpServo.cpp:935
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Generic class defining intrinsic camera parameters.
void setLambda(double c)
Definition: vpServo.h:406
Class which enables to project an image in the 3D space and get the view of a virtual camera...
void initScene(const vpSceneObject &obj, const vpSceneDesiredObject &desiredObject)
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:137
void getExternalImage(vpImage< unsigned char > &I)
Implementation of a wire frame simulator. Compared to the vpSimulator class, it does not require thir...
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:574
static double rad(double deg)
Definition: vpMath.h:108
void setExternalCameraParameters(const vpCameraParameters &cam)
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
void setCameraPositionRelObj(const vpHomogeneousMatrix &cMo_)
void getInternalImage(vpImage< unsigned char > &I)
static void setWindowPosition(const vpImage< unsigned char > &I, int winx, int winy)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:130
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))
void set_cVe(const vpVelocityTwistMatrix &cVe_)
Definition: vpServo.h:450
void setInternalCameraParameters(const vpCameraParameters &cam)
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:313
vpColVector getError() const
Definition: vpServo.h:282
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
void get_eJe(vpMatrix &eJe)
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:223
void setMaxTranslationVelocity(double maxVt)
Definition: vpRobot.cpp:239
vpHomogeneousMatrix getExternalCameraPosition() const