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;