Visual Servoing Platform  version 3.6.1 under development (2024-04-26)
vpPoseLagrange.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 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  * Pose computation.
32  */
33 
34 #include <visp3/vision/vpPose.h>
35 
36 #define DEBUG_LEVEL1 0
37 #define DEBUG_LEVEL2 0
38 
39 /**********************************************************************/
40 /* FONCTION : CalculTranslation */
41 /* ROLE : Calcul de la translation entre la */
42 /* camera et l'outil connaissant la */
43 /* rotation */
44 /**********************************************************************/
45 
46 static void calculTranslation(vpMatrix &a, vpMatrix &b, unsigned int nl, unsigned int nc1, unsigned int nc3,
47  vpColVector &x1, vpColVector &x2)
48 {
49 
50  try {
51  unsigned int i, j;
52 
53  vpMatrix ct(3, nl);
54  for (i = 0; i < 3; ++i) {
55  for (j = 0; j < nl; ++j) {
56  ct[i][j] = b[j][i + nc3];
57  }
58  }
59 
60  vpMatrix c;
61  c = ct.t();
62 
63  vpMatrix ctc;
64  ctc = ct * c;
65 
66  vpMatrix ctc1; // (C^T C)^(-1)
67  ctc1 = ctc.inverseByLU();
68 
69  vpMatrix cta;
70  vpMatrix ctb;
71  cta = ct * a; /* C^T A */
72  ctb = ct * b; /* C^T B */
73 
74 #if (DEBUG_LEVEL2)
75  {
76  std::cout << "ctc " << std::endl << ctc;
77  std::cout << "cta " << std::endl << cta;
78  std::cout << "ctb " << std::endl << ctb;
79  }
80 #endif
81 
82  vpColVector X2(nc3);
83  vpMatrix CTB(nc1, nc3);
84  for (i = 0; i < nc1; ++i) {
85  for (j = 0; j < nc3; ++j) {
86  CTB[i][j] = ctb[i][j];
87  }
88  }
89 
90  for (j = 0; j < nc3; ++j) {
91  X2[j] = x2[j];
92  }
93 
94  vpColVector sv; // C^T A X1 + C^T B X2)
95  sv = (cta * x1) + (CTB * X2); // C^T A X1 + C^T B X2)
96 
97 #if (DEBUG_LEVEL2)
98  std::cout << "sv " << sv.t();
99 #endif
100 
101  vpColVector X3; /* X3 = - (C^T C )^{-1} C^T (A X1 + B X2) */
102  X3 = -ctc1 * sv;
103 
104 #if (DEBUG_LEVEL2)
105  std::cout << "x3 " << X3.t();
106 #endif
107 
108  for (i = 0; i < nc1; ++i) {
109  x2[i + nc3] = X3[i];
110  }
111  }
112  catch (...) {
113 
114  // en fait il y a des dizaines de raisons qui font que cette fonction
115  // rende une erreur (matrice pas inversible, pb de memoire etc...)
116  vpERROR_TRACE(" ");
117  throw;
118  }
119 }
120 
121 //*********************************************************************
122 // FONCTION LAGRANGE :
123 // -------------------
124 // Resolution d'un systeme lineaire de la forme A x1 + B x2 = 0
125 // sous la contrainte || x1 || = 1
126 // ou A est de dimension nl x nc1 et B nl x nc2
127 //*********************************************************************
128 
129 // --comment: define EPS at 1.e-5
130 
131 static void lagrange(vpMatrix &a, vpMatrix &b, vpColVector &x1, vpColVector &x2)
132 {
133 #if (DEBUG_LEVEL1)
134  std::cout << "begin (CLagrange.cc)Lagrange(...) " << std::endl;
135 #endif
136 
137  try {
138  unsigned int i, imin;
139 
140  vpMatrix ata; // A^T A
141  ata = a.t() * a;
142  vpMatrix btb; // B^T B
143  btb = b.t() * b;
144 
145  vpMatrix bta; // B^T A
146  bta = b.t() * a;
147 
148  vpMatrix btb1; // (B^T B)^(-1)
149 
150  /* Warning:
151  when using btb.inverseByLU() that call cv::inv(cv::DECOMP_LU) with
152  OpenCV 3.1.0 and 3.2.0 we notice that OpenCV is not able to compute the
153  inverse of the following matrix:
154 
155  btb[9,9]=
156  0.015925 0.0 0.0030866 0.00035 0.0 0.000041 0.105
157  0.0 0.0346242 0.0 0.015925 -0.0050979 0.0 0.00035
158  -0.000063 0.0 0.105 -0.0637464 0.0030866 -0.0050979 0.0032301
159  0.000041 -0.000063 0.000016 0.0346242 -0.0637464 0.0311185 0.00035
160  0.0 0.000041 0.0001 0.0 0.000012 0.01 0.0
161  0.0011594 0.0 0.00035 -0.000063 0.0 0.0001 -0.000018
162  0.0 0.01 -0.0018040 0.000041 -0.000063 0.000016 0.000012
163  -0.000018 0.000005 0.0011594 -0.0018040 0.0004599 0.105 0.0
164  0.0346242 0.01 0.0 0.0011594 5.0 0.0 0.13287
165  0.0 0.105 -0.0637464 0.0 0.01 -0.0018040 0.0
166  5.0 -0.731499 0.0346242 -0.0637464 0.0311185 0.0011594 -0.0018040
167  0.0004599 0.13287 -0.731499 0.454006
168 
169  That's why instead of using inverseByLU() we are now using pseudoInverse()
170  */
171 #if 0
172  if (b.getRows() >= b.getCols()) {
173  btb1 = btb.inverseByLU();
174  }
175  else {
176  btb1 = btb.pseudoInverse();
177  }
178 #else
179  btb1 = btb.pseudoInverse();
180 #endif
181 
182 #if (DEBUG_LEVEL1)
183  {
184  std::cout << " BTB1 * BTB : " << std::endl << btb1 * btb << std::endl;
185  std::cout << " BTB * BTB1 : " << std::endl << btb * btb1 << std::endl;
186  }
187 #endif
188 
189  vpMatrix r; // (B^T B)^(-1) B^T A
190  r = btb1 * bta;
191 
192  vpMatrix e; // - A^T B (B^T B)^(-1) B^T A
193  e = -(a.t() * b) * r;
194 
195  e += ata; // calcul E = A^T A - A^T B (B^T B)^(-1) B^T A
196 
197 #if (DEBUG_LEVEL1)
198  {
199  std::cout << " E :" << std::endl << e << std::endl;
200  }
201 #endif
202 
203  // --comment: vpColVector sv
204  // --comment: vpMatrix v
205  e.svd(x1, ata); // destructif sur e
206  // calcul du vecteur propre de E correspondant a la valeur propre min.
207  /* calcul de SVmax */
208  imin = 0;
209  // --comment: FC : Pourquoi calculer SVmax ??????
210  // --comment: double svm = 0.0;
211  // --comment: for (i=0;i<x1.getRows(); ++i)
212  // --comment: {
213  // --comment: if (x1[i] > svm) { svm = x1[i]; imin = i; }
214  // --comment: }
215  // --comment: svm *= EPS; /* pour le rang */
216 
217  unsigned int v_x1_rows = x1.getRows();
218  for (i = 0; i < v_x1_rows; ++i) {
219  if (x1[i] < x1[imin]) {
220  imin = i;
221  }
222  }
223 
224 #if (DEBUG_LEVEL1)
225  {
226  printf("SV(E) : %.15lf %.15lf %.15lf\n", x1[0], x1[1], x1[2]);
227  std::cout << " i_min " << imin << std::endl;
228  }
229 #endif
230  unsigned int x1_rows = x1.getRows();
231  for (i = 0; i < x1_rows; ++i) {
232  x1[i] = ata[i][imin];
233  }
234 
235  x2 = -(r * x1); // X_2 = - (B^T B)^(-1) B^T A X_1
236 
237 #if (DEBUG_LEVEL1)
238  {
239  std::cout << " X1 : " << x1.t() << std::endl;
240  std::cout << " V : " << std::endl << ata << std::endl;
241  }
242 #endif
243  }
244  catch (...) {
245  vpERROR_TRACE(" ");
246  throw;
247  }
248 #if (DEBUG_LEVEL1)
249  std::cout << "end (CLagrange.cc)Lagrange(...) " << std::endl;
250 #endif
251 }
252 
253 // --comment: undefine EPS
254 
255 void vpPose::poseLagrangePlan(vpHomogeneousMatrix &cMo, bool *p_isPlan, double *p_a, double *p_b, double *p_c, double *p_d)
256 {
257 #if (DEBUG_LEVEL1)
258  std::cout << "begin vpPose::PoseLagrangePlan(...) " << std::endl;
259 #endif
260  // determination of the plane equation a X + b Y + c Z + d = 0
261  double a, b, c, d;
262 
263  // Checking if coplanar has already been called and if the plan coefficients have been given
264  bool p_isplan_and_p_a_no_null = (p_isPlan != nullptr) && (p_a != nullptr);
265  bool p_b_p_c_p_d_no_null = (p_b != nullptr) && (p_c != nullptr) && (p_d != nullptr);
266  if (p_isplan_and_p_a_no_null && p_b_p_c_p_d_no_null) {
267  if (*p_isPlan) {
268  // All the pointers towards the plan coefficients are different from nullptr => using them in the rest of the method
269  a = *p_a;
270  b = *p_b;
271  c = *p_c;
272  d = *p_d;
273  }
274  else {
275  // The call to coplanar that was performed outside vpPose::poseLagrangePlan indicated that the points are not coplanar.
276  throw vpException(vpException::fatalError, "Called vpPose::poseLagrangePlan but the call to vpPose::coplanar done outside the method indicated that the points are not coplanar");
277  }
278  }
279  else {
280  // At least one of the coefficient is a nullptr pointer => calling coplanar by ourselves
281  int coplanarType;
282  bool areCoplanar = coplanar(coplanarType, &a, &b, &c, &d);
283  if (!areCoplanar) {
284  throw vpException(vpException::fatalError, "Called vpPose::poseLagrangePlan but call to vpPose::coplanar indicates that the points are not coplanar");
285  }
286  }
287 
288  if (c < 0.0) { // imposing c >= 0
289  a = -a;
290  b = -b;
291  c = -c;
292  d = -d;
293  }
294  // to have (a,b,c) as a unit vector if it was not the case
295  double n = 1.0 / sqrt((a * a) + (b * b) + (c * c)); // Not possible to have a NaN...
296  a *= n;
297  b *= n;
298  c *= n;
299  d *= n;
300  // printf("a = %lf, b = %lf, c = %lf, d = %lf\n",a,b,c,d);
301  // transformation to have object plane with equation Z = 0
302  vpColVector r1(3), r2(3), r3(3);
303 
304  r3[0] = a;
305  r3[1] = b;
306  r3[2] = c;
307  // build r1 as a unit vector orthogonal to r3
308  double n1 = sqrt(1.0 - (a * a));
309  double n2 = sqrt(1.0 - (b * b));
310  if (n1 >= n2) {
311  r1[0] = n1;
312  r1[1] = (-a * b) / n1;
313  r1[2] = (-a * c) / n1;
314  }
315  else {
316  r1[0] = (-a * b) / n2;
317  r1[1] = n2;
318  r1[2] = (-b * c) / n2;
319  }
320  // --comment: double norm eq r1[0] mult r1[0] plus r1[1] mult r1[1] plus r1[2] mult r1[2]
321  // --comment: double crossprod eq r1[0] mult r3[0] plus r1[1] mult r3[1] plus r1[2] mult r3[2]
322  // --comment: print "r1 norm = 1 ? %lf, r1^T r3 = 0 ? %lf\n" norm crossprod
323  // --comment: r2 unit vector orthogonal to r3 and r1
324  r2 = vpColVector::crossProd(r3, r1);
325 
327  for (unsigned int i = 0; i < 3; ++i) {
328  fMo[0][i] = r1[i];
329  fMo[1][i] = r2[i];
330  fMo[2][i] = r3[i];
331  }
332  fMo[0][3] = 0.0;
333  fMo[1][3] = 0.0;
334  fMo[2][3] = d;
335 
336  // std::cout << "fMo : " << std::endl << fMo << std::endl;
337  // Build and solve the system
338  unsigned int k = 0;
339  unsigned int nl = npt * 2;
340 
341  vpMatrix A(nl, 3);
342  vpMatrix B(nl, 6);
343  vpPoint P;
344 
345  std::list<vpPoint>::const_iterator listp_end = listP.end();
346  for (std::list<vpPoint>::const_iterator it = listP.begin(); it != listp_end; ++it) {
347  P = *it;
348 
349  // Transform each point in plane Z = 0
350  vpColVector Xf, X(4);
351  X[0] = P.get_oX();
352  X[1] = P.get_oY();
353  X[2] = P.get_oZ();
354  X[3] = 1.0;
355  Xf = fMo * X;
356  // printf("Z = 0 = %lf\n",Xf[2]);
357  // build the system
358  A[k][0] = -Xf[0];
359  A[k][1] = 0.0;
360  A[k][2] = Xf[0] * P.get_x();
361 
362  A[k + 1][0] = 0.0;
363  A[k + 1][1] = -Xf[0];
364  A[k + 1][2] = Xf[0] * P.get_y();
365 
366  B[k][0] = -Xf[1];
367  B[k][1] = 0.0;
368  B[k][2] = Xf[1] * P.get_x();
369  B[k][3] = -1.0;
370  B[k][4] = 0.0;
371  B[k][5] = P.get_x();
372 
373  B[k + 1][0] = 0.0;
374  B[k + 1][1] = -Xf[1];
375  B[k + 1][2] = Xf[1] * P.get_y();
376  B[k + 1][3] = 0.0;
377  B[k + 1][4] = -1.0;
378  B[k + 1][5] = P.get_y();
379 
380  k += 2;
381  }
382  vpColVector X1(3);
383  vpColVector X2(6);
384 
385 #if (DEBUG_LEVEL2)
386  {
387  std::cout << "A " << std::endl << A << std::endl;
388  std::cout << "B " << std::endl << B << std::endl;
389  }
390 #endif
391 
392  lagrange(A, B, X1, X2);
393 
394 #if (DEBUG_LEVEL2)
395  {
396  std::cout << "A X1+B X2 (should be 0): " << (A * X1 + B * X2).t() << std::endl;
397  std::cout << " X1 norm: " << X1.sumSquare() << std::endl;
398  }
399 #endif
400 
401  if (X2[5] < 0.0) { /* to obtain Zo > 0 */
402  for (unsigned int i = 0; i < 3; ++i) {
403  X1[i] = -X1[i];
404  }
405  for (unsigned int i = 0; i < 6; ++i) {
406  X2[i] = -X2[i];
407  }
408  }
409  double s = 0.0;
410  for (unsigned int i = 0; i < 3; ++i) {
411  s += (X1[i] * X2[i]);
412  }
413  for (unsigned int i = 0; i < 3; ++i) {
414  X2[i] -= (s * X1[i]);
415  } /* X1^T X2 = 0 */
416 
417  // --comment: s equals 0.0
418  s = (X2[0] * X2[0]) + (X2[1] * X2[1]) + (X2[2] * X2[2]); // To avoid a Coverity copy/past error
419 
420  if (s < 1e-10) {
421  // std::cout << "Points that produce an error: " << std::endl;
422  // for (std::list<vpPoint>::const_iterator it = listP.begin(); it
423  // != listP.end(); ++it)
424  // {
425  // std::cout << "P: " << (*it).get_x() << " " << (*it).get_y() <<
426  // " "
427  // << (*it).get_oX() << " " << (*it).get_oY() << " " <<
428  // (*it).get_oZ() << std::endl;
429  // }
430  throw(vpException(vpException::divideByZeroError, "Division by zero in Lagrange pose computation "
431  "(planar plane case)"));
432  }
433 
434  s = 1.0 / sqrt(s);
435  for (unsigned int i = 0; i < 3; ++i) {
436  X2[i] *= s;
437  } /* X2^T X2 = 1 */
438 
439  calculTranslation(A, B, nl, 3, 3, X1, X2);
440 
441  // --comment: if err diff OK
442  // --comment: cout "in (vpCalculPose_plan.cc)CalculTranslation returns "
443  // --comment: PrintError err
444  // --comment: return err
445 
447  /* X1 x X2 */
448  cMf[0][2] = (X1[1] * X2[2]) - (X1[2] * X2[1]);
449  cMf[1][2] = (X1[2] * X2[0]) - (X1[0] * X2[2]);
450  cMf[2][2] = (X1[0] * X2[1]) - (X1[1] * X2[0]);
451  /* calcul de la matrice de passage */
452  for (unsigned int i = 0; i < 3; ++i) {
453  cMf[i][0] = X1[i];
454  cMf[i][1] = X2[i];
455  cMf[i][3] = X2[i + 3];
456  }
457 
458  // Apply the transform to go back to object frame
459  cMo = cMf * fMo;
460 
461 #if (DEBUG_LEVEL1)
462  std::cout << "end vpCalculPose::PoseLagrangePlan(...) " << std::endl;
463 #endif
464  // --comment: return OK
465 }
466 
468 {
469 
470 #if (DEBUG_LEVEL1)
471  std::cout << "begin CPose::PoseLagrangeNonPlan(...) " << std::endl;
472 #endif
473  try {
474  double s;
475  unsigned int i;
476 
477  unsigned int k = 0;
478  unsigned int nl = npt * 2;
479 
480  if (npt < 6) {
482  "Lagrange, non planar case, insufficient number of points %d < 6\n", npt));
483  }
484 
485  vpMatrix a(nl, 3);
486  vpMatrix b(nl, 9);
487  b = 0;
488 
489  vpPoint P;
490  i = 0;
491  std::list<vpPoint>::const_iterator listp_end = listP.end();
492  for (std::list<vpPoint>::const_iterator it = listP.begin(); it != listp_end; ++it) {
493  P = *it;
494  a[k][0] = -P.get_oX();
495  a[k][1] = 0.0;
496  a[k][2] = P.get_oX() * P.get_x();
497 
498  a[k + 1][0] = 0.0;
499  a[k + 1][1] = -P.get_oX();
500  a[k + 1][2] = P.get_oX() * P.get_y();
501 
502  b[k][0] = -P.get_oY();
503  b[k][1] = 0.0;
504  b[k][2] = P.get_oY() * P.get_x();
505 
506  b[k][3] = -P.get_oZ();
507  b[k][4] = 0.0;
508  b[k][5] = P.get_oZ() * P.get_x();
509 
510  b[k][6] = -1.0;
511  b[k][7] = 0.0;
512  b[k][8] = P.get_x();
513 
514  b[k + 1][0] = 0.0;
515  b[k + 1][1] = -P.get_oY();
516  b[k + 1][2] = P.get_oY() * P.get_y();
517 
518  b[k + 1][3] = 0.0;
519  b[k + 1][4] = -P.get_oZ();
520  b[k + 1][5] = P.get_oZ() * P.get_y();
521 
522  b[k + 1][6] = 0.0;
523  b[k + 1][7] = -1.0;
524  b[k + 1][8] = P.get_y();
525 
526  k += 2;
527  }
528  vpColVector X1(3);
529  vpColVector X2(9);
530 
531 #if (DEBUG_LEVEL2)
532  {
533  std::cout << "a " << a << std::endl;
534  std::cout << "b " << b << std::endl;
535  }
536 #endif
537 
538  lagrange(a, b, X1, X2);
539  // if err not eq OK
540  // cout "in (CLagrange.cc)Lagrange returns "
541  // PrintError err
542  // return err
543 
544 #if (DEBUG_LEVEL2)
545  {
546  std::cout << "ax1+bx2 (devrait etre 0) " << (a * X1 + b * X2).t() << std::endl;
547  std::cout << "norme X1 " << X1.sumSquare() << std::endl;
548  }
549 #endif
550 
551  if (X2[8] < 0.0) { /* car Zo > 0 */
552  X1 *= -1;
553  X2 *= -1;
554  }
555  s = 0.0;
556  for (i = 0; i < 3; ++i) {
557  s += (X1[i] * X2[i]);
558  }
559  for (i = 0; i < 3; ++i) {
560  X2[i] -= (s * X1[i]);
561  } /* X1^T X2 = 0 */
562 
563  s = (X2[0] * X2[0]) + (X2[1] * X2[1]) + (X2[2] * X2[2]); // To avoid a Coverity copy/past error
564 
565  if (s < 1e-10) {
566  // std::cout << "Points that produce an error: " << std::endl;
567  // for (std::list<vpPoint>::const_iterator it = listP.begin(); it
568  // != listP.end(); ++it)
569  // {
570  // std::cout << "P: " << (*it).get_x() << " " << (*it).get_y() <<
571  // " "
572  // << (*it).get_oX() << " " << (*it).get_oY() << " " <<
573  // (*it).get_oZ() << std::endl;
574  // }
575  // vpERROR_TRACE(" division par zero " ) ;
576  throw(vpException(vpException::divideByZeroError, "Division by zero in Lagrange pose computation (non "
577  "planar plane case)"));
578  }
579 
580  s = 1.0 / sqrt(s);
581  for (i = 0; i < 3; ++i) {
582  X2[i] *= s;
583  } /* X2^T X2 = 1 */
584 
585  X2[3] = (X1[1] * X2[2]) - (X1[2] * X2[1]);
586  X2[4] = (X1[2] * X2[0]) - (X1[0] * X2[2]);
587  X2[5] = (X1[0] * X2[1]) - (X1[1] * X2[0]);
588 
589  calculTranslation(a, b, nl, 3, 6, X1, X2);
590 
591  for (i = 0; i < 3; ++i) {
592  cMo[i][0] = X1[i];
593  cMo[i][1] = X2[i];
594  cMo[i][2] = X2[i + 3];
595  cMo[i][3] = X2[i + 6];
596  }
597 
598  }
599  catch (...) {
600  throw; // throw the original exception
601  }
602 
603 #if (DEBUG_LEVEL1)
604  std::cout << "end vpCalculPose::PoseLagrangeNonPlan(...) " << std::endl;
605 #endif
606 }
607 
608 #undef DEBUG_LEVEL1
609 #undef DEBUG_LEVEL2
unsigned int getCols() const
Definition: vpArray2D.h:327
unsigned int getRows() const
Definition: vpArray2D.h:337
Implementation of column vector and the associated operations.
Definition: vpColVector.h:163
double sumSquare() const
vpRowVector t() const
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ dimensionError
Bad dimension.
Definition: vpException.h:83
@ fatalError
Fatal error.
Definition: vpException.h:84
@ divideByZeroError
Division by zero.
Definition: vpException.h:82
Implementation of an homogeneous matrix and operations on such kind of matrices.
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:146
vpMatrix inverseByLU() const
void svd(vpColVector &w, vpMatrix &V)
Definition: vpMatrix.cpp:2132
vpMatrix t() const
Definition: vpMatrix.cpp:465
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition: vpMatrix.cpp:2343
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:77
double get_oX() const
Get the point oX coordinate in the object frame.
Definition: vpPoint.cpp:454
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:465
double get_oZ() const
Get the point oZ coordinate in the object frame.
Definition: vpPoint.cpp:458
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:463
double get_oY() const
Get the point oY coordinate in the object frame.
Definition: vpPoint.cpp:456
unsigned int npt
Number of point used in pose computation.
Definition: vpPose.h:114
void poseLagrangePlan(vpHomogeneousMatrix &cMo, bool *p_isPlan=nullptr, double *p_a=nullptr, double *p_b=nullptr, double *p_c=nullptr, double *p_d=nullptr)
std::list< vpPoint > listP
Array of point (use here class vpPoint)
Definition: vpPose.h:115
void poseLagrangeNonPlan(vpHomogeneousMatrix &cMo)
bool coplanar(int &coplanar_plane_type, double *p_a=nullptr, double *p_b=nullptr, double *p_c=nullptr, double *p_d=nullptr)
Definition: vpPose.cpp:117
#define vpERROR_TRACE
Definition: vpDebug.h:382