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