Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
servoMomentPoints.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 discrete points as object
33  * container
34  *
35  * Authors:
36  * Filip Novotny
37  *
38  *****************************************************************************/
39 
45 #include <iostream>
46 #include <visp3/core/vpCameraParameters.h>
47 #include <visp3/core/vpConfig.h>
48 #include <visp3/core/vpDebug.h>
49 #include <visp3/core/vpHomogeneousMatrix.h>
50 #include <visp3/core/vpIoTools.h>
51 #include <visp3/core/vpMath.h>
52 #include <visp3/core/vpMomentCommon.h>
53 #include <visp3/core/vpMomentDatabase.h>
54 #include <visp3/core/vpMomentObject.h>
55 #include <visp3/core/vpPlane.h>
56 #include <visp3/gui/vpDisplayGDI.h>
57 #include <visp3/gui/vpDisplayGTK.h>
58 #include <visp3/gui/vpDisplayX.h>
59 #include <visp3/robot/vpSimulatorAfma6.h>
60 #include <visp3/visual_features/vpFeatureBuilder.h>
61 #include <visp3/visual_features/vpFeatureMomentCommon.h>
62 #include <visp3/visual_features/vpFeaturePoint.h>
63 #include <visp3/vs/vpServo.h>
64 
65 #if !defined(_WIN32) && !defined(VISP_HAVE_PTHREAD)
66 // Robot simulator used in this example is not available
67 int main()
68 {
69  std::cout << "Can't run this example since vpSimulatorAfma6 capability is "
70  "not available."
71  << std::endl;
72  std::cout << "You should install pthread third-party library." << std::endl;
73  return EXIT_SUCCESS;
74 }
75 // No display available
76 #elif !defined(VISP_HAVE_X11) && !defined(VISP_HAVE_OPENCV) && !defined(VISP_HAVE_GDI) && !defined(VISP_HAVE_D3D9) && \
77  !defined(VISP_HAVE_GTK)
78 int main()
79 {
80  std::cout << "Can't run this example since no display capability is available." << std::endl;
81  std::cout << "You should install one of the following third-party library: "
82  "X11, OpenCV, GDI, GTK."
83  << std::endl;
84  return EXIT_SUCCESS;
85 }
86 #else
87 
88 // setup robot parameters
89 void paramRobot();
90 
91 // update moment objects and interface
92 void refreshScene(vpMomentObject &obj);
93 // initialize scene in the interface
94 void initScene();
95 // initialize the moment features
96 void initFeatures();
97 
98 void init(vpHomogeneousMatrix &cMo, vpHomogeneousMatrix &cdMo);
99 void execute(unsigned int nbIter); // launch the simulation
100 void setInteractionMatrixType(vpServo::vpServoIteractionMatrixType type);
101 double error();
102 void planeToABC(vpPlane &pl, double &A, double &B, double &C);
103 void paramRobot();
104 void removeJointLimits(vpSimulatorAfma6 &robot);
105 
106 int main()
107 {
108  try { // intial pose
109  vpHomogeneousMatrix cMo(0.05, 0.1, 1.5, vpMath::rad(30), vpMath::rad(20), -vpMath::rad(15));
110  // Desired pose
112 
113  // init and run the simulation
114  init(cMo, cdMo);
115  execute(1500);
116  return EXIT_SUCCESS;
117  } catch (const vpException &e) {
118  std::cout << "Catch an exception: " << e << std::endl;
119  return EXIT_FAILURE;
120  }
121 }
122 
123 // init the right display
124 #if defined VISP_HAVE_X11
125 vpDisplayX displayInt;
126 #elif defined VISP_HAVE_OPENCV
127 vpDisplayOpenCV displayInt;
128 #elif defined VISP_HAVE_GDI
129 vpDisplayGDI displayInt;
130 #elif defined VISP_HAVE_D3D9
131 vpDisplayD3D displayInt;
132 #elif defined VISP_HAVE_GTK
133 vpDisplayGTK displayInt;
134 #endif
135 
136 // start and destination positioning matrices
139 
140 vpSimulatorAfma6 robot(false); // robot used in this simulation
141 vpImage<vpRGBa> Iint(480, 640,
142  255); // internal image used for interface display
143 vpServo::vpServoIteractionMatrixType interaction_type; // current or desired
144 vpServo task; // servoing task
145 vpCameraParameters cam; // robot camera parameters
146 double _error; // current error
147 vpImageSimulator imsim; // image simulator used to simulate the
148  // perspective-projection camera
149 
150 // moment sets and their corresponding features
151 vpMomentCommon *moments;
152 vpMomentCommon *momentsDes;
153 vpFeatureMomentCommon *featureMoments;
154 vpFeatureMomentCommon *featureMomentsDes;
155 
156 // source and destination objects for moment manipulation
157 vpMomentObject src(6);
158 vpMomentObject dst(6);
159 
160 void initScene()
161 {
162  std::vector<vpPoint> src_pts;
163  std::vector<vpPoint> dst_pts;
164 
165  double x[8] = {1, 3, 4, -1, -3, -2, -1, 1};
166  double y[8] = {0, 1, 4, 4, -2, -2, 1, 0};
167  int nbpoints = 8;
168 
169  for (int i = 0; i < nbpoints; i++) {
170  vpPoint p(x[i] / 20, y[i] / 20, 0.0);
171  p.track(cMo);
172  src_pts.push_back(p);
173  }
174 
176  src.fromVector(src_pts);
177  for (int i = 0; i < nbpoints; i++) {
178  vpPoint p(x[i] / 20, y[i] / 20, 0.0);
179  p.track(cdMo);
180  dst_pts.push_back(p);
181  }
183  dst.fromVector(dst_pts);
184 }
185 
186 void initFeatures()
187 {
188  // A,B,C parameters of source and destination plane
189  double A;
190  double B;
191  double C;
192  double Ad;
193  double Bd;
194  double Cd;
195  // init main object: using moments up to order 6
196 
197  // Initializing values from regular plane (with ax+by+cz=d convention)
198  vpPlane pl;
199  pl.setABCD(0, 0, 1.0, 0);
200  pl.changeFrame(cMo);
201  planeToABC(pl, A, B, C);
202 
203  pl.setABCD(0, 0, 1.0, 0);
204  pl.changeFrame(cdMo);
205  planeToABC(pl, Ad, Bd, Cd);
206 
207  // extracting initial position (actually we only care about Zdst)
209  cdMo.extract(vec);
210 
213  // don't need to be specific, vpMomentCommon automatically loads
214  // Xg,Yg,An,Ci,Cj,Alpha moments
216  vpMomentCommon::getAlpha(dst), vec[2]);
218  vpMomentCommon::getAlpha(dst), vec[2]);
219  // same thing with common features
220  featureMoments = new vpFeatureMomentCommon(*moments);
221  featureMomentsDes = new vpFeatureMomentCommon(*momentsDes);
222 
223  moments->updateAll(src);
224  momentsDes->updateAll(dst);
225 
226  featureMoments->updateAll(A, B, C);
227  featureMomentsDes->updateAll(Ad, Bd, Cd);
228 
229  // setup the interaction type
230  task.setInteractionMatrixType(interaction_type);
233  task.addFeature(featureMoments->getFeatureGravityNormalized(), featureMomentsDes->getFeatureGravityNormalized());
234  task.addFeature(featureMoments->getFeatureAn(), featureMomentsDes->getFeatureAn());
235  task.addFeature(featureMoments->getFeatureCInvariant(), featureMomentsDes->getFeatureCInvariant(),
236  (1 << 3) | (1 << 5));
237  task.addFeature(featureMoments->getFeatureAlpha(), featureMomentsDes->getFeatureAlpha());
238 
239  task.setLambda(1.);
240 }
241 
242 void refreshScene(vpMomentObject &obj)
243 {
244  // double x[8] = { 0.05,0.15, 0.2,-0.05 ,-0.15,-0.1,-0.05,0.05};
245  // double y[8] = { 0,0.05, 0.2, 0.2, -0.1,-0.1, 0.05,0};
246  double x[8] = {1, 3, 4, -1, -3, -2, -1, 1};
247  double y[8] = {0, 1, 4, 4, -2, -2, 1, 0};
248  int nbpoints = 8;
249  std::vector<vpPoint> cur_pts;
250 
251  for (int i = 0; i < nbpoints; i++) {
252  vpPoint p(x[i] / 20, y[i] / 20, 0.0);
253  p.track(cMo);
254  cur_pts.push_back(p);
255  }
256  obj.fromVector(cur_pts);
257 }
258 
259 void init(vpHomogeneousMatrix &_cMo, vpHomogeneousMatrix &_cdMo)
260 
261 {
262  cMo = _cMo; // init source matrix
263  cdMo = _cdMo; // init destination matrix
264  interaction_type = vpServo::CURRENT; // use interaction matrix for current position
265 
266  displayInt.init(Iint, 700, 0, "Visual servoing with moments");
267 
268  paramRobot(); // set up robot parameters
269 
271  initScene(); // initialize graphical scene (for interface)
272  initFeatures(); // initialize moment features
273 }
274 
275 void execute(unsigned int nbIter)
276 {
277  // init main object: using moments up to order 6
278  vpMomentObject obj(6);
279  // setting object type (disrete, continuous[form polygon])
281 
282  vpTRACE("Display task information ");
283  task.print();
284 
285  vpDisplay::display(Iint);
286  robot.getInternalView(Iint);
287  vpDisplay::flush(Iint);
288  unsigned int iter = 0;
289 
291  while (iter++ < nbIter) {
292  vpColVector v;
293  // get the cMo
294  cMo = robot.get_cMo();
295  // setup the plane in A,B,C style
296  vpPlane pl;
297  double A, B, C;
298  pl.setABCD(0, 0, 1.0, 0);
299  pl.changeFrame(cMo);
300  planeToABC(pl, A, B, C);
301 
302  // track points, draw points and add refresh our object
303  refreshScene(obj);
304  // this is the most important thing to do: update our moments
305  moments->updateAll(obj);
306  // and update our features. Do it in that order. Features need to use the
307  // information computed by moments
308  featureMoments->updateAll(A, B, C);
309 
310  vpDisplay::display(Iint);
311  robot.getInternalView(Iint);
312  vpDisplay::flush(Iint);
313 
314  if (iter == 1)
315  vpDisplay::getClick(Iint);
316  v = task.computeControlLaw();
317 
318  // pilot robot using position control. The displacement is t*v with t=10ms
319  // step robot.setPosition(vpRobot::CAMERA_FRAME,0.01*v);
321 
322  _error = (task.getError()).sumSquare();
323  }
324 
325  task.kill();
326 
327  vpTRACE("\n\nClick in the internal view window to end...");
328  vpDisplay::getClick(Iint);
329 
330  delete moments;
331  delete momentsDes;
332  delete featureMoments;
333  delete featureMomentsDes;
334 }
335 
336 void removeJointLimits(vpSimulatorAfma6 &robot_)
337 {
338  vpColVector limMin(6);
339  vpColVector limMax(6);
340  limMin[0] = vpMath::rad(-3600);
341  limMin[1] = vpMath::rad(-3600);
342  limMin[2] = vpMath::rad(-3600);
343  limMin[3] = vpMath::rad(-3600);
344  limMin[4] = vpMath::rad(-3600);
345  limMin[5] = vpMath::rad(-3600);
346 
347  limMax[0] = vpMath::rad(3600);
348  limMax[1] = vpMath::rad(3600);
349  limMax[2] = vpMath::rad(3600);
350  limMax[3] = vpMath::rad(3600);
351  limMax[4] = vpMath::rad(3600);
352  limMax[5] = vpMath::rad(3600);
353 
354  robot_.setJointLimit(limMin, limMax);
355  robot_.setMaxRotationVelocity(99999);
356  robot_.setMaxTranslationVelocity(999999);
357 }
358 
359 void planeToABC(vpPlane &pl, double &A, double &B, double &C)
360 {
361  if (fabs(pl.getD()) < std::numeric_limits<double>::epsilon()) {
362  std::cout << "Invalid position:" << std::endl;
363  std::cout << cMo << std::endl;
364  std::cout << "Cannot put plane in the form 1/Z=Ax+By+C." << std::endl;
365  throw vpException(vpException::divideByZeroError, "invalid position!");
366  }
367  A = -pl.getA() / pl.getD();
368  B = -pl.getB() / pl.getD();
369  C = -pl.getC() / pl.getD();
370 }
371 
372 void paramRobot()
373 {
374  /*Initialise the robot and especially the camera*/
376  robot.setCurrentViewColor(vpColor(150, 150, 150));
377  robot.setDesiredViewColor(vpColor(200, 200, 200));
379  removeJointLimits(robot);
381  robot.setConstantSamplingTimeMode(true);
382  /*Initialise the position of the object relative to the pose of the robot's
383  * camera*/
384  robot.initialiseObjectRelativeToCamera(cMo);
385 
386  /*Set the desired position (for the displaypart)*/
387  robot.setDesiredCameraPosition(cdMo);
388  robot.getCameraParameters(cam, Iint);
389 }
390 
391 void setInteractionMatrixType(vpServo::vpServoIteractionMatrixType type) { interaction_type = type; }
392 double error() { return _error; }
393 
394 #endif
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel)
void setMaxTranslationVelocity(const double maxVt)
Definition: vpRobot.cpp:239
Implementation of an homogeneous matrix and operations on such kind of matrices.
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:129
Class to define colors available for display functionnalities.
Definition: vpColor.h:120
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:151
void addFeature(vpBasicFeature &s, vpBasicFeature &s_star, const unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:497
This class allows to access common vpFeatureMoments in a pre-filled database.
error that can be emited by ViSP classes.
Definition: vpException.h:71
void setJointLimit(const vpColVector &limitMin, const vpColVector &limitMax)
void setABCD(const double a, const double b, const double c, const double d)
Definition: vpPlane.h:90
Class for generic objects.
static void flush(const vpImage< unsigned char > &I)
virtual vpRobotStateType setRobotState(const vpRobot::vpRobotStateType newState)
Definition: vpRobot.cpp:201
Class that defines what is a point.
Definition: vpPoint.h:58
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed...
Definition: vpDisplayD3D.h:107
void kill()
Definition: vpServo.cpp:192
Initialize the velocity controller.
Definition: vpRobot.h:67
vpColVector getError() const
Definition: vpServo.h:282
vpColVector computeControlLaw()
Definition: vpServo.cpp:935
vpFeatureMomentAlpha & getFeatureAlpha()
void updateAll(double A, double B, double C)
void changeFrame(const vpHomogeneousMatrix &cMo)
Definition: vpPlane.cpp:354
#define vpTRACE
Definition: vpDebug.h:416
static std::vector< double > getMu3(vpMomentObject &object)
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:406
Class which enables to project an image in the 3D space and get the view of a virtual camera...
Simulator of Irisa&#39;s gantry robot named Afma6.
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:138
void extract(vpRotationMatrix &R) const
vpServoIteractionMatrixType
Definition: vpServo.h:185
void fromVector(std::vector< vpPoint > &points)
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:102
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
void updateAll(vpMomentObject &object)
void setMaxRotationVelocity(const double maxVr)
Definition: vpRobot.cpp:260
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:72
vpFeatureMomentGravityCenterNormalized & getFeatureGravityNormalized()
double getB() const
Definition: vpPlane.h:104
void setType(vpObjectType input_type)
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:313
double getA() const
Definition: vpPlane.h:102
double getC() const
Definition: vpPlane.h:106
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:58
vpFeatureMomentAreaNormalized & getFeatureAn()
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:223
Class that consider the case of a translation vector.
double getD() const
Definition: vpPlane.h:108