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