Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpCylinder.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Cylinder feature.
33  *
34 *****************************************************************************/
35 
36 #include <visp3/core/vpCylinder.h>
37 #include <visp3/core/vpFeatureDisplay.h>
38 
41 {
42  oP.resize(7);
43  cP.resize(7);
44 
45  p.resize(4);
46 }
47 
63 void vpCylinder::setWorldCoordinates(const vpColVector &o_P) { this->oP = o_P; }
64 
72 void vpCylinder::setWorldCoordinates(double oA, double oB, double oC, double oX, double oY, double oZ, double R)
73 {
74  oP[0] = oA;
75  oP[1] = oB;
76  oP[2] = oC;
77  oP[3] = oX;
78  oP[4] = oY;
79  oP[5] = oZ;
80  oP[6] = R;
81 }
82 
87 
104 {
105  init();
106  setWorldCoordinates(o_P);
107 }
108 
118 vpCylinder::vpCylinder(double oA, double oB, double oC, double oX, double oY, double oZ, double R)
119 {
120  init();
121  setWorldCoordinates(oA, oB, oC, oX, oY, oZ, R);
122 }
123 
148 
177 void vpCylinder::projection(const vpColVector &cP_, vpColVector &p_) const
178 {
179  p_.resize(4, false);
180 
181  double co, si, e, x0, y0, z0;
182  double A, B, C, X0, Y0, Z0, R;
183  double s, a, b, c, zero;
184 
185  A = cP_[0];
186  B = cP_[1];
187  C = cP_[2];
188  X0 = cP_[3];
189  Y0 = cP_[4];
190  Z0 = cP_[5];
191  R = cP_[6];
192  zero = A * X0 + B * Y0 + C * Z0; // should be zero for a good reprensetation of the cylinder
193 
194  s = X0 * X0 + Y0 * Y0 + Z0 * Z0 - R * R - zero * zero;
195  if (s < 0) {
196  throw vpException(vpException::fatalError, "The camera is inside the cylinder with s=%f!", s);
197  }
198  s = 1.0 / sqrt(s);
199  a = X0 - A * zero; //(1-A*A)*X0 - A*B*Y0 - A*C*Z0;
200  b = Y0 - B * zero; // - A*B*X0 + (1-B*B)*Y0 - B*C*Z0;
201  c = Z0 - C * zero; //- A*C*X0 - B*C*Y0 + (1-C*C)*Z0;
202  x0 = C * Y0 - B * Z0;
203  y0 = A * Z0 - C * X0;
204  z0 = B * X0 - A * Y0;
205 
206  // rho1 / theta1
207  co = R * a * s - x0;
208  si = R * b * s - y0;
209  e = sqrt(co * co + si * si);
210  p_[0] = -(R * c * s - z0) / e; // rho1
211  p_[1] = atan2(si, co); // theta 1
212 
213  // rho2 / theta2
214  co = R * a * s + x0;
215  si = R * b * s + y0;
216  e = sqrt(co * co + si * si);
217  p_[2] = -(R * c * s + z0) / e; // rho2
218  p_[3] = atan2(si, co); // theta2
219 }
220 
231 
243 {
244  cP_.resize(7, false);
245 
246  double X1, Y1, Z1;
247  double X2, Y2, Z2;
248  double s, a, b, c;
249 
250  double oA, oB, oC, oX0, oY0, oZ0;
251  oA = oP[0];
252  oB = oP[1];
253  oC = oP[2];
254  oX0 = oP[3];
255  oY0 = oP[4];
256  oZ0 = oP[5];
257 
258  X1 = cMo[0][0] * oA + cMo[0][1] * oB + cMo[0][2] * oC;
259  Y1 = cMo[1][0] * oA + cMo[1][1] * oB + cMo[1][2] * oC;
260  Z1 = cMo[2][0] * oA + cMo[2][1] * oB + cMo[2][2] * oC;
261  s = sqrt(X1 * X1 + Y1 * Y1 + Z1 * Z1);
262  a = X1 / s;
263  b = Y1 / s;
264  c = Z1 / s;
265 
266  // set axis coordinates in camera frame
267  cP_[0] = a;
268  cP_[1] = b;
269  cP_[2] = c;
270 
271  X2 = cMo[0][3] + cMo[0][0] * oX0 + cMo[0][1] * oY0 + cMo[0][2] * oZ0;
272  Y2 = cMo[1][3] + cMo[1][0] * oX0 + cMo[1][1] * oY0 + cMo[1][2] * oZ0;
273  Z2 = cMo[2][3] + cMo[2][0] * oX0 + cMo[2][1] * oY0 + cMo[2][2] * oZ0;
274 
275  // adding the constraint X0 is the nearest point to the origin (A^T . X0 =
276  // 0) using the projection operator (I - AA^T) orthogonal to A
277  cP_[3] = (1 - a * a) * X2 - a * b * Y2 - a * c * Z2;
278  cP_[4] = -a * b * X2 + (1 - b * b) * Y2 - b * c * Z2;
279  cP_[5] = -a * c * X2 - b * c * Y2 + (1 - c * c) * Z2;
280 
281  /* old version for the same onstraint
282  if ( fabs(a) > 0.25 )
283  {
284  double xx, yy, zz, xx1, yy1;
285 
286  xx1 = a*Y2 - b*X2;
287  yy1 = a*Z2 - c*X2;
288  xx = -( b*xx1 + c*yy1);
289  yy = (( a*a + c*c ) * xx1 - b*c*yy1 ) /a;
290  zz = ( -b*c*xx1 + ( a*a + b*b )*yy1) /a;
291 
292  // set point coordinates in camera frame
293  _cP[3] = xx ;
294  _cP[4] = yy ;
295  _cP[5] = zz ;
296  }
297  else if ( fabs(b) >0.25 )
298  {
299  double xx, yy, zz, xx1, yy1;
300 
301  xx1 = a*Y2 - b*X2;
302  yy1 = c*Y2 - b*Z2;
303  xx = - (( b*b + c*c ) * xx1 - a*c*yy1 ) /b;
304  yy = a*xx1 + c*yy1;
305  zz = - ( -a*c*xx1 + (a*a + b*b) * yy1 ) /b;
306 
307 
308  // set point coordinates in camera frame
309  _cP[3] = xx ;
310  _cP[4] = yy ;
311  _cP[5] = zz ;
312  }
313  else
314  {
315  double xx, yy, zz, xx1, yy1;
316 
317  xx1 = a*Z2 - c*X2;
318  yy1 = b*Z2 - c*Y2;
319  xx = (-( b*b + c*c ) * xx1 - a*c*yy1 ) /c;
320  yy = ( a*b*xx1 - ( a*a + c*c )*yy1) /c;
321  zz = a*xx1 + b*yy1;
322 
323  // set point coordinates in camera frame
324  _cP[3] = xx ;
325  _cP[4] = yy ;
326  _cP[5] = zz ;
327  }
328  */
329  // radius
330  cP_[6] = oP[6];
331 }
332 
337 double vpCylinder::computeZ(double x, double y) const
338 {
339  double A = x * x + y * y + 1 - ((getA() * x + getB() * y + getC()) * (getA() * x + getB() * y + getC()));
340  double B = (x * getX() + y * getY() + getZ());
341  double C = getX() * getX() + getY() * getY() + getZ() * getZ() - getR() * getR();
342 
343  return (B - std::sqrt(B * B - A * C)) / A;
344 }
345 
348 {
349  vpCylinder *feature = new vpCylinder(*this);
350  return feature;
351 }
352 
366  const vpColor &color, unsigned int thickness)
367 {
368 
369  vpColVector _cP(7), _p(4);
370  changeFrame(cMo, _cP);
371  projection(_cP, _p);
372  vpFeatureDisplay::displayCylinder(_p[0], _p[1], _p[2], _p[3], cam, I, color, thickness);
373 }
374 
388  const vpColor &color, unsigned int thickness)
389 {
390 
391  vpColVector _cP(7), _p(4);
392  changeFrame(cMo, _cP);
393  projection(_cP, _p);
394  vpFeatureDisplay::displayCylinder(_p[0], _p[1], _p[2], _p[3], cam, I, color, thickness);
395 }
396 
406  unsigned int thickness)
407 {
408  vpFeatureDisplay::displayCylinder(p[0], p[1], p[2], p[3], cam, I, color, thickness);
409 }
410 
419 void vpCylinder::display(const vpImage<vpRGBa> &I, const vpCameraParameters &cam, const vpColor &color,
420  unsigned int thickness)
421 {
422  vpFeatureDisplay::displayCylinder(p[0], p[1], p[2], p[3], cam, I, color, thickness);
423 }
424 END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:157
Class that defines a 3D cylinder in the object frame and allows forward projection of a 3D cylinder i...
Definition: vpCylinder.h:101
double getZ() const
Definition: vpCylinder.h:183
double getB() const
Definition: vpCylinder.h:163
void init() VP_OVERRIDE
Definition: vpCylinder.cpp:40
void display(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpColor &color=vpColor::green, unsigned int thickness=1) VP_OVERRIDE
Definition: vpCylinder.cpp:405
double getX() const
Definition: vpCylinder.h:173
double getY() const
Definition: vpCylinder.h:178
void changeFrame(const vpHomogeneousMatrix &cMo, vpColVector &cP) const VP_OVERRIDE
Definition: vpCylinder.cpp:242
double getA() const
Definition: vpCylinder.h:158
void projection() VP_OVERRIDE
Definition: vpCylinder.cpp:147
double getR() const
Definition: vpCylinder.h:188
vpCylinder * duplicate() const VP_OVERRIDE
For memory issue (used by the vpServo class only).
Definition: vpCylinder.cpp:347
double getC() const
Definition: vpCylinder.h:168
double computeZ(double x, double y) const
Definition: vpCylinder.cpp:337
void setWorldCoordinates(const vpColVector &oP) VP_OVERRIDE
Definition: vpCylinder.cpp:63
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ fatalError
Fatal error.
Definition: vpException.h:72
static void displayCylinder(double rho1, double theta1, double rho2, double theta2, 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.
vpColVector cP
Definition: vpTracker.h:73
vpColVector p
Definition: vpTracker.h:69