1 #include <visp3/core/vpConfig.h>
3 #include <visp3/core/vpMomentAreaNormalized.h>
4 #include <visp3/core/vpMomentBasic.h>
5 #include <visp3/core/vpMomentCentered.h>
6 #include <visp3/core/vpMomentDatabase.h>
7 #include <visp3/core/vpMomentGravityCenter.h>
8 #include <visp3/core/vpMomentGravityCenterNormalized.h>
9 #include <visp3/core/vpMomentObject.h>
10 #include <visp3/core/vpPixelMeterConversion.h>
11 #include <visp3/core/vpPoint.h>
12 #include <visp3/core/vpSerial.h>
13 #include <visp3/core/vpXmlParserCamera.h>
14 #include <visp3/detection/vpDetectorAprilTag.h>
15 #include <visp3/gui/vpDisplayFactory.h>
16 #include <visp3/io/vpImageIo.h>
17 #include <visp3/robot/vpUnicycle.h>
18 #include <visp3/sensor/vpV4l2Grabber.h>
19 #include <visp3/visual_features/vpFeatureMomentAreaNormalized.h>
20 #include <visp3/visual_features/vpFeatureMomentGravityCenterNormalized.h>
21 #include <visp3/vs/vpServo.h>
23 int main(
int argc,
const char **argv)
25 #if defined(VISP_HAVE_APRILTAG) && defined(VISP_HAVE_V4L2)
26 #ifdef ENABLE_VISP_NAMESPACE
32 double tagSize = 0.065;
33 float quad_decimate = 4.0;
35 std::string intrinsic_file =
"";
36 std::string camera_name =
"";
37 bool display_on =
false;
38 bool serial_off =
false;
39 #if defined(VISP_HAVE_DISPLAY)
40 bool display_tag =
false;
41 bool save_image =
false;
44 for (
int i = 1; i < argc; i++) {
45 if (std::string(argv[i]) ==
"--tag-size" && i + 1 < argc) {
46 tagSize = std::atof(argv[i + 1]);
48 else if (std::string(argv[i]) ==
"--input" && i + 1 < argc) {
49 device = std::atoi(argv[i + 1]);
51 else if (std::string(argv[i]) ==
"--quad-decimate" && i + 1 < argc) {
52 quad_decimate = (float)atof(argv[i + 1]);
54 else if (std::string(argv[i]) ==
"--nthreads" && i + 1 < argc) {
55 nThreads = std::atoi(argv[i + 1]);
57 else if (std::string(argv[i]) ==
"--intrinsic" && i + 1 < argc) {
58 intrinsic_file = std::string(argv[i + 1]);
60 else if (std::string(argv[i]) ==
"--camera-name" && i + 1 < argc) {
61 camera_name = std::string(argv[i + 1]);
63 #if defined(VISP_HAVE_DISPLAY)
64 else if (std::string(argv[i]) ==
"--display-tag") {
67 else if (std::string(argv[i]) ==
"--display-on") {
70 else if (std::string(argv[i]) ==
"--save-image") {
74 else if (std::string(argv[i]) ==
"--serial-off") {
77 else if (std::string(argv[i]) ==
"--tag-family" && i + 1 < argc) {
80 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
81 std::cout <<
"Usage: " << argv[0]
82 <<
" [--input <camera input>] [--tag-size <tag_size in m>]"
83 " [--quad-decimate <quad_decimate>] [--nthreads <nb>]"
84 " [--intrinsic <intrinsic file>] [--camera-name <camera name>]"
85 " [--tag-family <family> (0: TAG_36h11, 1: TAG_36h10, 2: TAG_36ARTOOLKIT, 3: TAG_25h9, 4: TAG_25h7, 5: TAG_16h5)]"
87 #if defined(VISP_HAVE_DISPLAY)
88 std::cout <<
" [--display-on] [--save-image]";
90 std::cout <<
" [--serial-off] [--help]" << std::endl;
104 serial =
new vpSerial(
"/dev/ttyAMA0", 115200);
106 serial->
write(
"LED_RING=0,0,0,0\n");
107 serial->
write(
"LED_RING=1,0,10,0\n");
114 std::ostringstream device_name;
115 device_name <<
"/dev/video" << device;
122 #ifdef VISP_HAVE_DISPLAY
131 #if defined(VISP_HAVE_PUGIXML)
133 if (!intrinsic_file.empty() && !camera_name.empty()) {
138 std::cout <<
"cam:\n" << cam << std::endl;
139 std::cout <<
"tagFamily: " << tagFamily << std::endl;
140 std::cout <<
"tagSize: " << tagSize << std::endl;
144 detector.setAprilTagQuadDecimate(quad_decimate);
145 detector.setAprilTagNbThreads(nThreads);
146 #ifdef VISP_HAVE_DISPLAY
147 detector.setDisplayTag(display_tag);
179 eJe[0][0] = eJe[5][1] = 1.0;
181 std::cout <<
"eJe: \n" << eJe << std::endl;
187 double X[4] = { tagSize / 2., tagSize / 2., -tagSize / 2., -tagSize / 2. };
188 double Y[4] = { tagSize / 2., -tagSize / 2., -tagSize / 2., tagSize / 2. };
189 std::vector<vpPoint> vec_P, vec_P_d;
191 for (
int i = 0; i < 4; i++) {
195 vec_P_d.push_back(P_d);
209 m_obj_d.fromVector(vec_P_d);
222 area = mb_d.
get(2, 0) + mb_d.
get(0, 2);
224 area = mb_d.
get(0, 0);
226 man_d.setDesiredArea(area);
234 double C = 1.0 / Z_d;
245 s_mgn_d.update(A, B, C);
246 s_mgn_d.compute_interaction();
248 s_man_d.update(A, B, C);
249 s_man_d.compute_interaction();
251 std::vector<double> time_vec;
255 #ifdef VISP_HAVE_DISPLAY
260 std::vector<vpHomogeneousMatrix> cMo_vec;
261 detector.detect(I, tagSize, cam, cMo_vec);
263 time_vec.push_back(t);
266 std::stringstream ss;
267 ss <<
"Detection time: " << t <<
" ms";
268 #ifdef VISP_HAVE_DISPLAY
273 if (detector.getNbObjects() == 1) {
275 serial->
write(
"LED_RING=2,0,10,0\n");
279 std::vector<vpImagePoint> vec_ip = detector.getPolygon(0);
281 for (
size_t i = 0; i < vec_ip.size(); i++) {
290 #ifdef VISP_HAVE_DISPLAY
301 m_obj.fromVector(vec_P);
315 s_mgn.update(A, B, C);
316 s_mgn.compute_interaction();
317 s_man.update(A, B, C);
318 s_man.compute_interaction();
326 std::cout <<
"Send velocity to the mbot: " << v[0] <<
" m/s " <<
vpMath::deg(v[1]) <<
" deg/s" << std::endl;
329 double radius = 0.0325;
331 double motor_left = (-v[0] - L * v[1]) / radius;
332 double motor_right = (v[0] - L * v[1]) / radius;
333 std::cout <<
"motor left vel: " << motor_left <<
" motor right vel: " << motor_right << std::endl;
338 std::stringstream ss;
339 double rpm_left = motor_left * 30. / M_PI;
340 double rpm_right = motor_right * 30. / M_PI;
342 std::cout <<
"Send: " << ss.str() << std::endl;
344 serial->
write(ss.str());
350 serial->
write(
"LED_RING=2,10,0,0\n");
353 serial->
write(
"MOTOR_RPM=0,-0\n");
357 #ifdef VISP_HAVE_DISPLAY
361 if (display_on && save_image) {
373 serial->
write(
"LED_RING=0,0,0,0\n");
376 std::cout <<
"Benchmark computation time" << std::endl;
377 std::cout <<
"Mean / Median / Std: " <<
vpMath::getMean(time_vec) <<
" ms"
389 std::cerr <<
"Catch an exception: " << e.
getMessage() << std::endl;
391 serial->
write(
"LED_RING=1,10,0,0\n");
399 #ifndef VISP_HAVE_APRILTAG
400 std::cout <<
"ViSP is not build with Apriltag support" << std::endl;
402 #ifndef VISP_HAVE_V4L2
403 std::cout <<
"ViSP is not build with v4l2 support" << std::endl;
405 std::cout <<
"Install missing 3rd parties, configure and build ViSP to run this tutorial" << std::endl;
Adaptive gain computation.
void initStandard(double gain_at_zero, double gain_at_infinity, double slope_at_zero)
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
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 getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
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.
const char * getMessage() const
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 selectXn()
Implementation of an homogeneous matrix and operations on such kind of matrices.
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
unsigned int getWidth() const
unsigned int getHeight() const
static double getMedian(const std::vector< double > &v)
static double getStdev(const std::vector< double > &v, bool useBesselCorrection=false)
static int round(double x)
static double getMean(const std::vector< double > &v)
static double deg(double rad)
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 .
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.
Class describing 2D gravity center moment.
Class for generic objects.
void linkTo(vpMomentDatabase &moments)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
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.
Implementation of a rotation matrix and operations on such kind of matrices.
void write(const std::string &s)
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 print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
void set_eJe(const vpMatrix &eJe_)
void setServo(const vpServoType &servo_type)
vpColVector computeControlLaw()
Class that consider the case of a translation vector.
Generic functions for unicycle mobile robots.
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setDevice(const std::string &devname)
void acquire(vpImage< unsigned char > &I)
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)
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT double measureTimeMs()