ViSP  2.6.2
vpPoseLagrange.cpp
1 /****************************************************************************
2 *
3 * $Id: vpPoseLagrange.cpp 3530 2012-01-03 10:52:12Z fspindle $
4 *
5 * This file is part of the ViSP software.
6 * Copyright (C) 2005 - 2012 by INRIA. All rights reserved.
7 *
8 * This software is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * ("GPL") version 2 as published by the Free Software Foundation.
11 * See the file LICENSE.txt at the root directory of this source
12 * distribution for additional information about the GNU GPL.
13 *
14 * For using ViSP with software that can not be combined with the GNU
15 * GPL, please contact INRIA about acquiring a ViSP Professional
16 * Edition License.
17 *
18 * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19 *
20 * This software was developed at:
21 * INRIA Rennes - Bretagne Atlantique
22 * Campus Universitaire de Beaulieu
23 * 35042 Rennes Cedex
24 * France
25 * http://www.irisa.fr/lagadic
26 *
27 * If you have questions regarding the use of this file, please contact
28 * INRIA at visp@inria.fr
29 *
30 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32 *
33 *
34 * Description:
35 * Pose computation.
36 *
37 * Authors:
38 * Eric Marchand
39 * Francois Chaumette
40 *
41 *****************************************************************************/
42 
43 
44 #include <visp/vpPose.h>
45 
46 #define DEBUG_LEVEL1 0
47 #define DEBUG_LEVEL2 0
48 
49 /**********************************************************************/
50 /* FONCTION : CalculTranslation */
51 /* ROLE : Calcul de la translation entre la */
52 /* camera et l'outil connaissant la */
53 /* rotation */
54 /**********************************************************************/
55 
56 static
57 void
58 calculTranslation (vpMatrix &a, vpMatrix &b, unsigned int nl, unsigned int nc1,
59  unsigned int nc3, vpColVector &x1, vpColVector &x2)
60 {
61 
62  try
63  {
64  unsigned int i,j;
65 
66  vpMatrix ct(3,nl) ;
67  for (i=0 ; i < 3 ; i++)
68  {
69  for (j=0 ; j < nl ; j++)
70  ct[i][j] = b[j][i+nc3] ;
71  }
72 
73  vpMatrix c ;
74  c = ct.t() ;
75 
76  vpMatrix ctc ;
77  ctc = ct*c ;
78 
79  vpMatrix ctc1 ; // (C^T C)^(-1)
80  ctc1 = ctc.inverseByLU() ;
81 
82  vpMatrix cta ;
83  vpMatrix ctb ;
84  cta = ct*a ; /* C^T A */
85  ctb = ct*b ; /* C^T B */
86 
87 #if (DEBUG_LEVEL2)
88  {
89  std::cout <<"ctc " << std::endl << ctc ;
90  std::cout <<"cta " << std::endl << cta ;
91  std::cout <<"ctb " << std::endl << ctb ;
92  }
93 #endif
94 
95  vpColVector X2(nc3) ;
96  vpMatrix CTB(nc1,nc3) ;
97  for (i=0 ; i < nc1 ; i++)
98  {
99  for (j=0 ; j < nc3 ; j++)
100  CTB[i][j] = ctb[i][j] ;
101  }
102 
103  for (j=0 ; j < nc3 ; j++)
104  X2[j] = x2[j] ;
105 
106  vpColVector sv ; // C^T A X1 + C^T B X2)
107  sv = cta*x1 + CTB*X2 ;// C^T A X1 + C^T B X2)
108 
109 #if (DEBUG_LEVEL2)
110  std::cout << "sv " << sv.t() ;
111 #endif
112 
113  vpColVector X3 ; /* X3 = - (C^T C )^{-1} C^T (A X1 + B X2) */
114  X3 = -ctc1*sv ;
115 
116 #if (DEBUG_LEVEL2)
117  std::cout << "x3 " << X3.t() ;
118 #endif
119 
120  for (i=0 ; i < nc1 ; i++)
121  x2[i+nc3] = X3[i] ;
122  }
123  catch(...)
124  {
125 
126  // en fait il y a des dizaines de raisons qui font que cette fonction
127  // rende une erreur (matrice pas inversible, pb de memoire etc...)
128  vpERROR_TRACE(" ") ;
129  throw ;
130  }
131 
132 
133 }
134 
135 
136 //*********************************************************************
137 // FONCTION LAGRANGE :
138 // -------------------
139 // Resolution d'un systeme lineaire de la forme A x1 + B x2 = 0
140 // sous la contrainte || x1 || = 1
141 // ou A est de dimension nl x nc1 et B nl x nc2
142 //*********************************************************************
143 
144 //#define EPS 1.e-5
145 
146 static
147 void
148 lagrange (vpMatrix &a, vpMatrix &b, vpColVector &x1, vpColVector &x2)
149 {
150 #if (DEBUG_LEVEL1)
151  std::cout << "begin (CLagrange.cc)Lagrange(...) " << std::endl;
152 #endif
153 
154  try{
155  unsigned int i,imin;
156 
157  vpMatrix ata ; // A^T A
158  ata = a.t()*a ;
159  vpMatrix btb ; // B^T B
160  btb = b.t()*b ;
161 
162  vpMatrix bta ; // B^T A
163  bta = b.t()*a ;
164 
165  vpMatrix btb1 ; // (B^T B)^(-1)
166 
167  if (b.getRows() >= b.getCols()) btb1 = btb.inverseByLU() ;
168  else btb1 = btb.pseudoInverse();
169 
170 #if (DEBUG_LEVEL1)
171  {
172  std::cout << " BTB1 * BTB : " << std::endl << btb1*btb << std::endl;
173  std::cout << " BTB * BTB1 : " << std::endl << btb*btb1 << std::endl;
174  }
175 #endif
176 
177  vpMatrix r ; // (B^T B)^(-1) B^T A
178  r = btb1*bta ;
179 
180  vpMatrix e ; // - A^T B (B^T B)^(-1) B^T A
181  e = - (a.t()*b) *r ;
182 
183  e += ata ; // calcul E = A^T A - A^T B (B^T B)^(-1) B^T A
184 
185 #if (DEBUG_LEVEL1)
186  {
187  std::cout << " E :" << std::endl << e << std::endl;
188  }
189 #endif
190 
191  // vpColVector sv ;
192  // vpMatrix v ;
193  e.svd(x1,ata) ;// destructif sur e
194  // calcul du vecteur propre de E correspondant a la valeur propre min.
195 
196  /* calcul de SVmax */
197  imin = 0;
198  // FC : Pourquoi calculer SVmax ??????
199  // double svm = 0.0;
200  // for (i=0;i<x1.getRows();i++)
201  // {
202  // if (x1[i] > svm) { svm = x1[i]; imin = i; }
203  // }
204  // svm *= EPS; /* pour le rang */
205 
206  for (i=0;i<x1.getRows();i++)
207  if (x1[i] < x1[imin]) imin = i;
208 
209 #if (DEBUG_LEVEL1)
210  {
211  printf("SV(E) : %.15lf %.15lf %.15lf\n",x1[0],x1[1],x1[2]);
212  std::cout << " i_min " << imin << std::endl;
213  }
214 #endif
215  for (i=0;i<x1.getRows();i++)
216  x1[i] = ata[i][imin];
217 
218  x2 = - (r*x1) ; // X_2 = - (B^T B)^(-1) B^T A X_1
219 
220 #if (DEBUG_LEVEL1)
221  {
222  std::cout << " X1 : " << x1.t() << std::endl;
223  std::cout << " V : " << std::endl << ata << std::endl;
224  }
225 #endif
226  }
227  catch(...)
228  {
229  vpERROR_TRACE(" ") ;
230  throw ;
231  }
232 #if (DEBUG_LEVEL1)
233  std::cout << "end (CLagrange.cc)Lagrange(...) " << std::endl;
234 #endif
235 }
236 
237 //#undef EPS
238 
242 void
244 {
245 
246 #if (DEBUG_LEVEL1)
247  std::cout << "begin vpPose::PoseLagrange(...) " << std::endl ;
248 #endif
249  try
250  {
251  double s;
252  unsigned int i;
253 
254  unsigned int k=0;
255  unsigned int nl=npt*2;
256 
257 
258  vpMatrix a(nl,3) ;
259  vpMatrix b(nl,6);
260  vpPoint P ;
261  i=0 ;
262  for (std::list<vpPoint>::const_iterator it = listP.begin(); it != listP.end(); ++it)
263  {
264  P = *it ;
265  a[k][0] = -P.get_oX();
266  a[k][1] = 0.0;
267  a[k][2] = P.get_oX()*P.get_x();
268 
269  a[k+1][0] = 0.0;
270  a[k+1][1] = -P.get_oX();
271  a[k+1][2] = P.get_oX()*P.get_y();
272 
273  b[k][0] = -P.get_oY();
274  b[k][1] = 0.0;
275  b[k][2] = P.get_oY()*P.get_x();
276  b[k][3] = -1.0;
277  b[k][4] = 0.0;
278  b[k][5] = P.get_x();
279 
280  b[k+1][0] = 0.0;
281  b[k+1][1] = -P.get_oY();
282  b[k+1][2] = P.get_oY()*P.get_y();
283  b[k+1][3] = 0.0;
284  b[k+1][4] = -1.0;
285  b[k+1][5] = P.get_y();
286 
287  k += 2;
288  }
289  vpColVector X1(3) ;
290  vpColVector X2(6) ;
291 
292 #if (DEBUG_LEVEL2)
293  {
294  std::cout <<"a " << a << std::endl ;
295  std::cout <<"b " << b << std::endl ;
296  }
297 #endif
298 
299  lagrange(a,b,X1,X2);
300 
301 #if (DEBUG_LEVEL2)
302  {
303  std::cout << "ax1+bx2 (devrait etre 0) " << (a*X1 + b*X2).t() << std::endl ;
304  std::cout << "norme X1 " << X1.sumSquare() << std::endl ;;
305  }
306 #endif
307 
308  if (X2[5] < 0.0)
309  { /* car Zo > 0 */
310  for (i=0;i<3;i++) X1[i] = -X1[i];
311  for (i=0;i<6;i++) X2[i] = -X2[i];
312  }
313  s = 0.0;
314  for (i=0;i<3;i++) {s += (X1[i]*X2[i]);}
315  for (i=0;i<3;i++) {X2[i] -= (s*X1[i]);} /* X1^T X2 = 0 */
316 
317  s = 0.0;
318  for (i=0;i<3;i++) {s += (X2[i]*X2[i]);}
319 
320  if (s<1e-10)
321  {
322  vpERROR_TRACE( "in vpCalculPose::PosePlan(...) division par zero ") ;
324  "division by zero ")) ;
325  }
326 
327  s = 1.0/sqrt(s);
328  for (i=0;i<3;i++) {X2[i] *= s;} /* X2^T X2 = 1 */
329 
330 
331  calculTranslation (a, b, nl, 3, 3, X1, X2) ;
332 
333  // if (err != OK)
334  {
335  // std::cout << "in (vpCalculPose_plan.cc)CalculTranslation returns " ;
336  // PrintError(err) ;
337  // return err ;
338  }
339 
340  cMo[0][2] = (X1[1]*X2[2])-(X1[2]*X2[1]);
341  cMo[1][2] = (X1[2]*X2[0])-(X1[0]*X2[2]);
342  cMo[2][2] = (X1[0]*X2[1])-(X1[1]*X2[0]);
343 
344  for (i=0;i<3;i++)
345  { /* calcul de la matrice de passage */
346  cMo[i][0] = X1[i];
347  cMo[i][1] = X2[i];
348  cMo[i][3] = X2[i+3];
349  }
350  }
351  catch(...)
352  {
353  vpERROR_TRACE(" ") ;
354  throw ;
355  }
356 
357 
358 #if (DEBUG_LEVEL1)
359  std::cout << "end vpCalculPose::PoseLagrange(...) " << std::endl ;
360 #endif
361  // return(OK);
362 }
363 
364 
365 void
367 {
368 
369 #if (DEBUG_LEVEL1)
370  std::cout << "begin CPose::PoseLagrange(...) " << std::endl ;
371 #endif
372  try{
373  double s;
374  unsigned int i;
375 
376  unsigned int k=0;
377  unsigned int nl=npt*2;
378 
379  vpMatrix a(nl,3) ;
380  vpMatrix b(nl,9);
381  b =0 ;
382 
383  vpPoint P ;
384  i=0 ;
385  for (std::list<vpPoint>::const_iterator it = listP.begin(); it != listP.end(); ++it)
386  {
387  P = *it;
388  a[k][0] = -P.get_oX();
389  a[k][1] = 0.0;
390  a[k][2] = P.get_oX()*P.get_x();
391 
392  a[k+1][0] = 0.0;
393  a[k+1][1] = -P.get_oX();
394  a[k+1][2] = P.get_oX()*P.get_y();
395 
396  b[k][0] = -P.get_oY();
397  b[k][1] = 0.0;
398  b[k][2] = P.get_oY()*P.get_x();
399 
400  b[k][3] = -P.get_oZ();
401  b[k][4] = 0.0;
402  b[k][5] = P.get_oZ()*P.get_x();
403 
404  b[k][6] = -1.0;
405  b[k][7] = 0.0;
406  b[k][8] = P.get_x();
407 
408  b[k+1][0] = 0.0;
409  b[k+1][1] = -P.get_oY();
410  b[k+1][2] = P.get_oY()*P.get_y();
411 
412  b[k+1][3] = 0.0;
413  b[k+1][4] = -P.get_oZ();
414  b[k+1][5] = P.get_oZ()*P.get_y();
415 
416  b[k+1][6] = 0.0;
417  b[k+1][7] = -1.0;
418  b[k+1][8] = P.get_y();
419 
420  k += 2;
421  }
422  vpColVector X1(3) ;
423  vpColVector X2(9) ;
424 
425 #if (DEBUG_LEVEL2)
426  {
427  std::cout <<"a " << a << std::endl ;
428  std::cout <<"b " << b << std::endl ;
429  }
430 #endif
431 
432  lagrange(a,b,X1,X2);
433  // if (err != OK)
434  {
435  // std::cout << "in (CLagrange.cc)Lagrange returns " ;
436  // PrintError(err) ;
437  // return err ;
438  }
439 
440 
441 #if (DEBUG_LEVEL2)
442  {
443  std::cout << "ax1+bx2 (devrait etre 0) " << (a*X1 + b*X2).t() << std::endl ;
444  std::cout << "norme X1 " << X1.sumSquare() << std::endl ;;
445  }
446 #endif
447 
448  if (X2[8] < 0.0)
449  { /* car Zo > 0 */
450  X1 *= -1 ;
451  X2 *= -1 ;
452  }
453  s = 0.0;
454  for (i=0;i<3;i++) {s += (X1[i]*X2[i]);}
455  for (i=0;i<3;i++) {X2[i] -= (s*X1[i]);} /* X1^T X2 = 0 */
456 
457  s = 0.0;
458  for (i=0;i<3;i++) {s += (X2[i]*X2[i]);}
459 
460  if (s<1e-10)
461  {
462  vpERROR_TRACE(" division par zero " ) ;
464  "division by zero ")) ;
465 
466  }
467 
468  s = 1.0/sqrt(s);
469  for (i=0;i<3;i++) {X2[i] *= s;} /* X2^T X2 = 1 */
470 
471  X2[3] = (X1[1]*X2[2])-(X1[2]*X2[1]);
472  X2[4] = (X1[2]*X2[0])-(X1[0]*X2[2]);
473  X2[5] = (X1[0]*X2[1])-(X1[1]*X2[0]);
474 
475  calculTranslation (a, b, nl, 3, 6, X1, X2) ;
476 
477 
478  for (i=0 ; i<3 ; i++)
479  {
480  cMo[i][0] = X1[i];
481  cMo[i][1] = X2[i];
482  cMo[i][2] = X2[i+3];
483  cMo[i][3] = X2[i+6];
484  }
485 
486  }
487  catch(...)
488  {
489  vpERROR_TRACE(" ") ;
490  throw ;
491  }
492 
493 #if (DEBUG_LEVEL1)
494  std::cout << "end vpCalculPose::PoseLagrange(...) " << std::endl ;
495 #endif
496 }
497 
498 
499 #undef DEBUG_LEVEL1
500 #undef DEBUG_LEVEL2
501 
502 
503 
504 /*
505 * Local variables:
506 * c-basic-offset: 2
507 * End:
508 */
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
#define vpERROR_TRACE
Definition: vpDebug.h:379
void poseLagrangeNonPlan(vpHomogeneousMatrix &cMo)
compute the pose using Lagrange approach (non planar object)
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.h:136
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.h:145
double sumSquare() const
return sum of the Aij^2 (for all i, for all j)
Definition: vpMatrix.cpp:758
std::list< vpPoint > listP
array of point (use here class vpPoint)
Definition: vpPose.h:97
Class that defines what is a point.
Definition: vpPoint.h:65
void svd(vpColVector &w, vpMatrix &v)
Definition: vpMatrix.cpp:1700
vpRowVector t() const
transpose of Vector
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.h:138
void poseLagrangePlan(vpHomogeneousMatrix &cMo)
compute the pose using Lagrange approach (planar object)
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.h:143
unsigned int npt
number of point used in pose computation
Definition: vpPose.h:96
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:134
vpMatrix t() const
Definition: vpMatrix.cpp:1174
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
vpMatrix inverseByLU() const
unsigned int getCols() const
Return the number of columns of the matrix.
Definition: vpMatrix.h:159
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1810
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:157