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