ViSP  2.9.0
vpPoseLowe.cpp
1 /****************************************************************************
2 *
3 * $Id: vpPoseLowe.cpp 4649 2014-02-07 14:57:11Z fspindle $
4 *
5 * This file is part of the ViSP software.
6 * Copyright (C) 2005 - 2014 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 
45 
46 
47 // besoin de la librairie mathematique, en particulier des
48 // fonctions de minimisation de Levenberg Marquartd
49 #include <visp/vpLevenbergMarquartd.h>
50 
51 #include <visp/vpPose.h>
52 #include <math.h>
53 #include <float.h>
54 #include <string.h>
55 #define NBR_PAR 6
56 #define X3_SIZE 3
57 #define MINIMUM 0.000001
58 
59 #define DEBUG_LEVEL1 0
60 
61 // ------------------------------------------------------------------------
62 // FONCTION LOWE :
63 // ------------------------------------------------------------------------
64 // Calcul de la pose pour un objet 3D
65 // ------------------------------------------------------------------------
66 
67 /*
68 * MACRO : MIJ
69 *
70 * ENTREE :
71 * m Matrice.
72 * i Indice ligne de l'element.
73 * j Indice colonne de l'element.
74 * s Taille en nombre d'elements d'une ligne de la matrice "m".
75 *
76 * DESCRIPTION :
77 * La macro-instruction calcule l'adresse de l'element de la "i"eme ligne et
78 * de la "j"eme colonne de la matrice "m", soit &m[i][j].
79 *
80 * RETOUR :
81 * L'adresse de m[i][j] est retournee.
82 *
83 * HISTORIQUE :
84 * 1.00 - 11/02/93 - Original.
85 */
86 #define MIJ(m,i,j,s) ((m) + ((long) (i) * (long) (s)) + (long) (j))
87 #define NBPTMAX 50
88 
89 // Je hurle d'horreur devant ces variable globale...
90 static double XI[NBPTMAX],YI[NBPTMAX];
91 static double XO[NBPTMAX],YO[NBPTMAX],ZO[NBPTMAX];
92 
93 
94 #define MINI 0.001
95 #define MINIMUM 0.000001
96 
97 void eval_function(int npt,double *xc,double *f);
98 void fcn (int m, int n, double *xc, double *fvecc, double *jac, int ldfjac, int iflag);
99 
100 void eval_function(int npt,double *xc,double *f)
101 {
102  int i;
103  double x,y,z,u[3];
104 
105  u[0] = xc[3]; /* Rx */
106  u[1] = xc[4]; /* Ry */
107  u[2] = xc[5]; /* Rz */
108 
109  vpRotationMatrix rd(u[0],u[1],u[2]) ;
110  // rot_mat(u,rd); /* matrice de rotation correspondante */
111  for (i=0;i<npt;i++)
112  {
113  x = rd[0][0]*XO[i] + rd[0][1]*YO[i] + rd[0][2]*ZO[i] + xc[0];
114  y = rd[1][0]*XO[i] + rd[1][1]*YO[i] + rd[1][2]*ZO[i] + xc[1];
115  z = rd[2][0]*XO[i] + rd[2][1]*YO[i] + rd[2][2]*ZO[i] + xc[2];
116  f[i] = x/z - XI[i];
117  f[npt+i] = y/z - YI[i];
118  // std::cout << f[i] << " " << f[i+1] << std::endl ;
119  }
120 }
121 
122 
123 /*
124 * PROCEDURE : fcn
125 *
126 * ENTREES :
127 * m Nombre d'equations.
128 * n Nombre de variables.
129 * xc Valeur courante des parametres.
130 * fvecc Resultat de l'evaluation de la fonction.
131 * ldfjac Plus grande dimension de la matrice jac.
132 * iflag Choix du calcul de la fonction ou du jacobien.
133 *
134 * SORTIE :
135 * jac Jacobien de la fonction.
136 *
137 * DESCRIPTION :
138 * La procedure calcule la fonction et le jacobien.
139 * Si iflag == 1, la procedure calcule la fonction en "xc" et le resultat est
140 * stocke dans "fvecc" et "fjac" reste inchange.
141 * Si iflag == 2, la procedure calcule le jacobien en "xc" et le resultat est
142 * stocke dans "fjac" et "fvecc" reste inchange.
143 *
144 * HISTORIQUE :
145 * 1.00 - xx/xx/xx - Original.
146 * 1.01 - 06/07/95 - Modifications.
147 * 2.00 - 24/10/95 - Tableau jac monodimensionnel.
148 */
149 void fcn (int m, int n, double *xc, double *fvecc, double *jac, int ldfjac, int iflag)
150 {
151  double u[X3_SIZE], rx, ry, rz;// rd[X3_SIZE][X3_SIZE],
152  double tt, mco, co, si, u1, u2, u3, x, y, z;
153  double drxt, drxu1, drxu2, drxu3;
154  double dryt, dryu1, dryu2, dryu3;
155  double drzt, drzu1, drzu2, drzu3;
156  double dxit, dxiu1, dxiu2, dxiu3;
157  double dyit, dyiu1, dyiu2, dyiu3;
158 
159  vpRotationMatrix rd ;
160  int i, npt;
161 
162  if (m < n) printf("pas assez de points\n");
163  npt = m / 2;
164 
165  if (iflag == 1) eval_function (npt, xc, fvecc);
166  else if (iflag == 2)
167  {
168  u[0] =xc[3];
169  u[1]= xc[4];
170  u[2]= xc[5];
171 
172  rd.buildFrom(u[0],u[1],u[2]) ;
173  /* a partir de l'axe de rotation, calcul de la matrice de rotation. */
174  // rot_mat(u, rd);
175 
176  tt = sqrt (u[0] * u[0] + u[1] * u[1] + u[2] * u[2]); /* angle de rot */
177  if (tt >= MINIMUM)
178  {
179  u1 = u[0] / tt;
180  u2 = u[1] / tt; /* axe de rotation unitaire */
181  u3 = u[2] / tt;
182  }
183  else u1 = u2 = u3 = 0.0;
184  co = cos(tt);
185  mco = 1.0 - co;
186  si = sin(tt);
187 
188  for (i = 0; i < npt; i++)
189  {
190  x = XO[i];
191  y = YO[i]; /* coordonnees du point i */
192  z = ZO[i];
193 
194  /* coordonnees du point i dans le repere camera */
195  rx = rd[0][0] * x + rd[0][1] * y + rd[0][2] * z + xc[0];
196  ry = rd[1][0] * x + rd[1][1] * y + rd[1][2] * z + xc[1];
197  rz = rd[2][0] * x + rd[2][1] * y + rd[2][2] * z + xc[2];
198 
199  /* derive des fonctions rx, ry et rz par rapport
200  * a tt, u1, u2, u3.
201  */
202  drxt = (si * u1 * u3 + co * u2) * z + (si * u1 * u2 - co * u3) * y
203  + (si * u1 * u1 - si) * x;
204  drxu1 = mco * u3 * z + mco * u2 * y + 2 * mco * u1 * x;
205  drxu2 = si * z + mco * u1 * y;
206  drxu3 = mco * u1 * z - si * y;
207 
208  dryt = (si * u2 * u3 - co * u1) * z + (si * u2 * u2 - si) * y
209  + (co * u3 + si * u1 * u2) * x;
210  dryu1 = mco * u2 * x - si * z;
211  dryu2 = mco * u3 * z + 2 * mco * u2 * y + mco * u1 * x;
212  dryu3 = mco * u2 * z + si * x;
213 
214  drzt = (si * u3 * u3 - si) * z + (si * u2 * u3 + co * u1) * y
215  + (si * u1 * u3 - co * u2) * x;
216  drzu1 = si * y + mco * u3 * x;
217  drzu2 = mco * u3 * y - si * x;
218  drzu3 = 2 * mco * u3 * z + mco * u2 * y + mco * u1 * x;
219 
220  /* derive de la fonction representant le modele de la
221  * camera (sans distortion) par rapport a tt, u1, u2 et u3.
222  */
223  dxit = drxt / rz - rx * drzt / (rz * rz);
224 
225  dyit = dryt / rz - ry * drzt / (rz * rz);
226 
227  dxiu1 = drxu1 / rz - drzu1 * rx / (rz * rz);
228  dyiu1 = dryu1 / rz - drzu1 * ry / (rz * rz);
229 
230  dxiu2 = drxu2 / rz - drzu2 * rx / (rz * rz);
231  dyiu2 = dryu2 / rz - drzu2 * ry / (rz * rz);
232 
233  dxiu3 = drxu3 / rz - drzu3 * rx / (rz * rz);
234  dyiu3 = dryu3 / rz - drzu3 * ry / (rz * rz);
235 
236  /* calcul du jacobien : le jacobien represente la
237  * derivee de la fonction representant le modele de la
238  * camera par rapport aux parametres.
239  */
240  *MIJ(jac, 0, i, ldfjac) = 1 / rz;
241  *MIJ(jac, 1, i, ldfjac) = 0.0;
242  *MIJ(jac, 2, i, ldfjac) = - rx / (rz * rz);
243  if (tt >= MINIMUM)
244  {
245  *MIJ(jac, 3, i, ldfjac) = u1 * dxit + (1 - u1 * u1) * dxiu1 / tt
246  - u1 * u2 * dxiu2 / tt - u1 * u3 * dxiu3 / tt;
247  *MIJ(jac, 4, i, ldfjac) = u2 * dxit - u1 * u2 * dxiu1 / tt
248  + (1 - u2 * u2) * dxiu2 / tt- u2 * u3 * dxiu3 / tt;
249 
250  *MIJ(jac, 5, i, ldfjac) = u3 * dxit - u1 * u3 * dxiu1 / tt - u2 * u3 * dxiu2 / tt
251  + (1 - u3 * u3) * dxiu3 / tt;
252  }
253  else
254  {
255  *MIJ(jac, 3, i, ldfjac) = 0.0;
256  *MIJ(jac, 4, i, ldfjac) = 0.0;
257  *MIJ(jac, 5, i, ldfjac) = 0.0;
258  }
259  *MIJ(jac, 0, npt + i, ldfjac) = 0.0;
260  *MIJ(jac, 1, npt + i, ldfjac) = 1 / rz;
261  *MIJ(jac, 2, npt + i, ldfjac) = - ry / (rz * rz);
262  if (tt >= MINIMUM)
263  {
264  *MIJ(jac, 3, npt + i, ldfjac) = u1 * dyit + (1 - u1 * u1) * dyiu1 / tt
265  - u1 * u2 * dyiu2 / tt - u1 * u3 * dyiu3 / tt;
266  *MIJ(jac, 4, npt + i, ldfjac) = u2 * dyit - u1 * u2 * dyiu1 / tt
267  + (1 - u2 * u2) * dyiu2 / tt- u2 * u3 * dyiu3 / tt;
268  *MIJ(jac, 5, npt + i, ldfjac) = u3 * dyit - u1 * u3 * dyiu1 / tt
269  - u2 * u3 * dyiu2 / tt + (1 - u3 * u3) * dyiu3 / tt;
270  }
271  else
272  {
273  *MIJ(jac, 3, npt + i, ldfjac) = 0.0;
274  *MIJ(jac, 4, npt + i, ldfjac) = 0.0;
275  *MIJ(jac, 5, npt + i, ldfjac) = 0.0;
276  }
277  }
278  } /* fin else if iflag ==2 */
279 }
280 
289 void
291 {
292 #if (DEBUG_LEVEL1)
293  std::cout << "begin CCalcuvpPose::PoseLowe(...) " << std::endl;
294 #endif
295  int n, m; /* nombre d'elements dans la matrice jac */
296  int lwa; /* taille du vecteur wa */
297  int ldfjac; /* taille maximum d'une ligne de jac */
298  int info, ipvt[NBR_PAR];
299  int tst_lmder;
300  double f[2 * NBPTMAX], sol[NBR_PAR];
301  double tol, jac[NBR_PAR][2 * NBPTMAX], wa[2 * NBPTMAX + 50];
302  // double u[3]; /* vecteur de rotation */
303  // double rd[3][3]; /* matrice de rotation */
304 
305  n = NBR_PAR; /* nombres d'inconnues */
306  m = (int)(2 * npt); /* nombres d'equations */
307  lwa = 2 * NBPTMAX + 50; /* taille du vecteur de travail */
308  ldfjac = 2 * NBPTMAX; /* nombre d'elements max sur une ligne */
309  tol = DBL_EPSILON; /* critere d'arret */
310 
311  // c = cam ;
312  // for (i=0;i<3;i++)
313  // for (j=0;j<3;j++) rd[i][j] = cMo[i][j];
314  // mat_rot(rd,u);
315  vpRotationMatrix cRo ;
316  cMo.extract(cRo) ;
317  vpThetaUVector u(cRo) ;
318  for (unsigned int i=0;i<3;i++)
319  {
320  sol[i] = cMo[i][3];
321  sol[i+3] = u[i];
322  }
323 
324  vpPoint P ;
325  unsigned int i_=0;
326  for (std::list<vpPoint>::const_iterator it = listP.begin(); it != listP.end(); ++it)
327  {
328  P = *it;
329  XI[i_] = P.get_x();//*cam.px + cam.xc ;
330  YI[i_] = P.get_y() ;//;*cam.py + cam.yc ;
331  XO[i_] = P.get_oX();
332  YO[i_] = P.get_oY();
333  ZO[i_] = P.get_oZ();
334  ++i_;
335  }
336  tst_lmder = lmder1 (&fcn, m, n, sol, f, &jac[0][0], ldfjac, tol, &info, ipvt, lwa, wa);
337  if (tst_lmder == -1)
338  {
339  std::cout << " in CCalculPose::PoseLowe(...) : " ;
340  std::cout << "pb de minimisation, returns FATAL_ERROR";
341  // return FATAL_ERROR ;
342  }
343 
344  for (unsigned int i = 0; i < 3; i++)
345  u[i] = sol[i + 3];
346 
347  for (unsigned int i=0;i<3;i++)
348  {
349  cMo[i][3] = sol[i];
350  u[i] = sol[i+3];
351  }
352 
353  vpRotationMatrix rd(u) ;
354  cMo.insert(rd) ;
355  // rot_mat(u,rd);
356  // for (i=0;i<3;i++) for (j=0;j<3;j++) cMo[i][j] = rd[i][j];
357 
358 #if (DEBUG_LEVEL1)
359  std::cout << "end CCalculPose::PoseLowe(...) " << std::endl;
360 #endif
361  // return OK ;
362 }
363 
364 
365 #undef MINI
366 #undef MINIMUM
367 
368 
369 #undef DEBUG_LEVEL1
370 
371 
372 /*
373 * Local variables:
374 * c-basic-offset: 2
375 * End:
376 */
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.h:129
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.h:138
std::list< vpPoint > listP
array of point (use here class vpPoint)
Definition: vpPose.h:95
Class that defines what is a point.
Definition: vpPoint.h:65
The vpRotationMatrix considers the particular case of a rotation matrix.
vpRotationMatrix buildFrom(const vpThetaUVector &v)
Transform a vector vpThetaUVector into an rotation matrix.
void insert(const vpRotationMatrix &R)
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.h:131
void poseLowe(vpHomogeneousMatrix &cMo)
Compute the pose using the Lowe non linear approach it consider the minimization of a residual using ...
Definition: vpPoseLowe.cpp:290
void extract(vpRotationMatrix &R) const
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.h:136
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:127
Class that consider the case of the parameterization for the rotation.