Visual Servoing Platform  version 3.0.1
servoPioneerPoint2DDepthWithoutVpServo.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * IBVS on Pioneer P3DX mobile platform
32  *
33  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 #include <iostream>
38 
39 #include <visp3/core/vpConfig.h>
40 #include <visp3/robot/vpRobotPioneer.h>
41 #include <visp3/core/vpCameraParameters.h>
42 #include <visp3/gui/vpDisplayGDI.h>
43 #include <visp3/gui/vpDisplayX.h>
44 #include <visp3/blob/vpDot2.h>
45 #include <visp3/visual_features/vpFeatureBuilder.h>
46 #include <visp3/visual_features/vpFeatureDepth.h>
47 #include <visp3/visual_features/vpFeaturePoint.h>
48 #include <visp3/core/vpHomogeneousMatrix.h>
49 #include <visp3/core/vpImage.h>
50 #include <visp3/core/vpImageConvert.h>
51 #include <visp3/sensor/vp1394TwoGrabber.h>
52 #include <visp3/sensor/vp1394CMUGrabber.h>
53 #include <visp3/sensor/vpOpenCVGrabber.h>
54 #include <visp3/sensor/vpV4l2Grabber.h>
55 #include <visp3/core/vpVelocityTwistMatrix.h>
56 
57 #if defined(VISP_HAVE_DC1394) || defined(VISP_HAVE_V4L2) || defined(VISP_HAVE_CMU1394) || (VISP_HAVE_OPENCV_VERSION >= 0x020100)
58 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)
59 #if defined(VISP_HAVE_PIONEER)
60 # define TEST_COULD_BE_ACHIEVED
61 #endif
62 #endif
63 #endif
64 
65 #undef VISP_HAVE_OPENCV // To use a firewire camera
66 #undef VISP_HAVE_V4L2 // To use a firewire camera
67 
87 #ifdef TEST_COULD_BE_ACHIEVED
88 int main(int argc, char **argv)
89 {
90  try {
91  vpImage<unsigned char> I; // Create a gray level image container
92  double depth = 1.;
93  double lambda = 0.6;
94  double coef = 1./6.77; // Scale parameter used to estimate the depth Z of the blob from its surface
95 
96  vpRobotPioneer robot;
97  ArArgumentParser parser(&argc, argv);
98  parser.loadDefaultArguments();
99 
100  // ArRobotConnector connects to the robot, get some initial data from it such as type and name,
101  // and then loads parameter files for this robot.
102  ArRobotConnector robotConnector(&parser, &robot);
103  if(!robotConnector.connectRobot())
104  {
105  ArLog::log(ArLog::Terse, "Could not connect to the robot.");
106  if(parser.checkHelpAndWarnUnparsed())
107  {
108  Aria::logOptions();
109  Aria::exit(1);
110  }
111  }
112  if (!Aria::parseArgs())
113  {
114  Aria::logOptions();
115  Aria::shutdown();
116  return false;
117  }
118 
119  // Wait 3 sec to be sure that the low level Aria thread used to control
120  // the robot is started. Without this delay we experienced a delay (arround 2.2 sec)
121  // between the velocity send to the robot and the velocity that is really applied
122  // to the wheels.
123  vpTime::sleepMs(3000);
124 
125  std::cout << "Robot connected" << std::endl;
126 
127  // Camera parameters. In this experiment we don't need a precise calibration of the camera
128  vpCameraParameters cam;
129 
130  // Create the camera framegrabber
131 #if defined(VISP_HAVE_OPENCV)
132  int device = 1;
133  std::cout << "Use device: " << device << std::endl;
134  cv::VideoCapture g(device); // open the default camera
135  g.set(CV_CAP_PROP_FRAME_WIDTH, 640);
136  g.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
137  if(!g.isOpened()) // check if we succeeded
138  return -1;
139  cv::Mat frame;
140  g >> frame; // get a new frame from camera
141  vpImageConvert::convert(frame, I);
142 
143  // Logitec sphere parameters
144  cam.initPersProjWithoutDistortion(558, 555, 312, 210);
145 #elif defined(VISP_HAVE_V4L2)
146  // Create a grabber based on v4l2 third party lib (for usb cameras under Linux)
147  vpV4l2Grabber g;
148  g.setScale(1);
149  g.setInput(0);
150  g.setDevice("/dev/video1");
151  g.open(I);
152  // Logitec sphere parameters
153  cam.initPersProjWithoutDistortion(558, 555, 312, 210);
154 #elif defined(VISP_HAVE_DC1394)
155  // Create a grabber based on libdc1394-2.x third party lib (for firewire cameras under Linux)
156  vp1394TwoGrabber g(false);
159  // AVT Pike 032C parameters
160  cam.initPersProjWithoutDistortion(800, 795, 320, 216);
161 #elif defined(VISP_HAVE_CMU1394)
162  // Create a grabber based on CMU 1394 third party lib (for firewire cameras under windows)
164  g.setVideoMode(0, 5); // 640x480 MONO8
165  g.setFramerate(4); // 30 Hz
166  g.open(I);
167  // AVT Pike 032C parameters
168  cam.initPersProjWithoutDistortion(800, 795, 320, 216);
169 #endif
170 
171  // Acquire an image from the grabber
172 #if defined(VISP_HAVE_OPENCV)
173  g >> frame; // get a new frame from camera
174  vpImageConvert::convert(frame, I);
175 #else
176  g.acquire(I);
177 #endif
178 
179  // Create an image viewer
180 #if defined(VISP_HAVE_X11)
181  vpDisplayX d(I, 10, 10, "Current frame");
182 #elif defined(VISP_HAVE_GDI)
183  vpDisplayGDI d(I, 10, 10, "Current frame");
184 #endif
186  vpDisplay::flush(I);
187 
188  // Create a blob tracker
189  vpDot2 dot;
190  dot.setGraphics(true);
191  dot.setComputeMoments(true);
192  dot.setEllipsoidShapePrecision(0.); // to track a blob without any constraint on the shape
193  dot.setGrayLevelPrecision(0.9); // to set the blob gray level bounds for binarisation
194  dot.setEllipsoidBadPointsPercentage(0.5); // to be accept 50% of bad inner and outside points with bad gray level
195  dot.initTracking(I);
196  vpDisplay::flush(I);
197 
198  // Current and desired visual feature associated to the x coordinate of the point
199  vpFeaturePoint s_x, s_xd;
200 
201  // Create the current x visual feature
202  vpFeatureBuilder::create(s_x, cam, dot);
203 
204  // Create the desired x* visual feature
205  s_xd.buildFrom(0, 0, depth);
207 
208  // Create the current log(Z/Z*) visual feature
209  vpFeatureDepth s_Z;
210  // Surface of the blob estimated from the image moment m00 and converted in meters
211  double surface = 1./sqrt(dot.m00/(cam.get_px()*cam.get_py()));
212  double Z, Zd;
213  // Initial depth of the blob in from of the camera
214  Z = coef * surface ;
215  // Desired depth Z* of the blob. This depth is learned and equal to the initial depth
216  Zd = Z;
217  s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z , 0); // log(Z/Z*) = 0 that's why the last parameter is 0
218  vpMatrix L_Z = s_Z.interaction();
219 
220  vpVelocityTwistMatrix cVe = robot.get_cVe();
221  vpMatrix eJe; // pioneer jacobian
222  robot.get_eJe(eJe);
223 
224  vpMatrix L; // Interaction matrix
225  L.stack(L_x); // constant since build with the desired feature
226  L.stack(L_Z); // not constant since it corresponds to log(Z/Z*) that evolves at each iteration
227 
228  vpColVector v; // vz, wx
229 
230  vpFeatureDepth s_Zd;
231  s_Zd.buildFrom(0, 0, 1, 0); // The value of s* is 0 with Z=1 meter.
232 
233  while(1)
234  {
235  // Acquire a new image
236 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)
237  g >> frame; // get a new frame from camera
238  vpImageConvert::convert(frame, I);
239 #else
240  g.acquire(I);
241 #endif
242  // Set the image as background of the viewer
244 
245  // Does the blob tracking
246  dot.track(I);
247  // Update the current x feature
248  vpFeatureBuilder::create(s_x, cam, dot);
249 
250  // Update log(Z/Z*) feature. Since the depth Z change, we need to update the intection matrix
251  surface = 1./sqrt(dot.m00/(cam.get_px()*cam.get_py()));
252  Z = coef * surface ;
253  s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z, log(Z/Zd)) ;
254  L_Z = s_Z.interaction();
255 
256  // Update the global interaction matrix
257  vpMatrix L;
258  L.stack(L_x); // constant since build with the desired feature
259  L.stack(L_Z); // not constant since it corresponds to log(Z/Z*) that evolves at each iteration
260 
261  // Update the global error s-s*
262  vpColVector error;
263  error.stack( s_x.error( s_xd, vpFeaturePoint::selectX() ) );
264  error.stack( s_Z.error( s_Zd ) );
265 
266  // Compute the control law. Velocities are computed in the mobile robot reference frame
267  v = -lambda * (L * cVe * eJe).pseudoInverse() * error;
268 
269  std::cout << "Send velocity to the pionner: " << v[0] << " m/s "
270  << vpMath::deg(v[1]) << " deg/s" << std::endl;
271 
272  // Send the velocity to the robot
274 
275  // Draw a vertical line which corresponds to the desired x coordinate of the dot cog
276  vpDisplay::displayLine(I, 0, 320, 479, 320, vpColor::red);
277  vpDisplay::flush(I);
278 
279  // A click in the viewer to exit
280  if ( vpDisplay::getClick(I, false) )
281  break;
282  }
283 
284  std::cout << "Ending robot thread..." << std::endl;
285  robot.stopRunning();
286 
287  // wait for the thread to stop
288  robot.waitForRunExit();
289  }
290  catch(vpException &e) {
291  std::cout << "Catch an exception: " << e << std::endl;
292  return 1;
293  }
294 }
295 #else
296 int main()
297 {
298  std::cout << "You don't have the right 3rd party libraries to run this example..." << std::endl;
299 }
300 #endif
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:97
vpVelocityTwistMatrix get_cVe() const
Definition: vpUnicycle.h:87
vpMatrix interaction(const unsigned int select=FEATURE_ALL)
void setVideoMode(unsigned long format, unsigned long mode)
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void open(vpImage< unsigned char > &I)
void stack(const double &d)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void get_eJe(vpMatrix &eJe)
void open(vpImage< unsigned char > &I)
vpColVector error(const vpBasicFeature &s_star, const unsigned int select=FEATURE_ALL)
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
void setEllipsoidBadPointsPercentage(const double &percentage=0.0)
Definition: vpDot2.h:292
void stack(const vpMatrix &A)
Definition: vpMatrix.cpp:2981
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel)
void buildFrom(const double x, const double y, const double Z, const double LogZoverZstar)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:153
void setDevice(const std::string &devname)
Class that defines a 3D point visual feature which is composed by one parameters that is that defin...
error that can be emited by ViSP classes.
Definition: vpException.h:73
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
Interface for Pioneer mobile robots based on Aria 3rd party library.
This tracker is meant to track a blob (connex pixels with same gray level) on a vpImage.
Definition: vpDot2.h:125
void track(const vpImage< unsigned char > &I)
Definition: vpDot2.cpp:461
static void flush(const vpImage< unsigned char > &I)
static const vpColor red
Definition: vpColor.h:163
void initPersProjWithoutDistortion(const double px, const double py, const double u0, const double v0)
vpMatrix interaction(const unsigned int select=FEATURE_ALL)
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition: vpDot2.cpp:783
Firewire cameras video capture based on CMU 1394 Digital Camera SDK.
void setFramerate(unsigned long fps)
static unsigned int selectX()
void acquire(vpImage< unsigned char > &I)
static void display(const vpImage< unsigned char > &I)
VISP_EXPORT void sleepMs(double t)
Definition: vpTime.cpp:266
Generic class defining intrinsic camera parameters.
double get_x() const
void setComputeMoments(const bool activate)
Definition: vpDot2.h:278
Implementation of a velocity twist matrix and operations on such kind of matrices.
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setEllipsoidShapePrecision(const double &ellipsoidShapePrecision)
Definition: vpDot2.cpp:858
void setInput(unsigned input=vpV4l2Grabber::DEFAULT_INPUT)
void buildFrom(const double x, const double y, const double Z)
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
static double deg(double rad)
Definition: vpMath.h:97
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
double get_y() const
void initTracking(const vpImage< unsigned char > &I, unsigned int size=0)
Definition: vpDot2.cpp:262
Class for firewire ieee1394 video devices using libdc1394-2.x api.
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
double m00
Definition: vpDot2.h:370
vpColVector error(const vpBasicFeature &s_star, const unsigned int select=FEATURE_ALL)
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
void setGraphics(const bool activate)
Definition: vpDot2.h:316
void setFramerate(vpV4l2FramerateType framerate)