Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
servoMomentPoints.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 * Example of visual servoing with moments using discrete points as object
32 * container
33 */
34
39
40#include <iostream>
41#include <visp3/core/vpCameraParameters.h>
42#include <visp3/core/vpConfig.h>
43#include <visp3/core/vpDebug.h>
44#include <visp3/core/vpHomogeneousMatrix.h>
45#include <visp3/core/vpIoTools.h>
46#include <visp3/core/vpMath.h>
47#include <visp3/core/vpMomentCommon.h>
48#include <visp3/core/vpMomentDatabase.h>
49#include <visp3/core/vpMomentObject.h>
50#include <visp3/core/vpPlane.h>
51#include <visp3/gui/vpDisplayFactory.h>
52#include <visp3/gui/vpPlot.h>
53#include <visp3/robot/vpSimulatorAfma6.h>
54#include <visp3/visual_features/vpFeatureBuilder.h>
55#include <visp3/visual_features/vpFeatureMomentCommon.h>
56#include <visp3/visual_features/vpFeaturePoint.h>
57#include <visp3/vs/vpServo.h>
58
59#if !defined(VISP_HAVE_DISPLAY)
60int main()
61{
62 std::cout << "Can't run this example since no display capability is available." << std::endl;
63 std::cout << "You should install one of the following third-party library: X11, OpenCV, GDI, GTK." << std::endl;
64 return EXIT_SUCCESS;
65}
66#elif !defined(VISP_HAVE_THREADS)
67int main()
68{
69 std::cout << "Can't run this example since multi-threading capability is not available." << std::endl;
70 std::cout << "You should maybe enable cxx11 standard." << std::endl;
71 return EXIT_SUCCESS;
72}
73#else
74
75#ifdef ENABLE_VISP_NAMESPACE
76using namespace VISP_NAMESPACE_NAME;
77#endif
78
79#ifndef DOXYGEN_SHOULD_SKIP_THIS
80class servoMoment
81{
82public:
83 servoMoment()
84 : m_width(640), m_height(480), m_cMo(), m_cdMo(), m_robot(false), m_Iint(m_height, m_width, vpRGBa(255)), m_task(), m_cam(),
85 m_error(0), m_imsim(), m_interaction_type(), m_src(6), m_dst(6), m_moments(nullptr), m_momentsDes(nullptr),
86 m_featureMoments(nullptr), m_featureMomentsDes(nullptr), m_displayInt(nullptr)
87 { }
88 ~servoMoment()
89 {
90#if defined(VISP_HAVE_DISPLAY) && (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
91 if (m_displayInt) {
92 delete m_displayInt;
93 }
94#endif
95 delete m_moments;
96 delete m_momentsDes;
97 delete m_featureMoments;
98 delete m_featureMomentsDes;
99 }
100
101 // initialize scene in the interface
102 void initScene()
103 {
104 std::vector<vpPoint> src_pts;
105 std::vector<vpPoint> dst_pts;
106
107 double x[8] = { 1, 3, 4, -1, -3, -2, -1, 1 };
108 double y[8] = { 0, 1, 4, 4, -2, -2, 1, 0 };
109 int nbpoints = 8;
110
111 for (int i = 0; i < nbpoints; i++) {
112 vpPoint p(x[i] / 20, y[i] / 20, 0.0);
113 p.track(m_cMo);
114 src_pts.push_back(p);
115 }
116
117 m_src.setType(vpMomentObject::DISCRETE);
118 m_src.fromVector(src_pts);
119 for (int i = 0; i < nbpoints; i++) {
120 vpPoint p(x[i] / 20, y[i] / 20, 0.0);
121 p.track(m_cdMo);
122 dst_pts.push_back(p);
123 }
124 m_dst.setType(vpMomentObject::DISCRETE);
125 m_dst.fromVector(dst_pts);
126 }
127
128 // initialize the moment features
129 void initFeatures()
130 {
131 // A,B,C parameters of source and destination plane
132 double A;
133 double B;
134 double C;
135 double Ad;
136 double Bd;
137 double Cd;
138 // init main object: using moments up to order 6
139
140 // Initializing values from regular plane (with ax+by+cz=d convention)
141 vpPlane pl;
142 pl.setABCD(0, 0, 1.0, 0);
143 pl.changeFrame(m_cMo);
144 planeToABC(pl, A, B, C);
145
146 pl.setABCD(0, 0, 1.0, 0);
147 pl.changeFrame(m_cdMo);
148 planeToABC(pl, Ad, Bd, Cd);
149
150 // extracting initial position (actually we only care about Zdst)
151 vpTranslationVector vec;
152 m_cdMo.extract(vec);
153
156 // don't need to be specific, vpMomentCommon automatically loads
157 // Xg,Yg,An,Ci,Cj,Alpha moments
158 m_moments = new vpMomentCommon(vpMomentCommon::getSurface(m_dst), vpMomentCommon::getMu3(m_dst),
159 vpMomentCommon::getAlpha(m_dst), vec[2]);
160 m_momentsDes = new vpMomentCommon(vpMomentCommon::getSurface(m_dst), vpMomentCommon::getMu3(m_dst),
161 vpMomentCommon::getAlpha(m_dst), vec[2]);
162 // same thing with common features
163 m_featureMoments = new vpFeatureMomentCommon(*m_moments);
164 m_featureMomentsDes = new vpFeatureMomentCommon(*m_momentsDes);
165
166 m_moments->updateAll(m_src);
167 m_momentsDes->updateAll(m_dst);
168
169 m_featureMoments->updateAll(A, B, C);
170 m_featureMomentsDes->updateAll(Ad, Bd, Cd);
171
172 // setup the interaction type
173 m_task.setInteractionMatrixType(m_interaction_type);
176 m_task.addFeature(m_featureMoments->getFeatureGravityNormalized(),
177 m_featureMomentsDes->getFeatureGravityNormalized());
178 m_task.addFeature(m_featureMoments->getFeatureAn(), m_featureMomentsDes->getFeatureAn());
179 m_task.addFeature(m_featureMoments->getFeatureCInvariant(), m_featureMomentsDes->getFeatureCInvariant(),
180 (1 << 3) | (1 << 5));
181 m_task.addFeature(m_featureMoments->getFeatureAlpha(), m_featureMomentsDes->getFeatureAlpha());
182
183 m_task.setLambda(1.);
184 }
185
186 // update moment objects and interface
187 void refreshScene(vpMomentObject &obj)
188 {
189 // double x[8] = { 0.05,0.15, 0.2,-0.05 ,-0.15,-0.1,-0.05,0.05};
190 // double y[8] = { 0,0.05, 0.2, 0.2, -0.1,-0.1, 0.05,0};
191 double x[8] = { 1, 3, 4, -1, -3, -2, -1, 1 };
192 double y[8] = { 0, 1, 4, 4, -2, -2, 1, 0 };
193 int nbpoints = 8;
194 std::vector<vpPoint> cur_pts;
195
196 for (int i = 0; i < nbpoints; i++) {
197 vpPoint p(x[i] / 20, y[i] / 20, 0.0);
198 p.track(m_cMo);
199 cur_pts.push_back(p);
200 }
201 obj.fromVector(cur_pts);
202 }
203
204 void init(vpHomogeneousMatrix &cMo, vpHomogeneousMatrix &cdMo)
205 {
206 m_cMo = cMo; // init source matrix
207 m_cdMo = cdMo; // init destination matrix
208
209 m_interaction_type = vpServo::CURRENT; // use interaction matrix for current position
210
211#ifdef VISP_HAVE_DISPLAY
212 // init the display
213#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
214 m_displayInt = vpDisplayFactory::createDisplay(m_Iint, 50, 50, "Visual servoing with moments");
215#else
216 m_displayInt = vpDisplayFactory::allocateDisplay(m_Iint, 50, 50, "Visual servoing with moments");
217#endif
218#endif
219
220 paramRobot(); // set up robot parameters
221
222 m_task.setServo(vpServo::EYEINHAND_CAMERA);
223 initScene(); // initialize graphical scene (for interface)
224 initFeatures(); // initialize moment features
225 }
226
227 // launch the simulation
228 void execute(unsigned int nbIter)
229 {
230 vpPlot ViSP_plot;
231 init_visp_plot(ViSP_plot); // Initialize plot object
232
233 // init main object: using moments up to order 6
234 vpMomentObject obj(6);
235 // setting object type (disrete, continuous[form polygon])
237
238 std::cout << "Display task information " << std::endl;
239 m_task.print();
240
241 vpDisplay::display(m_Iint);
242 m_robot.getInternalView(m_Iint);
243 vpDisplay::flush(m_Iint);
244 unsigned int iter = 0;
245
247 while (iter++ < nbIter) {
248 vpColVector v;
249 // get the cMo
250 m_cMo = m_robot.get_cMo();
251 // setup the plane in A,B,C style
252 vpPlane pl;
253 double A, B, C;
254 pl.setABCD(0, 0, 1.0, 0);
255 pl.changeFrame(m_cMo);
256 planeToABC(pl, A, B, C);
257
258 // track points, draw points and add refresh our object
259 refreshScene(obj);
260 // this is the most important thing to do: update our moments
261 m_moments->updateAll(obj);
262 // and update our features. Do it in that order. Features need to use the
263 // information computed by moments
264 m_featureMoments->updateAll(A, B, C);
265
266 vpDisplay::display(m_Iint);
267 m_robot.getInternalView(m_Iint);
268
269 if (iter == 1) {
270 vpDisplay::displayText(m_Iint, 20, 20, "Click to start servoing", vpColor::red);
271 vpDisplay::flush(m_Iint);
272 vpDisplay::getClick(m_Iint);
273 }
274 v = m_task.computeControlLaw();
275
276 // pilot robot using position control. The displacement is t*v with t=10ms
277 // step robot.setPosition(vpRobot::CAMERA_FRAME,0.01*v);
278 m_robot.setVelocity(vpRobot::CAMERA_FRAME, v);
279
280 ViSP_plot.plot(0, iter, v);
281 ViSP_plot.plot(1, iter, vpPoseVector(m_cMo)); // Plot the velocities
282 ViSP_plot.plot(2, iter, m_task.getError()); // cMo as translations and theta_u
283
284 m_error = (m_task.getError()).sumSquare();
285
286 vpDisplay::displayText(m_Iint, 20, 20, "Click to stop visual servo...", vpColor::red);
287 if (vpDisplay::getClick(m_Iint, false)) {
288 break;
289 }
290 vpDisplay::flush(m_Iint);
291 }
292
293 vpDisplay::display(m_Iint);
294 m_robot.getInternalView(m_Iint);
295 vpDisplay::displayText(m_Iint, 20, 20, "Click to quit...", vpColor::red);
296 vpDisplay::flush(m_Iint);
297 vpDisplay::getClick(m_Iint);
298 }
299
300 void removeJointLimits(vpSimulatorAfma6 &robot)
301 {
302 vpColVector limMin(6);
303 vpColVector limMax(6);
304 limMin[0] = vpMath::rad(-3600);
305 limMin[1] = vpMath::rad(-3600);
306 limMin[2] = vpMath::rad(-3600);
307 limMin[3] = vpMath::rad(-3600);
308 limMin[4] = vpMath::rad(-3600);
309 limMin[5] = vpMath::rad(-3600);
310
311 limMax[0] = vpMath::rad(3600);
312 limMax[1] = vpMath::rad(3600);
313 limMax[2] = vpMath::rad(3600);
314 limMax[3] = vpMath::rad(3600);
315 limMax[4] = vpMath::rad(3600);
316 limMax[5] = vpMath::rad(3600);
317
318 robot.setJointLimit(limMin, limMax);
319 robot.setMaxRotationVelocity(99999);
320 robot.setMaxTranslationVelocity(999999);
321 }
322
323 void planeToABC(vpPlane &pl, double &A, double &B, double &C)
324 {
325 if (fabs(pl.getD()) < std::numeric_limits<double>::epsilon()) {
326 std::cout << "Invalid position:" << std::endl;
327 std::cout << m_cMo << std::endl;
328 std::cout << "Cannot put plane in the form 1/Z=Ax+By+C." << std::endl;
329 throw vpException(vpException::divideByZeroError, "invalid position!");
330 }
331 A = -pl.getA() / pl.getD();
332 B = -pl.getB() / pl.getD();
333 C = -pl.getC() / pl.getD();
334 }
335
336 // setup robot parameters
337 void paramRobot()
338 {
339 /*Initialise the robot and especially the camera*/
341 m_robot.setCurrentViewColor(vpColor(150, 150, 150));
342 m_robot.setDesiredViewColor(vpColor(200, 200, 200));
343 m_robot.setRobotState(vpRobot::STATE_VELOCITY_CONTROL);
344 removeJointLimits(m_robot);
346 m_robot.setConstantSamplingTimeMode(true);
347 /*Initialise the position of the object relative to the pose of the robot's
348 * camera*/
349 m_robot.initialiseObjectRelativeToCamera(m_cMo);
350
351 /*Set the desired position (for the displaypart)*/
352 m_robot.setDesiredCameraPosition(m_cdMo);
353 m_robot.getCameraParameters(m_cam, m_Iint);
354 }
355
356 void setInteractionMatrixType(vpServo::vpServoIteractionMatrixType type) { m_interaction_type = type; }
357
358 double error() { return m_error; }
359
360 void init_visp_plot(vpPlot &ViSP_plot)
361 {
362 /* -------------------------------------
363 * Initialize ViSP Plotting
364 * -------------------------------------
365 */
366 const unsigned int NbGraphs = 3; // No. of graphs
367 const unsigned int NbCurves_in_graph[NbGraphs] = { 6, 6, 6 }; // Curves in each graph
368
369 ViSP_plot.init(NbGraphs, 800, 800, 100 + static_cast<int>(m_width), 50, "Visual Servoing results...");
370
371 vpColor Colors[6] = {// Colour for s1, s2, s3, in 1st plot
373
374 for (unsigned int p = 0; p < NbGraphs; p++) {
375 ViSP_plot.initGraph(p, NbCurves_in_graph[p]);
376 for (unsigned int c = 0; c < NbCurves_in_graph[p]; c++)
377 ViSP_plot.setColor(p, c, Colors[c]);
378 }
379
380 ViSP_plot.setTitle(0, "Robot velocities");
381 ViSP_plot.setLegend(0, 0, "v_x");
382 ViSP_plot.setLegend(0, 1, "v_y");
383 ViSP_plot.setLegend(0, 2, "v_z");
384 ViSP_plot.setLegend(0, 3, "w_x");
385 ViSP_plot.setLegend(0, 4, "w_y");
386 ViSP_plot.setLegend(0, 5, "w_z");
387
388 ViSP_plot.setTitle(1, "Camera pose cMo");
389 ViSP_plot.setLegend(1, 0, "tx");
390 ViSP_plot.setLegend(1, 1, "ty");
391 ViSP_plot.setLegend(1, 2, "tz");
392 ViSP_plot.setLegend(1, 3, "tu_x");
393 ViSP_plot.setLegend(1, 4, "tu_y");
394 ViSP_plot.setLegend(1, 5, "tu_z");
395
396 ViSP_plot.setTitle(2, "Error in visual features: ");
397 ViSP_plot.setLegend(2, 0, "x_n");
398 ViSP_plot.setLegend(2, 1, "y_n");
399 ViSP_plot.setLegend(2, 2, "a_n");
400 ViSP_plot.setLegend(2, 3, "sx");
401 ViSP_plot.setLegend(2, 4, "sy");
402 ViSP_plot.setLegend(2, 5, "alpha");
403 }
404
405protected:
406 // start and destination positioning matrices
407 unsigned int m_width;
408 unsigned int m_height;
409
410 // start and destination positioning matrices
411 vpHomogeneousMatrix m_cMo;
412 vpHomogeneousMatrix m_cdMo;
413
414 vpSimulatorAfma6 m_robot; // robot used in this simulation
415 vpImage<vpRGBa> m_Iint; // internal image used for interface display
416 vpServo m_task; // servoing task
417 vpCameraParameters m_cam; // robot camera parameters
418 double m_error; // current error
419 vpImageSimulator m_imsim; // image simulator used to simulate the perspective-projection camera
420
421 vpServo::vpServoIteractionMatrixType m_interaction_type; // current or desired
422 // source and destination objects for moment manipulation
423 vpMomentObject m_src;
424 vpMomentObject m_dst;
425
426 // moment sets and their corresponding features
427 vpMomentCommon *m_moments;
428 vpMomentCommon *m_momentsDes;
429 vpFeatureMomentCommon *m_featureMoments;
430 vpFeatureMomentCommon *m_featureMomentsDes;
431
432#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
433 std::shared_ptr<vpDisplay> m_displayInt;
434#else
435 vpDisplay *m_displayInt;
436#endif
437};
438#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
439
440int main()
441{
442 try { // intial pose
443 vpHomogeneousMatrix cMo(0.05, 0.1, 1.5, vpMath::rad(30), vpMath::rad(20), -vpMath::rad(15));
444 // Desired pose
446
447 servoMoment servo;
448 // init and run the simulation
449 servo.init(cMo, cdMo);
450 servo.execute(1500);
451 return EXIT_SUCCESS;
452 }
453 catch (const vpException &e) {
454 std::cout << "Catch an exception: " << e << std::endl;
455 return EXIT_FAILURE;
456 }
457}
458
459#endif
@ TOOL_CCMOP
Definition vpAfma6.h:125
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
static const vpColor red
Definition vpColor.h:198
static const vpColor cyan
Definition vpColor.h:207
static const vpColor orange
Definition vpColor.h:208
static const vpColor blue
Definition vpColor.h:204
static const vpColor purple
Definition vpColor.h:209
static const vpColor green
Definition vpColor.h:201
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
@ divideByZeroError
Division by zero.
Definition vpException.h:70
Implementation of an homogeneous matrix and operations on such kind of matrices.
static double rad(double deg)
Definition vpMath.h:129
static std::vector< double > getMu3(vpMomentObject &object)
static double getAlpha(vpMomentObject &object)
static double getSurface(vpMomentObject &object)
void setType(vpObjectType input_type)
void fromVector(std::vector< vpPoint > &points)
void changeFrame(const vpHomogeneousMatrix &cMo)
Definition vpPlane.cpp:465
double getD() const
Definition vpPlane.h:106
double getA() const
Definition vpPlane.h:100
double getC() const
Definition vpPlane.h:104
void setABCD(double a, double b, double c, double d)
Definition vpPlane.h:88
double getB() const
Definition vpPlane.h:102
void initGraph(unsigned int graphNum, unsigned int curveNbr)
Definition vpPlot.cpp:212
void init(unsigned int nbGraph, unsigned int height=700, unsigned int width=700, int x=-1, int y=-1, const std::string &title="")
Definition vpPlot.cpp:97
void setLegend(unsigned int graphNum, unsigned int curveNum, const std::string &legend)
Definition vpPlot.cpp:561
void plot(unsigned int graphNum, unsigned int curveNum, double x, double y)
Definition vpPlot.cpp:279
void setColor(unsigned int graphNum, unsigned int curveNum, vpColor color)
Definition vpPlot.cpp:255
void setTitle(unsigned int graphNum, const std::string &title)
Definition vpPlot.cpp:519
@ CAMERA_FRAME
Definition vpRobot.h:81
@ STATE_VELOCITY_CONTROL
Initialize the velocity controller.
Definition vpRobot.h:64
void setMaxRotationVelocity(double maxVr)
Definition vpRobot.cpp:259
void setMaxTranslationVelocity(double maxVt)
Definition vpRobot.cpp:238
@ EYEINHAND_CAMERA
Definition vpServo.h:176
vpServoIteractionMatrixType
Definition vpServo.h:211
@ CURRENT
Definition vpServo.h:217
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.