39 #include "boost/filesystem.hpp"
49 typedef PM::DataPoints
DP;
58 string& outputBaseFile,
59 string& initTranslation,
string& initRotation);
61 const int cloudDimension);
63 const int cloudDimension);
65 void usage(
const char *argv[]);
74 int main(
int argc,
const char *argv[])
76 bool isTransfoSaved =
false;
77 bool isVerbose =
false;
79 string outputBaseFile(
"test");
80 string initTranslation(
"0,0,0");
81 string initRotation(
"1,0,0;0,1,0;0,0,1");
82 const int ret =
validateArgs(argc, argv, isVerbose, isTransfoSaved, configFile,
83 outputBaseFile, initTranslation, initRotation);
88 const char *refFile(argv[argc-2]);
89 const char *dataFile(argv[argc-1]);
99 if (configFile.empty())
107 ifstream ifs(configFile.c_str());
110 cerr <<
"Cannot open config file " << configFile <<
", usage:";
usage(argv); exit(1);
112 icp.loadFromYaml(ifs);
118 if (!(cloudDimension == 2 || cloudDimension == 3))
120 cerr <<
"Invalid input point clouds dimension" << endl;
132 std::shared_ptr<PM::Transformation> rigidTrans;
133 rigidTrans =
PM::get().REG(Transformation).create(
"RigidTransformation");
135 if (!rigidTrans->checkParameters(initTransfo)) {
137 <<
"Initial transformation is not rigid, identiy will be used"
139 initTransfo = PM::TransformationParameters::Identity(
140 cloudDimension+1,cloudDimension+1);
143 const DP initializedData = rigidTrans->compute(data, initTransfo);
148 cout <<
"match ratio: " << icp.errorMinimizer->getWeightedPointUsedRatio() << endl;
151 DP data_out(initializedData);
152 icp.transformations.apply(data_out, T);
155 ref.
save(outputBaseFile +
"_ref.vtk");
156 data.
save(outputBaseFile +
"_data_in.vtk");
157 data_out.
save(outputBaseFile +
"_data_out.vtk");
159 ofstream transfoFile;
160 string initFileName = outputBaseFile +
"_init_transfo.txt";
161 string icpFileName = outputBaseFile +
"_icp_transfo.txt";
162 string completeFileName = outputBaseFile +
"_complete_transfo.txt";
164 transfoFile.open(initFileName.c_str());
165 if(transfoFile.is_open()) {
166 transfoFile << initTransfo << endl;
169 cerr <<
"Unable to write the initial transformation file\n" << endl;
172 transfoFile.open(icpFileName.c_str());
173 if(transfoFile.is_open()) {
174 transfoFile << T << endl;
177 cerr <<
"Unable to write the ICP transformation file\n" << endl;
180 transfoFile.open(completeFileName.c_str());
181 if(transfoFile.is_open()) {
182 transfoFile << T*initTransfo << endl;
185 cerr <<
"Unable to write the complete transformation file\n" << endl;
191 cout <<
"ICP transformation:" << endl << T << endl;
202 cout <<
"* " << name <<
" *\n" << endl;
203 for (BOOST_AUTO(it, registrar.begin()); it != registrar.end(); ++it)
205 cout << it->first << endl;
207 cout << it->second->availableParameters() << endl;
212 #define DUMP_REGISTRAR_CONTENT(pm, name, bib) \
213 dumpRegistrar(pm, pm.REG(name), # name, bib);
228 cout <<
"* Bibliography *" << endl << endl;
235 bool& isTransfoSaved,
237 string& outputBaseFile,
238 string& initTranslation,
string& initRotation)
242 cerr <<
"Not enough arguments, usage:";
248 if (
string(argv[1]) ==
"-l")
255 cerr <<
"Wrong option, usage:";
261 const int endOpt(argc - 2);
262 for (
int i = 1; i < endOpt; i += 2)
264 const string opt(argv[i]);
265 if (opt ==
"--verbose" || opt ==
"-v") {
272 cerr <<
"Missing value for option " << opt <<
", usage:";
usage(argv); exit(1);
274 if (opt ==
"--isTransfoSaved") {
275 if (strcmp(argv[i+1],
"1") == 0 || strcmp(argv[i+1],
"true") == 0) {
276 isTransfoSaved =
true;
278 else if (strcmp(argv[i+1],
"0") == 0
279 || strcmp(argv[i+1],
"false") == 0) {
280 isTransfoSaved =
false;
283 cerr <<
"Invalid value for parameter isTransfoSaved." << endl
284 <<
"Value must be true or false or 1 or 0." << endl
285 <<
"Default value will be used." << endl;
288 else if (opt ==
"--config") {
289 configFile = argv[i+1];
291 else if (opt ==
"--output") {
292 outputBaseFile = argv[i+1];
294 else if (opt ==
"--initTranslation") {
295 initTranslation = argv[i+1];
297 else if (opt ==
"--initRotation") {
298 initRotation = argv[i+1];
302 cerr <<
"Unknown option " << opt <<
", usage:";
usage(argv); exit(1);
309 const int cloudDimension) {
311 parsedTranslation = PM::TransformationParameters::Identity(
312 cloudDimension+1,cloudDimension+1);
314 translation.erase(std::remove(translation.begin(), translation.end(),
'['),
316 translation.erase(std::remove(translation.begin(), translation.end(),
']'),
318 std::replace( translation.begin(), translation.end(),
',',
' ');
319 std::replace( translation.begin(), translation.end(),
';',
' ');
321 float translationValues[3] = {0};
322 stringstream translationStringStream(translation);
323 for(
int i = 0; i < cloudDimension; i++) {
324 if(!(translationStringStream >> translationValues[i])) {
325 cerr <<
"An error occured while trying to parse the initial "
326 <<
"translation." << endl
327 <<
"No initial translation will be used" << endl;
328 return parsedTranslation;
331 float extraOutput = 0;
332 if((translationStringStream >> extraOutput)) {
333 cerr <<
"Wrong initial translation size" << endl
334 <<
"No initial translation will be used" << endl;
335 return parsedTranslation;
338 for(
int i = 0; i < cloudDimension; i++) {
339 parsedTranslation(i,cloudDimension) = translationValues[i];
342 return parsedTranslation;
346 const int cloudDimension){
348 parsedRotation = PM::TransformationParameters::Identity(
349 cloudDimension+1,cloudDimension+1);
351 rotation.erase(std::remove(rotation.begin(), rotation.end(),
'['),
353 rotation.erase(std::remove(rotation.begin(), rotation.end(),
']'),
355 std::replace( rotation.begin(), rotation.end(),
',',
' ');
356 std::replace( rotation.begin(), rotation.end(),
';',
' ');
358 float rotationMatrix[9] = {0};
359 stringstream rotationStringStream(rotation);
360 for(
int i = 0; i < cloudDimension*cloudDimension; i++) {
361 if(!(rotationStringStream >> rotationMatrix[i])) {
362 cerr <<
"An error occured while trying to parse the initial "
363 <<
"rotation." << endl
364 <<
"No initial rotation will be used" << endl;
365 return parsedRotation;
368 float extraOutput = 0;
369 if((rotationStringStream >> extraOutput)) {
370 cerr <<
"Wrong initial rotation size" << endl
371 <<
"No initial rotation will be used" << endl;
372 return parsedRotation;
375 for(
int i = 0; i < cloudDimension*cloudDimension; i++) {
376 parsedRotation(i/cloudDimension,i%cloudDimension) = rotationMatrix[i];
379 return parsedRotation;
386 cerr << endl << endl;
387 cerr <<
"* To list modules:" << endl;
388 cerr <<
" " << argv[0] <<
" -l" << endl;
390 cerr <<
"* To run ICP:" << endl;
391 cerr <<
" " << argv[0] <<
" [OPTIONS] reference.csv reading.csv" << endl;
393 cerr <<
"OPTIONS can be a combination of:" << endl;
394 cerr <<
"-v,--verbose Be more verbose (info logging to stdout)" << endl;
395 cerr <<
"--config YAML_CONFIG_FILE Load the config from a YAML file (default: default parameters)" << endl;
396 cerr <<
"--output BASEFILENAME Name of output files (default: test)" << endl;
397 cerr <<
"--initTranslation [x,y,z] Add an initial 3D translation before applying ICP (default: 0,0,0)" << endl;
398 cerr <<
"--initTranslation [x,y] Add an initial 2D translation before applying ICP (default: 0,0)" << endl;
399 cerr <<
"--initRotation [r00,r01,r02,r10,r11,r12,r20,r21,r22]" << endl;
400 cerr <<
" Add an initial 3D rotation before applying ICP (default: 1,0,0,0,1,0,0,0,1)" << endl;
401 cerr <<
"--initRotation [r00,r01,r10,r11]" << endl;
402 cerr <<
" Add an initial 2D rotation before applying ICP (default: 1,0,0,1)" << endl;
403 cerr <<
"--isTransfoSaved BOOL Save transformation matrix in three different files:" << endl;
404 cerr <<
" - BASEFILENAME_inti_transfo.txt" << endl;
405 cerr <<
" - BASEFILENAME_icp_transfo.txt" << endl;
406 cerr <<
" - BASEFILENAME_complete_transfo.txt" << endl;
407 cerr <<
" (default: false)" << endl;
409 cerr <<
"Running this program with a VTKFileInspector as Inspector will create three" << endl;
410 cerr <<
"vtk ouptput files: ./test_ref.vtk, ./test_data_in.vtk and ./test_data_out.vtk" << endl;
411 cerr << endl <<
"2D Example:" << endl;
412 cerr <<
" " << argv[0] <<
" ../examples/data/2D_twoBoxes.csv ../examples/data/2D_oneBox.csv" << endl;
413 cerr << endl <<
"3D Example:" << endl;
414 cerr <<
" " << argv[0] <<
" ../examples/data/car_cloud400.csv ../examples/data/car_cloud401.csv" << endl;