Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
servoMomentImage.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  * Example of visual servoing with moments using an image as object
33  * container
34  *
35  * Authors:
36  * Filip Novotny
37  * Manikandan.B
38  *****************************************************************************/
39 
45 #define PRINT_CONDITION_NUMBER
46 
47 #include <iostream>
48 #include <visp3/core/vpCameraParameters.h>
49 #include <visp3/core/vpConfig.h>
50 #include <visp3/core/vpDebug.h>
51 #include <visp3/core/vpHomogeneousMatrix.h>
52 #include <visp3/core/vpIoTools.h>
53 #include <visp3/core/vpMath.h>
54 #include <visp3/core/vpMomentCommon.h>
55 #include <visp3/core/vpMomentDatabase.h>
56 #include <visp3/core/vpMomentObject.h>
57 #include <visp3/core/vpPlane.h>
58 #include <visp3/core/vpPoseVector.h>
59 #include <visp3/gui/vpDisplayGDI.h>
60 #include <visp3/gui/vpDisplayGTK.h>
61 #include <visp3/gui/vpDisplayOpenCV.h>
62 #include <visp3/gui/vpDisplayX.h>
63 #include <visp3/gui/vpPlot.h>
64 #include <visp3/robot/vpImageSimulator.h>
65 #include <visp3/robot/vpSimulatorCamera.h>
66 #include <visp3/visual_features/vpFeatureBuilder.h>
67 #include <visp3/visual_features/vpFeatureMomentCommon.h>
68 #include <visp3/visual_features/vpFeaturePoint.h>
69 #include <visp3/vs/vpServo.h>
70 
71 #if !defined(_WIN32) && !defined(VISP_HAVE_PTHREAD)
72 // Robot simulator used in this example is not available
73 int main()
74 {
75  std::cout << "Can't run this example since vpSimulatorAfma6 capability is "
76  "not available."
77  << std::endl;
78  std::cout << "You should install pthread third-party library." << std::endl;
79  return EXIT_SUCCESS;
80 }
81 // No display available
82 #elif !defined(VISP_HAVE_X11) && !defined(VISP_HAVE_OPENCV) && !defined(VISP_HAVE_GDI) && !defined(VISP_HAVE_D3D9) && \
83  !defined(VISP_HAVE_GTK)
84 int main()
85 {
86  std::cout << "Can't run this example since no display capability is available." << std::endl;
87  std::cout << "You should install one of the following third-party library: "
88  "X11, OpenCV, GDI, GTK."
89  << std::endl;
90  return EXIT_SUCCESS;
91 }
92 #else
93 
94 // setup robot parameters
95 void paramRobot();
96 
97 // update moment objects and interface
98 void refreshScene(vpMomentObject &obj);
99 // initialize scene in the interface
100 void initScene();
101 // initialize the moment features
102 void initFeatures();
103 
104 void init(vpHomogeneousMatrix &cMo, vpHomogeneousMatrix &cdMo);
105 void execute(unsigned int nbIter); // launch the simulation
106 void setInteractionMatrixType(vpServo::vpServoIteractionMatrixType type);
107 double error();
108 void planeToABC(vpPlane &pl, double &A, double &B, double &C);
109 void paramRobot();
110 
111 void init_visp_plot(vpPlot &);
112 
113 int main()
114 {
115  try {
116  // intial pose
117  vpHomogeneousMatrix cMo(-0.1, -0.1, 1.5, -vpMath::rad(20), -vpMath::rad(20), -vpMath::rad(30));
118  // Desired pose
120 
121  // init the simulation
122  init(cMo, cdMo);
123 
124  execute(1500);
125  return EXIT_SUCCESS;
126  } catch (const vpException &e) {
127  std::cout << "Catch an exception: " << e << std::endl;
128  return EXIT_FAILURE;
129  }
130 }
131 
132 // init the right display
133 #if defined VISP_HAVE_X11
134 vpDisplayX displayInt;
135 #elif defined VISP_HAVE_OPENCV
136 vpDisplayOpenCV displayInt;
137 #elif defined VISP_HAVE_GDI
138 vpDisplayGDI displayInt;
139 #elif defined VISP_HAVE_D3D9
140 vpDisplayD3D displayInt;
141 #elif defined VISP_HAVE_GTK
142 vpDisplayGTK displayInt;
143 #endif
144 
145 // start and destination positioning matrices
148 
149 vpSimulatorCamera robot; // robot used in this simulation
150 vpImage<vpRGBa> Iint(480, 640, 0); // internal image used for interface
151  // display
152 vpServo task; // servoing task
153 vpCameraParameters cam; // robot camera parameters
154 double _error; // current error
155 vpImageSimulator imsim; // image simulator used to simulate the
156  // perspective-projection camera
157 
158 // several images used in the simulation
159 vpImage<unsigned char> cur_img(480, 640, 0);
160 vpImage<unsigned char> src_img(480, 640, 0);
161 vpImage<unsigned char> dst_img(480, 640, 0);
162 vpImage<vpRGBa> start_img(480, 640, 0);
163 vpServo::vpServoIteractionMatrixType interaction_type; // current or desired
164 // source and destination objects for moment manipulation
165 vpMomentObject src(6);
166 vpMomentObject dst(6);
167 
168 // moment sets and their corresponding features
169 vpMomentCommon *moments;
170 vpMomentCommon *momentsDes;
171 vpFeatureMomentCommon *featureMoments;
172 vpFeatureMomentCommon *featureMomentsDes;
173 
174 using namespace std;
175 
176 void initScene()
177 {
178  vpColVector X[4];
179  for (int i = 0; i < 4; i++)
180  X[i].resize(3);
181  X[0][0] = -0.2;
182  X[0][1] = -0.1;
183  X[0][2] = 0;
184 
185  X[1][0] = 0.2;
186  X[1][1] = -0.1;
187  X[1][2] = 0;
188 
189  X[2][0] = 0.2;
190  X[2][1] = 0.1;
191  X[2][2] = 0;
192 
193  X[3][0] = -0.2;
194  X[3][1] = 0.1;
195  X[3][2] = 0;
196  // init source and destination images
197  vpImage<unsigned char> tmp_img(480, 640, 255);
198  vpImage<vpRGBa> tmp_start_img(480, 640, vpRGBa(255, 0, 0));
199 
200  vpImageSimulator imsim_start;
202  imsim_start.init(tmp_start_img, X);
203  imsim_start.setCameraPosition(cdMo);
204  imsim_start.getImage(start_img, cam);
205 
207  imsim.init(tmp_img, X);
208 
209  imsim.setCameraPosition(cMo);
210  imsim.getImage(src_img, cam);
211 
213  src.fromImage(src_img, 128, cam);
214 
216  imsim.setCameraPosition(cdMo);
217  imsim.getImage(dst_img, cam);
218  dst.fromImage(dst_img, 128, cam);
219 }
220 
221 void refreshScene(vpMomentObject &obj)
222 {
223  cur_img = 0;
224  imsim.setCameraPosition(cMo);
225  imsim.getImage(cur_img, cam);
226  obj.fromImage(cur_img, 128, cam);
227 }
228 
229 void init(vpHomogeneousMatrix &_cMo, vpHomogeneousMatrix &_cdMo)
230 {
231  cMo = _cMo; // init source matrix
232  cdMo = _cdMo; // init destination matrix
233 
234  interaction_type = vpServo::CURRENT; // use interaction matrix for current position
235 
236  displayInt.init(Iint, 700, 0, "Visual servoing with moments");
237 
238  paramRobot(); // set up robot parameters
239 
241  initScene(); // initialize graphical scene (for interface)
242  initFeatures(); // initialize moment features
243 }
244 
245 void initFeatures()
246 {
247  // A,B,C parameters of source and destination plane
248  double A;
249  double B;
250  double C;
251  double Ad;
252  double Bd;
253  double Cd;
254  // init main object: using moments up to order 5
255 
256  // Initializing values from regular plane (with ax+by+cz=d convention)
257  vpPlane pl;
258  pl.setABCD(0, 0, 1.0, 0);
259  pl.changeFrame(cMo);
260  planeToABC(pl, A, B, C);
261 
262  pl.setABCD(0, 0, 1.0, 0);
263  pl.changeFrame(cdMo);
264  planeToABC(pl, Ad, Bd, Cd);
265 
266  // extracting initial position (actually we only care about Zdst)
268  cdMo.extract(vec);
269 
272  // don't need to be specific, vpMomentCommon automatically loads
273  // Xg,Yg,An,Ci,Cj,Alpha moments
275  vpMomentCommon::getAlpha(dst), vec[2], true);
277  vpMomentCommon::getAlpha(dst), vec[2], true);
278  // same thing with common features
279  featureMoments = new vpFeatureMomentCommon(*moments);
280  featureMomentsDes = new vpFeatureMomentCommon(*momentsDes);
281 
282  moments->updateAll(src);
283  momentsDes->updateAll(dst);
284 
285  featureMoments->updateAll(A, B, C);
286  featureMomentsDes->updateAll(Ad, Bd, Cd);
287 
288  // setup the interaction type
289  task.setInteractionMatrixType(interaction_type);
292  task.addFeature(featureMoments->getFeatureGravityNormalized(), featureMomentsDes->getFeatureGravityNormalized());
293  task.addFeature(featureMoments->getFeatureAn(), featureMomentsDes->getFeatureAn());
294  // the moments are different in case of a symmetric object
295  task.addFeature(featureMoments->getFeatureCInvariant(), featureMomentsDes->getFeatureCInvariant(),
296  (1 << 10) | (1 << 11));
297  task.addFeature(featureMoments->getFeatureAlpha(), featureMomentsDes->getFeatureAlpha());
298 
299  task.setLambda(1.);
300 }
301 
302 void execute(unsigned int nbIter)
303 {
304 
305  vpPlot ViSP_plot;
306  init_visp_plot(ViSP_plot); // Initialize plot object
307 
308  // init main object: using moments up to order 6
309  vpMomentObject obj(6);
310  // setting object type (disrete, continuous[form polygon])
312 
313  vpTRACE("Display task information ");
314  task.print();
315 
316  vpDisplay::display(Iint);
317  vpDisplay::flush(Iint);
318  unsigned int iter = 0;
319 
320  vpHomogeneousMatrix wMo; // Set to identity
321  vpHomogeneousMatrix wMc; // Camera position in the world frame
322  wMc = wMo * cMo.inverse();
323  robot.setPosition(wMc);
324  float sampling_time = 0.010f; // Sampling period in seconds
325  robot.setSamplingTime(sampling_time);
326 
327  // For plotting
328  vpPoseVector currentpose;
329  vpColVector err_features;
330 
332  while (iter++ < nbIter) {
333 
334  vpColVector v;
335  double t = vpTime::measureTimeMs();
336  // get the cMo
337  wMc = robot.getPosition();
338  cMo = wMc.inverse() * wMo;
339  currentpose.buildFrom(cMo); // For plot
340  // setup the plane in A,B,C style
341  vpPlane pl;
342  double A, B, C;
343  pl.setABCD(0, 0, 1.0, 0);
344  pl.changeFrame(cMo);
345  planeToABC(pl, A, B, C);
346 
347  // track points, draw points and add refresh our object
348  refreshScene(obj);
349  // this is the most important thing to do: update our moments
350  moments->updateAll(obj);
351  // and update our features. Do it in that order. Features need to use the
352  // information computed by moments
353  featureMoments->updateAll(A, B, C);
354  // some graphics again
355  imsim.setCameraPosition(cMo);
356 
357  Iint = start_img;
358 
359  imsim.getImage(Iint, cam);
360  vpDisplay::display(Iint);
361 
362  vpDisplay::flush(Iint);
363 
364  if (iter == 1)
365  vpDisplay::getClick(Iint);
366  v = task.computeControlLaw();
367  // pilot robot using position control. The displacement is t*v with t=10ms
368  // step robot.setPosition(vpRobot::CAMERA_FRAME,0.01*v);
369 
370  err_features = task.error;
371  std::cout << " || s - s* || = " << task.error.sumSquare() << std::endl;
372 
374  vpTime::wait(t, sampling_time * 1000); // Wait 10 ms
375 
376  ViSP_plot.plot(0, iter, v);
377  ViSP_plot.plot(1, iter, currentpose); // Plot the velocities
378  ViSP_plot.plot(2, iter, err_features); // cMo as translations and theta_u
379 
380  _error = (task.getError()).sumSquare();
381 
382 #if defined(PRINT_CONDITION_NUMBER)
383  /*
384  * Condition number of interaction matrix
385  */
386  vpMatrix Linteraction = task.L;
387  vpMatrix tmpry, U;
388  vpColVector singularvals;
389  Linteraction.svd(singularvals, tmpry);
390  double condno = static_cast<double>(singularvals.getMaxValue() / singularvals.getMinValue());
391  std::cout << "Condition Number: " << condno << std::endl;
392 #endif
393  }
394 
395  task.kill();
396 
397  vpTRACE("\n\nClick in the internal view window to end...");
398  vpDisplay::getClick(Iint);
399 
400  delete moments;
401  delete momentsDes;
402  delete featureMoments;
403  delete featureMomentsDes;
404 }
405 
406 void setInteractionMatrixType(vpServo::vpServoIteractionMatrixType type) { interaction_type = type; }
407 double error() { return _error; }
408 
409 void planeToABC(vpPlane &pl, double &A, double &B, double &C)
410 {
411  if (fabs(pl.getD()) < std::numeric_limits<double>::epsilon()) {
412  std::cout << "Invalid position:" << std::endl;
413  std::cout << cMo << std::endl;
414  std::cout << "Cannot put plane in the form 1/Z=Ax+By+C." << std::endl;
415  throw vpException(vpException::divideByZeroError, "invalid position!");
416  }
417  A = -pl.getA() / pl.getD();
418  B = -pl.getB() / pl.getD();
419  C = -pl.getC() / pl.getD();
420 }
421 
422 void paramRobot() { cam = vpCameraParameters(640, 480, 320, 240); }
423 
424 void init_visp_plot(vpPlot &ViSP_plot)
425 {
426  /* -------------------------------------
427  * Initialize ViSP Plotting
428  * -------------------------------------
429  */
430  const unsigned int NbGraphs = 3; // No. of graphs
431  const unsigned int NbCurves_in_graph[NbGraphs] = {6, 6, 6}; // Curves in each graph
432 
433  ViSP_plot.init(NbGraphs, 800, 800, 10, 10, "Visual Servoing results...");
434 
435  vpColor Colors[6] = {// Colour for s1, s2, s3, in 1st plot
437 
438  for (unsigned int p = 0; p < NbGraphs; p++) {
439  ViSP_plot.initGraph(p, NbCurves_in_graph[p]);
440  for (unsigned int c = 0; c < NbCurves_in_graph[p]; c++)
441  ViSP_plot.setColor(p, c, Colors[c]);
442  }
443 
444  ViSP_plot.setTitle(0, "Robot velocities");
445  ViSP_plot.setLegend(0, 0, "v_x");
446  ViSP_plot.setLegend(0, 1, "v_y");
447  ViSP_plot.setLegend(0, 2, "v_z");
448  ViSP_plot.setLegend(0, 3, "w_x");
449  ViSP_plot.setLegend(0, 4, "w_y");
450  ViSP_plot.setLegend(0, 5, "w_z");
451 
452  ViSP_plot.setTitle(1, "Camera pose cMo");
453  ViSP_plot.setLegend(1, 0, "tx");
454  ViSP_plot.setLegend(1, 1, "ty");
455  ViSP_plot.setLegend(1, 2, "tz");
456  ViSP_plot.setLegend(1, 3, "tu_x");
457  ViSP_plot.setLegend(1, 4, "tu_y");
458  ViSP_plot.setLegend(1, 5, "tu_z");
459 
460  ViSP_plot.setTitle(2, "Error in visual features: ");
461  ViSP_plot.setLegend(2, 0, "x_n");
462  ViSP_plot.setLegend(2, 1, "y_n");
463  ViSP_plot.setLegend(2, 2, "a_n");
464  ViSP_plot.setLegend(2, 3, "sx");
465  ViSP_plot.setLegend(2, 4, "sy");
466  ViSP_plot.setLegend(2, 5, "alpha");
467 }
468 #endif
void setPosition(const vpHomogeneousMatrix &wMc)
void svd(vpColVector &w, vpMatrix &V)
Definition: vpMatrix.cpp:2066
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:164
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:173
void init(const vpImage< unsigned char > &I, vpColVector *X)
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:497
void getImage(vpImage< unsigned char > &I, const vpCameraParameters &cam)
void init(unsigned int nbGraph, unsigned int height=700, unsigned int width=700, int x=-1, int y=-1, const std::string &title="")
Definition: vpPlot.cpp:100
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
Class to define colors available for display functionnalities.
Definition: vpColor.h:119
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:150
This class allows to access common vpFeatureMoments in a pre-filled database.
error that can be emited by ViSP classes.
Definition: vpException.h:71
Class for generic objects.
vpHomogeneousMatrix inverse() const
vpHomogeneousMatrix getPosition() const
void extract(vpRotationMatrix &R) const
static const vpColor green
Definition: vpColor.h:182
void setLegend(unsigned int graphNum, unsigned int curveNum, const std::string &legend)
Definition: vpPlot.cpp:547
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:126
Definition: vpRGBa.h:66
static const vpColor red
Definition: vpColor.h:179
void fromImage(const vpImage< unsigned char > &image, unsigned char threshold, const vpCameraParameters &cam)
static const vpColor orange
Definition: vpColor.h:189
Type getMaxValue() const
Definition: vpArray2D.h:913
virtual void setSamplingTime(const double &delta_t)
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed...
Definition: vpDisplayD3D.h:106
void kill()
Definition: vpServo.cpp:192
void setCameraPosition(const vpHomogeneousMatrix &cMt)
static const vpColor cyan
Definition: vpColor.h:188
Type getMinValue() const
Definition: vpArray2D.h:896
double getD() const
Definition: vpPlane.h:108
vpColVector computeControlLaw()
Definition: vpServo.cpp:935
vpFeatureMomentAlpha & getFeatureAlpha()
void updateAll(double A, double B, double C)
void setInterpolationType(const vpInterpolationType interplt)
void changeFrame(const vpHomogeneousMatrix &cMo)
Definition: vpPlane.cpp:354
#define vpTRACE
Definition: vpDebug.h:416
static std::vector< double > getMu3(vpMomentObject &object)
vpMatrix L
Interaction matrix.
Definition: vpServo.h:544
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
double getB() const
Definition: vpPlane.h:104
Generic class defining intrinsic camera parameters.
void setLambda(double c)
Definition: vpServo.h:406
vpPoseVector buildFrom(double tx, double ty, double tz, double tux, double tuy, double tuz)
Class which enables to project an image in the 3D space and get the view of a virtual camera...
void setTitle(unsigned int graphNum, const std::string &title)
Definition: vpPlot.cpp:498
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:137
void plot(unsigned int graphNum, unsigned int curveNum, double x, double y)
Definition: vpPlot.cpp:286
vpServoIteractionMatrixType
Definition: vpServo.h:185
void setABCD(double a, double b, double c, double d)
Definition: vpPlane.h:90
static double getSurface(vpMomentObject &object)
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:574
vpFeatureMomentCInvariant & getFeatureCInvariant()
static double rad(double deg)
Definition: vpMath.h:108
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
double getA() const
Definition: vpPlane.h:102
void updateAll(vpMomentObject &object)
void initGraph(unsigned int graphNum, unsigned int curveNbr)
Definition: vpPlot.cpp:206
This class initializes and allows access to commonly used moments.
static double getAlpha(vpMomentObject &object)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:130
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:151
vpFeatureMomentGravityCenterNormalized & getFeatureGravityNormalized()
double sumSquare() const
void setType(vpObjectType input_type)
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:313
double getC() const
Definition: vpPlane.h:106
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
Definition: vpPlot.h:115
vpColVector getError() const
Definition: vpServo.h:282
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:58
void setColor(unsigned int graphNum, unsigned int curveNum, vpColor color)
Definition: vpPlot.cpp:261
static const vpColor purple
Definition: vpColor.h:190
vpFeatureMomentAreaNormalized & getFeatureAn()
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:223
vpColVector error
Definition: vpServo.h:549
Class that consider the case of a translation vector.
static const vpColor blue
Definition: vpColor.h:185