ViSP  2.9.0
servoSimu4Points.cpp
1 /****************************************************************************
2  *
3  * $Id: servoSimu4Points.cpp 4659 2014-02-09 14:11:51Z fspindle $
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  * Demonstration of the wireframe simulator with a simple visual servoing
36  *
37  * Authors:
38  * Nicolas Melchior
39  *
40  *****************************************************************************/
41 
48 #include <stdlib.h>
49 
50 #include <visp/vpCameraParameters.h>
51 #include <visp/vpDisplayOpenCV.h>
52 #include <visp/vpDisplayX.h>
53 #include <visp/vpDisplayGTK.h>
54 #include <visp/vpDisplayGDI.h>
55 #include <visp/vpDisplayD3D.h>
56 #include <visp/vpFeatureBuilder.h>
57 #include <visp/vpFeaturePoint.h>
58 #include <visp/vpHomogeneousMatrix.h>
59 #include <visp/vpImage.h>
60 #include <visp/vpImageIo.h>
61 #include <visp/vpIoTools.h>
62 #include <visp/vpMath.h>
63 #include <visp/vpParseArgv.h>
64 #include <visp/vpServo.h>
65 #include <visp/vpSimulatorCamera.h>
66 #include <visp/vpTime.h>
67 #include <visp/vpVelocityTwistMatrix.h>
68 #include <visp/vpWireFrameSimulator.h>
69 
70 #define GETOPTARGS "dh"
71 
72 #ifdef VISP_HAVE_DISPLAY
73 
74 void usage(const char *name, std::string ipath, const char *badparam);
75 bool getOptions(int argc, const char **argv, std::string &ipath, bool &display);
76 
86 void usage(const char *name, std::string ipath, const char *badparam)
87 {
88  fprintf(stdout, "\n\
89 Demonstration of the wireframe simulator with a simple visual servoing.\n\
90  \n\
91 The visual servoing consists in bringing the camera at a desired \n\
92 position from the object.\n\
93  \n\
94 The visual features used to compute the pose of the camera and \n\
95 thus the control law are four points.\n\
96  \n\
97 This demonstration explains also how to move the object around a world\n\
98 reference frame. Here, the movement is a rotation around the x and y axis\n\
99 at a given distance from the world frame. In fact the object trajectory\n\
100 is on a sphere whose center is the origin of the world frame.\n\
101  \n\
102 SYNOPSIS\n\
103  %s [-d] [-h]\n", name);
104 
105  fprintf(stdout, "\n\
106 OPTIONS: Default\n\
107  -i <input image path> %s\n\
108  Set mire.pgm image input path.\n\
109  From this path read \"ViSP-images/mire/mire.pgm\" video.\n\
110  Setting the VISP_INPUT_IMAGE_PATH environment variable \n\
111  produces the same behaviour than using this option.\n\
112  \n\
113  -d \n\
114  Turn off the display.\n\
115  \n\
116  -h\n\
117  Print the help.\n", ipath.c_str());
118 
119  if (badparam)
120  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
121 }
122 
123 
136 bool getOptions(int argc, const char **argv, std::string &ipath, bool &display)
137 {
138  const char *optarg_;
139  int c;
140  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
141 
142  switch (c) {
143  case 'i': ipath = optarg_; break;
144  case 'd': display = false; break;
145  case 'h': usage(argv[0],ipath, NULL); return false; break;
146 
147  default:
148  usage(argv[0],ipath, optarg_);
149  return false; break;
150  }
151  }
152 
153  if ((c == 1) || (c == -1)) {
154  // standalone param or error
155  usage(argv[0], ipath, NULL);
156  std::cerr << "ERROR: " << std::endl;
157  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
158  return false;
159  }
160 
161  return true;
162 }
163 
164 
165 int
166 main(int argc, const char ** argv)
167 {
168  try {
169  bool opt_display = true;
170  std::string opt_ipath;
171  std::string env_ipath;
172  std::string ipath ;
173  std::string filename;
174 
175  // Read the command line options
176  if (getOptions(argc, argv, opt_ipath, opt_display) == false) {
177  exit (-1);
178  }
179 
180  vpImage<vpRGBa> Iint(480,640,255);
181  vpImage<vpRGBa> Iext1(480,640,255);
182  vpImage<vpRGBa> Iext2(480,640,255);
183 
184 #if defined VISP_HAVE_X11
185  vpDisplayX display[3];
186 #elif defined VISP_HAVE_OPENCV
187  vpDisplayOpenCV display[3];
188 #elif defined VISP_HAVE_GDI
189  vpDisplayGDI display[3];
190 #elif defined VISP_HAVE_D3D9
191  vpDisplayD3D display[3];
192 #elif defined VISP_HAVE_GTK
193  vpDisplayGTK display[3];
194 #endif
195 
196  if (opt_display)
197  {
198  // Display size is automatically defined by the image (I) size
199  display[0].init(Iint, 100, 100,"The internal view") ;
200  display[1].init(Iext1, 100, 100,"The first external view") ;
201  display[2].init(Iext2, 100, 100,"The second external view") ;
202  vpDisplay::setWindowPosition (Iint, 0, 0);
203  vpDisplay::setWindowPosition (Iext1, 700, 0);
204  vpDisplay::setWindowPosition (Iext2, 0, 550);
205  vpDisplay::display(Iint);
206  vpDisplay::flush(Iint);
207  vpDisplay::display(Iext1);
208  vpDisplay::flush(Iext1);
209  vpDisplay::display(Iext2);
210  vpDisplay::flush(Iext2);
211  }
212 
213  vpServo task;
214  vpSimulatorCamera robot ;
215  float sampling_time = 0.040f; // Sampling period in second
216  robot.setSamplingTime(sampling_time);
217 
218  // Since the task gain lambda is very high, we need to increase default max velocities
219  robot.setMaxTranslationVelocity(10);
221 
222  // Set initial position of the object in the camera frame
223  vpHomogeneousMatrix cMo(0,0.1,2.0,vpMath::rad(35),vpMath::rad(25),0);
224  // Set desired position of the object in the camera frame
225  vpHomogeneousMatrix cdMo(0.0,0.0,1.0,vpMath::rad(0),vpMath::rad(0),vpMath::rad(0));
226  // Set initial position of the object in the world frame
227  vpHomogeneousMatrix wMo(0.0,0.0,0.2,0,0,0);
228  // Position of the camera in the world frame
229  vpHomogeneousMatrix wMc, cMw;
230  wMc = wMo * cMo.inverse();
231  cMw = wMc.inverse();
232 
233  //The four point used as visual features
234  vpPoint point[4] ;
235  point[0].setWorldCoordinates(-0.1,-0.1,0) ;
236  point[3].setWorldCoordinates(-0.1,0.1,0) ;
237  point[2].setWorldCoordinates(0.1,0.1,0) ;
238  point[1].setWorldCoordinates(0.1,-0.1,0) ;
239 
240  // Projection of the points
241  for (int i = 0 ; i < 4 ; i++)
242  point[i].track(cMo);
243 
244  //Set the current visual feature
245  vpFeaturePoint p[4];
246  for (int i = 0 ; i < 4 ; i++)
247  vpFeatureBuilder::create(p[i], point[i]);
248 
249  // Projection of the points
250  for (int i = 0 ; i < 4 ; i++)
251  point[i].track(cdMo);
252 
253  vpFeaturePoint pd[4];
254  for (int i = 0 ; i < 4 ; i++)
255  vpFeatureBuilder::create(pd[i], point[i]);
256 
259 
260  vpHomogeneousMatrix cMe; // Identity
261  vpVelocityTwistMatrix cVe(cMe);
262  task.set_cVe(cVe);
263 
264  vpMatrix eJe;
265  robot.get_eJe(eJe);
266  task.set_eJe(eJe);
267 
268  for (int i = 0 ; i < 4 ; i++)
269  task.addFeature(p[i],pd[i]) ;
270 
271  task.setLambda(10);
272 
273  std::list<vpImageSimulator> list;
274  vpImageSimulator imsim;
275 
276  vpColVector X[4];
277  for (int i = 0; i < 4; i++) X[i].resize(3);
278  X[0][0] = -0.2;
279  X[0][1] = -0.2;
280  X[0][2] = 0;
281 
282  X[1][0] = 0.2;
283  X[1][1] = -0.2;
284  X[1][2] = 0;
285 
286  X[2][0] = 0.2;
287  X[2][1] = 0.2;
288  X[2][2] = 0;
289 
290  X[3][0] = -0.2;
291  X[3][1] = 0.2;
292  X[3][2] = 0;
293 
294  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
295  if (ptenv != NULL)
296  env_ipath = ptenv;
297 
298  if (! env_ipath.empty())
299  ipath = env_ipath;
300 
301  if (!opt_ipath.empty())
302  ipath = opt_ipath;
303 
304  filename = ipath + vpIoTools::path("/ViSP-images/mire/mire.pgm");
305 
306  imsim.init(filename.c_str(), X);
307 
308  list.push_back(imsim);
309 
311 
312  // Set the scene
314 
315  // Initialize simulator frames
316  sim.set_fMo( wMo ); // Position of the object in the world reference frame
317  sim.setCameraPositionRelObj(cMo) ; // initial position of the camera
318  sim.setDesiredCameraPosition(cdMo); // desired position of the camera
319 
320  // Set the External camera position
322  sim.setExternalCameraPosition(camMf);
323 
324  //Computes the position of a camera which is fixed in the object frame
325  vpHomogeneousMatrix camoMf(0,0.0,1.5,0,vpMath::rad(140),0);
326  camoMf = camoMf*(sim.get_fMo().inverse());
327 
328  //Set the parameters of the cameras (internal and external)
329  vpCameraParameters camera(1000,1000,320,240);
330  sim.setInternalCameraParameters(camera);
331  sim.setExternalCameraParameters(camera);
332 
333  int stop = 10;
334 
335  if (opt_display)
336  {
337  stop = 2500;
338 
339  //Get the internal and external views
340  sim.getInternalImage(Iint);
341  sim.getExternalImage(Iext1);
342  sim.getExternalImage(Iext2, camoMf);
343 
344  //Display the object frame (current and desired position)
345  vpDisplay::displayFrame(Iint,cMo,camera,0.2,vpColor::none);
346  vpDisplay::displayFrame(Iint,cdMo,camera,0.2,vpColor::none);
347 
348  //Display the object frame the world reference frame and the camera frame
349  vpDisplay::displayFrame(Iext1,camMf*sim.get_fMo()*cMo.inverse(),camera,0.2,vpColor::none);
350  vpDisplay::displayFrame(Iext1,camMf*sim.get_fMo(),camera,0.2,vpColor::none);
351  vpDisplay::displayFrame(Iext1,camMf,camera,0.2,vpColor::none);
352 
353  //Display the world reference frame and the object frame
354  vpDisplay::displayFrame(Iext2,camoMf,camera,0.2,vpColor::none);
355  vpDisplay::displayFrame(Iext2,camoMf*sim.get_fMo(),camera,0.05,vpColor::none);
356 
357  vpDisplay::flush(Iint);
358  vpDisplay::flush(Iext1);
359  vpDisplay::flush(Iext2);
360 
361  std::cout << "Click on a display" << std::endl;
362  while (!vpDisplay::getClick(Iint,false) && !vpDisplay::getClick(Iext1,false) && !vpDisplay::getClick(Iext2,false)){};
363  }
364 
365  robot.setPosition( wMc );
366  //Print the task
367  task.print() ;
368 
369  int iter = 0;
370  vpColVector v ;
371 
372  while(iter++ < stop)
373  {
374  if (opt_display)
375  {
376  vpDisplay::display(Iint) ;
377  vpDisplay::display(Iext1) ;
378  vpDisplay::display(Iext2) ;
379  }
380 
381  double t = vpTime::measureTimeMs();
382 
383  robot.get_eJe(eJe) ;
384  task.set_eJe(eJe) ;
385 
386  robot.getPosition(wMc) ;
387  cMo = wMc.inverse() * wMo;
388  for (int i = 0 ; i < 4 ; i++)
389  {
390  point[i].track(cMo) ;
391  vpFeatureBuilder::create(p[i],point[i]) ;
392  }
393 
394  v = task.computeControlLaw() ;
396 
397  //Compute the movement of the object around the world reference frame.
398  vpHomogeneousMatrix a(0, 0, 0.2, 0, 0, 0);
399  vpHomogeneousMatrix b(0, 0, 0, vpMath::rad(1.5*iter), 0, 0);
400  vpHomogeneousMatrix c(0, 0, 0, 0, vpMath::rad(2.5*iter), 0);
401 
402  // Move the object in the world frame
403  wMo = b*c*a;
404 
405  sim.set_fMo( wMo ); //Move the object in the simulator
406  sim.setCameraPositionRelObj(cMo);
407 
408  //Compute the position of the external view which is fixed in the object frame
409  camoMf.buildFrom(0,0.0,1.5,0,vpMath::rad(150),0);
410  camoMf = camoMf*(sim.get_fMo().inverse());
411 
412  if (opt_display)
413  {
414  //Get the internal and external views
415  sim.getInternalImage(Iint);
416  sim.getExternalImage(Iext1);
417  sim.getExternalImage(Iext2,camoMf);
418 
419  //Display the object frame (current and desired position)
420  vpDisplay::displayFrame(Iint,cMo,camera,0.2,vpColor::none);
421  vpDisplay::displayFrame(Iint,cdMo,camera,0.2,vpColor::none);
422 
423  //Display the camera frame, the object frame the world reference frame
427 
428  //Display the world reference frame and the object frame
429  vpDisplay::displayFrame(Iext2,camoMf,camera,0.2,vpColor::none);
430  vpDisplay::displayFrame(Iext2,camoMf*sim.get_fMo(),camera,0.05,vpColor::none);
431 
432  vpDisplay::flush(Iint);
433  vpDisplay::flush(Iext1);
434  vpDisplay::flush(Iext2);
435  }
436 
437  vpTime::wait(t, sampling_time * 1000); // Wait 40 ms
438 
439  std::cout << "|| s - s* || = " << ( task.getError() ).sumSquare() <<std::endl ;
440  }
441 
442  task.print() ;
443  task.kill() ;
444 
445  return 0;
446  }
447  catch(vpException e) {
448  std::cout << "Catch an exception: " << e << std::endl;
449  return 1;
450  }
451 }
452 #else
453 int
454 main()
455 {
456  vpERROR_TRACE("You do not have X11, OpenCV, GDI, D3D9 or GTK display functionalities...");
457 }
458 
459 #endif
void setPosition(const vpHomogeneousMatrix &wMc)
The object displayed at the desired position is the same than the scene object defined in vpSceneObje...
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
void init(const vpImage< unsigned char > &I, vpColVector *X)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel)
void setMaxTranslationVelocity(const double maxVt)
Definition: vpRobot.cpp:227
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.
A 40cm by 40cm plate with 4 points at coordinates (-0.1,-0.1,0), (0.1,-0.1,0), (0.1,0.1,0), (0.1,0.1,0). Each point is represented by a circle with 2cm radius.
void set_fMo(const vpHomogeneousMatrix &fMo_)
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
void set_eJe(const vpMatrix &eJe_)
Definition: vpServo.h:439
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
static const vpColor none
Definition: vpColor.h:179
error that can be emited by ViSP classes.
Definition: vpException.h:76
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
void track(const vpHomogeneousMatrix &cMo)
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
void setExternalCameraPosition(const vpHomogeneousMatrix &cam_Mf)
static double measureTimeMs()
Definition: vpTime.cpp:86
static int wait(double t0, double t)
Definition: vpTime.cpp:149
void setDesiredCameraPosition(const vpHomogeneousMatrix &cdMo_)
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
Class that defines what is a point.
Definition: vpPoint.h:65
virtual void setSamplingTime(const double &delta_t)
Display for windows using Direct3D.
Definition: vpDisplayD3D.h:109
void kill()
Definition: vpServo.cpp:189
vpColVector getError() const
Definition: vpServo.h:257
vpHomogeneousMatrix get_fMo() const
vpColVector computeControlLaw()
Definition: vpServo.cpp:902
virtual void setWindowPosition(int winx, int winy)=0
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
The vpDisplayOpenCV allows to display image using the opencv library.
Generic class defining intrinsic camera parameters.
void getPosition(vpHomogeneousMatrix &wMc) const
void setLambda(double c)
Definition: vpServo.h:370
Class which enables to project an image in the 3D space and get the view of a virtual camera...
void initScene(const vpSceneObject &obj, const vpSceneDesiredObject &desiredObject)
The vpDisplayGTK allows to display image using the GTK+ library version 1.2.
Definition: vpDisplayGTK.h:145
Class that consider the particular case of twist transformation matrix that allows to transform a vel...
void getExternalImage(vpImage< unsigned char > &I)
Implementation of a wire frame simulator. Compared to the vpSimulator class, it does not require thir...
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color, unsigned int thickness=1)
Definition: vpDisplay.cpp:371
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:522
static double rad(double deg)
Definition: vpMath.h:100
void setExternalCameraParameters(const vpCameraParameters &cam)
void setCameraPositionRelObj(const vpHomogeneousMatrix &cMo_)
void setMaxRotationVelocity(const double maxVr)
Definition: vpRobot.cpp:251
void getInternalImage(vpImage< unsigned char > &I)
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
void set_cVe(const vpVelocityTwistMatrix &cVe_)
Definition: vpServo.h:414
vpHomogeneousMatrix inverse() const
void setInternalCameraParameters(const vpCameraParameters &cam)
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)
void get_eJe(vpMatrix &eJe)
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:220
vpHomogeneousMatrix getExternalCameraPosition() const
void setWorldCoordinates(const double ox, const double oy, const double oz)
Set the point world coordinates. We mean here the coordinates of the point in the object frame...
Definition: vpPoint.cpp:74