43 #include <visp3/vision/vpHandEyeCalibration.h> 45 #define DEBUG_LEVEL1 0 46 #define DEBUG_LEVEL2 0 58 void vpHandEyeCalibration::calibrationVerifrMo(
const std::vector<vpHomogeneousMatrix> &cMo,
const std::vector<vpHomogeneousMatrix> &rMe,
const vpHomogeneousMatrix &eMc)
60 unsigned int nbPose = (
unsigned int) cMo.size();
61 std::vector<vpTranslationVector> rTo(nbPose);
62 std::vector<vpRotationMatrix> rRo(nbPose);
64 for (
unsigned int i = 0; i < nbPose; i++) {
74 std::cout <<
"Mean " << std::endl;
75 std::cout <<
"Translation: " << meanTrans.
t() << std::endl;
77 std::cout <<
"Rotation : theta (deg) = " <<
vpMath::deg(sqrt(P.sumSquare())) <<
" Matrice : " << std::endl << meanRot << std::endl;
84 for (
unsigned int i = 0; i < nbPose; i++) {
88 double theta = sqrt(P.sumSquare());
89 std::cout <<
"Distance theta between rMo(" << i <<
") and mean (deg) = " <<
vpMath::deg(theta) << std::endl;
92 resRot += theta*theta;
94 resRot = sqrt(resRot/nbPose);
95 std::cout <<
"Mean residual rMo(" << nbPose <<
") - rotation (deg) = " <<
vpMath::deg(resRot) << std::endl;
97 double resTrans = 0.0;
98 for (
unsigned int i = 0; i < nbPose; i++) {
101 std::cout <<
"Distance d between rMo(" << i <<
") and mean (m) = " << sqrt(errTrans.
sumSquare()) << std::endl;
103 resTrans = sqrt(resTrans/nbPose);
104 std::cout <<
"Mean residual rMo(" << nbPose <<
") - translation (m) = " << resTrans << std::endl;
105 double resPos = (resRot*resRot + resTrans*resTrans)*nbPose;
106 resPos = sqrt(resPos/(2*nbPose));
107 std::cout <<
"Mean residual rMo(" << nbPose <<
") - global = " << resPos << std::endl;
121 int vpHandEyeCalibration::calibrationRotationProcrustes(
const std::vector<vpHomogeneousMatrix> &cMo,
const std::vector<vpHomogeneousMatrix> &rMe,
vpRotationMatrix &eRc)
130 unsigned int nbPose = (
unsigned int) cMo.
size();
133 for (
unsigned int i = 0; i < nbPose; i++) {
135 rMe[i].extract(rRei);
136 cMo[i].extract(ciRo);
139 for (
unsigned int j = 0; j < nbPose; j++) {
143 rMe[j].extract(rRej);
144 cMo[j].extract(cjRo);
174 if (rank != 3)
return -1;
181 std::cout <<
"Rotation from Procrustes method " << std::endl;
185 residual = A * Ct.
t() - Et.
t();
188 printf(
"Mean residual (rotation) = %lf\n",res);
206 int vpHandEyeCalibration::calibrationRotationTsai(
const std::vector<vpHomogeneousMatrix> &cMo,
const std::vector<vpHomogeneousMatrix> &rMe,
vpRotationMatrix &eRc)
210 unsigned int nbPose = (
unsigned int) cMo.
size();
213 for (
unsigned int i = 0; i < nbPose; i++) {
215 rMe[i].extract(rRei);
216 cMo[i].extract(ciRo);
219 for (
unsigned int j = 0; j < nbPose; j++) {
223 rMe[j].extract(rRej);
224 cMo[j].extract(cjRo);
254 std::cout <<
"Tsai method: system A X = B " << std::endl;
255 std::cout <<
"A " << std::endl << A << std::endl;
256 std::cout <<
"B " << std::endl << B << std::endl;
264 if (rank != 3)
return -1;
272 double c = 1 / sqrt(1 + norm);
273 double alpha = acos(c);
275 for (
unsigned int i = 0; i < 3; i++) x[i] *= norm;
283 std::cout <<
"Rotation from Tsai method" << std::endl;
286 for (
unsigned int i = 0; i < 3; i++) x[i] /= norm;
291 printf(
"Mean residual (rotation) = %lf\n",res);
309 int vpHandEyeCalibration::calibrationRotationTsaiOld(
const std::vector<vpHomogeneousMatrix> &cMo,
const std::vector<vpHomogeneousMatrix> &rMe,
vpRotationMatrix &eRc)
311 unsigned int nbPose = (
unsigned int) cMo.size();
317 for (
unsigned int i = 0; i < nbPose; i++) {
319 rMe[i].extract(rRei);
320 cMo[i].extract(ciRo);
323 for (
unsigned int j = 0; j < nbPose; j++) {
326 rMe[j].extract(rRej);
327 cMo[j].extract(cjRo);
336 double theta = sqrt(rPeij[0] * rPeij[0] + rPeij[1] * rPeij[1] + rPeij[2] * rPeij[2]);
343 for (
unsigned int m = 0; m < 3; m++) {
348 theta = sqrt(cijPo[0] * cijPo[0] + cijPo[1] * cijPo[1] + cijPo[2] * cijPo[2]);
349 for (
unsigned int m = 0; m < 3; m++) {
384 if (rank != 3)
return -1;
405 for (
unsigned int i = 0; i < 3; i++)
406 x[i] = 2 * x[i] / sqrt(1 + d);
408 theta = 2 * asin(theta);
410 if (std::fabs(theta) > std::numeric_limits<double>::epsilon()) {
411 for (
unsigned int i = 0; i < 3; i++)
412 x[i] *= theta / (2 * sin(theta / 2));
422 std::cout <<
"Rotation from Old Tsai method" << std::endl;
429 printf(
"Mean residual (rotation) = %lf\n",res);
448 int vpHandEyeCalibration::calibrationTranslation(
const std::vector<vpHomogeneousMatrix> &cMo,
449 const std::vector<vpHomogeneousMatrix> &rMe,
456 unsigned int nbPose = (
unsigned int)cMo.size();
461 for (
unsigned int i = 0; i < nbPose; i++) {
462 for (
unsigned int j = 0; j < nbPose; j++) {
495 if (rank != 3)
return -1;
502 printf(
"New Hand-eye calibration : ");
503 std::cout <<
"Translation: " << eTc[0] <<
" " << eTc[1] <<
" " << eTc[2] << std::endl;
509 printf(
"Mean residual (translation) = %lf\n",res);
528 int vpHandEyeCalibration::calibrationTranslationOld(
const std::vector<vpHomogeneousMatrix> &cMo,
529 const std::vector<vpHomogeneousMatrix> &rMe,
540 unsigned int nbPose = (
unsigned int)cMo.size();
542 for (
unsigned int i = 0; i < nbPose; i++) {
545 rMe[i].extract(rRei);
546 cMo[i].extract(ciRo);
547 rMe[i].extract(rTei);
548 cMo[i].extract(ciTo);
550 for (
unsigned int j = 0; j < nbPose; j++) {
555 rMe[j].extract(rRej);
556 cMo[j].extract(cjRo);
559 rMe[j].extract(rTej);
560 cMo[j].extract(cjTo);
566 rTeij = rRej.
t() * rTeij;
571 b = eRc * cjTo - rReij * eRc * ciTo + rTeij;
591 if (rank != 3)
return -1;
593 AeTc = Ap * A.
t() * B;
598 printf(
"Old Hand-eye calibration : ");
599 std::cout <<
"Translation: " << eTc[0] <<
" " << eTc[1] <<
" " << eTc[2] << std::endl;
606 for (
unsigned int i=0; i < residual.
getRows(); i++)
607 res += residual[i]*residual[i];
608 res = sqrt(res/residual.
getRows());
609 printf(
"Mean residual (translation) = %lf\n",res);
627 double vpHandEyeCalibration::calibrationErrVVS(
const std::vector<vpHomogeneousMatrix> &cMo,
const std::vector<vpHomogeneousMatrix> &rMe,
630 unsigned int nbPose = (
unsigned int) cMo.size();
639 for (
unsigned int i = 0; i < nbPose; i++) {
640 for (
unsigned int j = 0; j < nbPose; j++) {
667 s = (
vpMatrix(ejRei) - I3) * eTc - eRc * cjTci + ejTei;
673 double resRot, resTrans, resPos;
674 resRot = resTrans = resPos = 0.0;
675 for (
unsigned int i=0; i < (
unsigned int) errVVS.
size() ; i += 6)
677 resRot += errVVS[i]*errVVS[i];
678 resRot += errVVS[i+1]*errVVS[i+1];
679 resRot += errVVS[i+2]*errVVS[i+2];
680 resTrans += errVVS[i+3]*errVVS[i+3];
681 resTrans += errVVS[i+4]*errVVS[i+4];
682 resTrans += errVVS[i+5]*errVVS[i+5];
684 resPos = resRot + resTrans;
685 resRot = sqrt(resRot*2/errVVS.
size());
686 resTrans = sqrt(resTrans*2/errVVS.
size());
687 resPos = sqrt(resPos/errVVS.
size());
690 printf(
"Mean VVS residual - rotation (deg) = %lf\n",
vpMath::deg(resRot));
691 printf(
"Mean VVS residual - translation = %lf\n",resTrans);
692 printf(
"Mean VVS residual - global = %lf\n",resPos);
708 #define NB_ITER_MAX 30 710 int vpHandEyeCalibration::calibrationVVS(
const std::vector<vpHomogeneousMatrix> &cMo,
711 const std::vector<vpHomogeneousMatrix> &rMe,
716 unsigned int nbPose = (
unsigned int) cMo.size();
731 while ((res > 1e-7) && (it < NB_ITER_MAX))
734 vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, err);
737 for (
unsigned int i = 0; i < nbPose; i++) {
738 for (
unsigned int j = 0; j < nbPose; j++) {
757 for (
unsigned int m=0;m<3;m++)
758 for (
unsigned int n=0;n<3;n++)
761 Ls[m][n+3] = Lw[m][n];
772 for (
unsigned int m=0;m<3;m++)
773 for (
unsigned int n=0;n<3;n++)
776 Ls[m][n+3] = Lw[m][n];
786 if (rank != 6)
return -1;
799 printf(
" Iteration number for NL hand-eye minimisation : %d\n",it);
802 std::cout <<
"Translation: " << eTc[0] <<
" " << eTc[1] <<
" " << eTc[2] << std::endl;
805 res = sqrt(res/err.getRows());
806 printf(
"Mean residual (rotation+translation) = %lf\n",res);
809 if (it == NB_ITER_MAX)
return 1;
816 #define HE_TSAI_OROT 1 817 #define HE_TSAI_ORNT 2 818 #define HE_TSAI_NROT 3 819 #define HE_TSAI_NRNT 4 820 #define HE_PROCRUSTES_OT 5 821 #define HE_PROCRUSTES_NT 6 840 if (cMo.size() != rMe.size())
850 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
851 double vmin = resPos;
853 int He_method = HE_I;
857 int err = vpHandEyeCalibration::calibrationRotationTsaiOld(cMo, rMe, eRc);
858 if (err != 0) printf(
"\n Problem in solving Hand-Eye Rotation by Old Tsai method \n");
862 err = vpHandEyeCalibration::calibrationTranslationOld(cMo, rMe, eRc, eTc);
863 if (err != 0) printf(
"\n Problem in solving Hand-Eye Translation by Old Tsai method after Old Tsai method for Rotation\n");
869 printf(
"\nRotation by (old) Tsai, old implementation for translation\n");
870 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
873 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
879 He_method = HE_TSAI_OROT;
883 err = vpHandEyeCalibration::calibrationTranslation(cMo, rMe, eRc, eTc);
884 if (err != 0) printf(
"\n Problem in solving Hand-Eye Translation after Old Tsai method for Rotation\n");
890 printf(
"\nRotation by (old) Tsai, new implementation for translation\n");
891 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
894 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
900 He_method = HE_TSAI_ORNT;
906 err = vpHandEyeCalibration::calibrationRotationTsai(cMo, rMe, eRc);
907 if (err != 0) printf(
"\n Problem in solving Hand-Eye Rotation by Tsai method \n");
911 err = vpHandEyeCalibration::calibrationTranslationOld(cMo, rMe, eRc, eTc);
912 if (err != 0) printf(
"\n Problem in solving Hand-Eye Translation by Old Tsai method after Tsai method for Rotation\n");
918 printf(
"\nRotation by Tsai, old implementation for translation\n");
919 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
922 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
928 He_method = HE_TSAI_NROT;
932 err = vpHandEyeCalibration::calibrationTranslation(cMo, rMe, eRc, eTc);
933 if (err != 0) printf(
"\n Problem in solving Hand-Eye Translation after Tsai method for Rotation \n");
939 printf(
"\nRotation by Tsai, new implementation for translation\n");
940 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
943 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
949 He_method = HE_TSAI_NRNT;
955 err = vpHandEyeCalibration::calibrationRotationProcrustes(cMo, rMe, eRc);
956 if (err != 0) printf(
"\n Problem in solving Hand-Eye Rotation by Procrustes method \n");
960 err = vpHandEyeCalibration::calibrationTranslationOld(cMo, rMe, eRc, eTc);
961 if (err != 0) printf(
"\n Problem in solving Hand-Eye Translation by Old Tsai method after Procrustes method for Rotation\n");
967 printf(
"\nRotation by Procrustes, old implementation for translation\n");
968 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
971 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
977 He_method = HE_PROCRUSTES_OT;
981 err = vpHandEyeCalibration::calibrationTranslation(cMo, rMe, eRc, eTc);
982 if (err != 0) printf(
"\n Problem in solving Hand-Eye Translation after Procrustes method for Rotation\n");
988 printf(
"\nRotation by Procrustes, new implementation for translation\n");
989 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
992 resPos = vpHandEyeCalibration::calibrationErrVVS(cMo, rMe, eMc, errVVS);
998 He_method = HE_PROCRUSTES_NT;
1008 if (He_method == HE_I) printf(
"Best method : I !!!, vmin = %lf\n",vmin);
1009 if (He_method == HE_TSAI_OROT) printf(
"Best method : TSAI_OROT, vmin = %lf\n",vmin);
1010 if (He_method == HE_TSAI_ORNT) printf(
"Best method : TSAI_ORNT, vmin = %lf\n",vmin);
1011 if (He_method == HE_TSAI_NROT) printf(
"Best method : TSAI_NROT, vmin = %lf\n",vmin);
1012 if (He_method == HE_TSAI_NRNT) printf(
"Best method : TSAI_NRNT, vmin = %lf\n",vmin);
1013 if (He_method == HE_PROCRUSTES_OT) printf(
"Best method : PROCRUSTES_OT, vmin = %lf\n",vmin);
1014 if (He_method == HE_PROCRUSTES_NT) printf(
"Best method : PROCRUSTES_NT, vmin = %lf\n",vmin);
1017 std::cout <<
"Translation: " << eMc[0][3] <<
" " << eMc[1][3] <<
" " << eMc[2][3] << std::endl;
1022 err = vpHandEyeCalibration::calibrationVVS(cMo, rMe, eMc);
1024 if (err != 0) printf(
"\n Problem in solving Hand-Eye Calibration by VVS \n");
1027 printf(
"\nRotation and translation after VVS\n");
1028 vpHandEyeCalibration::calibrationVerifrMo(cMo, rMe, eMc);
1038 #undef HE_PROCRUSTES_OT 1039 #undef HE_PROCRUSTES_NT Implementation of a matrix and operations on matrices.
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Implementation of an homogeneous matrix and operations on such kind of matrices.
static int calibrate(const std::vector< vpHomogeneousMatrix > &cMo, const std::vector< vpHomogeneousMatrix > &rMe, vpHomogeneousMatrix &eMc)
void stack(const vpMatrix &A)
error that can be emited by ViSP classes.
unsigned int getRows() const
vpHomogeneousMatrix inverse() const
unsigned int size() const
Return the number of elements of the 2D array.
void extract(vpRotationMatrix &R) const
vpRotationMatrix t() const
static double sinc(double x)
Implementation of a rotation matrix and operations on such kind of matrices.
unsigned int getCols() const
void insert(const vpRotationMatrix &R)
static vpRotationMatrix mean(const std::vector< vpHomogeneousMatrix > &vec_M)
static vpTranslationVector mean(const std::vector< vpHomogeneousMatrix > &vec_M)
vpTranslationVector getTranslationVector() const
static double deg(double rad)
Implementation of column vector and the associated operations.
static vpHomogeneousMatrix direct(const vpColVector &v)
static vpMatrix skew(const vpColVector &v)
Class that consider the case of a translation vector.
Implementation of a rotation vector as axis-angle minimal representation.
vpRotationMatrix getRotationMatrix() const