40#include <visp3/core/vpConfig.h>
41#include <visp3/core/vpIoTools.h>
42#include <visp3/vision/vpHandEyeCalibration.h>
44void usage(
const char *argv[],
int error)
46 std::cout <<
"Synopsis" << std::endl
48 <<
" [--data-path <path>]"
49 <<
" [--rPe <generic name>]"
50 <<
" [--cPo <generic name>]"
51 <<
" [--output-ePc <filename>]"
52 <<
" [--help, -h]" << std::endl
54 std::cout <<
"Description" << std::endl
55 <<
" Compute eye-in-hand calibration." << std::endl
57 <<
" --data-path <path>" << std::endl
58 <<
" Path to the folder containing pose_rPe_%d.yaml and pose_cPo_%d.yaml data files." << std::endl
59 <<
" Default: \"./\"" << std::endl
61 <<
" --rPe <generic name>" << std::endl
62 <<
" Generic name of the yaml files containing the pose of the end-effector expressed in the robot" << std::endl
63 <<
" base frame and located in the data path folder." << std::endl
64 <<
" Default: pose_rPe_%d.yaml" << std::endl
66 <<
" --cPo <generic name>" << std::endl
67 <<
" Generic name of the yaml files" << std::endl
68 <<
" containing the pose of the calibration grid expressed in the camera frame and located in the" << std::endl
69 <<
" data path folder." << std::endl
70 <<
" Default: pose_cPo_%d.yaml" << std::endl
72 <<
" --output-ePc <filename>" << std::endl
73 <<
" File in yaml format containing the pose of the camera" << std::endl
74 <<
" in the end-effector frame. Data are saved as a pose vector with first the 3 translations" << std::endl
75 <<
" along X,Y,Z in [m] and then the 3 rotations in axis-angle representation (thetaU) in [rad]." << std::endl
76 <<
" Default: ePc.yaml" << std::endl
78 <<
" --output-rPo <filename>" << std::endl
79 <<
" File in yaml format containing the pose of the object" << std::endl
80 <<
" in the robot reference frame. Data are saved as a pose vector with first the 3 translations" << std::endl
81 <<
" along X,Y,Z in [m] and then the 3 rotations in axis-angle representation (thetaU) in [rad]." << std::endl
82 <<
" Default: rPo.yaml" << std::endl
84 <<
" --help, -h" << std::endl
85 <<
" Print this helper message." << std::endl
88 std::cout <<
"Error" << std::endl
90 <<
"Unsupported parameter " << argv[
error] << std::endl;
94int main(
int argc,
const char *argv[])
96#if defined(ENABLE_VISP_NAMESPACE)
100 std::string opt_data_path =
"./";
101 std::string opt_rPe_files =
"pose_rPe_%d.yaml";
102 std::string opt_cPo_files =
"pose_cPo_%d.yaml";
103 std::string opt_ePc_file =
"ePc.yaml";
104 std::string opt_rPo_file =
"rPo.yaml";
106 for (
int i = 1;
i < argc;
i++) {
107 if (std::string(argv[i]) ==
"--data-path" && i + 1 < argc) {
108 opt_data_path = std::string(argv[++i]);
110 else if (std::string(argv[i]) ==
"--rPe" && i + 1 < argc) {
111 opt_rPe_files = std::string(argv[++i]);
113 else if (std::string(argv[i]) ==
"--cPo" && i + 1 < argc) {
114 opt_cPo_files = std::string(argv[++i]);
116 else if (std::string(argv[i]) ==
"--output-ePc" && i + 1 < argc) {
117 opt_ePc_file = std::string(argv[++i]);
119 else if (std::string(argv[i]) ==
"--output-rPo" && i + 1 < argc) {
120 opt_rPo_file = std::string(argv[++i]);
122 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
135 std::cout <<
"Create output directory: " << output_parent << std::endl;
139 std::vector<vpHomogeneousMatrix>
cMo;
140 std::vector<vpHomogeneousMatrix> rMe;
144 std::map<long, std::string> map_rPe_files;
145 std::map<long, std::string> map_cPo_files;
147 for (
unsigned int i = 0;
i < files.size();
i++) {
150 if (index_rPe != -1) {
151 map_rPe_files[index_rPe] = files[
i];
153 if (index_cPo != -1) {
154 map_cPo_files[index_cPo] = files[
i];
158 if (map_rPe_files.size() == 0) {
159 std::cout <<
"No " << opt_rPe_files
160 <<
" files found. Use --data-path <path> or --rPe <generic name> to be able to read your data." << std::endl;
161 std::cout <<
"Use --help option to see full usage..." << std::endl;
164 if (map_cPo_files.size() == 0) {
165 std::cout <<
"No " << opt_cPo_files
166 <<
" files found. Use --data-path <path> or --cPo <generic name> to be able to read your data." << std::endl;
167 std::cout <<
"Use --help option to see full usage..." << std::endl;
171 for (std::map<long, std::string>::const_iterator it_rPe = map_rPe_files.begin(); it_rPe != map_rPe_files.end();
174 std::map<long, std::string>::const_iterator it_cPo = map_cPo_files.find(it_rPe->first);
175 if (it_cPo != map_cPo_files.end()) {
177 if (rPe.
loadYAML(file_rPe, rPe) ==
false) {
178 std::cout <<
"Unable to read data from " << file_rPe <<
". Skip data" << std::endl;
184 if (cPo.
loadYAML(file_cPo, cPo) ==
false) {
185 std::cout <<
"Unable to read data from " << file_cPo <<
". Skip data" << std::endl;
188 std::cout <<
"Use data from " << opt_data_path <<
"/" << file_rPe <<
" and from " << file_cPo << std::endl;
194 if (rMe.size() < 3) {
195 std::cout <<
"Not enough data pairs found." << std::endl;
202 std::cout << std::endl <<
"Eye-in-hand calibration succeed" << std::endl;
203 std::cout << std::endl <<
"Estimated eMc transformation:" << std::endl;
204 std::cout <<
"-----------------------------" << std::endl;
207 std::cout <<
"- Corresponding pose vector [tx ty tz tux tuy tuz] in [m] and [rad]: " <<
vpPoseVector(eMc).
t() << std::endl;
210 std::cout << std::endl <<
"- Translation [m]: " << eMc[0][3] <<
" " << eMc[1][3] <<
" " << eMc[2][3] << std::endl;
211 std::cout <<
"- Rotation (theta-u representation) [rad]: " << erc.
t() << std::endl;
212 std::cout <<
"- Rotation (theta-u representation) [deg]: " <<
vpMath::deg(erc[0]) <<
" " <<
vpMath::deg(erc[1])
215 std::cout <<
"- Rotation (quaternion representation) [rad]: " << quaternion.t() << std::endl;
217 std::cout <<
"- Rotation (r-x-y-z representation) [rad]: " << rxyz.t() << std::endl;
218 std::cout <<
"- Rotation (r-x-y-z representation) [deg]: " <<
vpMath::deg(rxyz).t() << std::endl;
220 std::cout << std::endl <<
"Estimated rMo transformation:" << std::endl;
221 std::cout <<
"-----------------------------" << std::endl;
224 std::cout <<
"- Corresponding pose vector [tx ty tz tux tuy tuz] in [m] and [rad]: " <<
vpPoseVector(rMo).
t() << std::endl;
227 std::cout << std::endl <<
"- Translation [m]: " << rMo[0][3] <<
" " << rMo[1][3] <<
" " << rMo[2][3] << std::endl;
228 std::cout <<
"- Rotation (theta-u representation) [rad]: " << wrc.
t() << std::endl;
229 std::cout <<
"- Rotation (theta-u representation) [deg]: " <<
vpMath::deg(wrc[0]) <<
" " <<
vpMath::deg(wrc[1])
232 std::cout <<
"- Rotation (quaternion representation) [rad]: " << quaternion2.t() << std::endl;
234 std::cout <<
"- Rotation (r-x-y-z representation) [rad]: " << rxyz2.t() << std::endl;
235 std::cout <<
"- Rotation (r-x-y-z representation) [deg]: " <<
vpMath::deg(rxyz).t() << std::endl;
240 std::cout << std::endl <<
"Save transformation matrix eMc as an homogeneous matrix in: " << name_we << std::endl;
242#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_98)
243 std::ofstream file_eMc(name_we);
245 std::ofstream file_eMc(name_we.c_str());
252 std::cout <<
"Save transformation matrix eMc as a vpPoseVector in : " << output_filename << std::endl;
253 pose_vec.saveYAML(output_filename, pose_vec);
259 std::cout << std::endl <<
"Save transformation matrix rMo as an homogeneous matrix in: " << name_we << std::endl;
261#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_98)
262 std::ofstream file_rMo(name_we);
264 std::ofstream file_rMo(name_we.c_str());
271 std::cout <<
"Save transformation matrix rMo as a vpPoseVector in : " << output_filename << std::endl;
272 pose_vec.saveYAML(output_filename, pose_vec,
"Robot reference to object frames transformation (rMo)");
276 std::cout << std::endl <<
"** Eye-in-hand calibration failed" << std::endl;
277 std::cout << std::endl <<
"Check your input data and ensure they are covering the half sphere over the chessboard." << std::endl;
278 std::cout << std::endl <<
"See https://visp-doc.inria.fr/doxygen/visp-daily/tutorial-calibration-extrinsic-eye-in-hand.html" << std::endl;
static bool loadYAML(const std::string &filename, vpArray2D< Type > &A, char *header=nullptr)
vpArray2D< Type > t() const
Compute the transpose of the array.
static int calibrate(const std::vector< vpHomogeneousMatrix > &cMo, const std::vector< vpHomogeneousMatrix > &rMe, vpHomogeneousMatrix &eMc, vpHomogeneousMatrix &rMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
void save(std::ofstream &f) const
static double deg(double rad)
Implementation of a matrix and operations on matrices.
int print(std::ostream &s, unsigned int length, const std::string &intro="") const
Implementation of a pose vector and operations on poses.
Implementation of a rotation vector as quaternion angle minimal representation.
Implementation of a rotation vector as Euler angle minimal representation.
Implementation of a rotation vector as axis-angle minimal representation.