Example that shows how to control the Pioneer mobile robot by IBVS visual servoing with respect to a blob. The current visual features that are used are s = (x, log(Z/Z*)). The desired one are s* = (x*, 0), with:
The degrees of freedom that are controlled are (vx, wz), where wz is the rotational velocity and vx the translational velocity of the mobile platform at point M located at the middle between the two wheels.
The feature x allows to control wy, while log(Z/Z*) allows to control vz. The value of x is measured thanks to a blob tracker. The value of Z is estimated from the surface of the blob that is proportional to the depth Z.
#include <iostream>
#include <visp/vpCameraParameters.h>
#include <visp/vpDisplayX.h>
#include <visp/vpDot2.h>
#include <visp/vpFeatureBuilder.h>
#include <visp/vpFeatureDepth.h>
#include <visp/vpFeaturePoint.h>
#include <visp/vpHomogeneousMatrix.h>
#include <visp/vpImage.h>
#include <visp/vpImageConvert.h>
#include <visp/vpServo.h>
#include <visp/vpVelocityTwistMatrix.h>
#if defined(VISP_HAVE_DC1394_2) && defined(VISP_HAVE_X11)
# define TEST_COULD_BE_ACHIEVED
#endif
#ifdef TEST_COULD_BE_ACHIEVED
int main(
int argc,
char **argv)
{
try {
vpImage<unsigned char> I;
double depth = 1.;
double lambda = 0.6;
double coef = 1./6.77;
vpTime::sleepMs(3000);
std::cout << "Robot connected" << std::endl;
vpCameraParameters cam;
cam.initPersProjWithoutDistortion(600,600,I.getWidth()/2, I.getHeight()/2);
vpDisplayX
d(I, 10, 10,
"Current frame");
vpDisplay::display(I);
vpDisplay::flush(I);
dot.setGraphics(true);
dot.setComputeMoments(true);
dot.setEllipsoidShapePrecision(0.);
dot.setGrayLevelPrecision(0.9);
dot.setEllipsoidBadPointsPercentage(0.5);
dot.initTracking(I);
vpDisplay::flush(I);
vpServo task;
task.setServo(vpServo::EYEINHAND_L_cVe_eJe) ;
task.setInteractionMatrixType(vpServo::DESIRED, vpServo::PSEUDO_INVERSE) ;
task.setLambda(lambda) ;
vpVelocityTwistMatrix cVe ;
cVe = robot.get_cVe() ;
task.set_cVe(cVe) ;
std::cout << "cVe: \n" << cVe << std::endl;
vpMatrix eJe;
task.set_eJe(eJe) ;
std::cout << "eJe: \n" << eJe << std::endl;
vpFeaturePoint s_x, s_xd;
vpFeatureBuilder::create(s_x, cam, dot);
s_xd.buildFrom(0, 0, depth);
task.addFeature(s_x, s_xd) ;
vpFeatureDepth s_Z, s_Zd;
double surface = 1./sqrt(dot.m00/(cam.get_px()*cam.get_py()));
double Z, Zd;
Z = coef * surface ;
Zd = Z;
std::cout << "Z " << Z << std::endl;
s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z , 0);
s_Zd.buildFrom(s_x.get_x(), s_x.get_y(), Zd , 0);
task.addFeature(s_Z, s_Zd) ;
vpColVector v;
while(1)
{
vpDisplay::display(I);
dot.track(I);
vpFeatureBuilder::create(s_x, cam, dot);
surface = 1./sqrt(dot.m00/(cam.get_px()*cam.get_py()));
Z = coef * surface ;
s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z, log(Z/Zd)) ;
robot.get_cVe(cVe) ;
task.set_cVe(cVe) ;
task.set_eJe(eJe) ;
v = task.computeControlLaw() ;
std::cout << "Send velocity to the pionner: " << v[0] << " m/s "
<< vpMath::deg(v[1]) << " deg/s" << std::endl;
vpDisplay::displayLine(I, 0, 320, 479, 320, vpColor::red);
vpDisplay::flush(I);
if ( vpDisplay::getClick(I, false) )
break;
}
std::cout << "Ending robot thread..." << std::endl;
task.print() ;
task.kill();
}
catch(vpException e) {
std::cout << "Catch an exception: " << e << std::endl;
return 1;
}
}
#else
{
std::cout << "You don't have the right 3rd party libraries to run this example..." << std::endl;
}
#endif