ViSP  2.9.0
servoSimuCylinder2DCamVelocityDisplaySecondaryTask.cpp
1 /****************************************************************************
2  *
3  * $Id: servoSimuCylinder2DCamVelocityDisplaySecondaryTask.cpp 2457 2010-01-07 10:41:18Z nmelchio $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Simulation of a 2D visual servoing on a cylinder.
36  *
37  * Authors:
38  * Nicolas Melchior
39  *
40  *****************************************************************************/
57 #include <visp/vpConfig.h>
58 
59 #if (defined (VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
60 
61 #include <stdlib.h>
62 #include <stdio.h>
63 
64 #include <visp/vpCameraParameters.h>
65 #include <visp/vpCylinder.h>
66 #include <visp/vpDisplayX.h>
67 #include <visp/vpDisplayGTK.h>
68 #include <visp/vpDisplayGDI.h>
69 #include <visp/vpFeatureBuilder.h>
70 #include <visp/vpFeatureLine.h>
71 #include <visp/vpHomogeneousMatrix.h>
72 #include <visp/vpImage.h>
73 #include <visp/vpMath.h>
74 #include <visp/vpParseArgv.h>
75 #include <visp/vpProjectionDisplay.h>
76 #include <visp/vpServo.h>
77 #include <visp/vpSimulatorCamera.h>
78 #include <visp/vpServoDisplay.h>
79 
80 // List of allowed command line options
81 #define GETOPTARGS "cdh"
82 
83 void usage(const char *name, const char *badparam);
84 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
85 
94 void usage(const char *name, const char *badparam)
95 {
96  fprintf(stdout, "\n\
97 Simulation of a 2D visual servoing on a cylinder:\n\
98 - eye-in-hand control law,\n\
99 - velocity computed in the camera frame,\n\
100 - display the camera view.\n\
101  \n\
102 SYNOPSIS\n\
103  %s [-c] [-d] [-h]\n", name);
104 
105  fprintf(stdout, "\n\
106 OPTIONS: Default\n\
107  \n\
108  -c\n\
109  Disable the mouse click. Useful to automaze the \n\
110  execution of this program without humain intervention.\n\
111  \n\
112  -d \n\
113  Turn off the display.\n\
114  \n\
115  -h\n\
116  Print the help.\n");
117 
118  if (badparam)
119  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
120 }
121 
133 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
134 {
135  const char *optarg_;
136  int c;
137  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
138 
139  switch (c) {
140  case 'c': click_allowed = false; break;
141  case 'd': display = false; break;
142  case 'h': usage(argv[0], NULL); return false; break;
143 
144  default:
145  usage(argv[0], optarg_);
146  return false; break;
147  }
148  }
149 
150  if ((c == 1) || (c == -1)) {
151  // standalone param or error
152  usage(argv[0], NULL);
153  std::cerr << "ERROR: " << std::endl;
154  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
155  return false;
156  }
157 
158  return true;
159 }
160 
161 
162 int
163 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> Iint(512,512,0) ;
175  vpImage<unsigned char> Iext(512,512,0) ;
176 
177  // We open a window using either X11, GTK or GDI.
178 #if defined VISP_HAVE_X11
179  vpDisplayX displayInt;
180  vpDisplayX displayExt;
181 #elif defined VISP_HAVE_GTK
182  vpDisplayGTK displayInt;
183  vpDisplayGTK displayExt;
184 #elif defined VISP_HAVE_GDI
185  vpDisplayGDI displayInt;
186  vpDisplayGDI 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 or GDI display functionalities..." << std::endl;
460 }
461 
462 #endif
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:159
void print(const unsigned int select=FEATURE_ALL) const
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
#define vpERROR_TRACE
Definition: vpDebug.h:395
Class that defines the simplest robot: a free flying camera.
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
Define the X11 console to display images.
Definition: vpDisplayX.h:152
void addFeature(vpBasicFeature &s, vpBasicFeature &s_star, const unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:449
error that can be emited by ViSP classes.
Definition: vpException.h:76
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
static const vpColor red
Definition: vpColor.h:167
vpColVector secondaryTask(const vpColVector &de2dt)
Definition: vpServo.cpp:1416
void kill()
Definition: vpServo.cpp:189
vpColVector getError() const
Definition: vpServo.h:257
vpColVector computeControlLaw()
Definition: vpServo.cpp:902
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
Generic class defining intrinsic camera parameters.
void getPosition(vpHomogeneousMatrix &wMc) const
void setLambda(double c)
Definition: vpServo.h:370
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+ library version 1.2.
Definition: vpDisplayGTK.h:145
void insert(vpForwardProjection &fp)
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:522
static double rad(double deg)
Definition: vpMath.h:100
Class that defines what is a cylinder.
Definition: vpCylinder.h:97
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
vpHomogeneousMatrix inverse() const
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:251
virtual bool getClick(bool blocking=true)=0
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:220
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)