36#include <visp3/core/vpConfig.h>
39#if defined(VISP_HAVE_MAVSDK) && ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) && \
40 defined(VISP_HAVE_REALSENSE2) && defined(VISP_HAVE_PUGIXML)
42#include <visp3/core/vpImageConvert.h>
43#include <visp3/core/vpMomentAreaNormalized.h>
44#include <visp3/core/vpMomentBasic.h>
45#include <visp3/core/vpMomentCentered.h>
46#include <visp3/core/vpMomentDatabase.h>
47#include <visp3/core/vpMomentGravityCenter.h>
48#include <visp3/core/vpMomentGravityCenterNormalized.h>
49#include <visp3/core/vpMomentObject.h>
50#include <visp3/core/vpPixelMeterConversion.h>
51#include <visp3/core/vpPoint.h>
52#include <visp3/core/vpTime.h>
53#include <visp3/core/vpXmlParserCamera.h>
54#include <visp3/detection/vpDetectorAprilTag.h>
55#include <visp3/gui/vpDisplayFactory.h>
56#include <visp3/gui/vpPlot.h>
57#include <visp3/robot/vpRobotMavsdk.h>
58#include <visp3/sensor/vpRealSense2.h>
59#include <visp3/visual_features/vpFeatureBuilder.h>
60#include <visp3/visual_features/vpFeatureMomentAreaNormalized.h>
61#include <visp3/visual_features/vpFeatureMomentGravityCenterNormalized.h>
62#include <visp3/visual_features/vpFeatureVanishingPoint.h>
63#include <visp3/vs/vpServo.h>
64#include <visp3/vs/vpServoDisplay.h>
69#ifdef ENABLE_VISP_NAMESPACE
73bool compareImagePoint(std::pair<size_t, vpImagePoint> p1, std::pair<size_t, vpImagePoint> p2)
75 return (p1.second.get_v() < p2.second.get_v());
94int main(
int argc,
char **argv)
96#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
97 std::shared_ptr<vpDisplay> display;
102 std::string opt_connecting_info =
"udp://:192.168.30.111:14552";
104 double opt_distance_to_tag = -1;
105 bool opt_has_distance_to_tag =
false;
106 int opt_display_fps = 10;
107 bool opt_verbose =
false;
111 if (argc >= 3 && std::string(argv[1]) ==
"--tag-size") {
112 tagSize = std::atof(argv[2]);
114 std::cout <<
"Error : invalid tag size." << std::endl <<
"See " << argv[0] <<
" --help" << std::endl;
117 for (
int i = 3;
i < argc;
i++) {
118 if (std::string(argv[i]) ==
"--co" && i + 1 < argc) {
119 opt_connecting_info = std::string(argv[i + 1]);
122 else if (std::string(argv[i]) ==
"--distance-to-tag" && i + 1 < argc) {
123 opt_distance_to_tag = std::atof(argv[i + 1]);
124 if (opt_distance_to_tag <= 0) {
125 std::cout <<
"Error : invalid distance to tag." << std::endl <<
"See " << argv[0] <<
" --help" << std::endl;
128 opt_has_distance_to_tag =
true;
132 else if (std::string(argv[i]) ==
"--display-fps" && i + 1 < argc) {
133 opt_display_fps = std::stoi(std::string(argv[i + 1]));
136 else if (std::string(argv[i]) ==
"--verbose" || std::string(argv[i]) ==
"-v") {
140 std::cout <<
"Error : unknown parameter " << argv[
i] << std::endl
141 <<
"See " << argv[0] <<
" --help" << std::endl;
146 else if (argc >= 2 && (std::string(argv[1]) ==
"--help" || std::string(argv[1]) ==
"-h")) {
147 std::cout <<
"\nUsage:\n"
149 <<
" [--tag-size <tag size [m]>] [--co <connection information>] [--distance-to-tag <distance>]"
150 <<
" [--display-fps <display fps>] [--verbose] [-v] [--help] [-h]\n"
153 <<
" --tag-size <size>\n"
154 <<
" The size of the tag to detect in meters, required.\n\n"
155 <<
" --co <connection information>\n"
156 <<
" - UDP: udp://[host][:port]\n"
157 <<
" - TCP: tcp://[host][:port]\n"
158 <<
" - serial: serial://[path][:baudrate]\n"
159 <<
" - Default: udp://192.168.30.111:14552).\n\n"
160 <<
" --distance-to-tag <distance>\n"
161 <<
" The desired distance to the tag in meters (default: 1 meter).\n\n"
162 <<
" --display-fps <display_fps>\n"
163 <<
" The desired fps rate for the video display (default: 10 fps).\n\n"
164 <<
" --verbose, -v\n"
165 <<
" Enables verbosity (drone information messages and velocity commands\n"
166 <<
" are then displayed).\n\n"
168 <<
" Print help message.\n"
174 std::cout <<
"Error : tag size parameter required." << std::endl <<
"See " << argv[0] <<
" --help" << std::endl;
178 std::cout << std::endl
179 <<
"WARNING:" << std::endl
180 <<
" - This program does no sensing or avoiding of obstacles, " << std::endl
181 <<
" the drone WILL collide with any objects in the way! Make sure the " << std::endl
182 <<
" drone has approximately 3 meters of free space on all sides." << std::endl
183 <<
" - The drone uses a forward-facing camera for Apriltag detection," << std::endl
184 <<
" make sure the drone flies above a non-uniform flooring," << std::endl
185 <<
" or its movement will be inacurate and dangerous !" << std::endl
191 if (drone.isRunning()) {
196 std::cout <<
"Product line: " << product_line << std::endl;
199 if (product_line ==
"T200") {
200 std::cout <<
"This example doesn't support T200 product line family !" << std::endl;
205 config.enable_stream(RS2_STREAM_COLOR, 640, 480, RS2_FORMAT_RGBA8, acq_fps);
206 config.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, acq_fps);
207 config.enable_stream(RS2_STREAM_INFRARED, 640, 480, RS2_FORMAT_Y8, acq_fps);
213 cam.printParameters();
223 int orig_displayX = 100;
224 int orig_displayY = 100;
225#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
234 vpPlot plotter(1, 700, 700, orig_displayX +
static_cast<int>(I.getWidth()) + 20, orig_displayY,
235 "Visual servoing tasks");
236 unsigned int iter = 0;
242 detector.setAprilTagQuadDecimate(4.0);
243 detector.setAprilTagNbThreads(4);
244 detector.setDisplayTag(
true);
252 task.setLambda(lambda);
290 double Z_d = (opt_has_distance_to_tag ? opt_distance_to_tag : 1.);
293 double X[4] = { tagSize / 2., tagSize / 2., -tagSize / 2., -tagSize / 2. };
294 double Y[4] = { tagSize / 2., -tagSize / 2., -tagSize / 2., tagSize / 2. };
295 std::vector<vpPoint> vec_P, vec_P_d;
297 for (
int i = 0;
i < 4;
i++) {
301 vec_P_d.push_back(P_d);
313 m_obj_d.fromVector(vec_P_d);
326 area = mb_d.
get(2, 0) + mb_d.
get(0, 2);
328 area = mb_d.
get(0, 0);
330 man_d.setDesiredArea(area);
339 double C = 1.0 / Z_d;
347 task.addFeature(s_mgn, s_mgn_d);
348 task.addFeature(s_man, s_man_d);
355 plotter.setLegend(0, 3,
"atan(1/rho)");
358 s_mgn_d.update(A, B, C);
359 s_mgn_d.compute_interaction();
361 s_man_d.update(A, B, C);
362 s_man_d.compute_interaction();
370 bool vec_ip_has_been_sorted =
false;
371 bool send_velocities =
false;
372 std::vector<std::pair<size_t, vpImagePoint> > vec_ip_sorted;
375 while (drone.isRunning() && runLoop) {
382 condition = (startTime - time_since_last_display) > 1000. / opt_display_fps ?
true : false;
388 std::vector<vpHomogeneousMatrix> cMo_vec;
389 detector.detect(I, tagSize, cam, cMo_vec);
393 std::stringstream ss;
394 ss <<
"Detection time: " <<
t <<
" ms";
398 if (detector.getNbObjects() != 0) {
401 std::vector<vpImagePoint> vec_ip = detector.getPolygon(0);
403 for (
size_t i = 0;
i < vec_ip.size();
i++) {
414 m_obj.fromVector(vec_P);
423 man.setDesiredArea(area);
429 s_mgn.update(A, B, C);
430 s_mgn.compute_interaction();
431 s_man.update(A, B, C);
432 s_man.compute_interaction();
437 if (!vec_ip_has_been_sorted) {
438 for (
size_t i = 0;
i < vec_ip.size();
i++) {
441 std::pair<size_t, vpImagePoint> index_pair = std::pair<size_t, vpImagePoint>(i, vec_ip[i]);
442 vec_ip_sorted.push_back(index_pair);
446 std::sort(vec_ip_sorted.begin(), vec_ip_sorted.end(), compareImagePoint);
448 vec_ip_has_been_sorted =
true;
454 vec_ip[vec_ip_sorted[2].first], vec_ip[vec_ip_sorted[3].first],
463 if (!send_velocities) {
469 std::cout <<
"ve: " << ve.
t() << std::endl;
473 drone.setVelocity(ve);
477 for (
size_t i = 0;
i < 4;
i++) {
479 std::stringstream ss;
506 std::stringstream sserr;
507 sserr <<
"Failed to detect an Apriltag, or detected multiple ones";
513 std::cout << sserr.str() << std::endl;
522 std::stringstream ss;
523 ss <<
"Left click to " << (send_velocities ?
"stop the robot" :
"servo the robot")
524 <<
", right click to quit.";
536 send_velocities = !send_velocities;
550 std::stringstream sstime;
551 sstime <<
"Total time: " << totalTime <<
" ms";
561#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
562 if (display !=
nullptr) {
569 std::cout <<
"ERROR : failed to setup drone control." << std::endl;
570#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
571 if (display !=
nullptr) {
579 std::cout <<
"Caught an exception: " <<
e << std::endl;
580#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
581 if (display !=
nullptr) {
593#ifndef VISP_HAVE_MAVSDK
594 std::cout <<
"\nThis example requires mavsdk library. You should install it, configure and rebuild ViSP.\n" << std::endl;
596#ifndef VISP_HAVE_REALSENSE2
597 std::cout <<
"\nThis example requires librealsense2 library. You should install it, configure and rebuild ViSP.\n" << std::endl;
599#if !defined(VISP_HAVE_PUGIXML)
600 std::cout <<
"\nThis example requires pugixml built-in 3rdparty." << std::endl;
602#if !((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
604 <<
"\nThis example requires at least cxx17. You should enable cxx17 during ViSP configuration with cmake and "
Adaptive gain computation.
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
static const vpColor green
@ TAG_36h11
AprilTag 36h11 pattern (recommended).
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 displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
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)
static void displayPolygon(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &vip, const vpColor &color, unsigned int thickness=1, bool closed=true)
error that can be emitted by ViSP classes.
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
Functionality computation for normalized surface moment feature. Computes the interaction matrix asso...
Functionality computation for centered and normalized moment feature. Computes the interaction matrix...
static unsigned int selectAtanOneOverRho()
void setAlpha(double alpha)
Set vanishing point feature value.
void setAtanOneOverRho(double atan_one_over_rho)
Set vanishing point feature value.
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
static double rad(double deg)
Implementation of a matrix and operations on matrices.
Class handling the normalized surface moment that is invariant in scale and used to estimate depth.
This class defines the 2D basic moment . This class is a wrapper for vpMomentObject which allows to u...
const std::vector< double > & get() const
This class defines the double-indexed centered moment descriptor .
void compute() VP_OVERRIDE
This class allows to register all vpMoments so they can access each other according to their dependen...
virtual void updateAll(vpMomentObject &object)
Class describing 2D normalized gravity center moment.
void compute() VP_OVERRIDE
Class describing 2D gravity center moment.
void compute() VP_OVERRIDE
Class for generic objects.
void linkTo(vpMomentDatabase &moments)
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...
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
void set_x(double x)
Set the point x coordinate in the image plane.
void set_y(double y)
Set the point y coordinate in the image plane.
vpCameraParameters getCameraParameters(const rs2_stream &stream, vpCameraParameters::vpCameraParametersProjType type=vpCameraParameters::perspectiveProjWithDistortion, int index=-1) const
void acquire(vpImage< unsigned char > &grey, double *ts=nullptr)
bool open(const rs2::config &cfg=rs2::config())
rs2_intrinsics getIntrinsics(const rs2_stream &stream, int index=-1) const
std::string getProductLine()
Implementation of a rotation matrix and operations on such kind of matrices.
Implementation of a rotation vector as Euler angle minimal representation.
Class that consider the case of a translation vector.
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()
VISP_EXPORT int wait(double t0, double t)