Visual Servoing Platform  version 3.4.0
servoSimuLine2DCamVelocityDisplay.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 line.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 
48 #include <visp3/core/vpConfig.h>
49 #include <visp3/core/vpDebug.h>
50 
51 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)) \
52  && (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
53 
54 #include <stdio.h>
55 #include <stdlib.h>
56 
57 #include <visp3/core/vpCameraParameters.h>
58 #include <visp3/core/vpHomogeneousMatrix.h>
59 #include <visp3/core/vpImage.h>
60 #include <visp3/core/vpLine.h>
61 #include <visp3/core/vpMath.h>
62 #include <visp3/gui/vpDisplayGDI.h>
63 #include <visp3/gui/vpDisplayGTK.h>
64 #include <visp3/gui/vpDisplayOpenCV.h>
65 #include <visp3/gui/vpDisplayX.h>
66 #include <visp3/io/vpParseArgv.h>
67 #include <visp3/robot/vpSimulatorCamera.h>
68 #include <visp3/visual_features/vpFeatureBuilder.h>
69 #include <visp3/visual_features/vpFeatureLine.h>
70 #include <visp3/vs/vpServo.h>
71 #include <visp3/vs/vpServoDisplay.h>
72 
73 // List of allowed command line options
74 #define GETOPTARGS "cdh"
75 
76 void usage(const char *name, const char *badparam);
77 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
78 
87 void usage(const char *name, const char *badparam)
88 {
89  fprintf(stdout, "\n\
90 Simulation of 2D a visual servoing on a line:\n\
91 - eye-in-hand control law,\n\
92 - velocity computed in the camera frame,\n\
93 - display the camera view.\n\
94  \n\
95 SYNOPSIS\n\
96  %s [-c] [-d] [-h]\n", name);
97 
98  fprintf(stdout, "\n\
99 OPTIONS: Default\n\
100  \n\
101  -c\n\
102  Disable the mouse click. Useful to automaze the \n\
103  execution of this program without humain intervention.\n\
104  \n\
105  -d \n\
106  Turn off the display.\n\
107  \n\
108  -h\n\
109  Print the help.\n");
110 
111  if (badparam)
112  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
113 }
114 
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 
144  default:
145  usage(argv[0], optarg_);
146  return false;
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 int main(int argc, const char **argv)
162 {
163  try {
164  bool opt_display = true;
165  bool opt_click_allowed = true;
166 
167  // Read the command line options
168  if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
169  exit(-1);
170  }
171 
172  vpImage<unsigned char> I(512, 512, 0);
173 
174 // We open a window using either X11, GTK or GDI.
175 #if defined VISP_HAVE_X11
176  vpDisplayX display;
177 #elif defined VISP_HAVE_GTK
178  vpDisplayGTK display;
179 #elif defined VISP_HAVE_GDI
180  vpDisplayGDI display;
181 #elif defined VISP_HAVE_OPENCV
182  vpDisplayOpenCV display;
183 #endif
184 
185  if (opt_display) {
186  try {
187  // Display size is automatically defined by the image (I) size
188  display.init(I, 100, 100, "Camera view...");
189  // Display the image
190  // The image class has a member that specify a pointer toward
191  // the display that has been initialized in the display declaration
192  // therefore is is no longuer necessary to make a reference to the
193  // display variable.
195  vpDisplay::flush(I);
196  } catch (...) {
197  vpERROR_TRACE("Error while displaying the image");
198  exit(-1);
199  }
200  }
201 
202  double px = 500, py = 500;
203  double u0 = 150, v0 = 160;
204 
205  vpCameraParameters cam(px, py, u0, v0);
206 
207  vpServo task;
208  vpSimulatorCamera robot;
209 
210  // sets the initial camera location
211  vpHomogeneousMatrix cMo(-0.2, 0.1, 1, vpMath::rad(5), vpMath::rad(5), vpMath::rad(90));
212 
213  // Compute the position of the object in the world frame
214  vpHomogeneousMatrix wMc, wMo;
215  robot.getPosition(wMc);
216  wMo = wMc * cMo;
217 
218  // sets the final camera location (for simulation purpose)
219  vpHomogeneousMatrix cMod(0, 0, 1, vpMath::rad(0), vpMath::rad(0), vpMath::rad(0));
220 
221  // sets the line coordinates (2 planes) in the world frame
222  vpColVector plane1(4);
223  vpColVector plane2(4);
224  plane1[0] = 0; // z = 0
225  plane1[1] = 0;
226  plane1[2] = 1;
227  plane1[3] = 0;
228  plane2[0] = 0; // y =0
229  plane2[1] = 1;
230  plane2[2] = 0;
231  plane2[3] = 0;
232 
233  vpLine line;
234  line.setWorldCoordinates(plane1, plane2);
235 
236  // sets the desired position of the visual feature
237  line.track(cMod);
238  line.print();
239 
240  vpFeatureLine ld;
241  vpFeatureBuilder::create(ld, line);
242 
243  // computes the line coordinates in the camera frame and its 2D
244  // coordinates sets the current position of the visual feature
245  line.track(cMo);
246  line.print();
247 
248  vpFeatureLine l;
249  vpFeatureBuilder::create(l, line);
250  l.print();
251 
252  // define the task
253  // - we want an eye-in-hand control law
254  // - robot is controlled in the camera frame
256 
257  // we want to see a line on a line
258 
259  task.addFeature(l, ld);
261  vpServoDisplay::display(task, cam, I);
262  vpDisplay::flush(I);
263 
264  // set the gain
265  task.setLambda(1);
266  // Display task information " ) ;
267  task.print();
268 
269  if (opt_display && opt_click_allowed) {
270  std::cout << "\n\nClick in the camera view window to start..." << std::endl;
272  }
273 
274  unsigned int iter = 0;
275  // loop
276  while (iter++ < 200) {
277  std::cout << "---------------------------------------------" << iter << std::endl;
278  vpColVector v;
279 
280  // get the robot position
281  robot.getPosition(wMc);
282  // Compute the position of the object frame in the camera frame
283  cMo = wMc.inverse() * wMo;
284 
285  // new line position
286  line.track(cMo);
287  // retrieve x,y and Z of the vpLine structure
288  vpFeatureBuilder::create(l, line);
289 
290  if (opt_display) {
292  vpServoDisplay::display(task, cam, I);
293  vpDisplay::flush(I);
294  }
295 
296  // compute the control law
297  v = task.computeControlLaw();
298 
299  // send the camera velocity to the controller
301 
302  std::cout << "|| s - s* || = " << (task.getError()).sumSquare() << std::endl;
303  }
304 
305  if (opt_display && opt_click_allowed) {
306  vpDisplay::displayText(I, 20, 20, "Click to quit...", vpColor::white);
307  vpDisplay::flush(I);
309  }
310 
311  // Display task information
312  task.print();
313  return EXIT_SUCCESS;
314  } catch (const vpException &e) {
315  std::cout << "Catch a ViSP exception: " << e << std::endl;
316  return EXIT_FAILURE;
317  }
318 }
319 
320 #elif !(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
321 int main()
322 {
323  std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
324  return EXIT_SUCCESS;
325 }
326 #else
327 int main()
328 {
329  std::cout << "You do not have X11, or GTK, or GDI (Graphical Device Interface) functionalities to display images..." << std::endl;
330  std::cout << "Tip if you are on a unix-like system:" << std::endl;
331  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
332  std::cout << "Tip if you are on a windows-like system:" << std::endl;
333  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
334  return EXIT_SUCCESS;
335 }
336 #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
#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="")
void track(const vpHomogeneousMatrix &cMo)
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
Class that defines a 3D line in the object frame and allows forward projection of the line in the cam...
Definition: vpLine.h:104
vpColVector getError() const
Definition: vpServo.h:278
void setWorldCoordinates(const double &oA1, const double &oB1, const double &oC1, const double &oD1, const double &oA2, const double &oB2, const double &oC2, const double &oD2)
Definition: vpLine.cpp:85
virtual void print() const
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
static double rad(double deg)
Definition: vpMath.h:110
void print(unsigned int select=FEATURE_ALL) const
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)
static const vpColor white
Definition: vpColor.h:212
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)