Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
vpCylinder.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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 http://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  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpCylinder.h>
40 #include <visp3/core/vpFeatureDisplay.h>
41 
43 {
44 
45  oP.resize(7);
46  cP.resize(7);
47 
48  p.resize(4);
49 }
50 
71 void vpCylinder::setWorldCoordinates(const vpColVector &o_P) { this->oP = o_P; }
72 
81 void vpCylinder::setWorldCoordinates(double A, double B, double C, double X0, double Y0, double Z0, double R)
82 {
83  oP[0] = A;
84  oP[1] = B;
85  oP[2] = C;
86  oP[3] = X0;
87  oP[4] = Y0;
88  oP[5] = Z0;
89  oP[6] = R;
90 }
91 
96 
119 {
120  init();
121  setWorldCoordinates(o_P);
122 }
123 
134 vpCylinder::vpCylinder(double A, double B, double C, double X0, double Y0, double Z0, double R)
135 {
136  init();
137  setWorldCoordinates(A, B, C, X0, Y0, Z0, R);
138 }
139 
144 
166 
196 {
197  // calcul de la scene 2-D
198 
199  double co, si, e, x0, y0, z0;
200  double A, B, C, X0, Y0, Z0, R;
201  double s, a, b, c, zero;
202 
203  A = cP_[0];
204  B = cP_[1];
205  C = cP_[2];
206  X0 = cP_[3];
207  Y0 = cP_[4];
208  Z0 = cP_[5];
209  R = cP_[6];
210  zero = A * X0 + B * Y0 + C * Z0; // should be zero for a good reprensetation of the cylinder
211 
212  s = X0 * X0 + Y0 * Y0 + Z0 * Z0 - R * R - zero * zero;
213  if (s < 0) {
214  printf("The camera is inside the cylinder with s=%f !\n", s);
215  throw vpException(vpException::fatalError, "The camera is inside the cylinder!");
216  }
217  s = 1.0 / sqrt(s);
218  a = X0 - A * zero; //(1-A*A)*X0 - A*B*Y0 - A*C*Z0;
219  b = Y0 - B * zero; // - A*B*X0 + (1-B*B)*Y0 - B*C*Z0;
220  c = Z0 - C * zero; //- A*C*X0 - B*C*Y0 + (1-C*C)*Z0;
221  x0 = C * Y0 - B * Z0;
222  y0 = A * Z0 - C * X0;
223  z0 = B * X0 - A * Y0;
224 
225  // rho1 / theta1
226  co = R * a * s - x0;
227  si = R * b * s - y0;
228  e = sqrt(co * co + si * si);
229  p_[0] = -(R * c * s - z0) / e; // rho1
230  p_[1] = atan2(si, co); // theta 1
231 
232  // while (p[1] > M_PI/2) { p[1] -= M_PI ; p[0] *= -1 ; }
233  // while (p[1] < -M_PI/2) { p[1] += M_PI ; p[0] *= -1 ; }
234 
235  // rho2 / theta2
236  co = R * a * s + x0;
237  si = R * b * s + y0;
238  e = sqrt(co * co + si * si);
239  p_[2] = -(R * c * s + z0) / e; // rho2
240  p_[3] = atan2(si, co); // theta2
241 
242  // while (p[3] > M_PI/2) { p[3] -= M_PI ; p[2] *= -1 ; }
243  // while (p[3] < -M_PI/2) { p[3] += M_PI ; p[2] *= -1 ; }
244 
245  // std::cout << p.t() << std::endl ;
246 }
247 
258 
271 {
272  double X1, Y1, Z1;
273  double X2, Y2, Z2;
274  double s, a, b, c;
275 
276  double oA, oB, oC, oX0, oY0, oZ0;
277  oA = oP[0];
278  oB = oP[1];
279  oC = oP[2];
280  oX0 = oP[3];
281  oY0 = oP[4];
282  oZ0 = oP[5];
283 
284  X1 = cMo[0][0] * oA + cMo[0][1] * oB + cMo[0][2] * oC;
285  Y1 = cMo[1][0] * oA + cMo[1][1] * oB + cMo[1][2] * oC;
286  Z1 = cMo[2][0] * oA + cMo[2][1] * oB + cMo[2][2] * oC;
287  s = sqrt(X1 * X1 + Y1 * Y1 + Z1 * Z1);
288  a = X1 / s;
289  b = Y1 / s;
290  c = Z1 / s;
291 
292  // set axis coordinates in camera frame
293  cP_[0] = a;
294  cP_[1] = b;
295  cP_[2] = c;
296 
297  X2 = cMo[0][3] + cMo[0][0] * oX0 + cMo[0][1] * oY0 + cMo[0][2] * oZ0;
298  Y2 = cMo[1][3] + cMo[1][0] * oX0 + cMo[1][1] * oY0 + cMo[1][2] * oZ0;
299  Z2 = cMo[2][3] + cMo[2][0] * oX0 + cMo[2][1] * oY0 + cMo[2][2] * oZ0;
300 
301  // adding the constraint X0 is the nearest point to the origin (A^T . X0 =
302  // 0) using the projection operator (I - AA^T) orthogonal to A
303  cP_[3] = (1 - a * a) * X2 - a * b * Y2 - a * c * Z2;
304  cP_[4] = -a * b * X2 + (1 - b * b) * Y2 - b * c * Z2;
305  cP_[5] = -a * c * X2 - b * c * Y2 + (1 - c * c) * Z2;
306 
307  /* old version for the same onstraint
308  if ( fabs(a) > 0.25 )
309  {
310  double xx, yy, zz, xx1, yy1;
311 
312  xx1 = a*Y2 - b*X2;
313  yy1 = a*Z2 - c*X2;
314  xx = -( b*xx1 + c*yy1);
315  yy = (( a*a + c*c ) * xx1 - b*c*yy1 ) /a;
316  zz = ( -b*c*xx1 + ( a*a + b*b )*yy1) /a;
317 
318  // set point coordinates in camera frame
319  _cP[3] = xx ;
320  _cP[4] = yy ;
321  _cP[5] = zz ;
322  }
323  else if ( fabs(b) >0.25 )
324  {
325  double xx, yy, zz, xx1, yy1;
326 
327  xx1 = a*Y2 - b*X2;
328  yy1 = c*Y2 - b*Z2;
329  xx = - (( b*b + c*c ) * xx1 - a*c*yy1 ) /b;
330  yy = a*xx1 + c*yy1;
331  zz = - ( -a*c*xx1 + (a*a + b*b) * yy1 ) /b;
332 
333 
334  // set point coordinates in camera frame
335  _cP[3] = xx ;
336  _cP[4] = yy ;
337  _cP[5] = zz ;
338  }
339  else
340  {
341  double xx, yy, zz, xx1, yy1;
342 
343  xx1 = a*Z2 - c*X2;
344  yy1 = b*Z2 - c*Y2;
345  xx = (-( b*b + c*c ) * xx1 - a*c*yy1 ) /c;
346  yy = ( a*b*xx1 - ( a*a + c*c )*yy1) /c;
347  zz = a*xx1 + b*yy1;
348 
349  // set point coordinates in camera frame
350  _cP[3] = xx ;
351  _cP[4] = yy ;
352  _cP[5] = zz ;
353  }
354  */
355  // radius
356  cP_[6] = oP[6];
357 }
358 
363 double vpCylinder::computeZ(double x, double y) const
364 {
365  double A = x * x + y * y + 1 - ((getA() * x + getB() * y + getC()) * (getA() * x + getB() * y + getC()));
366  double B = (x * getX() + y * getY() + getZ());
367  double C = getX() * getX() + getY() * getY() + getZ() * getZ() - getR() * getR();
368 
369  return (B - std::sqrt(B * B - A * C)) / A;
370 }
371 
374 {
375  vpCylinder *feature = new vpCylinder(*this);
376  return feature;
377 }
378 
383  const vpColor &color, unsigned int thickness)
384 {
385 
386  vpColVector _cP(7), _p(4);
387  changeFrame(cMo, _cP);
388  projection(_cP, _p);
389  vpFeatureDisplay::displayCylinder(_p[0], _p[1], _p[2], _p[3], cam, I, color, thickness);
390 }
391 
396  unsigned int thickness)
397 {
398  vpFeatureDisplay::displayCylinder(p[0], p[1], p[2], p[3], cam, I, color, thickness);
399 }
void init()
Definition: vpCylinder.cpp:42
virtual ~vpCylinder()
Definition: vpCylinder.cpp:143
double getR() const
Definition: vpCylinder.h:174
double getA() const
Definition: vpCylinder.h:150
Implementation of an homogeneous matrix and operations on such kind of matrices.
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)
double getB() const
Definition: vpCylinder.h:154
Class to define colors available for display functionnalities.
Definition: vpColor.h:119
double getC() const
Definition: vpCylinder.h:158
error that can be emited by ViSP classes.
Definition: vpException.h:71
double computeZ(double x, double y) const
Definition: vpCylinder.cpp:363
void display(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpColor &color=vpColor::green, unsigned int thickness=1)
Definition: vpCylinder.cpp:395
void changeFrame(const vpHomogeneousMatrix &cMo, vpColVector &cP)
Definition: vpCylinder.cpp:270
vpColVector cP
Definition: vpTracker.h:75
Generic class defining intrinsic camera parameters.
double getY() const
Definition: vpCylinder.h:166
void projection()
Definition: vpCylinder.cpp:165
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:310
Class that defines what is a cylinder.
Definition: vpCylinder.h:96
double getZ() const
Definition: vpCylinder.h:170
vpCylinder * duplicate() const
for memory issue (used by the vpServo class only)
Definition: vpCylinder.cpp:373
Implementation of column vector and the associated operations.
Definition: vpColVector.h:130
double getX() const
Definition: vpCylinder.h:162
void setWorldCoordinates(const vpColVector &oP)
Definition: vpCylinder.cpp:71
vpColVector p
Definition: vpTracker.h:71