Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpCircle.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 * Visual feature circle.
32 */
33
34#include <visp3/core/vpCircle.h>
35
36#include <visp3/core/vpFeatureDisplay.h>
37
40{
41 const unsigned int val_7 = 7;
42 const unsigned int val_5 = 5;
43 oP.resize(val_7);
44 cP.resize(val_7);
45
46 p.resize(val_5);
47}
48
58void vpCircle::setWorldCoordinates(const vpColVector &oP_) { this->oP = oP_; }
59
75void vpCircle::setWorldCoordinates(double oA, double oB, double oC, double oX, double oY, double oZ, double R)
76{
77 const unsigned int index_0 = 0;
78 const unsigned int index_1 = 1;
79 const unsigned int index_2 = 2;
80 const unsigned int index_3 = 3;
81 const unsigned int index_4 = 4;
82 const unsigned int index_5 = 5;
83 const unsigned int index_6 = 6;
84 oP[index_0] = oA;
85 oP[index_1] = oB;
86 oP[index_2] = oC;
87 oP[index_3] = oX;
88 oP[index_4] = oY;
89 oP[index_5] = oZ;
90 oP[index_6] = R;
91}
92
97
110{
111 init();
113}
114
134vpCircle::vpCircle(double oA, double oB, double oC, double oX, double oY, double oZ, double R)
135{
136 init();
137 setWorldCoordinates(oA, oB, oC, oX, oY, oZ, R);
138}
139
152
172{
173 const int val_2 = 2;
174 const int val_4 = 4;
175 const unsigned int val_6 = 6;
176 const unsigned int val_5 = 5;
177 double det_threshold = 1e-10;
178 p_.resize(val_5, false);
179 const unsigned int index_0 = 0;
180 const unsigned int index_1 = 1;
181 const unsigned int index_2 = 2;
182 const unsigned int index_3 = 3;
183 const unsigned int index_4 = 4;
184 const unsigned int index_5 = 5;
185
186 vpColVector K(val_6);
187 {
188 double A = cP_[index_0];
189 double B = cP_[index_1];
190 double C = cP_[index_2];
191
192 double X0 = cP_[index_3];
193 double Y0 = cP_[index_4];
194 double Z0 = cP_[index_5];
195
196 double r = cP_[6];
197
198 // projection
199 double s = ((X0 * X0) + (Y0 * Y0) + (Z0 * Z0)) - (r * r);
200 double det = (A * X0) + (B * Y0) + (C * Z0);
201 A = A / det;
202 B = B / det;
203 C = C / det;
204
205 K[index_0] = (1 - (val_2 * A * X0)) + (A * A * s);
206 K[index_1] = (1 - (val_2 * B * Y0)) + (B * B * s);
207 K[index_2] = ((-A * Y0) - (B * X0)) + (A * B * s);
208 K[index_3] = ((-C * X0) - (A * Z0)) + (A * C * s);
209 K[index_4] = ((-C * Y0) - (B * Z0)) + (B * C * s);
210 K[index_5] = (1 - (val_2 * C * Z0)) + (C * C * s);
211 }
212
213 double det = (K[index_2] * K[index_2]) - (K[index_0] * K[index_1]);
214 if (fabs(det) < det_threshold) {
215 throw(vpException(vpException::divideByZeroError, "Division by 0 in vpCircle::projection."));
216 }
217
218 double xc = ((K[index_1] * K[index_3]) - (K[index_2] * K[index_4])) / det;
219 double yc = ((K[index_0] * K[index_4]) - (K[index_2] * K[index_3])) / det;
220
221 double c = sqrt(((K[index_0] - K[index_1]) * (K[index_0] - K[index_1])) + (4 * K[index_2] * K[index_2]));
222 double s = 2 * (((K[index_0] * xc * xc) + (2 * K[index_2] * xc * yc) + (K[1] * yc * yc)) - K[index_5]);
223
224 double A, B, E;
225
226 if (fabs(K[index_2]) < std::numeric_limits<double>::epsilon()) {
227 E = 0.0;
228 if (K[0] > K[1]) {
229 A = sqrt(s / ((K[0] + K[1]) + c));
230 B = sqrt(s / ((K[0] + K[1]) - c));
231 }
232 else {
233 A = sqrt(s / ((K[0] + K[1]) - c));
234 B = sqrt(s / ((K[0] + K[1]) + c));
235 }
236 }
237 else {
238 E = ((K[1] - K[0]) + c) / (val_2 * K[index_2]);
239 if (fabs(E) > 1.0) {
240 A = sqrt(s / ((K[0] + K[1]) + c));
241 B = sqrt(s / ((K[0] + K[1]) - c));
242 }
243 else {
244 A = sqrt(s / ((K[0] + K[1]) - c));
245 B = sqrt(s / ((K[0] + K[1]) + c));
246 E = -1.0 / E;
247 }
248 }
249
250 // Chaumette PhD Thesis 1990, eq 2.72 divided by 4 since n_ij = mu_ij_chaumette_thesis / 4
251 det = val_4 * (1.0 + vpMath::sqr(E));
252 double n20 = (vpMath::sqr(A) + vpMath::sqr(B * E)) / det;
253 double n11 = ((vpMath::sqr(A) - vpMath::sqr(B)) * E) / det;
254 double n02 = (vpMath::sqr(B) + vpMath::sqr(A * E)) / det;
255
256 p_[index_0] = xc;
257 p_[index_1] = yc;
258 p_[index_2] = n20;
259 p_[index_3] = n11;
260 p_[index_4] = n02;
261}
262
274{
275 const unsigned int val_7 = 7;
276 noP.resize(val_7, false);
277
278 double A, B, C;
279 const unsigned int index_0 = 0;
280 const unsigned int index_1 = 1;
281 const unsigned int index_2 = 2;
282 const unsigned int index_3 = 3;
283 const unsigned int index_4 = 4;
284 const unsigned int index_5 = 5;
285 const unsigned int index_6 = 6;
286 A = (noMo[index_0][0] * oP[0]) + (noMo[index_0][1] * oP[1]) + (noMo[index_0][index_2] * oP[index_2]);
287 B = (noMo[index_1][0] * oP[0]) + (noMo[index_1][1] * oP[1]) + (noMo[index_1][index_2] * oP[index_2]);
288 C = (noMo[index_2][0] * oP[0]) + (noMo[index_2][1] * oP[1]) + (noMo[index_2][index_2] * oP[index_2]);
289
290 double X0, Y0, Z0;
291 X0 = noMo[index_0][index_3] + (noMo[index_0][0] * oP[index_3]) + (noMo[index_0][1] * oP[index_4]) + (noMo[index_0][index_2] * oP[index_5]);
292 Y0 = noMo[index_1][index_3] + (noMo[index_1][0] * oP[index_3]) + (noMo[index_1][1] * oP[index_4]) + (noMo[index_1][index_2] * oP[index_5]);
293 Z0 = noMo[index_2][index_3] + (noMo[index_2][0] * oP[index_3]) + (noMo[index_2][1] * oP[index_4]) + (noMo[index_2][index_2] * oP[index_5]);
294 double R = oP[6];
295
296 noP[index_0] = A;
297 noP[index_1] = B;
298 noP[index_2] = C;
299
300 noP[index_3] = X0;
301 noP[index_4] = Y0;
302 noP[index_5] = Z0;
303
304 noP[index_6] = R;
305}
306
314{
315 double A, B, C;
316 const unsigned int index_0 = 0;
317 const unsigned int index_1 = 1;
318 const unsigned int index_2 = 2;
319 const unsigned int index_3 = 3;
320 const unsigned int index_4 = 4;
321 const unsigned int index_5 = 5;
322 const unsigned int index_6 = 6;
323 A = (cMo[index_0][0] * oP[0]) + (cMo[index_0][1] * oP[1]) + (cMo[index_0][index_2] * oP[index_2]);
324 B = (cMo[index_1][0] * oP[0]) + (cMo[index_1][1] * oP[1]) + (cMo[index_1][index_2] * oP[index_2]);
325 C = (cMo[index_2][0] * oP[0]) + (cMo[index_2][1] * oP[1]) + (cMo[index_2][index_2] * oP[index_2]);
326
327 double X0, Y0, Z0;
328 X0 = cMo[index_0][index_3] + (cMo[index_0][0] * oP[index_3]) + (cMo[index_0][1] * oP[index_4]) + (cMo[index_0][index_2] * oP[index_5]);
329 Y0 = cMo[index_1][index_3] + (cMo[index_1][0] * oP[index_3]) + (cMo[index_1][1] * oP[index_4]) + (cMo[index_1][index_2] * oP[index_5]);
330 Z0 = cMo[index_2][index_3] + (cMo[index_2][0] * oP[index_3]) + (cMo[index_2][1] * oP[index_4]) + (cMo[index_2][index_2] * oP[index_5]);
331 double R = oP[6];
332
333 cP[index_0] = A;
334 cP[index_1] = B;
335 cP[index_2] = C;
336
337 cP[index_3] = X0;
338 cP[index_4] = Y0;
339 cP[index_5] = Z0;
340
341 cP[index_6] = R;
342}
343
354 unsigned int thickness)
355{
356 const unsigned int index_0 = 0;
357 const unsigned int index_1 = 1;
358 const unsigned int index_2 = 2;
359 const unsigned int index_3 = 3;
360 const unsigned int index_4 = 4;
361 vpFeatureDisplay::displayEllipse(p[index_0], p[index_1], p[index_2], p[index_3], p[index_4], cam, I, color, thickness);
362}
363
373void vpCircle::display(const vpImage<vpRGBa> &I, const vpCameraParameters &cam, const vpColor &color,
374 unsigned int thickness)
375{
376 const unsigned int index_0 = 0;
377 const unsigned int index_1 = 1;
378 const unsigned int index_2 = 2;
379 const unsigned int index_3 = 3;
380 const unsigned int index_4 = 4;
381 vpFeatureDisplay::displayEllipse(p[index_0], p[index_1], p[index_2], p[index_3], p[index_4], cam, I, color, thickness);
382}
383
396 const vpColor &color, unsigned int thickness)
397{
398 vpColVector v_cP, v_p;
399 changeFrame(cMo, v_cP);
400 projection(v_cP, v_p);
401 const unsigned int index_0 = 0;
402 const unsigned int index_1 = 1;
403 const unsigned int index_2 = 2;
404 const unsigned int index_3 = 3;
405 const unsigned int index_4 = 4;
406 vpFeatureDisplay::displayEllipse(v_p[index_0], v_p[index_1], v_p[index_2], v_p[index_3], v_p[index_4], cam, I, color, thickness);
407}
408
421 const vpColor &color, unsigned int thickness)
422{
423 vpColVector v_cP, v_p;
424 changeFrame(cMo, v_cP);
425 projection(v_cP, v_p);
426 const unsigned int index_0 = 0;
427 const unsigned int index_1 = 1;
428 const unsigned int index_2 = 2;
429 const unsigned int index_3 = 3;
430 const unsigned int index_4 = 4;
431 vpFeatureDisplay::displayEllipse(v_p[index_0], v_p[index_1], v_p[index_2], v_p[index_3], v_p[index_4], cam, I, color, thickness);
432}
433
436{
437 vpCircle *feature = new vpCircle(*this);
438 return feature;
439}
440
458void vpCircle::computeIntersectionPoint(const vpCircle &circle, const vpCameraParameters &cam, const double &rho,
459 const double &theta, double &i, double &j)
460{
461 // This was taken from the code of art-v1. (from the artCylinder class)
462 double px = cam.get_px();
463 double py = cam.get_py();
464 double u0 = cam.get_u0();
465 double v0 = cam.get_v0();
466
467 const unsigned int index_0 = 0;
468 const unsigned int index_1 = 1;
469 const unsigned int index_2 = 2;
470 const unsigned int index_3 = 3;
471 const unsigned int index_4 = 4;
472
473 double n11 = circle.p[index_3];
474 double n02 = circle.p[index_4];
475 double n20 = circle.p[index_2];
476 double Xg = u0 + (circle.p[index_0] * px);
477 double Yg = v0 + (circle.p[index_1] * py);
478
479 // Find Intersection between line and ellipse in the image.
480
481 // Optimised calculation for X
482 double stheta = sin(theta);
483 double ctheta = cos(theta);
484 double sctheta = stheta * ctheta;
485 double m11yg = n11 * Yg;
486 double ctheta2 = vpMath::sqr(ctheta);
487 double m02xg = n02 * Xg;
488 double m11stheta = n11 * stheta;
489 j = ((((((((n11 * Xg * sctheta) - (n20 * Yg * sctheta)) + (n20 * rho * ctheta)) - m11yg) + (m11yg * ctheta2) + m02xg) -
490 (m02xg * ctheta2)) + (m11stheta * rho)) /
491 (((n20 * ctheta2) + (2.0 * m11stheta * ctheta) + n02) - (n02 * ctheta2)));
492 // Optimised calculation for Y
493 double rhom02 = rho * n02;
494 double sctheta2 = stheta * ctheta2;
495 double ctheta3 = ctheta2 * ctheta;
496 i = (-(((((((-rho * n11 * stheta * ctheta) - rhom02) + (rhom02 * ctheta2) + (n11 * Xg * sctheta2)) - (n20 * Yg * sctheta2)) -
497 (ctheta * n11 * Yg)) + (ctheta3 * n11 * Yg) + (ctheta * n02 * Xg)) - (ctheta3 * n02 * Xg)) /
498 (((n20 * ctheta2) + (2.0 * n11 * stheta * ctheta) + n02) - (n02 * ctheta2)) / stheta);
499}
500END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
void display(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpColor &color=vpColor::green, unsigned int thickness=1) VP_OVERRIDE
Definition vpCircle.cpp:353
void changeFrame(const vpHomogeneousMatrix &noMo, vpColVector &noP) const VP_OVERRIDE
Definition vpCircle.cpp:273
void projection() VP_OVERRIDE
Definition vpCircle.cpp:151
void setWorldCoordinates(const vpColVector &oP) VP_OVERRIDE
Definition vpCircle.cpp:58
void init() VP_OVERRIDE
Definition vpCircle.cpp:39
vpCircle * duplicate() const VP_OVERRIDE
For memory issue (used by the vpServo class only).
Definition vpCircle.cpp:435
static void computeIntersectionPoint(const vpCircle &circle, const vpCameraParameters &cam, const double &rho, const double &theta, double &i, double &j)
Definition vpCircle.cpp:458
Implementation of column vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ divideByZeroError
Division by zero.
Definition vpException.h:70
static void displayEllipse(double x, double y, double n20, double n11, double n02, const vpCameraParameters &cam, const vpImage< unsigned char > &I, const vpColor &color=vpColor::green, unsigned int thickness=1)
Implementation of an homogeneous matrix and operations on such kind of matrices.
Definition of the vpImage class member functions.
Definition vpImage.h:131
static double sqr(double x)
Definition vpMath.h:203
vpColVector cP
Definition vpTracker.h:73
vpColVector p
Definition vpTracker.h:69