/* * Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke * * This file is part of RTAB-Map. * * RTAB-Map is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RTAB-Map is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RTAB-Map. If not, see . */ #include #include #include "rtabmap/core/Rtabmap.h" #include "rtabmap/core/Camera.h" #include "rtabmap/core/SMState.h" #include #include #include #include #include #include #include #include using namespace rtabmap; #define GENERATED_GT_NAME "GroundTruth_generated.txt" void showUsage() { printf("\nUsage:\n" "rtabmap-console [options] \"path\"\n" " path For images, use the directory path. For videos, use full\n " " path name\n" "Options:\n" " -t #.## Time threshold (seconds)\n" " -rate #.## Acquisition time (seconds)\n" " -rateHz #.## Acquisition rate (Hz), for convenience\n" " -repeat # Repeat the process on the data set # times (minimum of 1)\n" " -createGT # Generate a ground truth file of dim # (>0, must match the size\n" " of the data set)\n" " -image_width # Force an image width (Default 0: original size used).\n" " The height must be also specified if changed.\n" " -image_height # Force an image height (Default 0: original size used)\n" " The height must be also specified if changed.\n" " -\"parameter name\" \"value\" Overwrite a specific RTAB-Map's parameter :\n" " -SURF/HessianThreshold 150\n" " For parameters in table format, add ',' between values :\n" " -Kp/RoiRatios 0,0,0.1,0\n" " Default parameters can be found in ~/.rtabmap/rtabmap.ini\n" " -default_params Show default RTAB-Map's parameters (WARNING : \n" " parameters from rtabmap.ini (if exists) overwrite the default \n" " ones shown here)\n" " -debug Set Log level to Debug (Default Error)\n" " -info Set Log level to Info (Default Error)\n" " -warn Set Log level to Warning (Default Error)\n" " -exit_warn Set exit level to Warning (Default Fatal)\n" " -exit_error Set exit level to Error (Default Fatal)\n" " -v Get version of RTAB-Map\n"); exit(1); } // catch ctrl-c bool g_forever = true; void sighandler(int sig) { printf("\nSignal %d caught...\n", sig); g_forever = false; } int main(int argc, char * argv[]) { signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); /*for(int i=0; ifirst.c_str(), iter->second.c_str()); } exit(0); } printf("\n"); std::string path; float timeThreshold = 0.0; float rate = 0.0; int loopDataset = 0; int repeat = 0; int createGT = 0; int imageWidth = 0; int imageHeight = 0; ParametersMap pm; ULogger::Level logLevel = ULogger::kError; ULogger::Level exitLevel = ULogger::kFatal; for(int i=1; i iterationMeanTime; Camera * camera = 0; if(UDirectory::exists(path)) { camera = new CameraImages(path, 1, false, 0.0f, false, imageWidth, imageHeight); } else { camera = new CameraVideo(path, 0.0f, false, imageWidth, imageHeight); } if(!camera || !camera->init()) { printf("Camera init failed, using path \"%s\"\n", path.c_str()); exit(1); } CvMat * groundTruthMat = 0; if(createGT) { printf("Creating the ground truth matrix...%dx%d\n", createGT, createGT); groundTruthMat = cvCreateMat(createGT, createGT, CV_32FC1); } // Create tasks Rtabmap * rtabmap = new Rtabmap(); rtabmap->init(); rtabmap->setMaxTimeAllowed(timeThreshold); // in sec //ULogger::setType(ULogger::kTypeConsole); ULogger::setType(ULogger::kTypeFile, rtabmap->getWorkingDir()+"/LogConsole.txt", false); ULogger::setBuffered(true); ULogger::setLevel(logLevel); ULogger::setExitLevel(exitLevel); // Disable statistics (we don't need them) pm.insert(ParametersPair(Parameters::kRtabmapPublishStats(), uBool2str(false))); rtabmap->init(pm); printf("Avpd init time = %fs\n", timer.ticks()); // Start thread's task IplImage * image = 0; int loopClosureId; int count = 0; int countLoopDetected=0; printf("\nParameters : \n"); printf(" Data set : %s\n", path.c_str()); printf(" Time threshold = %1.2f\n", timeThreshold); printf(" Image rate = %1.2f s (%1.2f Hz)\n", rate, 1/rate); printf(" Repeating dataset = %s\n", repeat?"true":"false"); printf(" Camera width=%d, height=%d (0 is default)\n", imageWidth, imageHeight); printf(" INFO: All other parameters are taken from the INI file located in \"~/.rtabmap\"\n"); if(pm.size()>1) { printf(" Overwritten parameters :\n"); for(ParametersMap::iterator iter = pm.begin(); iter!=pm.end(); ++iter) { printf(" %s=%s\n",iter->first.c_str(), iter->second.c_str()); } } printf("\nProcessing images...\n"); UTimer iterationTimer; int imagesProcessed = 0; std::list > teleopActions; int maxTeleopActions = 0; // TEST Lip6Indoor with 190, 0->disabled std::list > actions; while(loopDataset <= repeat && g_forever) { image = camera->takeImage(); int i=0; while(image && g_forever) { ++imagesProcessed; iterationTimer.start(); SMState * smState; if(i0 std::vector v(2); v[0] = 2; v[1] = 0; teleopActions.push_back(v); smState = new SMState(std::list >(), teleopActions); smState->setImage(image); } else { smState = new SMState(std::list >(), actions); smState->setImage(image); } rtabmap->process(smState); loopClosureId = rtabmap->getLoopClosureId(); actions = rtabmap->getActions(); if(rtabmap->getLoopClosureId()) { ++countLoopDetected; } image = camera->takeImage(); if(++count % 100 == 0) { printf(" count = %d, loop closures = %d\n", count, countLoopDetected); std::map wm = rtabmap->getWeights(); printf(" WM(%d)=[", (int)wm.size()); for(std::map::iterator iter=wm.begin(); iter!=wm.end();++iter) { if(iter != wm.begin()) { printf(";"); } printf("%d,%d", iter->first, iter->second); } printf("]\n"); } // Update generated ground truth matrix if(groundTruthMat) { if(loopClosureId > 0 && loopClosureId-1 < groundTruthMat->cols) { cvmSet(groundTruthMat, i, loopClosureId-1, 1); } } ++i; double iterationTime = iterationTimer.ticks(); ULogger::flush(); if(rate) { float delta = rate - iterationTime; if(delta > 0) { uSleep(delta*1000); } } if(rtabmap->getLoopClosureId()) { printf(" iteration(%d) actions=%d loop(%d) time=%fs\n", count, (int)actions.size(), rtabmap->getLoopClosureId(), iterationTime); } else { printf(" iteration(%d) actions=%d time=%fs\n", count, (int)actions.size(), iterationTime); } if(timeThreshold && iterationTime > timeThreshold*100.0f) { printf(" ERROR, there is problem, too much time taken... %fs", iterationTime); break; // there is problem, don't continue } } ++loopDataset; if(loopDataset <= repeat) { camera->init(); printf(" Beginning loop %d...\n", loopDataset); } } printf("Processing images completed. Loop closures found = %d\n", countLoopDetected); printf(" Total time = %fs\n", timer.ticks()); if(groundTruthMat) { if(rtabmap->getTotalMemSize() != groundTruthMat->rows) { printf("WARNING : Ground truth matrix size and the image count don't match : Image captured=%d, GroundTruthSize = %d\n", imagesProcessed, groundTruthMat->rows); } // Generate the ground truth file printf("Generate ground truth to file %s, size of %d\n", (rtabmap->getWorkingDir()+GENERATED_GT_NAME).c_str(), groundTruthMat->rows); FILE* fout = 0; #ifdef _MSC_VER fopen_s(&fout, (rtabmap->getWorkingDir()+GENERATED_GT_NAME).c_str(), "w+"); #else fout = fopen((rtabmap->getWorkingDir()+GENERATED_GT_NAME).c_str(), "w+"); #endif if(fout) { for(int i=0; irows; i++) { for(int j=0; jcols; j++) { fprintf(fout, "%d", cvmGet(groundTruthMat,i,j)>0?255:0); if(j+1cols) { fprintf(fout," "); } } if(i+1rows) { fprintf(fout,"\n"); } } fclose(fout); fout = 0; } else { printf("ERROR : Can't generate the ground truth file \"%s\"...\n", (rtabmap->getWorkingDir()+GENERATED_GT_NAME).c_str()); } cvReleaseMat(&groundTruthMat); groundTruthMat = 0; printf(" Creating ground truth file = %fs\n", timer.ticks()); } if(camera) { delete camera; camera = 0 ; } if(rtabmap) { delete rtabmap; rtabmap = 0; } printf(" Cleanup time = %fs\n", timer.ticks()); return 0; }