Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
servoSimuCylinder2DCamVelocityDisplay.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  * Simulation of a 2D visual servoing on a cylinder.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 
50 #include <visp3/core/vpConfig.h>
51 #include <visp3/core/vpDebug.h>
52 
53 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
54 
55 #include <stdio.h>
56 #include <stdlib.h>
57 
58 #include <visp3/core/vpCameraParameters.h>
59 #include <visp3/core/vpCylinder.h>
60 #include <visp3/core/vpHomogeneousMatrix.h>
61 #include <visp3/core/vpImage.h>
62 #include <visp3/core/vpMath.h>
63 #include <visp3/gui/vpDisplayGDI.h>
64 #include <visp3/gui/vpDisplayGTK.h>
65 #include <visp3/gui/vpDisplayOpenCV.h>
66 #include <visp3/gui/vpDisplayX.h>
67 #include <visp3/io/vpParseArgv.h>
68 #include <visp3/robot/vpSimulatorCamera.h>
69 #include <visp3/visual_features/vpFeatureBuilder.h>
70 #include <visp3/visual_features/vpFeatureLine.h>
71 #include <visp3/vs/vpServo.h>
72 #include <visp3/vs/vpServoDisplay.h>
73 
74 // List of allowed command line options
75 #define GETOPTARGS "cdh"
76 
77 void usage(const char *name, const char *badparam);
78 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
79 
88 void usage(const char *name, const char *badparam)
89 {
90  fprintf(stdout, "\n\
91 Simulation of a 2D visual servoing on a cylinder:\n\
92 - eye-in-hand control law,\n\
93 - velocity computed in the camera frame,\n\
94 - display the camera view.\n\
95  \n\
96 SYNOPSIS\n\
97  %s [-c] [-d] [-h]\n", name);
98 
99  fprintf(stdout, "\n\
100 OPTIONS: Default\n\
101  \n\
102  -c\n\
103  Disable the mouse click. Useful to automaze the \n\
104  execution of this program without humain intervention.\n\
105  \n\
106  -d \n\
107  Turn off the display.\n\
108  \n\
109  -h\n\
110  Print the help.\n");
111 
112  if (badparam)
113  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
114 }
115 
127 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
128 {
129  const char *optarg_;
130  int c;
131  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
132 
133  switch (c) {
134  case 'c':
135  click_allowed = false;
136  break;
137  case 'd':
138  display = false;
139  break;
140  case 'h':
141  usage(argv[0], NULL);
142  return false;
143  break;
144 
145  default:
146  usage(argv[0], optarg_);
147  return false;
148  break;
149  }
150  }
151 
152  if ((c == 1) || (c == -1)) {
153  // standalone param or error
154  usage(argv[0], NULL);
155  std::cerr << "ERROR: " << std::endl;
156  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
157  return false;
158  }
159 
160  return true;
161 }
162 
163 int main(int argc, const char **argv)
164 {
165  try {
166  bool opt_display = true;
167  bool opt_click_allowed = true;
168 
169  // Read the command line options
170  if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
171  exit(-1);
172  }
173 
174  vpImage<unsigned char> I(512, 512, 255);
175 
176 // We open a window using either X11, GTK or GDI.
177 #if defined VISP_HAVE_X11
178  vpDisplayX display;
179 #elif defined VISP_HAVE_GTK
180  vpDisplayGTK display;
181 #elif defined VISP_HAVE_GDI
182  vpDisplayGDI display;
183 #elif defined VISP_HAVE_OPENCV
184  vpDisplayOpenCV display;
185 #endif
186 
187  if (opt_display) {
188  try {
189  // Display size is automatically defined by the image (I) size
190  display.init(I, 100, 100, "Camera view...");
191  // Display the image
192  // The image class has a member that specify a pointer toward
193  // the display that has been initialized in the display declaration
194  // therefore is is no longuer necessary to make a reference to the
195  // display variable.
197  vpDisplay::flush(I);
198  } catch (...) {
199  vpERROR_TRACE("Error while displaying the image");
200  exit(-1);
201  }
202  }
203 
204  double px, py;
205  px = py = 600;
206  double u0, v0;
207  u0 = v0 = 256;
208 
209  vpCameraParameters cam(px, py, u0, v0);
210 
211  vpServo task;
212  vpSimulatorCamera robot;
213 
214  // sets the initial camera location
215  vpHomogeneousMatrix cMo(-0.2, 0.1, 2, vpMath::rad(5), vpMath::rad(5), vpMath::rad(20));
216 
217  vpHomogeneousMatrix wMc, wMo;
218  robot.getPosition(wMc);
219  wMo = wMc * cMo; // Compute the position of the object in the world frame
220 
221  // sets the final camera location (for simulation purpose)
222  vpHomogeneousMatrix cMod(0, 0, 1, vpMath::rad(-60), vpMath::rad(0), vpMath::rad(0));
223 
224  // sets the cylinder coordinates in the world frame
225  vpCylinder cylinder(0, 1, 0, // direction
226  0, 0, 0, // point of the axis
227  0.1); // radius
228 
229  // sets the desired position of the visual feature
230  cylinder.track(cMod);
231  cylinder.print();
232 
233  vpFeatureLine ld[2];
234  int i;
235  for (i = 0; i < 2; i++)
236  vpFeatureBuilder::create(ld[i], cylinder, i);
237 
238  // computes the cylinder coordinates in the camera frame and its 2D
239  // coordinates sets the current position of the visual feature
240  cylinder.track(cMo);
241  cylinder.print();
242 
243  vpFeatureLine l[2];
244  for (i = 0; i < 2; i++) {
245  vpFeatureBuilder::create(l[i], cylinder, i);
246  l[i].print();
247  }
248 
249  // define the task
250  // - we want an eye-in-hand control law
251  // - robot is controlled in the camera frame
253  // task.setInteractionMatrixType(vpServo::CURRENT,
254  // vpServo::PSEUDO_INVERSE) ;
255  // it can also be interesting to test these possibilities
256  // task.setInteractionMatrixType(vpServo::MEAN,
257  // vpServo::PSEUDO_INVERSE) ;
259  // task.setInteractionMatrixType(vpServo::DESIRED, vpServo::TRANSPOSE) ;
260  // task.setInteractionMatrixType(vpServo::CURRENT, vpServo::TRANSPOSE) ;
261 
262  // - we want to see 2 lines on 2 lines
263  task.addFeature(l[0], ld[0]);
264  task.addFeature(l[1], ld[1]);
265 
266  vpServoDisplay::display(task, cam, I);
267  vpDisplay::flush(I);
268 
269  // Display task information
270  task.print();
271 
272  if (opt_display && opt_click_allowed) {
273  std::cout << "\n\nClick in the camera view window to start..." << std::endl;
275  }
276 
277  // - set the gain
278  task.setLambda(1);
279 
280  // Display task information
281  task.print();
282 
283  unsigned int iter = 0;
284  // loop
285  do {
286  std::cout << "---------------------------------------------" << iter++ << std::endl;
287  vpColVector v;
288 
289  // get the robot position
290  robot.getPosition(wMc);
291  // Compute the position of the object frame in the camera frame
292  cMo = wMc.inverse() * wMo;
293 
294  // new line position
295  // retrieve x,y and Z of the vpLine structure
296  cylinder.track(cMo);
297  // cylinder.print() ;
298  for (i = 0; i < 2; i++) {
299  vpFeatureBuilder::create(l[i], cylinder, i);
300  // l[i].print() ;
301  }
302 
303  if (opt_display) {
305  vpServoDisplay::display(task, cam, I);
306  vpDisplay::flush(I);
307  }
308 
309  // compute the control law
310  v = task.computeControlLaw();
311 
312  // send the camera velocity to the controller
314 
315  std::cout << "|| s - s* || = " << (task.getError()).sumSquare() << std::endl;
316  ;
317 
318  // vpDisplay::getClick(I) ;
319  } while ((task.getError()).sumSquare() > 1e-9);
320 
321  if (opt_display && opt_click_allowed) {
322  std::cout << "\nClick in the camera view window to end..." << std::endl;
324  }
325 
326  // Display task information
327  task.print();
328  task.kill();
329  return EXIT_SUCCESS;
330  } catch (const vpException &e) {
331  std::cout << "Catch a ViSP exception: " << e << std::endl;
332  return EXIT_FAILURE;
333  }
334 }
335 
336 #else
337 int main()
338 {
339  std::cout << "You do not have X11, or GTK, or GDI (Graphical Device Interface) functionalities to display images..." << std::endl;
340  std::cout << "Tip if you are on a unix-like system:" << std::endl;
341  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
342  std::cout << "Tip if you are on a windows-like system:" << std::endl;
343  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
344  return EXIT_SUCCESS;
345 }
346 #endif
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.
void addFeature(vpBasicFeature &s, vpBasicFeature &s_star, unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:497
#define vpERROR_TRACE
Definition: vpDebug.h:393
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:150
error that can be emited by ViSP classes.
Definition: vpException.h:71
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
vpHomogeneousMatrix inverse() const
vpHomogeneousMatrix getPosition() const
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
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 ...
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:137
void print(unsigned int select=FEATURE_ALL) const
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:574
static double rad(double deg)
Definition: vpMath.h:108
Class that defines what is a cylinder.
Definition: vpCylinder.h:96
Implementation of column vector and the associated operations.
Definition: vpColVector.h:130
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 setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:223
static void display(const vpServo &s, const vpCameraParameters &cam, const vpImage< unsigned char > &I, vpColor currentColor=vpColor::green, vpColor desiredColor=vpColor::red, unsigned int thickness=1)