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;
59 namespace pt = boost::posix_time;
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);
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" )
434 emitter << YAML::Key <<
"path_result";
439 emitter << YAML::Key << it->second.name;
442 emitter << YAML::Key <<
"downloaded";
443 emitter << YAML::Value << it->second.downloaded;
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);
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;
603 std::ofstream fout(tmp_file_name.c_str());
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)
617 readCloud = PM::DataPoints::load(it_eval->readingFileName);
618 last_read_name = it_eval->readingFileName;
621 if(last_ref_name != it_eval->referenceFileName)
623 refCloud = PM::DataPoints::load(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);
po::options_description setupOptions(const string &name)
TransformationParameters initialTransformation
matrix of initial estimate transform
DataSetInfo(string name, bool downloaded)
IO Functions and classes that are dependant on scalar type are defined in this templatized class...
PointMatcherIO< float > PMIO
std::string referenceFileName
file name of the reference point cloud
void validateFileInfo(const PMIO::FileInfo &fileInfo)
std::string readingFileName
file name of the reading point cloud
void loadConfig(Config &config)
void downloadDataSets(Config &config, po::variables_map &vm)
PM::DataPoints DataPoints
string outputStatus(map< string, DataSetInfo > dataSetStatus)
void saveConfig(Config &config)
Functions and classes that are not dependant on scalar type are defined in this namespace.
bool GetNextDocument(Node &document)
int main(int argc, char *argv[])
string path_server_validation
string path_server_protocols
Information to exploit a reading from a file using this library. Fields might be left blank if unused...
const char * c_str() const
PM::TransformationParameters TP
A vector of file info, to be used in batch processing.
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)
string enterValidPath(string message)
map< string, DataSetInfo > dataSetStatus
void displayLoadingBar(const int &coreId, const int &i, const int &total, const int &nbFailures, const double sec, const double total_time)
Matrix TransformationParameters
A matrix holding the parameters a transformation.
void setConfig(Config &config)