60 #include <visp3/core/vpCameraParameters.h>
61 #include <visp3/core/vpConfig.h>
62 #include <visp3/core/vpXmlParserCamera.h>
63 #include <visp3/detection/vpDetectorAprilTag.h>
64 #include <visp3/gui/vpDisplayGDI.h>
65 #include <visp3/gui/vpDisplayX.h>
66 #include <visp3/gui/vpPlot.h>
67 #include <visp3/io/vpImageIo.h>
68 #include <visp3/robot/vpRobotFlirPtu.h>
69 #include <visp3/sensor/vpFlyCaptureGrabber.h>
70 #include <visp3/visual_features/vpFeatureBuilder.h>
71 #include <visp3/visual_features/vpFeaturePoint.h>
72 #include <visp3/vs/vpServo.h>
73 #include <visp3/vs/vpServoDisplay.h>
75 #if defined(VISP_HAVE_FLIR_PTU_SDK) && defined(VISP_HAVE_FLYCAPTURE) && \
76 (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)) && defined(VISP_HAVE_PUGIXML)
78 #ifdef ENABLE_VISP_NAMESPACE
83 std::vector<vpImagePoint> &traj_ip)
88 traj_ip.push_back(ip);
92 traj_ip.push_back(ip);
94 for (
size_t j = 1; j < traj_ip.size(); j++) {
99 int main(
int argc,
char **argv)
101 std::string opt_portname;
102 int opt_baudrate = 9600;
103 bool opt_network =
false;
104 std::string opt_extrinsic;
105 std::string opt_intrinsic;
106 std::string opt_camera_name;
107 bool display_tag =
true;
108 int opt_quad_decimate = 2;
109 double opt_tag_size = 0.120;
110 bool opt_verbose =
false;
111 bool opt_plot =
false;
112 bool opt_adaptive_gain =
false;
113 bool opt_task_sequencing =
false;
114 double opt_constant_gain = 0.5;
115 bool opt_display_trajectory =
true;
116 double convergence_threshold = 0.00005;
119 std::cout <<
"To see how to use this example, run: " << argv[0] <<
" --help" << std::endl;
123 for (
int i = 1; i < argc; i++) {
124 if ((std::string(argv[i]) ==
"--portname" || std::string(argv[i]) ==
"-p") && (i + 1 < argc)) {
125 opt_portname = std::string(argv[i + 1]);
127 else if ((std::string(argv[i]) ==
"--baudrate" || std::string(argv[i]) ==
"-b") && (i + 1 < argc)) {
128 opt_baudrate = std::atoi(argv[i + 1]);
130 else if ((std::string(argv[i]) ==
"--network" || std::string(argv[i]) ==
"-n")) {
133 else if (std::string(argv[i]) ==
"--extrinsic" && i + 1 < argc) {
134 opt_extrinsic = std::string(argv[i + 1]);
136 else if (std::string(argv[i]) ==
"--intrinsic" && i + 1 < argc) {
137 opt_intrinsic = std::string(argv[i + 1]);
139 else if (std::string(argv[i]) ==
"--camera-name" && i + 1 < argc) {
140 opt_camera_name = std::string(argv[i + 1]);
142 else if (std::string(argv[i]) ==
"--verbose" || std::string(argv[i]) ==
"-v") {
145 else if (std::string(argv[i]) ==
"--plot" || std::string(argv[i]) ==
"-p") {
148 else if (std::string(argv[i]) ==
"--display-image-trajectory" || std::string(argv[i]) ==
"-traj") {
149 opt_display_trajectory =
true;
151 else if (std::string(argv[i]) ==
"--adaptive-gain" || std::string(argv[i]) ==
"-a") {
152 opt_adaptive_gain =
true;
154 else if (std::string(argv[i]) ==
"--constant-gain" || std::string(argv[i]) ==
"-g") {
155 opt_constant_gain = std::stod(argv[i + 1]);
157 else if (std::string(argv[i]) ==
"--task-sequencing") {
158 opt_task_sequencing =
true;
160 else if (std::string(argv[i]) ==
"--quad-decimate" && i + 1 < argc) {
161 opt_quad_decimate = std::stoi(argv[i + 1]);
163 if (std::string(argv[i]) ==
"--tag-size" && i + 1 < argc) {
164 opt_tag_size = std::stod(argv[i + 1]);
166 else if (std::string(argv[i]) ==
"--no-convergence-threshold") {
167 convergence_threshold = 0.;
169 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
170 std::cout <<
"SYNOPSIS" << std::endl
171 <<
" " << argv[0] <<
" [--portname <portname>] [--baudrate <rate>] [--network] "
172 <<
"[--extrinsic <extrinsic.yaml>] [--intrinsic <intrinsic.xml>] [--camera-name <name>] "
173 <<
"[--quad-decimate <decimation>] [--tag-size <size>] "
174 <<
"[--adaptive-gain] [--constant-gain] [--display-image-trajectory] [--plot] [--task-sequencing] "
175 <<
"[--no-convergence-threshold] [--verbose] [--help] [-h]" << std::endl
177 std::cout <<
"DESCRIPTION" << std::endl
178 <<
" --portname, -p <portname>" << std::endl
179 <<
" Set serial or tcp port name." << std::endl
181 <<
" --baudrate, -b <rate>" << std::endl
182 <<
" Set serial communication baud rate. Default: " << opt_baudrate <<
"." << std::endl
184 <<
" --network, -n" << std::endl
185 <<
" Get PTU network information (Hostname, IP, Gateway) and exit. " << std::endl
187 <<
" --reset, -r" << std::endl
188 <<
" Reset PTU axis and exit. " << std::endl
190 <<
" --extrinsic <extrinsic.yaml>" << std::endl
191 <<
" YAML file containing extrinsic camera parameters as a vpHomogeneousMatrix." << std::endl
192 <<
" It corresponds to the homogeneous transformation eMc, between end-effector" << std::endl
193 <<
" and camera frame." << std::endl
195 <<
" --intrinsic <intrinsic.xml>" << std::endl
196 <<
" Intrinsic camera parameters obtained after camera calibration." << std::endl
198 <<
" --camera-name <name>" << std::endl
199 <<
" Name of the camera to consider in the xml file provided for intrinsic camera parameters."
202 <<
" --quad-decimate <decimation>" << std::endl
203 <<
" Decimation factor used to detect AprilTag. Default " << opt_quad_decimate <<
"." << std::endl
205 <<
" --tag-size <size>" << std::endl
206 <<
" Width in meter or the black part of the AprilTag used as target. Default " << opt_tag_size
209 <<
" --adaptive-gain, -a" << std::endl
210 <<
" Enable adaptive gain instead of constant gain to speed up convergence. " << std::endl
212 <<
" --constant-gain, -g" << std::endl
213 <<
" Constant gain value. Default value: " << opt_constant_gain << std::endl
215 <<
" --display-image-trajectory, -traj" << std::endl
216 <<
" Display the trajectory of the target cog in the image. " << std::endl
218 <<
" --plot, -p" << std::endl
219 <<
" Enable curve plotter. " << std::endl
221 <<
" --task-sequencing" << std::endl
222 <<
" Enable task sequencing that allows to smoothly control the velocity of the robot. " << std::endl
224 <<
" --no-convergence-threshold" << std::endl
225 <<
" Disable ending servoing when it reaches the desired position." << std::endl
227 <<
" --verbose, -v" << std::endl
228 <<
" Additional printings. " << std::endl
230 <<
" --help, -h" << std::endl
231 <<
" Print this helper message. " << std::endl
233 std::cout <<
"EXAMPLE" << std::endl
234 <<
" - How to get network IP" << std::endl
236 <<
" $ " << argv[0] <<
" --portname COM1 --network" << std::endl
237 <<
" Try to connect FLIR PTU to port: COM1 with baudrate: 9600" << std::endl
239 <<
" $ " << argv[0] <<
" -p /dev/ttyUSB0 --network" << std::endl
240 <<
" Try to connect FLIR PTU to port: /dev/ttyUSB0 with baudrate: 9600" << std::endl
242 <<
" PTU HostName: PTU-5" << std::endl
243 <<
" PTU IP : 169.254.110.254" << std::endl
244 <<
" PTU Gateway : 0.0.0.0" << std::endl
245 <<
" - How to run this binary using network communication" << std::endl
246 <<
" $ " << argv[0] <<
" --portname tcp:169.254.110.254 --tag-size 0.1 --gain 0.1" << std::endl;
255 std::cout <<
"Try to connect FLIR PTU to port: " << opt_portname <<
" with baudrate: " << opt_baudrate << std::endl;
256 robot.connect(opt_portname, opt_baudrate);
259 std::cout <<
"PTU HostName: " << robot.getNetworkHostName() << std::endl;
260 std::cout <<
"PTU IP : " << robot.getNetworkIP() << std::endl;
261 std::cout <<
"PTU Gateway : " << robot.getNetworkGateway() << std::endl;
273 eRc << 0, 0, 1, -1, 0, 0, 0, -1, 0;
274 etc << -0.1, -0.123, 0.035;
278 if (!opt_extrinsic.empty()) {
284 std::cout <<
"***************************************************************" << std::endl;
285 std::cout <<
"Warning, use hard coded values for extrinsic camera parameters." << std::endl;
286 std::cout <<
"Create a yaml file that contains the extrinsic:" << std::endl
288 <<
"$ cat eMc.yaml" << std::endl
289 <<
"rows: 4" << std::endl
290 <<
"cols: 4" << std::endl
291 <<
"data:" << std::endl
292 <<
" - [0, 0, 1, -0.1]" << std::endl
293 <<
" - [-1, 0, 0, -0.123]" << std::endl
294 <<
" - [0, -1, 0, 0.035]" << std::endl
295 <<
" - [0, 0, 0, 1]" << std::endl
297 <<
"and load this file with [--extrinsic <extrinsic.yaml] command line option, like:" << std::endl
299 <<
"$ " << argv[0] <<
"-p " << opt_portname <<
" --extrinsic eMc.yaml" << std::endl
301 std::cout <<
"***************************************************************" << std::endl;
304 std::cout <<
"Considered extrinsic transformation eMc:\n" << eMc << std::endl;
310 if (!opt_intrinsic.empty() && !opt_camera_name.empty()) {
315 std::cout <<
"***************************************************************" << std::endl;
316 std::cout <<
"Warning, use hard coded values for intrinsic camera parameters." << std::endl;
317 std::cout <<
"Calibrate your camera and load the parameters from command line options, like:" << std::endl
319 <<
"$ " << argv[0] <<
"-p " << opt_portname <<
" --intrinsic camera.xml --camera-name \"Camera\""
322 std::cout <<
"***************************************************************" << std::endl;
325 std::cout <<
"Considered intrinsic camera parameters:\n" << cam <<
"\n";
327 #if defined(VISP_HAVE_X11)
328 vpDisplayX dc(I, 10, 10,
"Color image");
329 #elif defined(VISP_HAVE_GDI)
336 detector.setAprilTagPoseEstimationMethod(poseEstimationMethod);
337 detector.setDisplayTag(display_tag);
338 detector.setAprilTagQuadDecimate(opt_quad_decimate);
353 if (opt_adaptive_gain) {
361 vpPlot *plotter =
nullptr;
365 plotter =
new vpPlot(2,
static_cast<int>(250 * 2), 500,
static_cast<int>(I.
getWidth()) + 80, 10,
366 "Real time curves plotter");
367 plotter->
setTitle(0,
"Visual features error");
368 plotter->
setTitle(1,
"Joint velocities");
371 plotter->
setLegend(0, 0,
"error_feat_p_x");
372 plotter->
setLegend(0, 1,
"error_feat_p_y");
377 bool final_quit =
false;
378 bool has_converged =
false;
379 bool send_velocities =
false;
380 bool servo_started =
false;
381 std::vector<vpImagePoint> traj_cog;
389 std::cout << cVe << std::endl;
394 while (!has_converged && !final_quit) {
401 std::vector<vpHomogeneousMatrix> cMo_vec;
402 detector.detect(I, opt_tag_size, cam, cMo_vec);
404 std::stringstream ss;
405 ss <<
"Left click to " << (send_velocities ?
"stop the robot" :
"servo the robot") <<
", right click to quit.";
411 if (detector.getNbObjects() == 1) {
414 double Z = cMo_vec[0][2][3];
420 std::cout <<
"Z: " << Z << std::endl;
429 if (opt_task_sequencing) {
430 if (!servo_started) {
431 if (send_velocities) {
432 servo_started =
true;
446 if (opt_display_trajectory) {
447 display_point_trajectory(I, cog, traj_cog);
452 plotter->
plot(1, iter_plot, qdot);
457 std::cout <<
"qdot: " << qdot.t() << std::endl;
462 ss <<
"error: " << error;
466 std::cout <<
"error: " << error << std::endl;
468 if (error < convergence_threshold) {
469 has_converged =
true;
470 std::cout <<
"Servo task has converged"
479 if (!send_velocities) {
495 send_velocities = !send_velocities;
508 std::cout <<
"Stop the robot " << std::endl;
511 if (opt_plot && plotter !=
nullptr) {
517 while (!final_quit) {
533 std::cout <<
"Catch Flir Ptu signal exception: " << e.
getMessage() << std::endl;
537 std::cout <<
"ViSP exception: " << e.
what() << std::endl;
538 std::cout <<
"Stop the robot " << std::endl;
547 #if !defined(VISP_HAVE_FLYCAPTURE)
548 std::cout <<
"Install FLIR Flycapture" << std::endl;
550 #if !defined(VISP_HAVE_FLIR_PTU_SDK)
551 std::cout <<
"Install FLIR PTU SDK." << std::endl;
553 #if !defined(VISP_HAVE_PUGIXML)
554 std::cout <<
"pugixml built-in 3rdparty is requested." << std::endl;
Adaptive gain computation.
static bool loadYAML(const std::string &filename, vpArray2D< Type > &A, char *header=nullptr)
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
Implementation of column vector and the associated operations.
static const vpColor green
@ TAG_36h11
AprilTag 36h11 pattern (recommended)
Display for windows using GDI (available on any windows 32 platform).
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
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.
const char * getMessage() const
const char * what() const
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
void set_xyZ(double x, double y, double Z)
void open(vpImage< unsigned char > &I)
void acquire(vpImage< unsigned char > &I)
Implementation of an homogeneous matrix and operations on such kind of matrices.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
unsigned int getWidth() const
unsigned int getHeight() const
Implementation of a matrix and operations on matrices.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
void initGraph(unsigned int graphNum, unsigned int curveNbr)
void setLegend(unsigned int graphNum, unsigned int curveNum, const std::string &legend)
void plot(unsigned int graphNum, unsigned int curveNum, double x, double y)
void setTitle(unsigned int graphNum, const std::string &title)
Implementation of a pose vector and operations on poses.
Error that can be emitted by the vpRobot class and its derivatives.
void get_eJe(vpMatrix &eJe) VP_OVERRIDE
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel) VP_OVERRIDE
@ STATE_VELOCITY_CONTROL
Initialize the velocity controller.
@ STATE_STOP
Stops robot motion especially in velocity and acceleration control.
virtual vpRobotStateType setRobotState(const vpRobot::vpRobotStateType newState)
Implementation of a rotation matrix and operations on such kind of matrices.
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)
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
void addFeature(vpBasicFeature &s_cur, vpBasicFeature &s_star, unsigned int select=vpBasicFeature::FEATURE_ALL)
void set_cVe(const vpVelocityTwistMatrix &cVe_)
void set_eJe(const vpMatrix &eJe_)
void setServo(const vpServoType &servo_type)
vpColVector getError() const
vpColVector computeControlLaw()
Class that consider the case of a translation vector.
vpVelocityTwistMatrix get_cVe() const
XML parser to load and save intrinsic camera parameters.
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, unsigned int image_width=0, unsigned int image_height=0, bool verbose=true)
VISP_EXPORT double measureTimeMs()