Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
servoViper850Point2DArtVelocity-jointAvoidance-basic.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  * tests the control law
33  * eye-in-hand control
34  * velocity computed in articular
35  *
36  * Authors:
37  * Eric Marchand
38  * Fabien Spindler
39  *
40  *****************************************************************************/
41 
51 #include <visp3/core/vpConfig.h>
52 #include <visp3/core/vpDebug.h> // Debug trace
53 
54 #include <cmath> // std::fabs
55 #include <fstream>
56 #include <iostream>
57 #include <limits> // numeric_limits
58 #include <sstream>
59 #include <stdio.h>
60 #include <stdlib.h>
61 
62 #if (defined(VISP_HAVE_VIPER850) && defined(VISP_HAVE_DC1394) && defined(VISP_HAVE_DISPLAY))
63 
64 #include <visp3/blob/vpDot2.h>
65 #include <visp3/core/vpDisplay.h>
66 #include <visp3/core/vpException.h>
67 #include <visp3/core/vpHomogeneousMatrix.h>
68 #include <visp3/core/vpImage.h>
69 #include <visp3/core/vpIoTools.h>
70 #include <visp3/core/vpMath.h>
71 #include <visp3/core/vpPoint.h>
72 #include <visp3/gui/vpDisplayGTK.h>
73 #include <visp3/gui/vpDisplayOpenCV.h>
74 #include <visp3/gui/vpDisplayX.h>
75 #include <visp3/gui/vpPlot.h>
76 #include <visp3/robot/vpRobotViper850.h>
77 #include <visp3/sensor/vp1394TwoGrabber.h>
78 #include <visp3/visual_features/vpFeatureBuilder.h>
79 #include <visp3/visual_features/vpFeaturePoint.h>
80 #include <visp3/vs/vpServo.h>
81 #include <visp3/vs/vpServoDisplay.h>
82 
83 int main()
84 {
85  try {
86  vpRobotViper850 robot;
87 
88  vpServo task;
89 
91 
92  bool reset = false;
93  vp1394TwoGrabber g(reset);
95  g.setFramerate(vp1394TwoGrabber::vpFRAMERATE_60);
96  g.open(I);
97 
98  g.acquire(I);
99 
100  double Tloop = 1. / 60.f;
101 
103  g.getFramerate(fps);
104  switch (fps) {
106  Tloop = 1.f / 15.f;
107  break;
109  Tloop = 1.f / 30.f;
110  break;
112  Tloop = 1.f / 60.f;
113  break;
115  Tloop = 1.f / 120.f;
116  break;
117  default:
118  break;
119  }
120  std::cout << "Tloop: " << Tloop << std::endl;
121 
122 #ifdef VISP_HAVE_X11
123  vpDisplayX display(I, 800, 100, "Current image");
124 #elif defined(VISP_HAVE_OPENCV)
125  vpDisplayOpenCV display(I, 800, 100, "Current image");
126 #elif defined(VISP_HAVE_GTK)
127  vpDisplayGTK display(I, 800, 100, "Current image");
128 #endif
129 
131  vpDisplay::flush(I);
132 
133  vpColVector jointMin(6), jointMax(6);
134  jointMin = robot.getJointMin();
135  jointMax = robot.getJointMax();
136 
137  vpColVector Qmin(6), tQmin(6);
138  vpColVector Qmax(6), tQmax(6);
139  vpColVector Qmiddle(6);
140  vpColVector data(10);
141 
142  double rho = 0.25;
143  for (unsigned int i = 0; i < 6; i++) {
144  Qmin[i] = jointMin[i] + 0.5 * rho * (jointMax[i] - jointMin[i]);
145  Qmax[i] = jointMax[i] - 0.5 * rho * (jointMax[i] - jointMin[i]);
146  }
147  Qmiddle = (Qmin + Qmax) / 2.;
148  double rho1 = 0.1;
149 
150  for (unsigned int i = 0; i < 6; i++) {
151  tQmin[i] = Qmin[i] + 0.5 * (rho1) * (Qmax[i] - Qmin[i]);
152  tQmax[i] = Qmax[i] - 0.5 * (rho1) * (Qmax[i] - Qmin[i]);
153  }
154 
155  vpColVector q(6);
156 
157  // Create a window with two graphics
158  // - first graphic to plot q(t), Qmin, Qmax, tQmin and tQmax
159  // - second graphic to plot the cost function h_s
160  vpPlot plot(2);
161 
162  // The first graphic contains 10 data to plot: q(t), Qmin, Qmax, tQmin and
163  // tQmax
164  plot.initGraph(0, 10);
165  plot.initGraph(1, 6);
166 
167  // For the first graphic :
168  // - along the x axis the expected values are between 0 and 200 and
169  // the step is 1
170  // - along the y axis the expected values are between -1.2 and 1.2 and the
171  // step is 0.1
172  plot.initRange(0, 0, 200, 1, -1.2, 1.2, 0.1);
173  plot.setTitle(0, "Joint behavior");
174  plot.initRange(1, 0, 200, 1, -0.01, 0.01, 0.05);
175  plot.setTitle(1, "Joint velocity");
176 
177  // For the first graphic, set the curves legend
178  char legend[10];
179  for (unsigned int i = 0; i < 6; i++) {
180  sprintf(legend, "q%u", i + 1);
181  plot.setLegend(0, i, legend);
182  sprintf(legend, "q%u", i + 1);
183  plot.setLegend(1, i, legend);
184  }
185  plot.setLegend(0, 6, "tQmin");
186  plot.setLegend(0, 7, "tQmax");
187  plot.setLegend(0, 8, "Qmin");
188  plot.setLegend(0, 9, "Qmax");
189 
190  // Set the curves color
191  plot.setColor(0, 0, vpColor::red);
192  plot.setColor(0, 1, vpColor::green);
193  plot.setColor(0, 2, vpColor::blue);
194  plot.setColor(0, 3, vpColor::orange);
195  plot.setColor(0, 4, vpColor(0, 128, 0));
196  plot.setColor(0, 5, vpColor::cyan);
197  for (unsigned int i = 6; i < 10; i++)
198  plot.setColor(0, i, vpColor::black); // for Q and tQ [min,max]
199  // Set the curves color
200 
201  plot.setColor(1, 0, vpColor::red);
202  plot.setColor(1, 1, vpColor::green);
203  plot.setColor(1, 2, vpColor::blue);
204  plot.setColor(1, 3, vpColor::orange);
205  plot.setColor(1, 4, vpColor(0, 128, 0));
206  plot.setColor(1, 5, vpColor::cyan);
207  vpDot2 dot;
208 
209  std::cout << "Click on a dot..." << std::endl;
210  dot.initTracking(I);
211  vpImagePoint cog = dot.getCog();
213  vpDisplay::flush(I);
214 
215  vpCameraParameters cam;
216  // Update camera parameters
217  robot.getCameraParameters(cam, I);
218 
219  // sets the current position of the visual feature
220  vpFeaturePoint p;
221  vpFeatureBuilder::create(p, cam, dot); // retrieve x,y and Z of the vpPoint structure
222 
223  p.set_Z(1);
224  // sets the desired position of the visual feature
225  vpFeaturePoint pd;
226  pd.buildFrom(0, 0, 1);
227 
228  // Define the task
229  // - we want an eye-in-hand control law
230  // - articular velocity are computed
233 
235  robot.get_cVe(cVe);
236  std::cout << cVe << std::endl;
237  task.set_cVe(cVe);
238 
239  // - Set the Jacobian (expressed in the end-effector frame)") ;
240  vpMatrix eJe;
241  robot.get_eJe(eJe);
242  task.set_eJe(eJe);
243 
244  // - we want to see a point on a point..") ;
245  std::cout << std::endl;
246  task.addFeature(p, pd);
247 
248  // - set the gain
249  double lambda = 0.8;
250  // set to -1 to suppress the lambda used in the
251  // vpServo::computeControlLaw()
252  task.setLambda(-1);
253 
254  // Display task information " ) ;
255  task.print();
256 
258 
259  int iter = 0;
260  double t_1 = vpTime::measureTimeMs();
261 
262  std::cout << "\nHit CTRL-C to stop the loop...\n" << std::flush;
263  for (;;) {
264  iter++;
265 
266  double t_0 = vpTime::measureTimeMs(); // t_0: current time
267 
268  // Update loop time in second
269  double Tv = (double)(t_0 - t_1) / 1000.0;
270  std::cout << "Tv: " << Tv << std::endl;
271 
272  // Update time for next iteration
273  t_1 = t_0;
274 
275  // Acquire a new image from the camera
276  dc1394video_frame_t *frame = g.dequeue(I);
277 
278  // Display this image
280 
281  // Achieve the tracking of the dot in the image
282  dot.track(I);
283  cog = dot.getCog();
284 
285  // Display a green cross at the center of gravity position in the image
287 
288  // Get the measured joint positions of the robot
290 
291  // Update the point feature from the dot location
292  vpFeatureBuilder::create(p, cam, dot);
293 
294  // Get the jacobian of the robot
295  robot.get_eJe(eJe);
296  // Update this jacobian in the task structure. It will be used to
297  // compute the velocity skew (as an articular velocity) qdot = -lambda *
298  // L^+ * cVe * eJe * (s-s*)
299  task.set_eJe(eJe);
300 
301  vpColVector prim_task;
302  vpColVector e2(6);
303  // Compute the visual servoing skew vector
304  prim_task = task.computeControlLaw();
305 
306  vpColVector qpre(6);
307 
308  qpre = q;
309  qpre += -lambda * prim_task * (4 * Tloop);
310 
311  // Identify the joints near the limits
312  vpColVector pb(6);
313  pb = 0;
314  unsigned int npb = 0;
315  for (unsigned int i = 0; i < 6; i++) {
316  if (q[i] < tQmin[i])
317  if (fabs(Qmin[i] - q[i]) > fabs(Qmin[i] - qpre[i])) {
318  pb[i] = 1;
319  npb++;
320  std::cout << "Joint " << i << " near limit " << std::endl;
321  }
322  if (q[i] > tQmax[i]) {
323  if (fabs(Qmax[i] - q[i]) > fabs(Qmax[i] - qpre[i])) {
324  pb[i] = 1;
325  npb++;
326  std::cout << "Joint " << i << " near limit " << std::endl;
327  }
328  }
329  }
330 
331  vpColVector a0;
332  vpMatrix J1 = task.getTaskJacobian();
333  vpMatrix kernelJ1;
334  J1.kernel(kernelJ1);
335 
336  unsigned int dimKernelL = kernelJ1.getCols();
337  if (npb != 0) {
338  // Build linear system a0*E = S
339  vpMatrix E(npb, dimKernelL);
340  vpColVector S(npb);
341 
342  unsigned int k = 0;
343 
344  for (unsigned int j = 0; j < 6; j++) // j is the joint
345  // if (pb[j]==1) {
346  if (std::fabs(pb[j] - 1) <= std::numeric_limits<double>::epsilon()) {
347  for (unsigned int i = 0; i < dimKernelL; i++)
348  E[k][i] = kernelJ1[j][i];
349 
350  S[k] = -prim_task[j];
351  k++;
352  }
353  vpMatrix Ep;
354  // vpTRACE("nbp %d", npb);
355  Ep = E.t() * (E * E.t()).pseudoInverse();
356  a0 = Ep * S;
357 
358  e2 = (kernelJ1 * a0);
359  // cout << "e2 " << e2.t() ;
360  } else {
361  e2 = 0;
362  }
363  // std::cout << "e2: " << e2.t() << std::endl;
364 
365  vpColVector v;
366  v = -lambda * (prim_task + e2);
367 
368  // Display the current and desired feature points in the image display
369  vpServoDisplay::display(task, cam, I);
370 
371  // Apply the computed joint velocities to the robot
373 
374  {
375  // Add the material to plot curves
376 
377  // q normalized between (entre -1 et 1)
378  for (unsigned int i = 0; i < 6; i++) {
379  data[i] = (q[i] - Qmiddle[i]);
380  data[i] /= (Qmax[i] - Qmin[i]);
381  data[i] *= 2;
382  }
383  unsigned int joint = 2;
384  data[6] = 2 * (tQmin[joint] - Qmiddle[joint]) / (Qmax[joint] - Qmin[joint]);
385  data[7] = 2 * (tQmax[joint] - Qmiddle[joint]) / (Qmax[joint] - Qmin[joint]);
386  data[8] = -1;
387  data[9] = 1;
388 
389  plot.plot(0, iter, data); // plot q, Qmin, Qmax, tQmin, tQmax
390  plot.plot(1, iter, v); // plot joint velocities applied to the robot
391  }
392 
393  vpDisplay::flush(I);
394 
395  // Synchronize the loop with the image frame rate
396  vpTime::wait(t_0, 1000. * Tloop);
397  // Release the ring buffer used for the last image to start a new acq
398  g.enqueue(frame);
399  }
400 
401  // Display task information
402  task.print();
403  task.kill();
404  return EXIT_SUCCESS;
405  }
406  catch (const vpException &e) {
407  std::cout << "Catch an exception: " << e.getMessage() << std::endl;
408  return EXIT_FAILURE;
409  }
410 }
411 
412 #else
413 int main()
414 {
415  std::cout << "You do not have an Viper 850 robot connected to your computer..." << std::endl;
416  return EXIT_SUCCESS;
417 }
418 #endif
void getPosition(const vpRobot::vpControlFrameType frame, vpColVector &position)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:150
vpMatrix getTaskJacobian() const
Definition: vpServo.cpp:1790
void getCameraParameters(vpCameraParameters &cam, const unsigned int &image_width, const unsigned int &image_height) const
Definition: vpViper850.cpp:540
Control of Irisa&#39;s Viper S850 robot named Viper850.
static const vpColor black
Definition: vpColor.h:174
Class to define colors available for display functionnalities.
Definition: vpColor.h:120
void set_eJe(const vpMatrix &eJe_)
Definition: vpServo.h:508
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
vpRobot::vpRobotStateType setRobotState(vpRobot::vpRobotStateType newState)
error that can be emited by ViSP classes.
Definition: vpException.h:71
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
unsigned int getCols() const
Definition: vpArray2D.h:146
void get_eJe(vpMatrix &eJe)
static const vpColor green
Definition: vpColor.h:183
This tracker is meant to track a blob (connex pixels with same gray level) on a vpImage.
Definition: vpDot2.h:126
void track(const vpImage< unsigned char > &I)
Definition: vpDot2.cpp:438
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:88
static const vpColor red
Definition: vpColor.h:180
static const vpColor orange
Definition: vpColor.h:190
vpImagePoint getCog() const
Definition: vpDot2.h:161
void kill()
Definition: vpServo.cpp:192
Initialize the velocity controller.
Definition: vpRobot.h:67
static const vpColor cyan
Definition: vpColor.h:189
vpColVector computeControlLaw()
Definition: vpServo.cpp:935
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
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:138
const char * getMessage(void) const
Definition: vpException.cpp:90
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:574
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &velocity)
void buildFrom(const double x, const double y, const double Z)
vpColVector getJointMin() const
Definition: vpViper.cpp:1199
void get_cVe(vpVelocityTwistMatrix &cVe) const
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
vpMatrix t() const
Definition: vpMatrix.cpp:375
vpColVector getJointMax() const
Definition: vpViper.cpp:1208
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
void set_cVe(const vpVelocityTwistMatrix &cVe_)
Definition: vpServo.h:450
void initTracking(const vpImage< unsigned char > &I, unsigned int size=0)
Definition: vpDot2.cpp:253
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:313
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
Definition: vpPlot.h:115
Class for firewire ieee1394 video devices using libdc1394-2.x api.
unsigned int kernel(vpMatrix &kerAt, double svThreshold=1e-6) const
Definition: vpMatrix.cpp:4821
void set_Z(const double Z)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:223
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)
static const vpColor blue
Definition: vpColor.h:186