00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <rtabmap/utilite/ULogger.h>
00029 #include <rtabmap/utilite/UTimer.h>
00030 #include "rtabmap/core/Rtabmap.h"
00031 #include "rtabmap/core/CameraRGB.h"
00032 #include <rtabmap/utilite/UDirectory.h>
00033 #include <rtabmap/utilite/UFile.h>
00034 #include <rtabmap/utilite/UConversion.h>
00035 #include <rtabmap/utilite/UStl.h>
00036 #include <fstream>
00037 #include <queue>
00038 #include <opencv2/core/core.hpp>
00039 #include <signal.h>
00040
00041 using namespace rtabmap;
00042
00043 #define GENERATED_GT_NAME "GroundTruth_generated.bmp"
00044
00045 void showUsage()
00046 {
00047 printf("\nUsage:\n"
00048 "rtabmap-console [options] \"path\"\n"
00049 " path For images, use the directory path. For videos or databases, use full\n "
00050 " path name\n"
00051 "Options:\n"
00052 " -rate #.## Acquisition time (seconds)\n"
00053 " -rateHz #.## Acquisition rate (Hz), for convenience\n"
00054 " -repeat # Repeat the process on the data set # times (minimum of 1)\n"
00055 " -createGT Generate a ground truth file\n"
00056 " -start_at # When \"path\" is a directory of images, set this parameter\n"
00057 " to start processing at image # (default 0).\n"
00058 " -skip # Skip X images while reading directory (default 0).\n"
00059 " -v Get version of RTAB-Map\n"
00060 " -input \"path\" Load previous database if it exists.\n"
00061 "%s\n",
00062 rtabmap::Parameters::showUsage());
00063 exit(1);
00064 }
00065
00066
00067 bool g_forever = true;
00068 void sighandler(int sig)
00069 {
00070 printf("\nSignal %d caught...\n", sig);
00071 g_forever = false;
00072 }
00073
00074 int main(int argc, char * argv[])
00075 {
00076 signal(SIGABRT, &sighandler);
00077 signal(SIGTERM, &sighandler);
00078 signal(SIGINT, &sighandler);
00079
00080 ULogger::setType(ULogger::kTypeConsole);
00081 ULogger::setLevel(ULogger::kWarning);
00082
00083 ParametersMap pm = Parameters::parseArguments(argc, argv);
00084 pm.insert(ParametersPair(Parameters::kRtabmapWorkingDirectory(), "."));
00085
00086 if(argc < 2)
00087 {
00088 showUsage();
00089 }
00090 else if(argc == 2 && strcmp(argv[1], "-v") == 0)
00091 {
00092 printf("%s\n", Parameters::getVersion().c_str());
00093 exit(0);
00094 }
00095 printf("\n");
00096
00097 std::string path;
00098 float rate = 0.0;
00099 int loopDataset = 0;
00100 int repeat = 0;
00101 bool createGT = false;
00102 std::string inputDbPath;
00103 int startAt = 0;
00104 int skip = 0;
00105
00106 for(int i=1; i<argc; ++i)
00107 {
00108 if(i == argc-1)
00109 {
00110
00111 path = argv[i];
00112 if(!UDirectory::exists(path.c_str()) && !UFile::exists(path.c_str()))
00113 {
00114 printf("Path not valid : %s\n", path.c_str());
00115 showUsage();
00116 exit(1);
00117 }
00118 break;
00119 }
00120 if(strcmp(argv[i], "-rate") == 0)
00121 {
00122 ++i;
00123 if(i < argc)
00124 {
00125 rate = uStr2Float(argv[i]);
00126 if(rate < 0)
00127 {
00128 showUsage();
00129 }
00130 }
00131 else
00132 {
00133 showUsage();
00134 }
00135 continue;
00136 }
00137 if(strcmp(argv[i], "-rateHz") == 0)
00138 {
00139 ++i;
00140 if(i < argc)
00141 {
00142 rate = uStr2Float(argv[i]);
00143 if(rate < 0)
00144 {
00145 showUsage();
00146 }
00147 else if(rate)
00148 {
00149 rate = 1/rate;
00150 }
00151 }
00152 else
00153 {
00154 showUsage();
00155 }
00156 continue;
00157 }
00158 if(strcmp(argv[i], "-repeat") == 0)
00159 {
00160 ++i;
00161 if(i < argc)
00162 {
00163 repeat = std::atoi(argv[i]);
00164 if(repeat < 1)
00165 {
00166 showUsage();
00167 }
00168 }
00169 else
00170 {
00171 showUsage();
00172 }
00173 continue;
00174 }
00175 if(strcmp(argv[i], "-start_at") == 0)
00176 {
00177 ++i;
00178 if(i < argc)
00179 {
00180 startAt = std::atoi(argv[i]);
00181 if(startAt < 0)
00182 {
00183 showUsage();
00184 }
00185 }
00186 else
00187 {
00188 showUsage();
00189 }
00190 continue;
00191 }
00192 if (strcmp(argv[i], "-skip") == 0)
00193 {
00194 ++i;
00195 if (i < argc)
00196 {
00197 skip = std::atoi(argv[i]);
00198 if (skip < 0)
00199 {
00200 showUsage();
00201 }
00202 }
00203 else
00204 {
00205 showUsage();
00206 }
00207 continue;
00208 }
00209 if(strcmp(argv[i], "-createGT") == 0)
00210 {
00211 createGT = true;
00212 continue;
00213 }
00214 if(strcmp(argv[i], "-input") == 0)
00215 {
00216 ++i;
00217 if(i < argc)
00218 {
00219 inputDbPath = argv[i];
00220 }
00221 else
00222 {
00223 showUsage();
00224 }
00225 continue;
00226 }
00227 if(strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "--help") == 0)
00228 {
00229 showUsage();
00230 }
00231 }
00232
00233 if(repeat && createGT)
00234 {
00235 printf("Cannot create a Ground truth if repeat is on.\n");
00236 showUsage();
00237 }
00238
00239 UTimer timer;
00240 timer.start();
00241 std::queue<double> iterationMeanTime;
00242
00243 Camera * camera = 0;
00244 if(UDirectory::exists(path))
00245 {
00246 camera = new CameraImages(path, rate>0.0f?1.0f/rate:0.0f);
00247 ((CameraImages*)camera)->setStartIndex(startAt);
00248 }
00249 else
00250 {
00251 camera = new CameraVideo(path, false, rate>0.0f?1.0f/rate:0.0f);
00252 }
00253
00254 if(!camera || !camera->init())
00255 {
00256 printf("Camera init failed, using path \"%s\"\n", path.c_str());
00257 exit(1);
00258 }
00259
00260 std::map<int, int> groundTruth;
00261
00262
00263 Rtabmap rtabmap;
00264 if(inputDbPath.empty())
00265 {
00266 inputDbPath = "rtabmapconsole.db";
00267 if(UFile::erase(inputDbPath) == 0)
00268 {
00269 printf("Deleted database \"%s\".\n", inputDbPath.c_str());
00270 }
00271 }
00272 else
00273 {
00274 printf("Loading database \"%s\".\n", inputDbPath.c_str());
00275 }
00276
00277
00278 uInsert(pm, ParametersPair(Parameters::kRtabmapPublishStats(), "false"));
00279 uInsert(pm, ParametersPair(Parameters::kRGBDEnabled(), "false"));
00280
00281
00282 ULogger::Level level = ULogger::level();
00283 ULogger::setLevel(ULogger::kError);
00284 cv::Mat tmp = cv::Mat::zeros(640,480,CV_8UC1);
00285 rtabmap.init(pm);
00286 rtabmap.process(tmp);
00287 rtabmap.close(false);
00288 ULogger::setLevel(level);
00289
00290 rtabmap.init(pm, inputDbPath);
00291
00292 printf("rtabmap init time = %fs\n", timer.ticks());
00293
00294
00295 int loopClosureId;
00296 int count = 0;
00297 int countLoopDetected=0;
00298
00299 printf("\nParameters : \n");
00300 printf(" Data set : %s\n", path.c_str());
00301 printf(" Time threshold = %1.2f ms\n", rtabmap.getTimeThreshold());
00302 printf(" Image rate = %1.2f s (%1.2f Hz)\n", rate, 1/rate);
00303 printf(" Repeating data set = %s\n", repeat?"true":"false");
00304 printf(" Camera starts at image %d (default 0)\n", startAt);
00305 printf(" Skip image = %d\n", skip);
00306 if(createGT)
00307 {
00308 printf(" Creating the ground truth matrix.\n");
00309 }
00310 printf(" INFO: All other parameters are set to defaults\n");
00311 if(pm.size()>1)
00312 {
00313 printf(" Overwritten parameters :\n");
00314 for(ParametersMap::iterator iter = pm.begin(); iter!=pm.end(); ++iter)
00315 {
00316 printf(" %s=%s\n",iter->first.c_str(), iter->second.c_str());
00317 }
00318 }
00319 if(rtabmap.getWM().size() || rtabmap.getSTM().size())
00320 {
00321 printf("[Warning] RTAB-Map database is not empty (%s)\n", inputDbPath.c_str());
00322 }
00323 printf("\nProcessing images...\n");
00324
00325 UTimer iterationTimer;
00326 UTimer rtabmapTimer;
00327 int imagesProcessed = 0;
00328 std::list<std::vector<float> > teleopActions;
00329 while(loopDataset <= repeat && g_forever)
00330 {
00331 SensorData data = camera->takeImage();
00332 int i=0;
00333 double maxIterationTime = 0.0;
00334 int maxIterationTimeId = 0;
00335 while(!data.imageRaw().empty() && g_forever)
00336 {
00337 ++imagesProcessed;
00338 iterationTimer.start();
00339 rtabmapTimer.start();
00340 rtabmap.process(data.imageRaw());
00341 double rtabmapTime = rtabmapTimer.elapsed();
00342 loopClosureId = rtabmap.getLoopClosureId();
00343 if(rtabmap.getLoopClosureId())
00344 {
00345 ++countLoopDetected;
00346 }
00347 for(int j=0; j<=skip; ++j)
00348 {
00349 data = camera->takeImage();
00350 }
00351 if(++count % 100 == 0)
00352 {
00353 printf(" count = %d, loop closures = %d, max time (at %d) = %fs\n",
00354 count, countLoopDetected, maxIterationTimeId, maxIterationTime);
00355 maxIterationTime = 0.0;
00356 maxIterationTimeId = 0;
00357 std::map<int, int> wm = rtabmap.getWeights();
00358 printf(" WM(%d)=[", (int)wm.size());
00359 for(std::map<int, int>::iterator iter=wm.begin(); iter!=wm.end();++iter)
00360 {
00361 if(iter != wm.begin())
00362 {
00363 printf(";");
00364 }
00365 printf("%d,%d", iter->first, iter->second);
00366 }
00367 printf("]\n");
00368 }
00369
00370
00371 if(createGT)
00372 {
00373 if(loopClosureId > 0)
00374 {
00375 groundTruth.insert(std::make_pair(i, loopClosureId-1));
00376 }
00377 }
00378
00379 ++i;
00380
00381 double iterationTime = iterationTimer.ticks();
00382
00383 if(rtabmapTime > maxIterationTime)
00384 {
00385 maxIterationTime = rtabmapTime;
00386 maxIterationTimeId = count;
00387 }
00388
00389 ULogger::flush();
00390
00391 if(rtabmap.getLoopClosureId())
00392 {
00393 printf(" iteration(%d) loop(%d) hyp(%.2f) time=%fs/%fs *\n",
00394 count, rtabmap.getLoopClosureId(), rtabmap.getLoopClosureValue(), rtabmapTime, iterationTime);
00395 }
00396 else if(rtabmap.getHighestHypothesisId())
00397 {
00398 printf(" iteration(%d) high(%d) hyp(%.2f) time=%fs/%fs\n",
00399 count, rtabmap.getHighestHypothesisId(), rtabmap.getHighestHypothesisValue(), rtabmapTime, iterationTime);
00400 }
00401 else
00402 {
00403 printf(" iteration(%d) time=%fs/%fs\n", count, rtabmapTime, iterationTime);
00404 }
00405
00406 if(rtabmap.getTimeThreshold() && rtabmapTime > rtabmap.getTimeThreshold()*100.0f)
00407 {
00408 printf(" ERROR, there is problem, too much time taken... %fs", rtabmapTime);
00409 break;
00410 }
00411 }
00412 ++loopDataset;
00413 if(loopDataset <= repeat)
00414 {
00415 camera->init();
00416 printf(" Beginning loop %d...\n", loopDataset);
00417 }
00418 }
00419 printf("Processing images completed. Loop closures found = %d\n", countLoopDetected);
00420 printf(" Total time = %fs\n", timer.ticks());
00421
00422 if(imagesProcessed && createGT)
00423 {
00424 cv::Mat groundTruthMat = cv::Mat::zeros(imagesProcessed, imagesProcessed, CV_8U);
00425
00426 for(std::map<int, int>::iterator iter = groundTruth.begin(); iter!=groundTruth.end(); ++iter)
00427 {
00428 groundTruthMat.at<unsigned char>(iter->first, iter->second) = 255;
00429 }
00430
00431
00432 printf("Generate ground truth to file %s, size of %d\n", GENERATED_GT_NAME, groundTruthMat.rows);
00433 cv::imwrite(GENERATED_GT_NAME, groundTruthMat);
00434 printf(" Creating ground truth file = %fs\n", timer.ticks());
00435 }
00436
00437 if(camera)
00438 {
00439 delete camera;
00440 camera = 0 ;
00441 }
00442
00443 rtabmap.close();
00444
00445 printf(" Cleanup time = %fs\n", timer.ticks());
00446
00447 printf("Database (\"%s\") and log files saved to current directory.\n", inputDbPath.c_str());
00448
00449 return 0;
00450 }