Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
servoSimuCylinder2DCamVelocityDisplaySecondaryTask.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Simulation of a 2D visual servoing on a cylinder.
32  *
33  * Authors:
34  * Nicolas Melchior
35  *
36  *****************************************************************************/
53 #include <visp3/core/vpConfig.h>
54 
55 #if (defined (VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
56 
57 #include <stdlib.h>
58 #include <stdio.h>
59 
60 #include <visp3/core/vpCameraParameters.h>
61 #include <visp3/core/vpCylinder.h>
62 #include <visp3/gui/vpDisplayX.h>
63 #include <visp3/gui/vpDisplayGTK.h>
64 #include <visp3/gui/vpDisplayGDI.h>
65 #include <visp3/gui/vpDisplayOpenCV.h>
66 #include <visp3/visual_features/vpFeatureBuilder.h>
67 #include <visp3/visual_features/vpFeatureLine.h>
68 #include <visp3/core/vpHomogeneousMatrix.h>
69 #include <visp3/core/vpImage.h>
70 #include <visp3/core/vpMath.h>
71 #include <visp3/io/vpParseArgv.h>
72 #include <visp3/gui/vpProjectionDisplay.h>
73 #include <visp3/vs/vpServo.h>
74 #include <visp3/robot/vpSimulatorCamera.h>
75 #include <visp3/vs/vpServoDisplay.h>
76 
77 // List of allowed command line options
78 #define GETOPTARGS "cdh"
79 
80 void usage(const char *name, const char *badparam);
81 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
82 
91 void usage(const char *name, const char *badparam)
92 {
93  fprintf(stdout, "\n\
94 Simulation of a 2D visual servoing on a cylinder:\n\
95 - eye-in-hand control law,\n\
96 - velocity computed in the camera frame,\n\
97 - display the camera view.\n\
98  \n\
99 SYNOPSIS\n\
100  %s [-c] [-d] [-h]\n", name);
101 
102  fprintf(stdout, "\n\
103 OPTIONS: Default\n\
104  \n\
105  -c\n\
106  Disable the mouse click. Useful to automaze the \n\
107  execution of this program without humain intervention.\n\
108  \n\
109  -d \n\
110  Turn off the display.\n\
111  \n\
112  -h\n\
113  Print the help.\n");
114 
115  if (badparam)
116  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
117 }
118 
130 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
131 {
132  const char *optarg_;
133  int c;
134  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
135 
136  switch (c) {
137  case 'c': click_allowed = false; break;
138  case 'd': display = false; break;
139  case 'h': usage(argv[0], NULL); return false; break;
140 
141  default:
142  usage(argv[0], optarg_);
143  return false; break;
144  }
145  }
146 
147  if ((c == 1) || (c == -1)) {
148  // standalone param or error
149  usage(argv[0], NULL);
150  std::cerr << "ERROR: " << std::endl;
151  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
152  return false;
153  }
154 
155  return true;
156 }
157 
158 
159 int
160 main(int argc, const char ** argv)
161 {
162  try {
163  bool opt_display = true;
164  bool opt_click_allowed = true;
165 
166  // Read the command line options
167  if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
168  exit (-1);
169  }
170 
171  vpImage<unsigned char> Iint(512,512,0) ;
172  vpImage<unsigned char> Iext(512,512,0) ;
173 
174  // We open a window using either X11, GTK or GDI.
175 #if defined VISP_HAVE_X11
176  vpDisplayX displayInt;
177  vpDisplayX displayExt;
178 #elif defined VISP_HAVE_GTK
179  vpDisplayGTK displayInt;
180  vpDisplayGTK displayExt;
181 #elif defined VISP_HAVE_GDI
182  vpDisplayGDI displayInt;
183  vpDisplayGDI displayExt;
184 #elif defined VISP_HAVE_OPENCV
185  vpDisplayOpenCV displayInt;
186  vpDisplayOpenCV displayExt;
187 #endif
188 
189  if (opt_display) {
190  try{
191  // Display size is automatically defined by the image (Iint) and (Iext) size
192  displayInt.init(Iint, 100, 100,"Internal view") ;
193  displayExt.init(Iext, (int)(130+Iint.getWidth()), 100, "External view") ;
194  // Display the image
195  // The image class has a member that specify a pointer toward
196  // the display that has been initialized in the display declaration
197  // therefore is is no longuer necessary to make a reference to the
198  // display variable.
199  vpDisplay::display(Iint) ;
200  vpDisplay::display(Iext) ;
201  vpDisplay::flush(Iint) ;
202  vpDisplay::flush(Iext) ;
203  }
204  catch(...)
205  {
206  vpERROR_TRACE("Error while displaying the image") ;
207  exit(-1);
208  }
209  }
210 
211  vpProjectionDisplay externalview ;
212 
213  //Set the camera parameters
214  double px, py ; px = py = 600 ;
215  double u0, v0 ; u0 = v0 = 256 ;
216 
217  vpCameraParameters cam(px,py,u0,v0);
218 
219  vpServo task ;
220  vpSimulatorCamera robot ;
221 
222  // sets the initial camera location
223  vpHomogeneousMatrix cMo(-0.2,0.1,2,
224  vpMath::rad(5), vpMath::rad(5), vpMath::rad(20));
225 
226  vpHomogeneousMatrix wMc, wMo;
227  robot.getPosition(wMc) ;
228  wMo = wMc * cMo; // Compute the position of the object in the world frame
229 
230  // sets the final camera location (for simulation purpose)
231  vpHomogeneousMatrix cMod(0,0,1,
232  vpMath::rad(0), vpMath::rad(0), vpMath::rad(0));
233 
234  // sets the cylinder coordinates in the world frame
235  vpCylinder cylinder(0,1,0, // direction
236  0,0,0, // point of the axis
237  0.1) ; // radius
238 
239  externalview.insert(cylinder) ;
240 
241  // sets the desired position of the visual feature
242  cylinder.track(cMod) ;
243  cylinder.print() ;
244 
245  //Build the desired line features thanks to the cylinder and especially its paramaters in the image frame
246  vpFeatureLine ld[2] ;
247  int i ;
248  for(i=0 ; i < 2 ; i++)
249  vpFeatureBuilder::create(ld[i],cylinder,i) ;
250 
251  // computes the cylinder coordinates in the camera frame and its 2D coordinates
252  // sets the current position of the visual feature
253  cylinder.track(cMo) ;
254  cylinder.print() ;
255 
256  //Build the current line features thanks to the cylinder and especially its paramaters in the image frame
257  vpFeatureLine l[2] ;
258  for(i=0 ; i < 2 ; i++)
259  {
260  vpFeatureBuilder::create(l[i],cylinder,i) ;
261  l[i].print() ;
262  }
263 
264  // define the task
265  // - we want an eye-in-hand control law
266  // - robot is controlled in the camera frame
269  // it can also be interesting to test these possibilities
270  // task.setInteractionMatrixType(vpServo::CURRENT,vpServo::PSEUDO_INVERSE) ;
271  // task.setInteractionMatrixType(vpServo::MEAN, vpServo::PSEUDO_INVERSE) ;
272  // task.setInteractionMatrixType(vpServo::CURRENT, vpServo::PSEUDO_INVERSE) ;
273  // task.setInteractionMatrixType(vpServo::DESIRED, vpServo::TRANSPOSE) ;
274  // task.setInteractionMatrixType(vpServo::CURRENT, vpServo::TRANSPOSE) ;
275 
276  // we want to see 2 lines on 2 lines
277  task.addFeature(l[0],ld[0]) ;
278  task.addFeature(l[1],ld[1]) ;
279 
280  // Set the point of view of the external view
281  vpHomogeneousMatrix cextMo(0,0,6,
282  vpMath::rad(40), vpMath::rad(10), vpMath::rad(60)) ;
283 
284  // Display the initial scene
285  vpServoDisplay::display(task,cam,Iint) ;
286  externalview.display(Iext,cextMo, cMo, cam, vpColor::red);
287  vpDisplay::flush(Iint) ;
288  vpDisplay::flush(Iext) ;
289 
290  // Display task information
291  task.print() ;
292 
293  if (opt_display && opt_click_allowed) {
294  std::cout << "\n\nClick in the internal camera view window to start..." << std::endl;
295  vpDisplay::getClick(Iint) ;
296  }
297 
298  // set the gain
299  task.setLambda(1) ;
300 
301  // Display task information
302  task.print() ;
303 
304  unsigned int iter=0 ;
305  // The first loop is needed to reach the desired position
306  do
307  {
308  std::cout << "---------------------------------------------" << iter++ <<std::endl ;
309  vpColVector v ;
310 
311  // get the robot position
312  robot.getPosition(wMc) ;
313  // Compute the position of the camera wrt the object frame
314  cMo = wMc.inverse() * wMo;
315 
316  // new line position
317  // retrieve x,y and Z of the vpLine structure
318  // Compute the parameters of the cylinder in the camera frame and in the image frame
319  cylinder.track(cMo) ;
320 
321  //Build the current line features thanks to the cylinder and especially its paramaters in the image frame
322  for(i=0 ; i < 2 ; i++)
323  {
324  vpFeatureBuilder::create(l[i],cylinder,i) ;
325  }
326 
327  // Display the current scene
328  if (opt_display) {
329  vpDisplay::display(Iint) ;
330  vpDisplay::display(Iext) ;
331  vpServoDisplay::display(task,cam,Iint) ;
332  externalview.display(Iext,cextMo, cMo, cam, vpColor::red);
333  vpDisplay::flush(Iint);
334  vpDisplay::flush(Iext);
335  }
336 
337  // compute the control law
338  v = task.computeControlLaw() ;
339 
340  // send the camera velocity to the controller
342 
343  std::cout << "|| s - s* || = " << ( task.getError() ).sumSquare() <<std::endl ;
344  }
345  while(( task.getError() ).sumSquare() > 1e-9) ;
346 
347 
348  // Second loop is to compute the control law while taking into account the secondary task.
349  // In this example the secondary task is cut in four steps.
350  // The first one consists in impose a movement of the robot along the x axis of the object frame with a velocity of 0.5.
351  // The second one consists in impose a movement of the robot along the y axis of the object frame with a velocity of 0.5.
352  // The third one consists in impose a movement of the robot along the x axis of the object frame with a velocity of -0.5.
353  // The last one consists in impose a movement of the robot along the y axis of the object frame with a velocity of -0.5.
354  // Each steps is made during 200 iterations.
355  vpColVector e1(6) ; e1 = 0 ;
356  vpColVector e2(6) ; e2 = 0 ;
357  vpColVector proj_e1 ;
358  vpColVector proj_e2 ;
359  iter = 0;
360  double rapport = 0;
361  double vitesse = 0.5;
362  unsigned int tempo = 800;
363 
364  while(iter < tempo)
365  {
366  vpColVector v ;
367 
368  robot.getPosition(wMc) ;
369  // Compute the position of the camera wrt the object frame
370  cMo = wMc.inverse() * wMo;
371 
372  cylinder.track(cMo) ;
373 
374  for(i=0 ; i < 2 ; i++)
375  {
376  vpFeatureBuilder::create(l[i],cylinder,i) ;
377  }
378 
379  if (opt_display)
380  {
381  vpDisplay::display(Iint) ;
382  vpDisplay::display(Iext) ;
383  vpServoDisplay::display(task,cam,Iint) ;
384  externalview.display(Iext,cextMo, cMo, cam, vpColor::red);
385  vpDisplay::flush(Iint);
386  vpDisplay::flush(Iext);
387  }
388 
389  v = task.computeControlLaw() ;
390 
391  if ( iter%tempo < 200 /*&& iter%tempo >= 0*/)
392  {
393  e2 = 0;
394  e1[0] = fabs(vitesse) ;
395  proj_e1 = task.secondaryTask(e1);
396  rapport = vitesse/proj_e1[0];
397  proj_e1 *= rapport ;
398  v += proj_e1 ;
399  }
400 
401  if ( iter%tempo < 400 && iter%tempo >= 200)
402  {
403  e1 = 0;
404  e2[1] = fabs(vitesse) ;
405  proj_e2 = task.secondaryTask(e2);
406  rapport = vitesse/proj_e2[1];
407  proj_e2 *= rapport ;
408  v += proj_e2 ;
409  }
410 
411  if ( iter%tempo < 600 && iter%tempo >= 400)
412  {
413  e2 = 0;
414  e1[0] = -fabs(vitesse) ;
415  proj_e1 = task.secondaryTask(e1);
416  rapport = -vitesse/proj_e1[0];
417  proj_e1 *= rapport ;
418  v += proj_e1 ;
419  }
420 
421  if ( iter%tempo < 800 && iter%tempo >= 600)
422  {
423  e1 = 0;
424  e2[1] = -fabs(vitesse) ;
425  proj_e2 = task.secondaryTask(e2);
426  rapport = -vitesse/proj_e2[1];
427  proj_e2 *= rapport ;
428  v += proj_e2 ;
429  }
430 
432 
433  std::cout << "|| s - s* || = " << ( task.getError() ).sumSquare() <<std::endl ;
434 
435  iter++;
436  }
437 
438  if (opt_display && opt_click_allowed) {
439  std::cout << "\nClick in the internal camera view window to end..." << std::endl;
440  vpDisplay::getClick(Iint) ;
441  }
442 
443  // Display task information
444  task.print() ;
445  task.kill();
446  return 0;
447  }
448  catch(vpException &e) {
449  std::cout << "Catch a ViSP exception: " << e << std::endl;
450  return 1;
451  }
452 }
453 
454 #else
455 #include <iostream>
456 
457 int main()
458 {
459  std::cout << "You do not have X11, GTK, GDI or OpenCV display functionalities..." << std::endl;
460 }
461 
462 #endif
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel)
void display(vpImage< unsigned char > &I, const vpHomogeneousMatrix &cextMo, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &color, const bool &displayTraj=false, const unsigned int thickness=1)
unsigned int getWidth() const
Definition: vpImage.h:226
void print(const unsigned int select=FEATURE_ALL) const
Implementation of an homogeneous matrix and operations on such kind of matrices.
Class that defines the simplest robot: a free flying camera.
#define vpERROR_TRACE
Definition: vpDebug.h:391
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:153
void addFeature(vpBasicFeature &s, vpBasicFeature &s_star, const unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:512
error that can be emited by ViSP classes.
Definition: vpException.h:73
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:76
static const vpColor red
Definition: vpColor.h:163
vpColVector secondaryTask(const vpColVector &de2dt, const bool &useLargeProjectionOperator=false)
Definition: vpServo.cpp:1513
void kill()
Definition: vpServo.cpp:191
vpColVector getError() const
Definition: vpServo.h:271
vpColVector computeControlLaw()
Definition: vpServo.cpp:954
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:391
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:138
void insert(vpForwardProjection &fp)
vpHomogeneousMatrix getPosition() const
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:585
static double rad(double deg)
Definition: vpMath.h:104
Class that defines what is a cylinder.
Definition: vpCylinder.h:93
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpHomogeneousMatrix inverse() const
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:314
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
interface with the image for feature display
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:222
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)