47 #include <boost/program_options.hpp> 
   48 #include <boost/filesystem.hpp> 
   49 #include <boost/date_time/posix_time/posix_time.hpp> 
   50 #include <boost/date_time/posix_time/posix_time_io.hpp> 
   51 #include <boost/thread/thread.hpp> 
   52 #include <boost/thread/mutex.hpp> 
   57 namespace po = boost::program_options;
 
   58 namespace fs = boost::filesystem;
 
   73                 downloaded(downloaded)
 
   89                 path_config = 
string(getenv(
"HOME")) + 
"/.lpm/eval_solution.conf";
 
   90                 path_download = 
string(getenv(
"HOME")) + 
"/.lpm/download/";
 
   92                 path_server_validation = 
"robotics.ethz.ch/~asl-datasets/evaluations/validation";
 
   93                 path_server_protocols = 
"robotics.ethz.ch/~asl-datasets/evaluations/protocols";
 
   96                 info.
path = 
"robotics.ethz.ch/~asl-datasets/apartment_03-Dec-2011-18_13_33/csv_local/local_frame.zip";
 
   97                 dataSetStatus[info.
name] = info;
 
   99                 info.
path = 
"http://robotics.ethz.ch/~asl-datasets/ETH_hauptgebaude_23-Aug-2011-18_43_49/csv_local/local_frame.zip";
 
  100                 dataSetStatus[info.
name] = info;
 
  102                 info.
path = 
"http://robotics.ethz.ch/~asl-datasets/plain_01-Sep-2011-16_39_18/csv_local/local_frame.zip";
 
  103                 dataSetStatus[info.
name] = info;
 
  105                 info.
path = 
"http://robotics.ethz.ch/~asl-datasets/stairs_26-Aug-2011-14_26_14/csv_local/local_frame.zip";
 
  106                 dataSetStatus[info.
name] = info;
 
  108                 info.
path = 
"http://robotics.ethz.ch/~asl-datasets/gazebo_winter_18-Jan-2012-16_10_04/csv_local/local_frame.zip";
 
  109                 dataSetStatus[info.
name] = info;
 
  111                 info.
path = 
"http://robotics.ethz.ch/~asl-datasets/wood_summer_25-Aug-2011-13_00_30/csv_local/local_frame.zip";
 
  112                 dataSetStatus[info.
name] = info;
 
  124         void evaluateSolution(
const string &tmp_file_name, 
const string &yaml_config, 
const int &coreId, PMIO::FileInfoVector::const_iterator it_eval, PMIO::FileInfoVector::const_iterator it_end);
 
  128 po::options_description 
setupOptions(
const string & name);
 
  129 string outputStatus(map<string, DataSetInfo> dataSetStatus);
 
  136 void displayLoadingBar(
const int &coreId, 
const int &i, 
const int &total, 
const int &nbFailures, 
const double sec, 
const double total_time);
 
  138 int main(
int argc, 
char *argv[])
 
  140         srand ( time(NULL) );
 
  144         po::positional_options_description p;
 
  145         p.add(
"icp-config", -1);
 
  147         po::variables_map vm;
 
  148         po::store(po::command_line_parser(argc, argv).
 
  149                   options(desc).positional(p).
run(), vm);
 
  155         if (vm.count(
"help")) {
 
  156                 cout << desc << endl;
 
  162         if(fs::exists(c_path) == 
false)
 
  164                 fs::create_directories(c_path.parent_path());
 
  165                 cout << 
">> no configuration found. Using default values." << endl;
 
  173         if (vm.count(
"config")) 
 
  180         if (vm.count(
"download")) 
 
  187         if (vm.count(
"icp-config") == 
false)
 
  189                 cerr << 
"You must provide a YAMl file to evaluate it." << endl;
 
  193         const string yaml_config = vm[
"icp-config"].as<
string>();
 
  195                 ifstream cfgIfs(yaml_config.c_str());
 
  198                         cerr << 
"Cannot open YAML file name: it must exist and be readable." << endl;
 
  208                 if(vm.count(
"all") || vm.count(it->second.name))
 
  210                         if(it->second.downloaded == 
false)
 
  213                                 cerr << 
">> Please download data set first." << endl
 
  214                                      << 
">> You can use the option --download -A to download them all." << endl;
 
  218                         const string protocol_name = config.
path_download + 
"protocols/" + it->second.name + 
"_protocol.csv";
 
  219                         const string data_directory = config.
path_download + it->second.name + 
"/";
 
  221                         if(!fs::exists(fs::path(protocol_name)))
 
  224                                 cerr << 
">> Missing protocol file: " << protocol_name << endl
 
  225                                      << 
">> You can use the option --download to download it back." << endl;
 
  235                         mvprintw(0, 0, 
" <<< Evaluating %s >>>", it->second.name.c_str());
 
  239                         const int maxNbCore = 16;
 
  241                         if(vm[
"threads"].as<int>() > 1 || vm[
"threads"].as<int>() < maxNbCore)
 
  243                                 nbCore = vm[
"threads"].as<
int>();
 
  247                         boost::thread a_threads[maxNbCore];
 
  248                         std::vector<EvaluationModule> v_evalModules;
 
  250                         const int nbPerThread = eval_list.size()/nbCore;
 
  251                         PMIO::FileInfoVector::const_iterator it_start = eval_list.begin();
 
  252                         for (
int j=0; j<nbCore; ++j)
 
  255                                 v_evalModules[j].coreId = j;
 
  257                                 name << 
".tmp_core" << j << 
"_" << rand() << 
".csv";
 
  258                                 v_evalModules[j].tmp_file_name = name.str();
 
  270                                         it_start += nbPerThread;
 
  276                         for (
int k=0; k<nbCore; ++k)
 
  278                                 if(a_threads[k].joinable())
 
  283                         stringstream ss_path_time;
 
  284                         pt::time_facet *facet = 
new pt::time_facet(
"%d-%b-%Y-%H_%M_%S");
 
  285                         ss_path_time.imbue(locale(ss_path_time.getloc(), facet));
 
  287                         ss_path_time << config.
path_result << it->second.name << 
"_";
 
  288                         ss_path_time << pt::second_clock::local_time() << 
".csv";
 
  292                         mvprintw(nbCore+3, 0, 
"Last result written to: %s", ss_path_time.str().c_str());
 
  293                         std::ofstream fout(ss_path_time.str().c_str());
 
  296                                 cerr << 
"Warning, cannot open result file " << ss_path_time << 
", results were not saved" << endl;
 
  302                         for(
int r=0; r<4;++r)
 
  303                                 for(
int c=0; c<4;++c)
 
  304                                         fout << 
", T" << r << c;
 
  310                         for(
unsigned i=0; i<v_evalModules.size(); ++i)
 
  312                                 const string tmp_file_name = v_evalModules[i].tmp_file_name;
 
  313                                 ifstream tmp_file(tmp_file_name.c_str());
 
  314                                 if(tmp_file.is_open())
 
  316                                         fout << tmp_file.rdbuf();
 
  318                                         fs::remove(fs::path(tmp_file_name));
 
  323                                         cerr << 
"Cannot find tmp file named "<< tmp_file_name << endl;
 
  338         po::options_description desc(
"Allowed options");
 
  340             (
"help,h", 
"Print this message")
 
  341                 (
"icp-config", po::value<string>(), 
"YAML configuration file")
 
  342                 (
"config,C", 
"Interactive configuration")
 
  343                 (
"download,D", 
"Download selected data sets from the web")
 
  344                 (
"evaluate,E", 
"Evaluate a solution over selected data sets")
 
  345                 (
"threads,j", po::value<int>()->default_value(1), 
"Number of threads to use. Max 16.")
 
  346                 (
"apartment,a", 
"Apply action only on the data set Apartment")
 
  347                 (
"eth,e", 
"Apply action only on the data set ETH Hauptgebaude")
 
  348                 (
"plain,p", 
"Apply action only on the data set Mountain Plain")
 
  349                 (
"stairs,s", 
"Apply action only on the data set Stairs")
 
  350                 (
"gazebo,g", 
"Apply action only on the data set Gazebo Winter")
 
  351                 (
"wood,w", 
"Apply action only on the data set Wood Summer")
 
  352                 (
"all,A", 
"Apply action for all data sets")
 
  362         for(BOOST_AUTO(it, dataSetStatus.begin()); it != dataSetStatus.end(); ++it)
 
  364                 string paddedName = it->second.name + 
":";
 
  365                 while (paddedName.length() < 12) paddedName += 
" ";
 
  366                 ss << 
"\t" << paddedName;
 
  367                 if(it->second.downloaded)
 
  373                         ss << 
"not on your system.";
 
  385         bool validPath = 
false;
 
  390                 getline(cin, path_name);
 
  391                 validPath = fs::is_directory(fs::path(path_name));
 
  392                 if(validPath == 
false)
 
  393                         cout << 
">> Not a valid path" << endl;
 
  403         cout << 
"Current configuration:" << endl
 
  405                  << 
"\t Result path: " << config.
path_result << endl;
 
  407         cout << 
"Data set status:" << endl;
 
  410         while(!(answer == 
"" || answer == 
"y" ||answer == 
"Y" || answer == 
"n" || answer == 
"N")) 
 
  412                 cout << endl << 
"Do you want to change something? [y/N]: ";
 
  413                 getline(cin, answer);
 
  417                 if(answer == 
"y" ||answer == 
"Y" )
 
  451                         cerr << 
"Warning, cannot open config file " << config.
path_config << 
", content was not saved" << endl;
 
  454                 fout << emitter.
c_str();
 
  461         if (!f_config.good())
 
  463                 cerr << 
"Warning, cannot open config file " << config.
path_config << 
", content was not loaded" << endl;
 
  475                         string dataSetName = it->second.name;
 
  477                         node[
"downloaded"] >> it->second.downloaded;
 
  486         if(!fs::is_directory(extra_path))
 
  487                 fs::create_directories(extra_path);
 
  489         if(!fs::is_directory(extra_path))
 
  490                 fs::create_directories(extra_path);
 
  494                 if(vm.count(
"all") || vm.count(it->second.name))
 
  496                         cout << 
">> Fetching files for: " << it->second.name << 
"..." << endl << endl;
 
  498                         if(!fs::is_directory(d_path))
 
  499                                 fs::create_directories(d_path);
 
  503                         #define CHECK_RES if (sysRes != 0) { cerr << "Warning, system command \"" << cmd << "\" failed with result code " << sysRes << endl; } 
  506                         cout << 
">> Downloading validation file ..." << endl;
 
  508                         sysRes = system(
cmd.c_str());
 
  512                         cout << 
">> Downloading protocol file ..." << endl;
 
  514                         sysRes = system(
cmd.c_str());
 
  518                         cout << 
">> Downloading data set files ..." << endl;
 
  519                         cmd = 
"wget -P " + d_path.string() + 
" " + it->second.path;
 
  520                         sysRes = system(
cmd.c_str());
 
  523                         cout << 
">> Unzipping dataset..." << endl;
 
  524                         cmd = 
"unzip -q " + d_path.string() + 
"/local_frame.zip -d " + d_path.string() + 
"/";
 
  525                         sysRes = system(
cmd.c_str());
 
  528                         cmd = 
"rm " + d_path.string() + 
"/local_frame.zip";
 
  529                         sysRes = system(
cmd.c_str());
 
  532                         it->second.downloaded = 
true;
 
  541                 cout << 
"Missing columns representing initial transformation \"iTxy\"" << endl;
 
  547                 cout << 
"Missing column named \"reading\"" << endl;
 
  553                 cout << 
"Missing column named \"reference\"" << endl;
 
  560 void displayLoadingBar(
const int &coreId, 
const int &i, 
const int &total, 
const int &nbFailures, 
const double sec, 
const double total_time)
 
  562         const double average_time = total_time/double(i+1);
 
  563         int time = average_time*double(total-i);
 
  564         const int h=time/3600;
 
  575         mvprintw(coreId+1, 10, 
" Core %2d: %5d/%5d  failed: %2d last dur: %2.3f sec, avr: %2.3f sec, eta: %3dh%02dm%02d",coreId,i+1, total, nbFailures, sec, average_time, 
h, m, 
s);
 
  594 void EvaluationModule::evaluateSolution(
const string &tmp_file_name, 
const string &yaml_config, 
const int &coreId, PMIO::FileInfoVector::const_iterator it_eval, PMIO::FileInfoVector::const_iterator it_end)
 
  596         PM::DataPoints refCloud, readCloud;
 
  597         string last_read_name = 
"";
 
  598         string last_ref_name = 
"";
 
  599         const int count = std::distance(it_eval, it_end);
 
  600         int current_line = 0;
 
  606                 cerr << 
"Warning, cannot open temporary result file " << 
tmp_file_name << 
", evaluation was skipped" << endl;
 
  610         for( ; it_eval < it_end; ++it_eval)
 
  615                 if(last_read_name != it_eval->readingFileName)
 
  618                         last_read_name = it_eval->readingFileName;
 
  621                 if(last_ref_name != it_eval->referenceFileName)
 
  624                         last_ref_name = it_eval->referenceFileName;
 
  629                 ifstream ifs(yaml_config.c_str());
 
  630                 icp.loadFromYaml(ifs);
 
  632                 const TP Tinit = it_eval->initialTransformation;
 
  637                 TP Tresult = TP::Identity(4,4);
 
  641                         Tresult = icp(readCloud, refCloud, Tinit);
 
  643                 catch (PM::ConvergenceError error)
 
  650                 for(
int r=0; r<4;++r)
 
  651                         for(
int c=0; c<4;++c)
 
  652                                 fout << 
", " << Tresult(r,c);