34 #include <visp3/core/vpMath.h>
35 #include <visp3/vision/vpPose.h>
37 #define SEUIL_RESIDUAL 0.0001
46 const int id0 = 0, id1 = 1, id2 = 2;
47 double normI3 = sqrt((I4[id0] * I4[id0]) + (I4[id1] * I4[id1]) + (I4[id2] * I4[id2]));
48 double normJ3 = sqrt((J4[id0] * J4[id0]) + (J4[id1] * J4[id1]) + (J4[id2] * J4[id2]));
50 if ((normI3 < 1e-10) || (normJ3 < 1e-10)) {
52 "Division by zero in Dementhon pose computation: normI or normJ = 0"));
55 double Z0 = 2.0 / (normI3 + normJ3);
57 const unsigned int sizeVectors = 3;
58 vpColVector I3(sizeVectors), J3(sizeVectors), K3(sizeVectors);
59 for (
unsigned int i = 0; i < sizeVectors; ++i) {
60 I3[i] = I4[i] / normI3;
61 J3[i] = J4[i] / normJ3;
70 const unsigned int idX = 0, idY = 1, idZ = 2, idTranslation = 3;
71 cMo[idX][idX] = I3[idX];
72 cMo[idX][idY] = I3[idY];
73 cMo[idX][idZ] = I3[idZ];
74 cMo[idX][idTranslation] = I4[idTranslation] * Z0;
76 cMo[idY][idX] = J3[idX];
77 cMo[idY][idY] = J3[idY];
78 cMo[idY][idZ] = J3[idZ];
79 cMo[idY][idTranslation] = J4[idTranslation] * Z0;
81 cMo[idZ][idX] = K3[idX];
82 cMo[idZ][idY] = K3[idY];
83 cMo[idZ][idZ] = K3[idZ];
84 cMo[idZ][idTranslation] = Z0;
90 const unsigned int idX = 0, idY = 1, idZ = 2, size = 3;
96 std::list<vpPoint>::const_iterator listp_end =
listP.end();
97 for (std::list<vpPoint>::const_iterator it =
listP.begin(); it != listp_end; ++it) {
104 for (
unsigned int i = 0; i < size; ++i) {
111 std::list<vpPoint>::const_iterator listp_end_s =
listP.end();
112 for (std::list<vpPoint>::const_iterator it =
listP.begin(); it != listp_end_s; ++it) {
120 const unsigned int idHomogeneousCoord = 3;
121 const unsigned int homogeneousCoordSize = 4;
124 for (
unsigned int i = 0; i <
npt; ++i) {
125 A[i][idX] = c3d[i].get_oX();
126 A[i][idY] = c3d[i].get_oY();
127 A[i][idZ] = c3d[i].get_oZ();
128 A[i][idHomogeneousCoord] = 1.0;
135 for (
unsigned int i = 0; i <
npt; ++i) {
136 xprim[i] = c3d[i].get_x();
137 yprim[i] = c3d[i].get_y();
139 vpColVector I4(homogeneousCoordSize), J4(homogeneousCoordSize);
144 calculSolutionDementhon(I4, J4, cMo);
146 const unsigned int idTranslation = 3;
148 for (
unsigned int i = 0; i <
npt; ++i) {
150 z = (cMo[idZ][idX] * c3d[i].get_oX()) + (cMo[idZ][idY] * c3d[i].get_oY()) + (cMo[idZ][idZ] * c3d[i].get_oZ()) + cMo[idZ][idTranslation];
160 double res_old = 2.0 * res;
165 while ((cpt < ITER_MAX) && (res > SEUIL_RESIDUAL) && (res < res_old)) {
171 for (
unsigned int i = 0; i <
npt; ++i) {
173 ((cMo[idZ][idX] * c3d[i].get_oX()) + (cMo[idZ][idY] * c3d[i].get_oY()) + (cMo[idZ][idZ] * c3d[i].get_oZ())) / cMo[idZ][idTranslation];
175 xprim[i] = (1.0 + eps) * c3d[i].get_x();
176 yprim[i] = (1.0 + eps) * c3d[i].get_y();
181 calculSolutionDementhon(I4, J4, cMo);
183 for (
unsigned int i = 0; i <
npt; ++i) {
185 z = (cMo[idZ][idX] * c3d[i].get_oX()) + (cMo[idZ][idY] * c3d[i].get_oY()) + (cMo[idZ][idZ] * c3d[i].get_oZ()) + cMo[idZ][idTranslation];
201 cMo[idX][idTranslation] -= ((cdg[idX] * cMo[idX][idX]) + (cdg[idY] * cMo[idX][idY]) + (cdg[idZ] * cMo[idX][idZ]));
202 cMo[idY][idTranslation] -= ((cdg[idX] * cMo[idY][idX]) + (cdg[idY] * cMo[idY][idY]) + (cdg[idZ] * cMo[idY][idZ]));
203 cMo[idZ][idTranslation] -= ((cdg[idX] * cMo[idZ][idX]) + (cdg[idY] * cMo[idZ][idY]) + (cdg[idZ] * cMo[idZ][idZ]));
206 static void calculRTheta(
double s,
double c,
double &r,
double &theta)
208 if ((fabs(c) > EPS_DEM) || (fabs(s) > EPS_DEM)) {
209 r = sqrt(sqrt((s * s) + (c * c)));
210 theta = atan2(s, c) / 2.0;
213 if (fabs(c) > fabs(s)) {
237 const unsigned int size = 3;
239 for (
unsigned int i = 0; i < size; ++i) {
244 double c = J0.sumSquare() - I0.sumSquare();
247 calculRTheta(s, c, r, theta);
248 double co = cos(theta);
249 double si = sin(theta);
252 const unsigned int sizeHomogeneous = 4;
253 vpColVector I(sizeHomogeneous), J(sizeHomogeneous);
254 I = I04 + (U * r * co);
255 J = J04 + (U * r * si);
257 calculSolutionDementhon(I, J, cMo1);
260 I = I04 - (U * r * co);
261 J = J04 - (U * r * si);
263 calculSolutionDementhon(I, J, cMo2);
271 const unsigned int idX = 0, idY = 1, idZ = 2, idTranslation = 3;
272 for (
unsigned int i = 0; i <
npt; ++i) {
274 z = (cMo[idZ][idX] * c3d[i].get_oX()) + (cMo[idZ][idY] * c3d[i].get_oY()) + (cMo[idZ][idZ] * c3d[i].get_oZ()) + cMo[idZ][idTranslation];
281 unsigned int cpt = 0;
283 double res_old = 2.0 * res_min;
286 while ((cpt < ITER_MAX) && (res_min > SEUIL_RESIDUAL) && (res_min < res_old)) {
293 for (
unsigned int i = 0; i <
npt; ++i) {
295 ((cMo[idZ][idX] * c3d[i].get_oX()) + (cMo[idZ][idY] * c3d[i].get_oY()) + (cMo[idZ][idZ] * c3d[i].get_oZ())) / cMo[idZ][idTranslation];
297 xprim[i] = (1.0 + eps) * c3d[i].get_x();
298 yprim[i] = (1.0 + eps) * c3d[i].get_y();
301 const unsigned int sizeHomogeneous = 4;
302 vpColVector I04(sizeHomogeneous), J04(sizeHomogeneous);
306 calculTwoSolutionsDementhonPlan(I04, J04, U, cMo1, cMo2);
311 for (
unsigned int i = 0; i <
npt; ++i) {
313 z = (cMo1[idZ][idX] * c3d[i].get_oX()) + (cMo1[idZ][idY] * c3d[i].get_oY()) + (cMo1[idZ][idZ] * c3d[i].get_oZ()) + cMo1[idZ][idTranslation];
317 z = (cMo2[idZ][idX] * c3d[i].get_oX()) + (cMo2[idZ][idY] * c3d[i].get_oY()) + (cMo2[idZ][idZ] * c3d[i].get_oZ()) + cMo2[idZ][idTranslation];
323 if ((erreur1 == -1) && (erreur2 == -1)) {
327 if ((erreur1 == 0) && (erreur2 == -1)) {
331 if ((erreur1 == -1) && (erreur2 == 0)) {
335 if ((erreur1 == 0) && (erreur2 == 0)) {
348 if (res_min > res_old) {
359 const double svdFactorUsedWhenFailure = 10.;
360 const double svdThresholdLimit = 1e-2;
361 const double lnOfSvdFactorUsed = std::log(svdFactorUsedWhenFailure);
362 const double logNOfSvdThresholdLimit = std::log(svdThresholdLimit)/lnOfSvdFactorUsed;
364 const unsigned int idX = 0, idY = 1, idZ = 2, size3Dpt = 3;
365 double cdg[size3Dpt];
370 std::list<vpPoint>::const_iterator listp_end =
listP.end();
371 for (std::list<vpPoint>::const_iterator it =
listP.begin(); it != listp_end; ++it) {
378 for (
unsigned int i = 0; i < size3Dpt; ++i) {
385 std::list<vpPoint>::const_iterator listp_end_decl2 =
listP.end();
386 for (std::list<vpPoint>::const_iterator it =
listP.begin(); it != listp_end_decl2; ++it) {
394 const unsigned int sizeHomogeneous = 4, idHomogeneous = 3;
397 for (
unsigned int i = 0; i <
npt; ++i) {
398 A[i][idX] = c3d[i].get_oX();
399 A[i][idY] = c3d[i].get_oY();
400 A[i][idZ] = c3d[i].get_oZ();
401 A[i][idHomogeneous] = 1.0;
405 bool isRankEqualTo3 =
false;
409 int nbMaxIter =
static_cast<int>(std::max<double>(std::ceil(logNOfSvdThresholdLimit - logNofSvdThresh), 1.));
411 unsigned int irank = 0;
413 const unsigned int expectedRank = 3;
414 while ((i < nbMaxIter) && (!isRankEqualTo3)) {
415 irank = A.
pseudoInverse(Ap, sv, svdThreshold, imA, imAt, kAt);
416 if (irank == expectedRank) {
417 isRankEqualTo3 =
true;
420 isRankEqualTo3 =
false;
421 svdThreshold *= svdFactorUsedWhenFailure;
426 if (!isRankEqualTo3) {
427 std::stringstream errorMsg;
428 errorMsg <<
"In Dementhon planar, after ";
429 errorMsg << nbMaxIter;
430 errorMsg <<
" trials multiplying the svd threshold by ";
431 errorMsg << svdFactorUsedWhenFailure;
432 errorMsg <<
", rank (";
434 errorMsg <<
") is still not 3";
439 for (
unsigned int i = 0; i < sizeHomogeneous; ++i) {
446 for (
unsigned int i = 0; i <
npt; ++i) {
447 xi[i] = c3d[i].get_x();
448 yi[i] = c3d[i].get_y();
451 vpColVector I04(sizeHomogeneous), J04(sizeHomogeneous);
456 calculTwoSolutionsDementhonPlan(I04, J04, U, cMo1, cMo2);
461 if ((erreur1 == -1) && (erreur2 == -1)) {
465 if ((erreur1 == 0) && (erreur2 == -1)) {
468 if ((erreur1 == -1) && (erreur2 == 0)) {
471 if ((erreur1 == 0) && (erreur2 == 0)) {
482 const unsigned int idTranslation = 3;
483 cMo[idX][idTranslation] -= ((cdg[idX] * cMo[idX][idX]) + (cdg[idY] * cMo[idX][idY]) + (cdg[idZ] * cMo[idX][idZ]));
484 cMo[idY][idTranslation] -= ((cdg[idX] * cMo[idY][idX]) + (cdg[idY] * cMo[idY][idY]) + (cdg[idZ] * cMo[idY][idZ]));
485 cMo[idZ][idTranslation] -= ((cdg[idX] * cMo[idZ][idX]) + (cdg[idY] * cMo[idZ][idY]) + (cdg[idZ] * cMo[idZ][idZ]));
490 double squared_error = 0;
495 const unsigned int idX = 0, idY = 1, idZ = 2, idTranslation = 3;
496 for (
unsigned int i = 0; i <
npt; ++i) {
498 double X = (c3d[i].get_oX() * cMo[idX][idX]) + (c3d[i].get_oY() * cMo[idX][idY]) + (c3d[i].get_oZ() * cMo[idX][idZ]) + cMo[idX][idTranslation];
499 double Y = (c3d[i].get_oX() * cMo[idY][idX]) + (c3d[i].get_oY() * cMo[idY][idY]) + (c3d[i].get_oZ() * cMo[idY][idZ]) + cMo[idY][idTranslation];
500 double Z = (c3d[i].get_oX() * cMo[idZ][idX]) + (c3d[i].get_oY() * cMo[idZ][idY]) + (c3d[i].get_oZ() * cMo[idZ][idZ]) + cMo[idZ][idTranslation];
507 return squared_error;
513 #undef SEUIL_RESIDUAL
Implementation of column vector and the associated operations.
static double dotProd(const vpColVector &a, const vpColVector &b)
static vpColVector cross(const vpColVector &a, const vpColVector &b)
error that can be emitted by ViSP classes.
@ divideByZeroError
Division by zero.
Implementation of an homogeneous matrix and operations on such kind of matrices.
static double sqr(double x)
Implementation of a matrix and operations on matrices.
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
double get_oX() const
Get the point oX coordinate in the object frame.
double get_oZ() const
Get the point oZ coordinate in the object frame.
void set_oY(double oY)
Set the point oY coordinate in the object frame.
void set_oZ(double oZ)
Set the point oZ coordinate in the object frame.
void set_oX(double oX)
Set the point oX coordinate in the object frame.
double get_oY() const
Get the point oY coordinate in the object frame.
double computeResidualDementhon(const vpHomogeneousMatrix &cMo)
unsigned int npt
Number of point used in pose computation.
void poseDementhonNonPlan(vpHomogeneousMatrix &cMo)
double m_dementhonSvThresh
SVD threshold use for the pseudo-inverse computation in poseDementhonPlan.
std::list< vpPoint > listP
Array of point (use here class vpPoint)
int calculArbreDementhon(vpMatrix &b, vpColVector &U, vpHomogeneousMatrix &cMo)
void poseDementhonPlan(vpHomogeneousMatrix &cMo)