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