Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
servoSimuCylinder.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/vpCylinder.h>
49 #include <visp3/core/vpHomogeneousMatrix.h>
50 #include <visp3/core/vpImage.h>
51 #include <visp3/core/vpIoTools.h>
52 #include <visp3/core/vpMath.h>
53 #include <visp3/core/vpTime.h>
54 #include <visp3/core/vpVelocityTwistMatrix.h>
55 #include <visp3/gui/vpDisplayD3D.h>
56 #include <visp3/gui/vpDisplayGDI.h>
57 #include <visp3/gui/vpDisplayGTK.h>
58 #include <visp3/gui/vpDisplayOpenCV.h>
59 #include <visp3/gui/vpDisplayX.h>
60 #include <visp3/io/vpImageIo.h>
61 #include <visp3/io/vpParseArgv.h>
62 #include <visp3/robot/vpSimulatorCamera.h>
63 #include <visp3/robot/vpWireFrameSimulator.h>
64 #include <visp3/visual_features/vpFeatureBuilder.h>
65 #include <visp3/vs/vpServo.h>
66 
67 #define GETOPTARGS "dh"
68 
69 #ifdef VISP_HAVE_DISPLAY
70 void usage(const char *name, const char *badparam);
71 bool getOptions(int argc, const char **argv, bool &display);
72 
81 void usage(const char *name, const char *badparam)
82 {
83  fprintf(stdout, "\n\
84 Demonstration of the wireframe simulator with a simple visual servoing.\n\
85  \n\
86 The visual servoing consists in bringing the camera at a desired position\n\
87 from the object.\n\
88  \n\
89 The visual features used to compute the pose of the camera and \n\
90 thus the control law are two lines. These features are computed thanks \n\
91 to the equation of a cylinder.\n\
92  \n\
93 This demonstration explains also how to move the object around a world \n\
94 reference frame. Here, the movment is a rotation around the x and y axis \n\
95 at a given distance from the world frame. In fact the object trajectory \n\
96 is on a sphere whose center is the origin of the world frame.\n\
97  \n\
98 SYNOPSIS\n\
99  %s [-d] [-h]\n", name);
100 
101  fprintf(stdout, "\n\
102 OPTIONS: \n\
103  -d \n\
104  Turn off the display.\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 
124 bool getOptions(int argc, const char **argv, bool &display)
125 {
126  const char *optarg_;
127  int c;
128  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
129 
130  switch (c) {
131  case 'd':
132  display = false;
133  break;
134  case 'h':
135  usage(argv[0], NULL);
136  return false;
137  break;
138 
139  default:
140  usage(argv[0], optarg_);
141  return false;
142  break;
143  }
144  }
145 
146  if ((c == 1) || (c == -1)) {
147  // standalone param or error
148  usage(argv[0], NULL);
149  std::cerr << "ERROR: " << std::endl;
150  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
151  return false;
152  }
153 
154  return true;
155 }
156 
157 int main(int argc, const char **argv)
158 {
159  try {
160  bool opt_display = true;
161 
162  // Read the command line options
163  if (getOptions(argc, argv, opt_display) == false) {
164  exit(-1);
165  }
166 
167  vpImage<vpRGBa> Iint(480, 640, 255);
168  vpImage<vpRGBa> Iext(480, 640, 255);
169 
170 #if defined VISP_HAVE_X11
171  vpDisplayX display[2];
172 #elif defined VISP_HAVE_OPENCV
173  vpDisplayOpenCV display[2];
174 #elif defined VISP_HAVE_GDI
175  vpDisplayGDI display[2];
176 #elif defined VISP_HAVE_D3D9
177  vpDisplayD3D display[2];
178 #elif defined VISP_HAVE_GTK
179  vpDisplayGTK display[2];
180 #endif
181 
182  if (opt_display) {
183  // Display size is automatically defined by the image (I) size
184  display[0].init(Iint, 100, 100, "The internal view");
185  display[1].init(Iext, 100, 100, "The first external view");
186  vpDisplay::setWindowPosition(Iint, 0, 0);
187  vpDisplay::setWindowPosition(Iext, 700, 0);
188  vpDisplay::display(Iint);
189  vpDisplay::flush(Iint);
190  vpDisplay::display(Iext);
191  vpDisplay::flush(Iext);
192  }
193 
194  vpServo task;
195  vpSimulatorCamera robot;
196  float sampling_time = 0.040f; // Sampling period in second
197  robot.setSamplingTime(sampling_time);
198 
199  // Set initial position of the object in the camera frame
200  vpHomogeneousMatrix cMo(0, 0.1, 0.3, vpMath::rad(35), vpMath::rad(25), vpMath::rad(75));
201  // Set desired position of the object in the camera frame
202  vpHomogeneousMatrix cdMo(0.0, 0.0, 0.5, vpMath::rad(90), vpMath::rad(0), vpMath::rad(0));
203  // Set initial position of the object in the world frame
204  vpHomogeneousMatrix wMo(0.0, 0.0, 0, 0, 0, 0);
205  // Position of the camera in the world frame
207  wMc = wMo * cMo.inverse();
208 
209  // Create a cylinder
210  vpCylinder cylinder(0, 0, 1, 0, 0, 0, 0.1);
211 
212  // Projection of the cylinder
213  cylinder.track(cMo);
214 
215  // Set the current visual feature
216  vpFeatureLine l[2];
219 
220  // Projection of the cylinder
221  cylinder.track(cdMo);
222 
223  vpFeatureLine ld[2];
226 
229 
231  vpVelocityTwistMatrix cVe(cMe);
232  task.set_cVe(cVe);
233 
234  vpMatrix eJe;
235  robot.get_eJe(eJe);
236  task.set_eJe(eJe);
237 
238  for (int i = 0; i < 2; i++)
239  task.addFeature(l[i], ld[i]);
240 
241  task.setLambda(1);
242 
244 
245  // Set the scene
247 
248  // Initialize simulator frames
249  sim.set_fMo(wMo); // Position of the object in the world reference frame
250  sim.setCameraPositionRelObj(cMo); // Initial position of the object in the camera frame
251  sim.setDesiredCameraPosition(cdMo); // Desired position of the object in the camera frame
252 
253  // Set the External camera position
254  vpHomogeneousMatrix camMf(vpHomogeneousMatrix(0.0, 0, 3.5, vpMath::rad(0), vpMath::rad(30), 0));
255  sim.setExternalCameraPosition(camMf);
256 
257  // Set the parameters of the cameras (internal and external)
258  vpCameraParameters camera(1000, 1000, 320, 240);
259  sim.setInternalCameraParameters(camera);
260  sim.setExternalCameraParameters(camera);
261 
262  int stop = 10;
263 
264  if (opt_display) {
265  stop = 2500;
266 
267  // Get the internal and external views
268  sim.getInternalImage(Iint);
269  sim.getExternalImage(Iext);
270 
271  // Display the object frame (current and desired position)
272  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
273  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
274 
275  // Display the object frame the world reference frame and the camera
276  // frame
277  vpDisplay::displayFrame(Iext, camMf * sim.get_fMo() * cMo.inverse(), camera, 0.2, vpColor::none);
278  vpDisplay::displayFrame(Iext, camMf * sim.get_fMo(), camera, 0.2, vpColor::none);
279  vpDisplay::displayFrame(Iext, camMf, camera, 0.2, vpColor::none);
280 
281  vpDisplay::flush(Iint);
282  vpDisplay::flush(Iext);
283 
284  std::cout << "Click on a display" << std::endl;
285  while (!vpDisplay::getClick(Iint, false) && !vpDisplay::getClick(Iext, false)) {
286  };
287  }
288 
289  robot.setPosition(wMc);
290 
291  // Print the task
292  task.print();
293 
294  int iter = 0;
295  vpColVector v;
296 
297  // Set the secondary task parameters
298  vpColVector e1(6);
299  e1 = 0;
300  vpColVector e2(6);
301  e2 = 0;
302  vpColVector proj_e1;
303  vpColVector proj_e2;
304  iter = 0;
305  double rapport = 0;
306  double vitesse = 0.3;
307  int tempo = 600;
308 
309  while (iter++ < stop) {
310  if (opt_display) {
311  vpDisplay::display(Iint);
312  vpDisplay::display(Iext);
313  }
314 
315  double t = vpTime::measureTimeMs();
316 
317  robot.get_eJe(eJe);
318  task.set_eJe(eJe);
319 
320  wMc = robot.getPosition();
321  cMo = wMc.inverse() * wMo;
322 
323  cylinder.track(cMo);
326 
327  v = task.computeControlLaw();
328 
329  // Compute the velocity with the secondary task
330  if (iter % tempo < 200 && iter % tempo >= 0) {
331  e2 = 0;
332  e1[0] = -fabs(vitesse);
333  proj_e1 = task.secondaryTask(e1);
334  rapport = -vitesse / proj_e1[0];
335  proj_e1 *= rapport;
336  v += proj_e1;
337  }
338 
339  if (iter % tempo < 300 && iter % tempo >= 200) {
340  e1 = 0;
341  e2[1] = -fabs(vitesse);
342  proj_e2 = task.secondaryTask(e2);
343  rapport = -vitesse / proj_e2[1];
344  proj_e2 *= rapport;
345  v += proj_e2;
346  }
347 
348  if (iter % tempo < 500 && iter % tempo >= 300) {
349  e2 = 0;
350  e1[0] = -fabs(vitesse);
351  proj_e1 = task.secondaryTask(e1);
352  rapport = vitesse / proj_e1[0];
353  proj_e1 *= rapport;
354  v += proj_e1;
355  }
356 
357  if (iter % tempo < 600 && iter % tempo >= 500) {
358  e1 = 0;
359  e2[1] = -fabs(vitesse);
360  proj_e2 = task.secondaryTask(e2);
361  rapport = vitesse / proj_e2[1];
362  proj_e2 *= rapport;
363  v += proj_e2;
364  }
365 
367 
368  // Update the simulator frames
369  sim.set_fMo(wMo); // This line is not really requested since the object
370  // doesn't move
371  sim.setCameraPositionRelObj(cMo);
372 
373  if (opt_display) {
374  // Get the internal and external views
375  sim.getInternalImage(Iint);
376  sim.getExternalImage(Iext);
377 
378  // Display the object frame (current and desired position)
379  vpDisplay::displayFrame(Iint, cMo, camera, 0.2, vpColor::none);
380  vpDisplay::displayFrame(Iint, cdMo, camera, 0.2, vpColor::none);
381 
382  // Display the object frame the world reference frame and the camera
383  // frame
384  vpDisplay::displayFrame(Iext, sim.getExternalCameraPosition() * sim.get_fMo() * cMo.inverse(), camera, 0.2,
385  vpColor::none);
386  vpDisplay::displayFrame(Iext, sim.getExternalCameraPosition() * sim.get_fMo(), camera, 0.2, vpColor::none);
388  ;
389 
390  vpDisplay::flush(Iint);
391  vpDisplay::flush(Iext);
392  }
393 
394  vpTime::wait(t, sampling_time * 1000); // Wait 40 ms
395 
396  std::cout << "|| s - s* || = " << (task.getError()).sumSquare() << std::endl;
397  }
398 
399  task.print();
400  task.kill();
401 
402  return EXIT_SUCCESS;
403  } catch (const vpException &e) {
404  std::cout << "Catch an exception: " << e << std::endl;
405  return EXIT_FAILURE;
406  }
407 }
408 #else
409 int main()
410 {
411  std::cout << "You do not have X11, or GDI (Graphical Device Interface), or GTK functionalities to display images..." << std::endl;
412  std::cout << "Tip if you are on a unix-like system:" << std::endl;
413  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
414  std::cout << "Tip if you are on a windows-like system:" << std::endl;
415  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
416  return EXIT_SUCCESS;
417 }
418 
419 #endif
void setPosition(const vpHomogeneousMatrix &wMc)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:164
A cylinder of 80cm length and 10cm radius.
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:173
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel)
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
vpHomogeneousMatrix inverse() const
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
vpColVector secondaryTask(const vpColVector &de2dt, const bool &useLargeProjectionOperator=false)
Definition: vpServo.cpp:1485
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
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 that defines a 2D line visual feature which is composed by two parameters that are and ...
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)
Class that defines what is a cylinder.
Definition: vpCylinder.h:96
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
vpHomogeneousMatrix getExternalCameraPosition() const