Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
servoSimuCircle2DCamVelocityDisplay.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Simulation of a 2D visual servoing on a circle.
32 */
33
43
44#include <visp3/core/vpConfig.h>
45#include <visp3/core/vpDebug.h>
46
47#if defined(VISP_HAVE_DISPLAY) && \
48 (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
49
50#include <stdio.h>
51#include <stdlib.h>
52
53#include <visp3/core/vpCameraParameters.h>
54#include <visp3/core/vpCircle.h>
55#include <visp3/core/vpHomogeneousMatrix.h>
56#include <visp3/core/vpImage.h>
57#include <visp3/core/vpMath.h>
58#include <visp3/gui/vpDisplayFactory.h>
59#include <visp3/io/vpParseArgv.h>
60#include <visp3/robot/vpSimulatorCamera.h>
61#include <visp3/visual_features/vpFeatureBuilder.h>
62#include <visp3/visual_features/vpFeatureLine.h>
63#include <visp3/vs/vpServo.h>
64#include <visp3/vs/vpServoDisplay.h>
65
66// List of allowed command line options
67#define GETOPTARGS "cdh"
68
69#ifdef ENABLE_VISP_NAMESPACE
70using namespace VISP_NAMESPACE_NAME;
71#endif
72
73void usage(const char *name, const char *badparam);
74bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
75
84void usage(const char *name, const char *badparam)
85{
86 fprintf(stdout, "\n\
87Simulation of a 2D visual servoing on a circle:\n\
88- eye-in-hand control law,\n\
89- velocity computed in the camera frame,\n\
90- display the camera view.\n\
91 \n\
92SYNOPSIS\n\
93 %s [-c] [-d] [-h]\n",
94 name);
95
96 fprintf(stdout, "\n\
97OPTIONS: Default\n\
98 \n\
99 -c\n\
100 Disable the mouse click. Useful to automate the \n\
101 execution of this program without human intervention.\n\
102 \n\
103 -d \n\
104 Turn off the display.\n\
105 \n\
106 -h\n\
107 Print the help.\n");
108
109 if (badparam) {
110 fprintf(stderr, "ERROR: \n");
111 fprintf(stderr, "\nBad parameter [%s]\n", badparam);
112 }
113}
114
127bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
128{
129 const char *optarg_;
130 int c;
131 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
132
133 switch (c) {
134 case 'c':
135 click_allowed = false;
136 break;
137 case 'd':
138 display = false;
139 break;
140 case 'h':
141 usage(argv[0], nullptr);
142 return false;
143
144 default:
145 usage(argv[0], optarg_);
146 return false;
147 }
148 }
149
150 if ((c == 1) || (c == -1)) {
151 // standalone param or error
152 usage(argv[0], nullptr);
153 std::cerr << "ERROR: " << std::endl;
154 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
155 return false;
156 }
157
158 return true;
159}
160
161int main(int argc, const char **argv)
162{
163#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
164 std::shared_ptr<vpDisplay> display;
165#else
166 vpDisplay *display = nullptr;
167#endif
168 try {
169 bool opt_display = true;
170 bool opt_click_allowed = true;
171
172 // Read the command line options
173 if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
174 return (EXIT_FAILURE);
175 }
176
177 vpImage<unsigned char> I(512, 512, 0);
178
179 if (opt_display) {
180 // Display size is automatically defined by the image (I) size
181#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
182 display = vpDisplayFactory::createDisplay(I, 100, 100, "Camera view...");
183#else
184 display = vpDisplayFactory::allocateDisplay(I, 100, 100, "Camera view...");
185#endif
186 // Display the image
187 // The image class has a member that specify a pointer toward
188 // the display that has been initialized in the display declaration
189 // therefore is is no longer necessary to make a reference to the
190 // display variable.
193 }
194
195 double px = 600, py = 600;
196 double u0 = I.getWidth() / 2., v0 = I.getHeight() / 2.;
197
198 vpCameraParameters cam(px, py, u0, v0);
199
201 vpSimulatorCamera robot;
202
203 // sets the initial camera location
205 vpHomogeneousMatrix wMc, wMo;
206 robot.getPosition(wMc);
207 wMo = wMc * cMo; // Compute the position of the object in the world frame
208
209 vpHomogeneousMatrix cMod(-0.1, -0.1, 0.7, vpMath::rad(40), vpMath::rad(10), vpMath::rad(30));
210
211 // sets the circle coordinates in the world frame
212 vpCircle circle;
213 circle.setWorldCoordinates(0, 0, 1, 0, 0, 0, 0.1);
214
215 // sets the desired position of the visual feature
217 circle.track(cMod);
218 vpFeatureBuilder::create(pd, circle);
219
220 // project : computes the circle coordinates in the camera frame and its
221 // 2D coordinates sets the current position of the visual feature
223 circle.track(cMo);
224 vpFeatureBuilder::create(p, circle);
225
226 // define the task
227 // - we want an eye-in-hand control law
228 // - robot is controlled in the camera frame
230 task.setInteractionMatrixType(vpServo::DESIRED);
231 // - we want to see a circle on a circle
232 task.addFeature(p, pd);
233 // - set the gain
234 task.setLambda(1);
235
236 // Display task information
237 task.print();
238
239 unsigned int iter = 0;
240 // loop
241 while (iter++ < 200) {
242 std::cout << "---------------------------------------------" << iter << std::endl;
244
245 // get the robot position
246 robot.getPosition(wMc);
247 // Compute the position of the object frame in the camera frame
248 cMo = wMc.inverse() * wMo;
249
250 // new circle position
251 // retrieve x,y and Z of the vpCircle structure
252 circle.track(cMo);
253 vpFeatureBuilder::create(p, circle);
254 circle.print();
255 p.print();
256
257 if (opt_display) {
259 vpServoDisplay::display(task, cam, I);
261 }
262
263 // compute the control law
264 v = task.computeControlLaw();
265 std::cout << "task rank: " << task.getTaskRank() << std::endl;
266 // send the camera velocity to the controller
267 robot.setVelocity(vpRobot::CAMERA_FRAME, v);
268
269 std::cout << "|| s - s* || = " << (task.getError()).sumSquare() << std::endl;
270 }
271
272 // Display task information
273 task.print();
274
275 if (opt_display && opt_click_allowed) {
276 vpDisplay::displayText(I, 20, 20, "Click to quit...", vpColor::white);
279 }
280#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
281 if (display != nullptr) {
282 delete display;
283 }
284#endif
285 return EXIT_SUCCESS;
286 }
287 catch (const vpException &e) {
288 std::cout << "Catch a ViSP exception: " << e << std::endl;
289#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
290 if (display != nullptr) {
291 delete display;
292 }
293#endif
294 return EXIT_FAILURE;
295 }
296}
297#elif !(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
298int main()
299{
300 std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
301 return EXIT_SUCCESS;
302}
303#else
304int main()
305{
306 std::cout << "You do not have X11, or GTK, or GDI (Graphical Device Interface) or OpenCV functionalities to display "
307 "images..."
308 << std::endl;
309 std::cout << "Tip if you are on a unix-like system:" << std::endl;
310 std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
311 std::cout << "Tip if you are on a windows-like system:" << std::endl;
312 std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
313 return EXIT_SUCCESS;
314}
315#endif
Generic class defining intrinsic camera parameters.
Class that defines a 3D circle in the object frame and allows forward projection of a 3D circle in th...
Definition vpCircle.h:87
void setWorldCoordinates(const vpColVector &oP) VP_OVERRIDE
Definition vpCircle.cpp:58
Implementation of column vector and the associated operations.
static const vpColor white
Definition vpColor.h:193
Class that defines generic functionalities for display.
Definition vpDisplay.h:171
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.
Definition vpException.h:60
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
Class that defines 2D ellipse visual feature.
virtual void print() const
void track(const vpHomogeneousMatrix &cMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
static double rad(double deg)
Definition vpMath.h:129
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
@ CAMERA_FRAME
Definition vpRobot.h:81
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)
@ EYEINHAND_CAMERA
Definition vpServo.h:176
@ DESIRED
Definition vpServo.h:223
Class that defines the simplest robot: a free flying camera.
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.