Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpHomographyVVS.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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  * Homography transformation.
32  */
33 
34 #include <iostream>
35 #include <visp3/core/vpExponentialMap.h>
36 #include <visp3/core/vpHomogeneousMatrix.h>
37 #include <visp3/core/vpMath.h>
38 #include <visp3/core/vpMatrix.h>
39 #include <visp3/core/vpPlane.h>
40 #include <visp3/core/vpPoint.h>
41 #include <visp3/core/vpRobust.h>
42 #include <visp3/vision/vpHomography.h>
43 
45 
46 const double vpHomography::m_threshold_rotation = 1e-7;
47 const double vpHomography::m_threshold_displacement = 1e-18;
48 
49 #ifndef DOXYGEN_SHOULD_SKIP_THIS
50 
51 static void updatePoseRotation(vpColVector &dx, vpHomogeneousMatrix &mati)
52 {
54  const unsigned int val_3 = 3;
55 
56  double s = sqrt((dx[0] * dx[0]) + (dx[1] * dx[1]) + (dx[2] * dx[2]));
57  if (s > 1.e-25) {
58  double u[3];
59 
60  for (unsigned int i = 0; i < val_3; ++i) {
61  u[i] = dx[i] / s;
62  }
63  double sinu = sin(s);
64  double cosi = cos(s);
65  double mcosi = 1 - cosi;
66  rd[0][0] = cosi + (mcosi * u[0] * u[0]);
67  rd[0][1] = (-sinu * u[2]) + (mcosi * u[0] * u[1]);
68  rd[0][2] = (sinu * u[1]) + (mcosi * u[0] * u[2]);
69  rd[1][0] = (sinu * u[2]) + (mcosi * u[1] * u[0]);
70  rd[1][1] = cosi + (mcosi * u[1] * u[1]);
71  rd[1][2] = (-sinu * u[0]) + (mcosi * u[1] * u[2]);
72  rd[2][0] = (-sinu * u[1]) + (mcosi * u[2] * u[0]);
73  rd[2][1] = (sinu * u[0]) + (mcosi * u[2] * u[1]);
74  rd[2][2] = cosi + (mcosi * u[2] * u[2]);
75  }
76  else {
77  for (unsigned int i = 0; i < val_3; ++i) {
78  for (unsigned int j = 0; j < val_3; ++j) {
79  rd[i][j] = 0.0;
80  }
81  rd[i][i] = 1.0;
82  }
83  }
84 
85  vpHomogeneousMatrix Delta;
86  Delta.insert(rd);
87 
88  mati = Delta.inverse() * mati;
89 }
90 
91 double vpHomography::computeRotation(unsigned int nbpoint, vpPoint *c1P, vpPoint *c2P, vpHomogeneousMatrix &c2Mc1,
92  int userobust)
93 {
94  vpColVector e(2);
95  double r_1 = -1;
96 
97  vpColVector p2(3);
98  vpColVector p1(3);
99  vpColVector Hp2(3);
100  vpColVector Hp1(3);
101 
102  vpMatrix H2(2, 3);
103  vpColVector e2(2);
104  vpMatrix H1(2, 3);
105  vpColVector e1(2);
106 
107  bool only_1 = false;
108  bool only_2 = false;
109  int iter = 0;
110  const unsigned int val_3 = 3;
111 
112  unsigned int n = 0;
113  for (unsigned int i = 0; i < nbpoint; ++i) {
114  // Check if c2P[i].get_x() and c1P[i].get_x() are different from -1
115  if ((std::fabs(c2P[i].get_x() + 1) > std::fabs(vpMath::maximum(c2P[i].get_x(), 1.))) &&
116  (std::fabs(c1P[i].get_x() + 1) > std::fabs(vpMath::maximum(c1P[i].get_x(), 1.)))) {
117  ++n;
118  }
119  }
120  if ((!only_1) && (!only_2)) {
121  n *= 2;
122  }
123 
125  vpColVector res(n);
126  vpColVector w(n);
127  w = 1;
128  robust.setMinMedianAbsoluteDeviation(0.00001);
129  vpMatrix W(2 * n, 2 * n);
130  W = 0;
131  vpMatrix c2Rc1(3, 3);
132  double r = 0;
133  bool stop = false;
134  while ((vpMath::equal(r_1, r, m_threshold_rotation) == false) && (stop == false)) {
135 
136  r_1 = r;
137  // compute current position
138 
139  // Change frame (current)
140  for (unsigned int i = 0; i < val_3; ++i) {
141  for (unsigned int j = 0; j < val_3; ++j) {
142  c2Rc1[i][j] = c2Mc1[i][j];
143  }
144  }
145 
146  vpMatrix L(2, 3), Lp;
147  int k = 0;
148  for (unsigned int i = 0; i < nbpoint; ++i) {
149  if ((std::fabs(c2P[i].get_x() + 1) > std::fabs(vpMath::maximum(c2P[i].get_x(), 1.))) &&
150  (std::fabs(c1P[i].get_x() + 1) > std::fabs(vpMath::maximum(c1P[i].get_x(), 1.)))) {
151  p2[0] = c2P[i].get_x();
152  p2[1] = c2P[i].get_y();
153  p2[2] = 1.0;
154  p1[0] = c1P[i].get_x();
155  p1[1] = c1P[i].get_y();
156  p1[2] = 1.0;
157 
158  Hp2 = c2Rc1.t() * p2; // p2 = Hp1
159  Hp1 = c2Rc1 * p1; // p1 = Hp2
160 
161  Hp2 /= Hp2[2]; // normalization
162  Hp1 /= Hp1[2];
163 
164  // set up the interaction matrix
165  double x = Hp2[0];
166  double y = Hp2[1];
167 
168  H2[0][0] = x * y;
169  H2[0][1] = -(1 + (x * x));
170  H2[0][2] = y;
171  H2[1][0] = 1 + (y * y);
172  H2[1][1] = -x * y;
173  H2[1][2] = -x;
174  H2 *= -1;
175  H2 = H2 * c2Rc1.t();
176 
177  // Set up the error vector
178  e2[0] = Hp2[0] - c1P[i].get_x();
179  e2[1] = Hp2[1] - c1P[i].get_y();
180 
181  // set up the interaction matrix
182  x = Hp1[0];
183  y = Hp1[1];
184 
185  H1[0][0] = x * y;
186  H1[0][1] = -(1 + (x * x));
187  H1[0][2] = y;
188  H1[1][0] = 1 + (y * y);
189  H1[1][1] = -x * y;
190  H1[1][2] = -x;
191 
192  // Set up the error vector
193  e1[0] = Hp1[0] - c2P[i].get_x();
194  e1[1] = Hp1[1] - c2P[i].get_y();
195 
196  if (only_2) {
197  if (k == 0) {
198  L = H2;
199  e = e2;
200  }
201  else {
202  L = vpMatrix::stack(L, H2);
203  e = vpColVector::stack(e, e2);
204  }
205  }
206  else if (only_1) {
207  if (k == 0) {
208  L = H1;
209  e = e1;
210  }
211  else {
212  L = vpMatrix::stack(L, H1);
213  e = vpColVector::stack(e, e1);
214  }
215  }
216  else {
217  if (k == 0) {
218  L = H2;
219  e = e2;
220  }
221  else {
222  L = vpMatrix::stack(L, H2);
223  e = vpColVector::stack(e, e2);
224  }
225  L = vpMatrix::stack(L, H1);
226  e = vpColVector::stack(e, e1);
227  }
228 
229  ++k;
230  }
231  }
232 
233  if (userobust) {
234  for (unsigned int l = 0; l < n; ++l) {
235  res[l] = vpMath::sqr(e[2 * l]) + vpMath::sqr(e[(2 * l)+ 1]);
236  }
237  robust.MEstimator(vpRobust::TUKEY, res, w);
238 
239  // compute the pseudo inverse of the interaction matrix
240  for (unsigned int l = 0; l < n; ++l) {
241  W[2 * l][2 * l] = w[l];
242  W[(2 * l) + 1][(2 * l) + 1] = w[l];
243  }
244  }
245  else {
246  for (unsigned int l = 0; l < (2 * n); ++l) {
247  W[l][l] = 1;
248  }
249  }
250  L.pseudoInverse(Lp, 1e-6);
251  // Compute the camera velocity
252  vpColVector c2rc1, v(6);
253 
254  c2rc1 = -2 * Lp * W * e;
255  for (unsigned int i = 0; i < val_3; ++i) {
256  v[i + 3] = c2rc1[i];
257  }
258 
259  // only for simulation
260 
261  updatePoseRotation(c2rc1, c2Mc1);
262  r = e.sumSquare();
263 
264  if (((W * e).sumSquare() < 1e-10) || (iter > 25)) {
265  stop = true;
266  }
267  ++iter;
268  }
269 
270  return (W * e).sumSquare();
271 }
272 
273 static void getPlaneInfo(vpPlane &oN, vpHomogeneousMatrix &cMo, vpColVector &cN, double &cd)
274 {
275  double A1 = (cMo[0][0] * oN.getA()) + (cMo[0][1] * oN.getB()) + (cMo[0][2] * oN.getC());
276  double B1 = (cMo[1][0] * oN.getA()) + (cMo[1][1] * oN.getB()) + (cMo[1][2] * oN.getC());
277  double C1 = (cMo[2][0] * oN.getA()) + (cMo[2][1] * oN.getB()) + (cMo[2][2] * oN.getC());
278  double D1 = oN.getD() - ((cMo[0][3] * A1) + (cMo[1][3] * B1) + (cMo[2][3] * C1));
279 
280  cN.resize(3);
281  cN[0] = A1;
282  cN[1] = B1;
283  cN[2] = C1;
284  cd = -D1;
285 }
286 
287 double vpHomography::computeDisplacement(unsigned int nbpoint, vpPoint *c1P, vpPoint *c2P, vpPlane &oN,
288  vpHomogeneousMatrix &c2Mc1, vpHomogeneousMatrix &c1Mo, int userobust)
289 {
290  vpColVector e(2);
291  double r_1 = -1;
292 
293  vpColVector p2(3);
294  vpColVector p1(3);
295  vpColVector Hp2(3);
296  vpColVector Hp1(3);
297 
298  vpMatrix H2(2, 6);
299  vpColVector e2(2);
300  vpMatrix H1(2, 6);
301  vpColVector e1(2);
302 
303  bool only_1 = true;
304  bool only_2 = false;
305  int iter = 0;
306  unsigned int n = 0;
307  n = nbpoint;
308 
310  vpColVector res(n);
311  vpColVector w(n);
312  w = 1;
313  robust.setMinMedianAbsoluteDeviation(0.00001);
314  vpMatrix W(2 * n, 2 * n);
315  W = 0;
316 
317  vpColVector N1(3), N2(3);
318  double d1, d2;
319 
320  double r = 1e10;
321  iter = 0;
322  vpMatrix sTR;
323  bool stop = false;
324  while ((!vpMath::equal(r_1, r, m_threshold_displacement)) && (stop == false)) {
325  r_1 = r;
326  // compute current position
327 
328  // Change frame (current)
329  vpHomogeneousMatrix c1Mc2, c2Mo;
330  vpRotationMatrix c1Rc2, c2Rc1;
331  vpTranslationVector c1Tc2, c2Tc1;
332  c1Mc2 = c2Mc1.inverse();
333  c2Mc1.extract(c2Rc1);
334  c2Mc1.extract(c2Tc1);
335  c2Mc1.extract(c1Rc2);
336  c1Mc2.extract(c1Tc2);
337 
338  c2Mo = c2Mc1 * c1Mo;
339 
340  getPlaneInfo(oN, c1Mo, N1, d1);
341  getPlaneInfo(oN, c2Mo, N2, d2);
342 
343  vpMatrix L(2, 3), Lp;
344  int k = 0;
345  for (unsigned int i = 0; i < nbpoint; ++i) {
346  p2[0] = c2P[i].get_x();
347  p2[1] = c2P[i].get_y();
348  p2[2] = 1.0;
349  p1[0] = c1P[i].get_x();
350  p1[1] = c1P[i].get_y();
351  p1[2] = 1.0;
352 
353  vpMatrix H(3, 3);
354 
355  Hp2 = (static_cast<vpMatrix>(c1Rc2) + ((c1Tc2 * N2.t()) / d2)) * p2; // p2 = Hp1
356  Hp1 = (static_cast<vpMatrix>(c2Rc1) + ((c2Tc1 * N1.t()) / d1)) * p1; // p1 = Hp2
357 
358  Hp2 /= Hp2[2]; // normalization
359  Hp1 /= Hp1[2];
360 
361  // set up the interaction matrix
362  double x = Hp2[0];
363  double y = Hp2[1];
364  double Z1;
365 
366  Z1 = ((N1[0] * x) + (N1[1] * y) + N1[2]) / d1; // 1/z
367 
368  H2[0][0] = -Z1;
369  H2[0][1] = 0;
370  H2[0][2] = x * Z1;
371  H2[1][0] = 0;
372  H2[1][1] = -Z1;
373  H2[1][2] = y * Z1;
374  H2[0][3] = x * y;
375  H2[0][4] = -(1 + (x * x));
376  H2[0][5] = y;
377  H2[1][3] = 1 + (y * y);
378  H2[1][4] = -x * y;
379  H2[1][5] = -x;
380  H2 *= -1;
381 
382  vpMatrix c1CFc2(6, 6);
383 
384  sTR = c1Tc2.skew() * c1Rc2;
385  for (unsigned int k_ = 0; k_ < 3; ++k_) {
386  for (unsigned int l = 0; l < 3; ++l) {
387  c1CFc2[k_][l] = c1Rc2[k_][l];
388  c1CFc2[k_ + 3][l + 3] = c1Rc2[k_][l];
389  c1CFc2[k_][l + 3] = sTR[k_][l];
390  }
391  }
392 
393  H2 = H2 * c1CFc2;
394 
395  // Set up the error vector
396  e2[0] = Hp2[0] - c1P[i].get_x();
397  e2[1] = Hp2[1] - c1P[i].get_y();
398 
399  x = Hp1[0];
400  y = Hp1[1];
401 
402  Z1 = ((N2[0] * x) + (N2[1] * y) + N2[2]) / d2; // 1/z
403 
404  H1[0][0] = -Z1;
405  H1[0][1] = 0;
406  H1[0][2] = x * Z1;
407  H1[1][0] = 0;
408  H1[1][1] = -Z1;
409  H1[1][2] = y * Z1;
410  H1[0][3] = x * y;
411  H1[0][4] = -(1 + (x * x));
412  H1[0][5] = y;
413  H1[1][3] = 1 + (y * y);
414  H1[1][4] = -x * y;
415  H1[1][5] = -x;
416 
417  // Set up the error vector
418  e1[0] = Hp1[0] - c2P[i].get_x();
419  e1[1] = Hp1[1] - c2P[i].get_y();
420 
421  if (only_2) {
422  if (k == 0) {
423  L = H2;
424  e = e2;
425  }
426  else {
427  L = vpMatrix::stack(L, H2);
428  e = vpColVector::stack(e, e2);
429  }
430  }
431  else if (only_1) {
432  if (k == 0) {
433  L = H1;
434  e = e1;
435  }
436  else {
437  L = vpMatrix::stack(L, H1);
438  e = vpColVector::stack(e, e1);
439  }
440  }
441  else {
442  if (k == 0) {
443  L = H2;
444  e = e2;
445  }
446  else {
447  L = vpMatrix::stack(L, H2);
448  e = vpColVector::stack(e, e2);
449  }
450  L = vpMatrix::stack(L, H1);
451  e = vpColVector::stack(e, e1);
452  }
453 
454  ++k;
455  }
456 
457  if (userobust) {
458  for (unsigned int l = 0; l < n; ++l) {
459  res[l] = vpMath::sqr(e[2 * l]) + vpMath::sqr(e[(2 * l)+ 1]);
460  }
461  robust.MEstimator(vpRobust::TUKEY, res, w);
462 
463  // compute the pseudo inverse of the interaction matrix
464  for (unsigned int l = 0; l < n; ++l) {
465  W[2 * l][2 * l] = w[l];
466  W[(2 * l) + 1][(2 * l) + 1] = w[l];
467  }
468  }
469  else {
470  for (unsigned int l = 0; l < (2 * n); ++l) {
471  W[l][l] = 1;
472  }
473  }
474  (W * L).pseudoInverse(Lp, 1e-16);
475  // Compute the camera velocity
476  vpColVector c2Tcc1;
477 
478  c2Tcc1 = -1 * Lp * W * e;
479 
480  // only for simulation
481 
482  c2Mc1 = vpExponentialMap::direct(c2Tcc1).inverse() * c2Mc1;
483  r = (W * e).sumSquare();
484 
485  if ((r < 1e-15) || (iter > 1000) || (r > r_1)) {
486  stop = true;
487  }
488  ++iter;
489  }
490 
491  return (W * e).sumSquare();
492 }
493 
494 double vpHomography::computeDisplacement(unsigned int nbpoint, vpPoint *c1P, vpPoint *c2P, vpPlane *oN,
495  vpHomogeneousMatrix &c2Mc1, vpHomogeneousMatrix &c1Mo, int userobust)
496 {
497 
498  vpColVector e(2);
499  double r_1 = -1;
500 
501  vpColVector p2(3);
502  vpColVector p1(3);
503  vpColVector Hp2(3);
504  vpColVector Hp1(3);
505 
506  vpMatrix H2(2, 6);
507  vpColVector e2(2);
508  vpMatrix H1(2, 6);
509  vpColVector e1(2);
510 
511  bool only_1 = true;
512  bool only_2 = false;
513  int iter = 0;
514  unsigned int i;
515  unsigned int n = 0;
516  n = nbpoint;
517 
519  vpColVector res(n);
520  vpColVector w(n);
521  w = 1;
522  robust.setMinMedianAbsoluteDeviation(0.00001);
523  vpMatrix W(2 * n, 2 * n);
524  W = 0;
525 
526  vpColVector N1(3), N2(3);
527  double d1, d2;
528 
529  double r = 1e10;
530  iter = 0;
531  vpMatrix sTR;
532  bool stop = false;
533  while ((!vpMath::equal(r_1, r, m_threshold_displacement)) && (stop == false)) {
534  r_1 = r;
535  // compute current position
536 
537  // Change frame (current)
538  vpHomogeneousMatrix c1Mc2, c2Mo;
539  vpRotationMatrix c1Rc2, c2Rc1;
540  vpTranslationVector c1Tc2, c2Tc1;
541  c1Mc2 = c2Mc1.inverse();
542  c2Mc1.extract(c2Rc1);
543  c2Mc1.extract(c2Tc1);
544  c2Mc1.extract(c1Rc2);
545  c1Mc2.extract(c1Tc2);
546 
547  c2Mo = c2Mc1 * c1Mo;
548 
549  vpMatrix L(2, 3), Lp;
550  int k = 0;
551  for (i = 0; i < nbpoint; ++i) {
552  getPlaneInfo(oN[i], c1Mo, N1, d1);
553  getPlaneInfo(oN[i], c2Mo, N2, d2);
554  p2[0] = c2P[i].get_x();
555  p2[1] = c2P[i].get_y();
556  p2[2] = 1.0;
557  p1[0] = c1P[i].get_x();
558  p1[1] = c1P[i].get_y();
559  p1[2] = 1.0;
560 
561  vpMatrix H(3, 3);
562 
563  Hp2 = (static_cast<vpMatrix>(c1Rc2) + ((c1Tc2 * N2.t()) / d2)) * p2; // p2 = Hp1
564  Hp1 = (static_cast<vpMatrix>(c2Rc1) + ((c2Tc1 * N1.t()) / d1)) * p1; // p1 = Hp2
565 
566  Hp2 /= Hp2[2]; // normalization
567  Hp1 /= Hp1[2];
568 
569  // set up the interaction matrix
570  double x = Hp2[0];
571  double y = Hp2[1];
572  double Z1;
573 
574  Z1 = ((N1[0] * x) + (N1[1] * y) + N1[2]) / d1; // 1/z
575 
576  H2[0][0] = -Z1;
577  H2[0][1] = 0;
578  H2[0][2] = x * Z1;
579  H2[1][0] = 0;
580  H2[1][1] = -Z1;
581  H2[1][2] = y * Z1;
582  H2[0][3] = x * y;
583  H2[0][4] = -(1 + (x * x));
584  H2[0][5] = y;
585  H2[1][3] = 1 + (y * y);
586  H2[1][4] = -x * y;
587  H2[1][5] = -x;
588  H2 *= -1;
589 
590  vpMatrix c1CFc2(6, 6);
591 
592  sTR = c1Tc2.skew() * static_cast<vpMatrix>(c1Rc2);
593  for (unsigned int k_ = 0; k_ < 3; ++k_) {
594  for (unsigned int l = 0; l < 3; ++l) {
595  c1CFc2[k_][l] = c1Rc2[k_][l];
596  c1CFc2[k_ + 3][l + 3] = c1Rc2[k_][l];
597  c1CFc2[k_][l + 3] = sTR[k_][l];
598  }
599  }
600 
601  H2 = H2 * c1CFc2;
602 
603  // Set up the error vector
604  e2[0] = Hp2[0] - c1P[i].get_x();
605  e2[1] = Hp2[1] - c1P[i].get_y();
606 
607  x = Hp1[0];
608  y = Hp1[1];
609 
610  Z1 = ((N2[0] * x) + (N2[1] * y) + N2[2]) / d2; // 1/z
611 
612  H1[0][0] = -Z1;
613  H1[0][1] = 0;
614  H1[0][2] = x * Z1;
615  H1[1][0] = 0;
616  H1[1][1] = -Z1;
617  H1[1][2] = y * Z1;
618  H1[0][3] = x * y;
619  H1[0][4] = -(1 + (x * x));
620  H1[0][5] = y;
621  H1[1][3] = 1 + (y * y);
622  H1[1][4] = -x * y;
623  H1[1][5] = -x;
624 
625  // Set up the error vector
626  e1[0] = Hp1[0] - c2P[i].get_x();
627  e1[1] = Hp1[1] - c2P[i].get_y();
628 
629  if (only_2) {
630  if (k == 0) {
631  L = H2;
632  e = e2;
633  }
634  else {
635  L = vpMatrix::stack(L, H2);
636  e = vpColVector::stack(e, e2);
637  }
638  }
639  else if (only_1) {
640  if (k == 0) {
641  L = H1;
642  e = e1;
643  }
644  else {
645  L = vpMatrix::stack(L, H1);
646  e = vpColVector::stack(e, e1);
647  }
648  }
649  else {
650  if (k == 0) {
651  L = H2;
652  e = e2;
653  }
654  else {
655  L = vpMatrix::stack(L, H2);
656  e = vpColVector::stack(e, e2);
657  }
658  L = vpMatrix::stack(L, H1);
659  e = vpColVector::stack(e, e1);
660  }
661 
662  ++k;
663  }
664 
665  if (userobust) {
666  for (unsigned int k_ = 0; k_ < n; ++k_) {
667  res[k_] = vpMath::sqr(e[2 * k_]) + vpMath::sqr(e[(2 * k_) + 1]);
668  }
669  robust.MEstimator(vpRobust::TUKEY, res, w);
670 
671  // compute the pseudo inverse of the interaction matrix
672  for (unsigned int k_ = 0; k_ < n; ++k_) {
673  W[2 * k_][2 * k_] = w[k_];
674  W[(2 * k_) + 1][(2 * k_) + 1] = w[k_];
675  }
676  }
677  else {
678  for (unsigned int k_ = 0; k_ < (2 * n); ++k_) {
679  W[k_][k_] = 1;
680  }
681  }
682  (W * L).pseudoInverse(Lp, 1e-16);
683  // Compute the camera velocity
684  vpColVector c2Tcc1;
685 
686  c2Tcc1 = -1 * Lp * W * e;
687 
688  // only for simulation
689 
690  c2Mc1 = vpExponentialMap::direct(c2Tcc1).inverse() * c2Mc1;
691  r = (W * e).sumSquare();
692 
693  if ((r < 1e-15) || (iter > 1000) || (r > r_1)) {
694  stop = true;
695  }
696  ++iter;
697  }
698 
699  return (W * e).sumSquare();
700 }
701 
702 #endif //#ifndef DOXYGEN_SHOULD_SKIP_THIS
703 
704 END_VISP_NAMESPACE
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
void stack(double d)
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
static vpHomogeneousMatrix direct(const vpColVector &v)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
void extract(vpRotationMatrix &R) const
void insert(const vpRotationMatrix &R)
void computeDisplacement(vpRotationMatrix &aRb, vpTranslationVector &atb, vpColVector &n)
static void robust(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, vpHomography &aHb, std::vector< bool > &inliers, double &residual, double weights_threshold=0.4, unsigned int niter=4, bool normalization=true)
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:254
static double sqr(double x)
Definition: vpMath.h:203
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:458
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
void stack(const vpMatrix &A)
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:57
double getD() const
Definition: vpPlane.h:106
double getA() const
Definition: vpPlane.h:100
double getC() const
Definition: vpPlane.h:104
double getB() const
Definition: vpPlane.h:102
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:79
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:422
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:420
Contains an M-estimator and various influence function.
Definition: vpRobust.h:84
@ TUKEY
Tukey influence function.
Definition: vpRobust.h:89
Implementation of a rotation matrix and operations on such kind of matrices.
Class that consider the case of a translation vector.