Example of eye-in-hand control law. We control here a real robot, the Afma6 robot (cartesian robot, with 6 degrees of freedom). The velocity is computed in the camera frame. Visual features are the two lines corresponding to the edges of a cylinder.
#include <iostream>
#include <visp3/core/vpConfig.h>
#if defined(VISP_HAVE_REALSENSE2) && defined(VISP_HAVE_AFMA6)
#include <visp3/core/vpImage.h>
#include <visp3/gui/vpDisplayFactory.h>
#include <visp3/io/vpImageIo.h>
#include <visp3/sensor/vpRealSense2.h>
#include <visp3/core/vpCylinder.h>
#include <visp3/core/vpHomogeneousMatrix.h>
#include <visp3/core/vpMath.h>
#include <visp3/me/vpMeLine.h>
#include <visp3/visual_features/vpFeatureBuilder.h>
#include <visp3/visual_features/vpFeatureLine.h>
#include <visp3/robot/vpRobotAfma6.h>
#include <visp3/vs/vpServoDisplay.h>
#include <visp3/vs/vpServo.h>
#ifdef ENABLE_VISP_NAMESPACE
#endif
{
double rho1 = s_line1.
getRho();
double rho2 = s_line2.
getRho();
double rhoi = s_line_di.
getRho();
double rhoj = s_line_dj.
getRho();
unsigned int config = 0;
double err = 0.0;
double err_min = 1.e6;
double er_theta1 = theta1-thetai;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
double er_theta2 = theta2-thetaj;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1-rhoi)*(rho1-rhoi) + er_theta1*er_theta1
+ (rho2-rhoj)*(rho2-rhoj) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 1 (1,2) <-> (i,j), err = " << err << std::endl;
er_theta1 = theta1-thetai;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetaj-M_PI;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1-rhoi)*(rho1-rhoi) + er_theta1*er_theta1
+ (rho2+rhoj)*(rho2+rhoj) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 2 (1,2) <-> (i,-j), err = " << err << std::endl;
er_theta1 = theta1-thetai-M_PI;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetaj;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1+rhoi)*(rho1+rhoi) + er_theta1*er_theta1
+ (rho2-rhoj)*(rho2-rhoj) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 3 (1,2) <-> (-i,j), err = " << err << std::endl;
er_theta1 = theta1-thetai-M_PI;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetaj-M_PI;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1+rhoi)*(rho1+rhoi) + er_theta1*er_theta1
+ (rho2+rhoj)*(rho2+rhoj) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 4 (1,2) <-> (-i,-j), err = " << err << std::endl;
er_theta1 = theta1-thetaj;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetai;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1-rhoj)*(rho1-rhoj) + er_theta1*er_theta1
+ (rho2-rhoi)*(rho2-rhoi) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 5 (1,2) <-> (j,i), err = " << err << std::endl;
er_theta1 = theta1-thetaj-M_PI;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetai;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1+rhoj)*(rho1+rhoj) + er_theta1*er_theta1
+ (rho2-rhoi)*(rho2-rhoi) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 6 (1,2) <-> (-j,i), err = " << err << std::endl;
er_theta1 = theta1-thetaj;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetai-M_PI;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1-rhoj)*(rho1-rhoj) + er_theta1*er_theta1
+ (rho2+rhoi)*(rho2+rhoi) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 7 (1,2) <-> (j,-i), err = " << err << std::endl;
er_theta1 = theta1-thetaj-M_PI;
if (er_theta1 > M_PI) er_theta1 -= 2.0*M_PI;
else if (er_theta1 < -M_PI) er_theta1 += 2.0*M_PI;
er_theta2 = theta2-thetai-M_PI;
if (er_theta2 > M_PI) er_theta2 -= 2.0*M_PI;
else if (er_theta2 < -M_PI) er_theta2 += 2.0*M_PI;
err = (rho1+rhoj)*(rho1+rhoj) + er_theta1*er_theta1
+ (rho2+rhoi)*(rho2+rhoi) + er_theta2*er_theta2;
if (err < err_min) {
config++;
err_min = err;
}
std::cout << "Test 8 (1,2) <-> (-j,-i), err = " << err << std::endl;
std::cout << "Test choisi = " << config << std::endl;
if (config == 2) {
}
else if (config == 3) {
}
else if (config == 4) {
}
else if (config == 5) {
}
else if (config == 6) {
}
else if (config == 7) {
}
else if (config == 8) {
}
}
int main(int argc, char **argv)
{
bool opt_verbose = false;
bool opt_adaptive_gain = false;
for (int i = 1; i < argc; ++i) {
if (std::string(argv[i]) == "--verbose") {
opt_verbose = true;
}
else if (std::string(argv[i]) == "--adaptive-gain") {
opt_adaptive_gain = true;
}
else if ((std::string(argv[i]) == "--help") || (std::string(argv[i]) == "-h")) {
std::cout
<< argv[0]
<< " [--adaptive-gain]"
<< " [--verbose]"
<< " [--help] [-h]"
<< std::endl;
return EXIT_SUCCESS;
}
}
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
std::shared_ptr<vpDisplay> display;
#else
#endif
try {
std::cout << "WARNING: This example will move the robot! "
<< "Please make sure to have the user stop button at hand!" << std::endl
<< "Press Enter to continue..." << std::endl;
std::cin.ignore();
config.enable_stream(RS2_STREAM_COLOR, width, height, RS2_FORMAT_RGBA8, fps);
config.enable_stream(RS2_STREAM_DEPTH, width, height, RS2_FORMAT_Z16, fps);
config.enable_stream(RS2_STREAM_INFRARED, width, height, RS2_FORMAT_Y8, fps);
for (
size_t i = 0;
i < 10; ++
i) {
}
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
#else
#endif
int nblines = 2;
std::vector<vpMeLine> line(nblines);
for (
int i = 0;
i < nblines; ++
i) {
}
robot.getCameraParameters(cam, I);
std::cout <<
"cam:\n" <<
cam << std::endl;
std::vector<vpFeatureLine> s_line(nblines);
for (
int i = 0;
i < nblines; ++
i) {
}
cylinder.project(c_M_o);
std::vector<vpFeatureLine> s_line_d(nblines);
{
std::cout << "Measured features: " << std::endl;
std::cout <<
" - line 1: rho: " << s_line[0].getRho() <<
" theta: " <<
vpMath::deg(s_line[0].getTheta()) <<
"deg" << std::endl;
std::cout <<
" - line 2: rho: " << s_line[1].getRho() <<
" theta: " <<
vpMath::deg(s_line[1].getTheta()) <<
"deg" << std::endl;
std::cout << "Desired features: " << std::endl;
std::cout <<
" - line 1: rho: " << s_line_d[0].getRho() <<
" theta: " <<
vpMath::deg(s_line_d[0].getTheta()) <<
"deg" << std::endl;
std::cout <<
" - line 2: rho: " << s_line_d[1].getRho() <<
" theta: " <<
vpMath::deg(s_line_d[1].getTheta()) <<
"deg" << std::endl;
}
match(s_line[0], s_line[1], s_line_d[0], s_line_d[1]);
{
std::cout << "Modified desired features: " << std::endl;
std::cout <<
" - line 1: rho: " << s_line_d[0].getRho() <<
" theta: " <<
vpMath::deg(s_line_d[0].getTheta()) <<
"deg" << std::endl;
std::cout <<
" - line 2: rho: " << s_line_d[1].getRho() <<
" theta: " <<
vpMath::deg(s_line_d[1].getTheta()) <<
"deg" << std::endl;
}
for (
int i = 0;
i < nblines; ++
i) {
task.addFeature(s_line[i], s_line_d[i]);
}
if (opt_adaptive_gain) {
}
else {
}
bool final_quit = false;
bool send_velocities = false;
while (!final_quit) {
std::stringstream ss;
ss << "Left click to " << (send_velocities ? "stop the robot" : "servo the robot") << ", right click to quit.";
for (
int i = 0;
i < nblines; ++
i) {
}
v_c =
task.computeControlLaw();
if (opt_verbose) {
std::cout << "v: " << v_c.t() << std::endl;
std::cout <<
"\t\t || s - s* || = " <<
task.getError().sumSquare() << std::endl;
}
if (!send_velocities) {
v_c = 0;
}
ss.str("");
switch (button) {
send_velocities = !send_velocities;
break;
final_quit = true;
break;
default:
break;
}
}
}
std::cout << "Stop the robot " << std::endl;
if (!final_quit) {
while (!final_quit) {
final_quit = true;
}
}
}
}
std::cout <<
"ViSP exception: " <<
e.what() << std::endl;
std::cout << "Stop the robot " << std::endl;
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
if (display != nullptr) {
delete display;
}
#endif
return EXIT_FAILURE;
}
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
if (display != nullptr) {
delete display;
}
#endif
return EXIT_SUCCESS;
}
#else
int main()
{
std::cout << "You do not have an afma6 robot connected to your computer..." << std::endl;
return EXIT_SUCCESS;
}
#endif
Adaptive gain computation.
Generic class defining intrinsic camera parameters.
vpCameraParametersProjType
@ perspectiveProjWithDistortion
Perspective projection with distortion model.
Implementation of column vector and the associated operations.
static const vpColor green
Class that defines a 3D cylinder in the object frame and allows forward projection of a 3D cylinder i...
Class that defines generic functionalities for display.
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
Class that defines a 2D line visual feature which is composed by two parameters that are and ,...
void setRhoTheta(double rho, double theta)
Implementation of an homogeneous matrix and operations on such kind of matrices.
Definition of the vpImage class member functions.
static double rad(double deg)
static double deg(double rad)
void setPointsToTrack(const int &points_to_track)
void setRange(const unsigned int &range)
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
void setThreshold(const double &threshold)
void setSampleStep(const double &sample_step)
void acquire(vpImage< unsigned char > &grey, double *ts=nullptr)
bool open(const rs2::config &cfg=rs2::config())
Control of Irisa's gantry robot named Afma6.
@ STATE_VELOCITY_CONTROL
Initialize the velocity controller.
@ STATE_STOP
Stops robot motion especially in velocity and acceleration control.
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT double measureTimeMs()