31 #ifdef RTABMAP_OCTOMAP 48 #include <pcl/io/pcd_io.h> 56 " rtabmap-reprocess [options] \"input.db\" \"output.db\"\n" 57 " rtabmap-reprocess [options] \"input1.db;input2.db;input3.db\" \"output.db\"\n" 59 " For the second example, only parameters from the first database are used.\n" 60 " If Mem/IncrementalMemory is false, RTAB-Map is initialized with the first input database,\n" 61 " then localization-only is done with next databases against the first one.\n" 62 " To see warnings when loop closures are rejected, add \"--uwarn\" argument.\n" 63 " To upgrade version of an old database to newest version:\n" 64 " rtabmap-reprocess --Db/TargetVersion \"\" \"input.db\" \"output.db\"\n" 67 " -r Use database stamps as input rate.\n" 68 " -skip # Skip # frames after each processed frame (default 0=don't skip any frames).\n" 69 " -c \"path.ini\" Configuration file, overwriting parameters read \n" 70 " from the database. If custom parameters are also set as \n" 71 " arguments, they overwrite those in config file and the database.\n" 72 " -default Input database's parameters are ignored, using default ones instead.\n" 73 " -odom Recompute odometry. See \"Odom/\" parameters with --params. If -skip option\n" 74 " is used, it will be applied to odometry frames, not rtabmap frames. Multi-session\n" 75 " cannot be detected in this mode (assuming the database contains continuous frames\n" 76 " of a single session).\n" 77 " -start # Start from this node ID.\n" 78 " -stop # Last node to process.\n" 79 " -start_s # Start from this map session ID.\n" 80 " -stop_s # Last map session to process.\n" 81 " -a Append mode: if Mem/IncrementalMemory is true, RTAB-Map is initialized with the first input database,\n" 82 " then next databases are reprocessed on top of the first one.\n" 83 " -cam # Camera index to stream. Ignored if a database doesn't contain multi-camera data.\n" 84 " -nolandmark Don't republish landmarks contained in input database.\n" 85 " -pub_loops Republish loop closures contained in input database.\n" 86 " -loc_null On localization mode, reset localization pose to null and map correction to identity between sessions.\n" 87 " -gt When reprocessing a single database, load its original optimized graph, then \n" 88 " set it as ground truth for output database. If there was a ground truth in the input database, it will be ignored.\n" 89 " -g2 Assemble 2D occupancy grid map and save it to \"[output]_map.pgm\". Use with -db to save in database.\n" 90 " -g3 Assemble 3D cloud map and save it to \"[output]_map.pcd\".\n" 91 " -o2 Assemble OctoMap 2D projection and save it to \"[output]_octomap.pgm\". Use with -db to save in database.\n" 92 " -o3 Assemble OctoMap 3D cloud and save it to \"[output]_octomap.pcd\".\n" 93 " -db Save assembled 2D occupancy grid in database instead of a file.\n" 94 " -p Save odometry and localization poses (*.g2o).\n" 95 " -scan_from_depth Generate scans from depth images (overwrite previous\n" 96 " scans if they exist).\n" 97 " -scan_downsample # Downsample input scans.\n" 98 " -scan_range_min #.# Filter input scans with minimum range (m).\n" 99 " -scan_range_max #.# Filter input scans with maximum range (m).\n" 100 " -scan_voxel_size #.# Voxel filter input scans (m).\n" 101 " -scan_normal_k # Compute input scan normals (k-neighbors approach).\n" 102 " -scan_normal_radius #.# Compute input scan normals (radius(m)-neighbors approach).\n\n" 112 printf(
"\nSignal %d caught...\n", sig);
142 printf(
"Average localization time = %f ms (stddev=%f ms)\n", m, stddev);
158 float mA =
uMean(localizationAngleVariations);
159 float maxA =
uMax(localizationAngleVariations);
160 float varA =
uVariance(localizationAngleVariations, mA);
164 stddevA =
sqrt(varA);
166 printf(
"Average localization variations = %f m, %f deg (stddev=%f m, %f deg) (max=%f m, %f deg)\n", m, mA, stddev, stddevA, max, maxA);
177 printf(
"Average distance from previous localization = %f m (stddev=%f m)\n", m, stddev);
188 printf(
"Average odometry distances = %f m (stddev=%f m)\n", m, stddev);
193 std::string outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3);
198 printf(
"Exported %s and %s\n", oName.c_str(), lName.c_str());
233 bool save2DMap =
false;
234 bool assemble2dMap =
false;
235 bool assemble3dMap =
false;
236 bool assemble2dOctoMap =
false;
237 bool assemble3dOctoMap =
false;
238 bool useDatabaseRate =
false;
239 bool useDefaultParameters =
false;
240 bool recomputeOdometry =
false;
245 bool appendMode =
false;
246 int cameraIndex = -1;
247 int framesToSkip = 0;
248 bool ignoreLandmarks =
false;
249 bool republishLoopClosures =
false;
250 bool locNull =
false;
251 bool originalGraphAsGT =
false;
252 bool scanFromDepth =
false;
253 int scanDecimation = 1;
254 float scanRangeMin = 0.0f;
255 float scanRangeMax = 0.0f;
256 float scanVoxelSize = 0;
258 float scanNormalRadius = 0.0f;
260 for(
int i=1; i<argc-2; ++i)
262 if(strcmp(argv[i],
"-r") == 0 || strcmp(argv[i],
"--r") == 0)
264 useDatabaseRate =
true;
265 printf(
"Using database stamps as input rate.\n");
267 else if (strcmp(argv[i],
"-c") == 0 || strcmp(argv[i],
"--c") == 0)
273 printf(
"Using %d parameters from config file \"%s\"\n", (
int)configParameters.size(), argv[i]);
275 else if(i < argc - 2)
277 printf(
"Config file \"%s\" is not valid or doesn't exist!\n", argv[i]);
282 printf(
"Config file is not set!\n");
286 else if(strcmp(argv[i],
"-default") == 0 || strcmp(argv[i],
"--default") == 0)
288 useDefaultParameters =
true;
289 printf(
"Using default parameters.\n");
291 else if(strcmp(argv[i],
"-odom") == 0 || strcmp(argv[i],
"--odom") == 0)
293 recomputeOdometry =
true;
295 else if (strcmp(argv[i],
"-start") == 0 || strcmp(argv[i],
"--start") == 0)
300 startId = atoi(argv[i]);
301 printf(
"Start at node ID = %d.\n", startId);
305 printf(
"-start option requires a value\n");
309 else if (strcmp(argv[i],
"-stop") == 0 || strcmp(argv[i],
"--stop") == 0)
314 stopId = atoi(argv[i]);
315 printf(
"Stop at node ID = %d.\n", stopId);
319 printf(
"-stop option requires a value\n");
323 else if (strcmp(argv[i],
"-start_s") == 0 || strcmp(argv[i],
"--start_s") == 0)
328 startMapId = atoi(argv[i]);
329 printf(
"Start at map session ID = %d.\n", startMapId);
333 printf(
"-start_s option requires a value\n");
337 else if (strcmp(argv[i],
"-stop_s") == 0 || strcmp(argv[i],
"--stop_s") == 0)
342 stopMapId = atoi(argv[i]);
343 printf(
"Stop at map session ID = %d.\n", stopMapId);
347 printf(
"-stop option requires a value\n");
351 else if (strcmp(argv[i],
"-a") == 0 || strcmp(argv[i],
"--a") == 0)
354 printf(
"Append mode enabled (initialize with first database then reprocess next ones)\n");
356 else if (strcmp(argv[i],
"-cam") == 0 || strcmp(argv[i],
"--cam") == 0)
361 cameraIndex = atoi(argv[i]);
362 printf(
"Camera index = %d.\n", cameraIndex);
366 printf(
"-cam option requires a value\n");
370 else if (strcmp(argv[i],
"-skip") == 0 || strcmp(argv[i],
"--skip") == 0)
375 framesToSkip = atoi(argv[i]);
376 printf(
"Will skip %d frames.\n", framesToSkip);
380 printf(
"-skip option requires a value\n");
384 else if(strcmp(argv[i],
"-nolandmark") == 0 || strcmp(argv[i],
"--nolandmark") == 0)
386 ignoreLandmarks =
true;
387 printf(
"Ignoring landmarks from input database (-nolandmark option).\n");
389 else if(strcmp(argv[i],
"-pub_loops") == 0 || strcmp(argv[i],
"--pub_loops") == 0)
391 republishLoopClosures =
true;
392 printf(
"Republish loop closures from input database (-pub_loops option).\n");
394 else if(strcmp(argv[i],
"-loc_null") == 0 || strcmp(argv[i],
"--loc_null") == 0)
397 printf(
"In localization mode, when restarting a new session, the current localization pose is set to null (-loc_null option).\n");
399 else if(strcmp(argv[i],
"-gt") == 0 || strcmp(argv[i],
"--gt") == 0)
401 originalGraphAsGT =
true;
402 printf(
"Original graph is used as ground truth for output database (-gt option).\n");
404 else if(strcmp(argv[i],
"-p") == 0 || strcmp(argv[i],
"--p") == 0)
407 printf(
"Odometry trajectory and localization poses will be exported in g2o format (-p option).\n");
409 else if(strcmp(argv[i],
"-db") == 0 || strcmp(argv[i],
"--db") == 0)
412 printf(
"2D occupancy grid will be saved in database (-db option).\n");
414 else if(strcmp(argv[i],
"-g2") == 0 || strcmp(argv[i],
"--g2") == 0)
416 assemble2dMap =
true;
417 printf(
"2D occupancy grid will be assembled (-g2 option).\n");
419 else if(strcmp(argv[i],
"-g3") == 0 || strcmp(argv[i],
"--g3") == 0)
421 assemble3dMap =
true;
422 printf(
"3D cloud map will be assembled (-g3 option).\n");
424 else if(strcmp(argv[i],
"-o2") == 0 || strcmp(argv[i],
"--o2") == 0)
426 #ifdef RTABMAP_OCTOMAP 427 assemble2dOctoMap =
true;
428 printf(
"OctoMap will be assembled (-o2 option).\n");
430 printf(
"RTAB-Map is not built with OctoMap support, cannot set -o2 option!\n");
433 else if(strcmp(argv[i],
"-o3") == 0 || strcmp(argv[i],
"--o3") == 0)
435 #ifdef RTABMAP_OCTOMAP 436 assemble3dOctoMap =
true;
437 printf(
"OctoMap will be assembled (-o3 option).\n");
439 printf(
"RTAB-Map is not built with OctoMap support, cannot set -o3 option!\n");
442 else if (strcmp(argv[i],
"-scan_from_depth") == 0 || strcmp(argv[i],
"--scan_from_depth") == 0)
444 scanFromDepth =
true;
446 else if (strcmp(argv[i],
"-scan_downsample") == 0 || strcmp(argv[i],
"--scan_downsample") == 0 ||
447 strcmp(argv[i],
"-scan_decimation") == 0 || strcmp(argv[i],
"--scan_decimation") == 0)
452 scanDecimation = atoi(argv[i]);
453 printf(
"Scan from depth decimation = %d.\n", scanDecimation);
457 printf(
"-scan_downsample option requires 1 value\n");
461 else if (strcmp(argv[i],
"-scan_range_min") == 0 || strcmp(argv[i],
"--scan_range_min") == 0)
466 scanRangeMin = atof(argv[i]);
467 printf(
"Scan range min = %f m.\n", scanRangeMin);
471 printf(
"-scan_range_min option requires 1 value\n");
475 else if (strcmp(argv[i],
"-scan_range_max") == 0 || strcmp(argv[i],
"--scan_range_max") == 0)
480 scanRangeMax = atof(argv[i]);
481 printf(
"Scan range max = %f m.\n", scanRangeMax);
485 printf(
"-scan_range_max option requires 1 value\n");
489 else if (strcmp(argv[i],
"-scan_voxel_size") == 0 || strcmp(argv[i],
"--scan_voxel_size") == 0)
494 scanVoxelSize = atof(argv[i]);
495 printf(
"Scan voxel size = %f m.\n", scanVoxelSize);
499 printf(
"-scan_voxel_size option requires 1 value\n");
503 else if (strcmp(argv[i],
"-scan_normal_k") == 0 || strcmp(argv[i],
"--scan_normal_k") == 0)
508 scanNormalK = atoi(argv[i]);
509 printf(
"Scan normal k = %d.\n", scanNormalK);
513 printf(
"-scan_normal_k option requires 1 value\n");
517 else if (strcmp(argv[i],
"-scan_normal_radius") == 0 || strcmp(argv[i],
"--scan_normal_radius") == 0)
522 scanNormalRadius = atof(argv[i]);
523 printf(
"Scan normal radius = %f m.\n", scanNormalRadius);
527 printf(
"-scan_normal_radius option requires 1 value\n");
536 std::list<std::string> databases =
uSplit(inputDatabasePath,
';');
537 if (databases.empty())
539 printf(
"No input database \"%s\" detected!\n", inputDatabasePath.c_str());
542 for (std::list<std::string>::iterator iter = databases.begin(); iter != databases.end(); ++iter)
546 printf(
"Input database \"%s\" doesn't exist!\n", iter->c_str());
552 printf(
"File \"%s\" is not a database format (*.db)!\n", iter->c_str());
559 printf(
"File \"%s\" is not a database format (*.db)!\n", outputDatabasePath.c_str());
572 printf(
"Failed opening input database!\n");
578 std::string targetVersion;
579 if(!useDefaultParameters)
583 parameters.insert(
ParametersPair(Parameters::kDbTargetVersion(), targetVersion));
584 if(parameters.empty())
586 printf(
"WARNING: Failed getting parameters from database, reprocessing will be done with default parameters! Database version may be too old (%s).\n", dbDriver->
getDatabaseVersion().c_str());
590 if(customParameters.size())
592 printf(
"Custom parameters:\n");
593 for(ParametersMap::iterator iter=customParameters.begin(); iter!=customParameters.end(); ++iter)
595 printf(
" %s\t= %s\n", iter->first.c_str(), iter->second.c_str());
599 bool useOdomFeatures = Parameters::defaultMemUseOdomFeatures();
600 if((configParameters.find(Parameters::kKpDetectorStrategy())!=configParameters.end() ||
601 configParameters.find(Parameters::kVisFeatureType())!=configParameters.end() ||
602 customParameters.find(Parameters::kKpDetectorStrategy())!=customParameters.end() ||
603 customParameters.find(Parameters::kVisFeatureType())!=customParameters.end()) &&
604 configParameters.find(Parameters::kMemUseOdomFeatures())==configParameters.end() &&
605 customParameters.find(Parameters::kMemUseOdomFeatures())==customParameters.end())
607 Parameters::parse(parameters, Parameters::kMemUseOdomFeatures(), useOdomFeatures);
610 printf(
"[Warning] %s and/or %s are overwritten but parameter %s is true in the opened database. " 611 "Setting it to false for convenience to use the new selected feature detector. Set %s " 612 "explicitly to suppress this warning.\n",
613 Parameters::kKpDetectorStrategy().c_str(),
614 Parameters::kVisFeatureType().c_str(),
615 Parameters::kMemUseOdomFeatures().c_str(),
616 Parameters::kMemUseOdomFeatures().c_str());
618 useOdomFeatures =
false;
622 if(useOdomFeatures && databases.size() > 1 &&
623 configParameters.find(Parameters::kMemUseOdomFeatures())==configParameters.end() &&
624 customParameters.find(Parameters::kMemUseOdomFeatures())==customParameters.end())
626 printf(
"[Warning] Parameter %s is set to false for convenience as " 627 "there are more than one input database (which could " 628 "contain different features). Set %s " 629 "explicitly to suppress this warning.\n",
630 Parameters::kMemUseOdomFeatures().c_str(),
631 Parameters::kMemUseOdomFeatures().c_str());
632 useOdomFeatures =
false;
635 if(republishLoopClosures)
637 if(databases.size() > 1)
639 printf(
"[Warning] \"pub_loops\" option cannot be used with multiple databases input. " 640 "Disabling \"pub_loops\" to avoid mismatched loop closue ids.\n");
641 republishLoopClosures =
false;
645 bool generateIds = Parameters::defaultMemGenerateIds();
651 if(configParameters.find(Parameters::kMemGenerateIds())!=configParameters.end() ||
652 customParameters.find(Parameters::kMemGenerateIds())!=customParameters.end())
654 printf(
"[Warning] \"pub_loops\" option is used but parameter %s is set to true in custom arguments. " 655 "Disabling \"pub_loops\" to avoid mismatched loop closure ids.\n",
656 Parameters::kMemGenerateIds().c_str());
657 republishLoopClosures =
false;
661 printf(
"[Warning] \"pub_loops\" option is used but parameter %s is true in the opened database. " 662 "Setting parameter %s to false for convenience so that republished loop closure ids match.\n",
663 Parameters::kMemGenerateIds().c_str(),
664 Parameters::kMemGenerateIds().c_str());
670 uInsert(parameters, configParameters);
671 uInsert(parameters, customParameters);
673 bool incrementalMemory = Parameters::defaultMemIncrementalMemory();
674 Parameters::parse(parameters, Parameters::kMemIncrementalMemory(), incrementalMemory);
676 bool intermediateNodes = Parameters::defaultRtabmapCreateIntermediateNodes();
677 Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), intermediateNodes);
681 dbDriver->
getAllNodeIds(ids,
false,
false, !intermediateNodes);
684 printf(
"Input database doesn't have any nodes saved in it.\n");
689 if(!((!incrementalMemory || appendMode) && databases.size() > 1))
691 totalIds = ids.size();
694 std::map<int, Transform> gt;
695 if(databases.size() == 1 && originalGraphAsGT)
703 for (std::list<std::string>::iterator iter = ++databases.begin(); iter != databases.end(); ++iter)
707 printf(
"Failed opening input database!\n");
712 dbDriver->
getAllNodeIds(ids,
false,
false, !intermediateNodes);
713 totalIds += ids.size();
721 totalIds/=framesToSkip+1;
725 printf(
"Set working directory to \"%s\".\n", workingDirectory.c_str());
726 if(!targetVersion.empty())
728 printf(
"Target database version: \"%s\" (set explicitly --%s \"\" to output with latest version.\n", targetVersion.c_str(), Parameters::kDbTargetVersion().c_str());
733 if((!incrementalMemory || appendMode ) && databases.size() > 1)
735 UFile::copy(databases.front(), outputDatabasePath);
736 if(!incrementalMemory)
738 printf(
"Parameter \"%s\" is set to false, initializing RTAB-Map with \"%s\" for localization...\n", Parameters::kMemIncrementalMemory().c_str(), databases.front().c_str());
740 databases.pop_front();
741 inputDatabasePath =
uJoin(databases,
";");
745 rtabmap.
init(parameters, outputDatabasePath);
747 if(!incrementalMemory && locNull)
752 bool rgbdEnabled = Parameters::defaultRGBDEnabled();
754 bool odometryIgnored = !rgbdEnabled;
758 useDatabaseRate?-1:0,
775 #ifdef RTABMAP_OCTOMAP 779 float linearUpdate = Parameters::defaultRGBDLinearUpdate();
780 float angularUpdate = Parameters::defaultRGBDAngularUpdate();
785 float rtabmapUpdateRate = Parameters::defaultRtabmapDetectionRate();
786 double lastUpdateStamp = 0;
787 if(recomputeOdometry)
791 printf(
"odom option is set but %s parameter is false, odometry won't be recomputed...\n", Parameters::kRGBDEnabled().c_str());
792 recomputeOdometry =
false;
796 printf(
"Odometry will be recomputed (odom option is set)\n");
797 Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), rtabmapUpdateRate);
798 if(rtabmapUpdateRate!=0)
800 rtabmapUpdateRate = 1.0f/rtabmapUpdateRate;
806 printf(
"Reprocessing data of \"%s\"...\n", inputDatabasePath.c_str());
807 std::map<std::string, float> globalMapStats;
812 camThread.
setScanParameters(scanFromDepth, scanDecimation, scanRangeMin, scanRangeMax, scanVoxelSize, scanNormalK, scanNormalRadius);
819 bool inMotion =
true;
822 if(recomputeOdometry)
826 printf(
"Processed %d/%d frames (visual=%d/%d lidar=%f lost=%s)... odometry = %dms\n",
832 odomInfo.
lost?
"true":
"false",
834 if(lastUpdateStamp > 0.0 && data.
stamp() < lastUpdateStamp + rtabmapUpdateRate)
838 int skippedFrames = framesToSkip;
839 while(skippedFrames-- > 0)
857 lastUpdateStamp = data.
stamp();
864 printf(
"Skipping node %d as it doesn't have odometry pose set.\n", data.
id());
870 printf(
"High variance detected, triggering a new map...\n");
871 if(!incrementalMemory && processed>0)
874 lastLocalizationOdomPose = info.
odomPose;
877 if(!incrementalMemory && locNull)
884 if(originalGraphAsGT)
892 printf(
"Failed processing node %d.\n", data.
id());
893 globalMapStats.clear();
897 if(republishLoopClosures && dbReader->
driver())
899 std::multimap<int, Link> links;
901 for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
907 iter->second.to() < data.
id())
909 if(!iter->second.transform().isNull() &&
913 printf(
"Added link %d->%d from input database.\n", iter->second.from(), iter->second.to());
919 if(assemble2dMap || assemble3dMap || assemble2dOctoMap || assemble3dOctoMap)
921 globalMapStats.clear();
922 double timeRtabmap = t.
ticks();
923 double timeUpdateInit = 0.0;
924 double timeUpdateGrid = 0.0;
925 #ifdef RTABMAP_OCTOMAP 926 double timeUpdateOctoMap = 0.0;
931 int id = stats.
poses().rbegin()->first;
935 bool updateGridMap =
false;
936 bool updateOctoMap =
false;
939 updateGridMap =
true;
941 #ifdef RTABMAP_OCTOMAP 942 if((assemble2dOctoMap || assemble3dOctoMap) && octomap.
addedNodes().find(
id) == octomap.
addedNodes().end())
944 updateOctoMap =
true;
947 if(updateGridMap || updateOctoMap)
949 cv::Mat ground, obstacles, empty;
952 timeUpdateInit = t.
ticks();
956 grid.
addToCache(
id, ground, obstacles, empty);
958 timeUpdateGrid = t.
ticks() + timeUpdateInit;
960 #ifdef RTABMAP_OCTOMAP 964 octomap.
addToCache(
id, ground, obstacles, empty, viewpoint);
966 timeUpdateOctoMap = t.
ticks() + timeUpdateInit;
973 globalMapStats.insert(std::make_pair(std::string(
"GlobalGrid/GridUpdate/ms"), timeUpdateGrid*1000.0
f));
974 #ifdef RTABMAP_OCTOMAP 976 double timePub2dOctoMap = 0.0;
977 double timePub3dOctoMap = 0.0;
978 if(assemble2dOctoMap)
980 float xMin, yMin, size;
982 timePub2dOctoMap = t.
ticks();
984 if(assemble3dOctoMap)
987 timePub3dOctoMap = t.
ticks();
990 globalMapStats.insert(std::make_pair(std::string(
"GlobalGrid/OctoMapUpdate/ms"), timeUpdateOctoMap*1000.0f));
991 globalMapStats.insert(std::make_pair(std::string(
"GlobalGrid/OctoMapProjection/ms"), timePub2dOctoMap*1000.0f));
992 globalMapStats.insert(std::make_pair(std::string(
"GlobalGrid/OctomapToCloud/ms"), timePub3dOctoMap*1000.0f));
993 globalMapStats.insert(std::make_pair(std::string(
"GlobalGrid/TotalWithRtabmap/ms"), (timeUpdateGrid+timeUpdateOctoMap+timePub2dOctoMap+timePub3dOctoMap+timeRtabmap)*1000.0f));
995 globalMapStats.insert(std::make_pair(std::string(
"GlobalGrid/TotalWithRtabmap/ms"), (timeUpdateGrid+timeRtabmap)*1000.0f));
1004 int landmarkId = (int)
uValue(stats.
data(), rtabmap::Statistics::kLoopLandmark_detected(), 0.0f);
1027 printf(
"Processed %d/%d nodes [id=%d map=%d opt_graph=%d]... %dms %s on %d [%d]\n", ++processed, totalIds, refId, refMapId,
int(stats.
poses().size()),
int(iterationTime.
ticks() * 1000), stats.
loopClosureId() > 0?
"Loop":
"Prox", loopId, loopMapId);
1029 else if(landmarkId != 0)
1031 printf(
"Processed %d/%d nodes [id=%d map=%d opt_graph=%d]... %dms Loop on landmark %d\n", ++processed, totalIds, refId, refMapId,
int(stats.
poses().size()),
int(iterationTime.
ticks() * 1000), landmarkId);
1035 printf(
"Processed %d/%d nodes [id=%d map=%d opt_graph=%d]... %dms\n", ++processed, totalIds, refId, refMapId,
int(stats.
poses().size()),
int(iterationTime.
ticks() * 1000));
1039 if(!incrementalMemory &&
1040 !lastLocalizationOdomPose.
isNull() &&
1043 if(loopId>0 || landmarkId != 0)
1046 lastLocalizationOdomPose = info.
odomPose;
1049 if(!incrementalMemory)
1051 float totalTime =
uValue(stats.
data(), rtabmap::Statistics::kTimingTotal(), 0.0f);
1053 if(stats.
data().find(Statistics::kLoopOdom_correction_norm()) != stats.
data().end())
1073 if(framesToSkip>0 && !recomputeOdometry)
1075 int skippedFrames = framesToSkip;
1076 while(skippedFrames-- > 0)
1082 printf(
"High variance detected, triggering a new map...\n");
1083 if(!incrementalMemory && processed>0)
1086 lastLocalizationOdomPose = info.
odomPose;
1101 if(!incrementalMemory &&
1108 if(distance < linearUpdate && angle <= angularUpdate)
1115 int databasesMerged = 0;
1116 if(!incrementalMemory)
1124 if(databases.size()>1)
1126 std::map<int, Transform> poses;
1127 std::multimap<int, Link> constraints;
1128 rtabmap.
getGraph(poses, constraints, 0, 1, 0,
false,
false,
false,
false,
false,
false);
1129 std::set<int> mapIds;
1130 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
1138 databasesMerged = mapIds.size();
1142 printf(
"Closing database \"%s\"...\n", outputDatabasePath.c_str());
1143 rtabmap.
close(
true);
1144 printf(
"Closing database \"%s\"... done!\n", outputDatabasePath.c_str());
1150 std::string outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_map.pgm";
1152 cv::Mat map = grid.
getMap(xMin, yMin);
1161 printf(
"Saving occupancy grid to database... done!\n");
1167 cv::Mat map8U(map.rows, map.cols, CV_8U);
1169 for (
int i = 0; i < map.rows; ++i)
1171 for (
int j = 0; j < map.cols; ++j)
1173 char v = map.at<
char>(i, j);
1187 map8U.at<
unsigned char>(i, j) = gray;
1191 if(cv::imwrite(outputPath, map8U))
1193 printf(
"Saving occupancy grid \"%s\"... done!\n", outputPath.c_str());
1197 printf(
"Saving occupancy grid \"%s\"... failed!\n", outputPath.c_str());
1203 printf(
"2D map is empty! Cannot save it!\n");
1208 std::string outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_obstacles.pcd";
1209 if(pcl::io::savePCDFileBinary(outputPath, *grid.
getMapObstacles()) == 0)
1211 printf(
"Saving 3d obstacles \"%s\"... done!\n", outputPath.c_str());
1215 printf(
"Saving 3d obstacles \"%s\"... failed!\n", outputPath.c_str());
1219 outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_ground.pcd";
1220 if(pcl::io::savePCDFileBinary(outputPath, *grid.
getMapGround()) == 0)
1222 printf(
"Saving 3d ground \"%s\"... done!\n", outputPath.c_str());
1226 printf(
"Saving 3d ground \"%s\"... failed!\n", outputPath.c_str());
1231 outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_empty.pcd";
1234 printf(
"Saving 3d empty cells \"%s\"... done!\n", outputPath.c_str());
1238 printf(
"Saving 3d empty cells \"%s\"... failed!\n", outputPath.c_str());
1242 #ifdef RTABMAP_OCTOMAP 1243 if(assemble2dOctoMap)
1245 std::string outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_octomap.pgm";
1246 float xMin,yMin,cellSize;
1255 driver->
save2DMap(map, xMin, yMin, cellSize);
1256 printf(
"Saving occupancy grid to database... done!\n");
1262 cv::Mat map8U(map.rows, map.cols, CV_8U);
1264 for (
int i = 0; i < map.rows; ++i)
1266 for (
int j = 0; j < map.cols; ++j)
1268 char v = map.at<
char>(i, j);
1282 map8U.at<
unsigned char>(i, j) = gray;
1285 if(cv::imwrite(outputPath, map8U))
1287 printf(
"Saving octomap 2D projection \"%s\"... done!\n", outputPath.c_str());
1291 printf(
"Saving octomap 2D projection \"%s\"... failed!\n", outputPath.c_str());
1297 printf(
"OctoMap 2D projection map is empty! Cannot save it!\n");
1300 if(assemble3dOctoMap)
1302 std::string outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_octomap_occupied.pcd";
1303 std::vector<int> obstacles, emptySpace, ground;
1304 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = octomap.
createCloud(0, &obstacles, &emptySpace, &ground);
1305 if(pcl::io::savePCDFile(outputPath, *cloud, obstacles,
true) == 0)
1307 printf(
"Saving obstacles cloud \"%s\"... done!\n", outputPath.c_str());
1311 printf(
"Saving obstacles cloud \"%s\"... failed!\n", outputPath.c_str());
1315 outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_octomap_ground.pcd";
1316 if(pcl::io::savePCDFile(outputPath, *cloud, ground,
true) == 0)
1318 printf(
"Saving empty space cloud \"%s\"... done!\n", outputPath.c_str());
1322 printf(
"Saving empty space cloud \"%s\"... failed!\n", outputPath.c_str());
1325 if(emptySpace.size())
1327 outputPath = outputDatabasePath.substr(0, outputDatabasePath.size()-3) +
"_octomap_empty.pcd";
1328 if(pcl::io::savePCDFile(outputPath, *cloud, emptySpace,
true) == 0)
1330 printf(
"Saving empty space cloud \"%s\"... done!\n", outputPath.c_str());
1334 printf(
"Saving empty space cloud \"%s\"... failed!\n", outputPath.c_str());
1340 return databasesMerged;
static std::string homeDir()
T uVariance(const T *v, unsigned int size, T meanV)
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
bool update(const std::map< int, Transform > &poses)
void save2DMap(const cv::Mat &map, float xMin, float yMin, float cellSize) const
T uMean(const T *v, unsigned int size)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr createCloud(unsigned int treeDepth=0, std::vector< int > *obstacleIndices=0, std::vector< int > *emptyIndices=0, std::vector< int > *groundIndices=0, bool originalRefPoints=true, std::vector< int > *frontierIndices=0, std::vector< double > *cloudProb=0) const
float getCellSize() const
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
void setLaserScan(const LaserScan &laserScan, bool clearPreviousData=true)
static const char * showUsage()
std::vector< float > localizationAngleVariations
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
const Statistics & getStatistics() const
static std::string getDir(const std::string &filePath)
std::pair< std::string, std::string > ParametersPair
void setInitialPose(const Transform &initialPose)
const pcl::PointCloud< pcl::PointXYZRGB >::Ptr & getMapObstacles() const
const DBDriver * driver() const
static ParametersMap parseArguments(int argc, char *argv[], bool onlyParameters=false)
static int erase(const std::string &filePath)
const pcl::PointCloud< pcl::PointXYZRGB >::Ptr & getMapEmptyCells() const
int main(int argc, char *argv[])
std::map< std::string, std::string > ParametersMap
GLM_FUNC_DECL genType::value_type distance(genType const &p0, genType const &p1)
void init(const ParametersMap ¶meters, const std::string &databasePath="", bool loadDatabaseParameters=false)
Basic mathematics functions.
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
std::vector< float > odomVelocity
void loadLinks(int signatureId, std::multimap< int, Link > &links, Link::Type type=Link::kUndef) const
std::string getExtension()
static void setLevel(ULogger::Level level)
std::vector< float > localizationVariations
int loopClosureMapId() const
Transform process(SensorData &data, OdometryInfo *info=0)
const std::map< int, Transform > & poses() const
std::map< int, Transform > loadOptimizedPoses(Transform *lastlocalizationPose=0) const
float gridCellSize() const
const std::map< std::string, float > & data() const
int loopClosureId() const
std::vector< float > odomDistances
bool openConnection(const std::string &url, bool overwritten=false)
bool update(const std::map< int, Transform > &poses)
SensorData takeImage(CameraInfo *info=0)
Wrappers of STL for convenient functions.
int proximityDetectionMapId() const
std::list< std::string > uSplit(const std::string &str, char separator=' ')
void addToCache(int nodeId, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &ground, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &obstacles, const pcl::PointXYZ &viewPoint)
std::string uJoin(const std::list< std::string > &strings, const std::string &separator="")
void close(bool databaseSaved=true, const std::string &ouputDatabasePath="")
const std::map< int, Transform > & addedNodes() const
static Odometry * create(const ParametersMap ¶meters=ParametersMap())
std::vector< float > previousLocalizationDistances
void closeConnection(bool save=true, const std::string &outputUrl="")
void addToCache(int nodeId, const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty)
void setScanParameters(bool fromDepth, int downsampleStep=1, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalsK=0, int normalsRadius=0.0f, float groundNormalsUp=0.0f)
const Memory * getMemory() const
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false, bool ignoreIntermediateNodes=false) const
const Transform & mapCorrection() const
static void setType(Type type, const std::string &fileName=kDefaultLogFileName, bool append=true)
bool addLink(const Link &link)
bool process(const SensorData &data, Transform odomPose, const cv::Mat &odomCovariance=cv::Mat::eye(6, 6, CV_64FC1), const std::vector< float > &odomVelocity=std::vector< float >(), const std::map< std::string, float > &externalStats=std::map< std::string, float >())
Main loop of rtabmap.
static void copy(const std::string &from, const std::string &to)
cv::Mat getMap(float &xMin, float &yMin) const
std::string UTILITE_EXP uReplaceChar(const std::string &str, char before, char after)
bool RTABMAP_EXP exportPoses(const std::string &filePath, int format, const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints=std::multimap< int, Link >(), const std::map< int, double > &stamps=std::map< int, double >(), const ParametersMap ¶meters=ParametersMap())
static DBDriver * create(const ParametersMap ¶meters=ParametersMap())
T uMax(const T *v, unsigned int size, unsigned int &index)
const std::map< int, Transform > & addedNodes() const
const cv::Point3f & gridViewPoint() const
void postUpdate(SensorData *data, CameraInfo *info=0) const
const std::map< int, double > & getWorkingMem() const
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
SensorData & sensorData()
int getMapId(int id, bool lookInDatabase=false) const
void showLocalizationStats(const std::string &outputDatabasePath)
std::vector< float > localizationTime
const Signature & getLastSignatureData() const
void getGraph(std::map< int, Transform > &poses, std::multimap< int, Link > &constraints, bool optimized, bool global, std::map< int, Signature > *signatures=0, bool withImages=false, bool withScan=false, bool withUserData=false, bool withGrid=false, bool withWords=true, bool withGlobalDescriptors=true) const
ParametersMap getLastParameters() const
std::map< int, Transform > odomTrajectoryPoses
static void readINI(const std::string &configFile, ParametersMap ¶meters, bool modifiedOnly=false)
std::map< int, Transform > localizationPoses
int refImageMapId() const
void setGroundTruth(const Transform &pose)
std::string getDatabaseVersion() const
const pcl::PointCloud< pcl::PointXYZRGB >::Ptr & getMapGround() const
cv::Mat createProjectionMap(float &xMin, float &yMin, float &gridCellSize, float minGridSize=0.0f, unsigned int treeDepth=0)
int proximityDetectionId() const
std::multimap< int, Link > odomTrajectoryLinks
std::string UTILITE_EXP uFormat(const char *fmt,...)
void uncompressDataConst(cv::Mat *imageRaw, cv::Mat *depthOrRightRaw, LaserScan *laserScanRaw=0, cv::Mat *userDataRaw=0, cv::Mat *groundCellsRaw=0, cv::Mat *obstacleCellsRaw=0, cv::Mat *emptyCellsRaw=0) const
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
void setCloudAssembling(bool enabled)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)