43 #include <pcl/common/common.h> 52 "rtabmap-kitti_dataset [options] path\n" 53 " path Folder of the sequence (e.g., \"~/KITTI/dataset/sequences/07\")\n" 54 " containing least calib.txt, times.txt, image_0 and image_1 folders.\n" 55 " Optional image_2, image_3 and velodyne folders.\n" 56 " --output Output directory. By default, results are saved in \"path\".\n" 57 " --output_name Output database name (default \"rtabmap\").\n" 58 " --gt \"path\" Ground truth path (e.g., ~/KITTI/devkit/cpp/data/odometry/poses/07.txt)\n" 59 " --quiet Don't show log messages and iteration updates.\n" 60 " --color Use color images for stereo (image_2 and image_3 folders).\n" 61 " --height Add car's height to camera local transform (1.67m).\n" 62 " --disp Generate full disparity.\n" 63 " --exposure_comp Do exposure compensation between left and right images.\n" 64 " --scan Include velodyne scan in node's data.\n" 65 " --scan_step # Scan downsample step (default=1).\n" 66 " --scan_voxel #.# Scan voxel size (default 0.5 m).\n" 67 " --scan_k Scan normal K (default 0).\n" 68 " --scan_radius Scan normal radius (default 0).\n\n" 71 " $ rtabmap-kitti_dataset \\\n" 72 " --Rtabmap/PublishRAMUsage true\\\n" 73 " --Rtabmap/DetectionRate 2\\\n" 74 " --Rtabmap/CreateIntermediateNodes true\\\n" 75 " --RGBD/LinearUpdate 0\\\n" 76 " --GFTT/QualityLevel 0.01\\\n" 77 " --GFTT/MinDistance 7\\\n" 78 " --OdomF2M/MaxSize 3000\\\n" 79 " --Mem/STMSize 30\\\n" 80 " --Kp/MaxFeatures 750\\\n" 81 " --Vis/MaxFeatures 1500\\\n" 82 " --gt \"~/KITTI/devkit/cpp/data/odometry/poses/07.txt\"\\\n" 91 printf(
"\nSignal %d caught...\n", sig);
107 std::string outputName =
"rtabmap";
113 bool exposureCompensation =
false;
115 float scanVoxel = 0.5f;
117 float scanNormalRadius = 0.0f;
126 for(
int i=1; i<argc; ++i)
128 if(std::strcmp(argv[i],
"--output") == 0)
132 else if(std::strcmp(argv[i],
"--output_name") == 0)
134 outputName = argv[++i];
136 else if(std::strcmp(argv[i],
"--quiet") == 0)
140 else if(std::strcmp(argv[i],
"--scan_step") == 0)
142 scanStep = atoi(argv[++i]);
145 printf(
"scan_step should be > 0\n");
149 else if(std::strcmp(argv[i],
"--scan_voxel") == 0)
151 scanVoxel = atof(argv[++i]);
154 printf(
"scan_voxel should be >= 0.0\n");
158 else if(std::strcmp(argv[i],
"--scan_k") == 0)
160 scanNormalK = atoi(argv[++i]);
163 printf(
"scanNormalK should be >= 0\n");
167 else if(std::strcmp(argv[i],
"--scan_radius") == 0)
169 scanNormalRadius = atof(argv[++i]);
170 if(scanNormalRadius < 0.0
f)
172 printf(
"scanNormalRadius should be >= 0\n");
176 else if(std::strcmp(argv[i],
"--gt") == 0)
180 else if(std::strcmp(argv[i],
"--color") == 0)
184 else if(std::strcmp(argv[i],
"--height") == 0)
188 else if(std::strcmp(argv[i],
"--scan") == 0)
192 else if(std::strcmp(argv[i],
"--disp") == 0)
196 else if(std::strcmp(argv[i],
"--exposure_comp") == 0)
198 exposureCompensation =
true;
214 parameters.insert(
ParametersPair(Parameters::kRtabmapWorkingDirectory(), output));
215 parameters.insert(
ParametersPair(Parameters::kRtabmapPublishRAMUsage(),
"true"));
218 seq =
uSplit(path,
'/').back();
221 UWARN(
"Sequence number \"%s\" should be between 0 and 21 (official KITTI datasets).", seq.c_str());
224 std::string pathLeftImages = path+(color?
"/image_2":
"/image_0");
225 std::string pathRightImages = path+(color?
"/image_3":
"/image_1");
226 std::string pathCalib = path+
"/calib.txt";
227 std::string pathTimes = path+
"/times.txt";
228 std::string pathScan;
231 " Sequence number: %s\n" 232 " Sequence path: %s\n" 236 " right images: %s\n" 243 pathLeftImages.c_str(),
244 pathRightImages.c_str(),
253 UWARN(
"Ground truth file path doesn't exist: \"%s\", benchmark values won't be computed.", gtPath.c_str());
258 printf(
" Ground Truth: %s\n", gtPath.c_str());
261 printf(
" Exposure Compensation: %s\n", exposureCompensation?
"true":
"false");
262 printf(
" Disparity: %s\n", disp?
"true":
"false");
265 pathScan = path+
"/velodyne";
266 printf(
" Scan: %s\n", pathScan.c_str());
267 printf(
" Scan step: %d\n", scanStep);
268 printf(
" Scan voxel: %fm\n", scanVoxel);
269 printf(
" Scan normal k: %d\n", scanNormalK);
270 printf(
" Scan normal radius: %f\n", scanNormalRadius);
275 pFile = fopen(pathCalib.c_str(),
"r");
278 UERROR(
"Cannot open calibration file \"%s\"", pathCalib.c_str());
281 cv::Mat_<double> P0(3,4);
282 cv::Mat_<double> P1(3,4);
283 cv::Mat_<double> P2(3,4);
284 cv::Mat_<double> P3(3,4);
285 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
286 &P0(0, 0), &P0(0, 1), &P0(0, 2), &P0(0, 3),
287 &P0(1, 0), &P0(1, 1), &P0(1, 2), &P0(1, 3),
288 &P0(2, 0), &P0(2, 1), &P0(2, 2), &P0(2, 3)) != 12)
290 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
293 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
294 &P1(0, 0), &P1(0, 1), &P1(0, 2), &P1(0, 3),
295 &P1(1, 0), &P1(1, 1), &P1(1, 2), &P1(1, 3),
296 &P1(2, 0), &P1(2, 1), &P1(2, 2), &P1(2, 3)) != 12)
298 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
301 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
302 &P2(0, 0), &P2(0, 1), &P2(0, 2), &P2(0, 3),
303 &P2(1, 0), &P2(1, 1), &P2(1, 2), &P2(1, 3),
304 &P2(2, 0), &P2(2, 1), &P2(2, 2), &P2(2, 3)) != 12)
306 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
309 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
310 &P3(0, 0), &P3(0, 1), &P3(0, 2), &P3(0, 3),
311 &P3(1, 0), &P3(1, 1), &P3(1, 2), &P3(1, 3),
312 &P3(2, 0), &P3(2, 1), &P3(2, 2), &P3(2, 3)) != 12)
314 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
324 UERROR(
"Failed to read first image of \"%s\"", firstImage.c_str());
329 image.size(), P0.colRange(0,3), cv::Mat(), cv::Mat(), P0,
330 image.size(), P1.colRange(0,3), cv::Mat(), cv::Mat(), P1,
331 cv::Mat(), cv::Mat(), cv::Mat(), cv::Mat());
332 if(!model.save(output,
true))
334 UERROR(
"Could not save calibration!");
337 printf(
"Saved calibration \"%s\" to \"%s\"\n", (outputName+
"_calib").c_str(), output.c_str());
339 if(!parameters.empty())
341 printf(
"Parameters:\n");
342 for(ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
344 printf(
" %s=%s\n", iter->first.c_str(), iter->second.c_str());
348 printf(
"RTAB-Map version: %s\n", RTABMAP_VERSION);
356 Transform opticalRotation(0,0,1,0, -1,0,0,color?-0.06:0, 0,-1,0,height?1.67:0.0);
363 opticalRotation), parameters);
365 if(exposureCompensation)
377 if(!pathScan.empty())
382 Transform(-0.27
f, 0.0
f, 0.08+(height?1.67
f:0.0
f), 0.0f, 0.0f, 0.0f));
394 float detectionRate = Parameters::defaultRtabmapDetectionRate();
395 bool intermediateNodes = Parameters::defaultRtabmapCreateIntermediateNodes();
396 int odomStrategy = Parameters::defaultOdomStrategy();
398 Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), detectionRate);
399 Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), intermediateNodes);
402 int mapUpdate = detectionRate>0?10 / detectionRate:1;
408 std::string databasePath = output+
"/"+outputName+
".db";
410 if(cameraThread.
camera()->
init(output, outputName+
"_calib"))
414 printf(
"Processing %d images...\n", totalImages);
417 odomParameters.erase(Parameters::kRtabmapPublishRAMUsage());
420 rtabmap.
init(parameters, databasePath);
432 int odomKeyFrames = 0;
449 if(odomStrategy == 2)
458 bool processData =
true;
459 if(iteration % mapUpdate != 0)
463 data.
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
464 processData = intermediateNodes;
466 if(covariance.empty() || odomInfo.
reg.
covariance.at<
double>(0,0) > covariance.at<
double>(0,0))
474 std::map<std::string, float> externalStats;
476 externalStats.insert(std::make_pair(
"Camera/BilateralFiltering/ms", cameraInfo.
timeBilateralFiltering*1000.0f));
477 externalStats.insert(std::make_pair(
"Camera/Capture/ms", cameraInfo.
timeCapture*1000.0f));
478 externalStats.insert(std::make_pair(
"Camera/Disparity/ms", cameraInfo.
timeDisparity*1000.0f));
479 externalStats.insert(std::make_pair(
"Camera/ImageDecimation/ms", cameraInfo.
timeImageDecimation*1000.0f));
480 externalStats.insert(std::make_pair(
"Camera/Mirroring/ms", cameraInfo.
timeMirroring*1000.0f));
482 externalStats.insert(std::make_pair(
"Camera/ScanFromDepth/ms", cameraInfo.
timeScanFromDepth*1000.0f));
483 externalStats.insert(std::make_pair(
"Camera/TotalTime/ms", cameraInfo.
timeTotal*1000.0f));
484 externalStats.insert(std::make_pair(
"Camera/UndistortDepth/ms", cameraInfo.
timeUndistortDepth*1000.0f));
486 externalStats.insert(std::make_pair(
"Odometry/LocalBundle/ms", odomInfo.
localBundleTime*1000.0f));
487 externalStats.insert(std::make_pair(
"Odometry/LocalBundleConstraints/", odomInfo.
localBundleConstraints));
488 externalStats.insert(std::make_pair(
"Odometry/LocalBundleOutliers/", odomInfo.
localBundleOutliers));
489 externalStats.insert(std::make_pair(
"Odometry/TotalTime/ms", odomInfo.
timeEstimation*1000.0f));
490 externalStats.insert(std::make_pair(
"Odometry/Registration/ms", odomInfo.
reg.
totalTime*1000.0f));
491 externalStats.insert(std::make_pair(
"Odometry/Speed/kph", speed));
492 externalStats.insert(std::make_pair(
"Odometry/Inliers/", odomInfo.
reg.
inliers));
493 externalStats.insert(std::make_pair(
"Odometry/Features/", odomInfo.
features));
494 externalStats.insert(std::make_pair(
"Odometry/DistanceTravelled/m", odomInfo.
distanceTravelled));
495 externalStats.insert(std::make_pair(
"Odometry/KeyFrameAdded/", odomInfo.
keyFrameAdded));
496 externalStats.insert(std::make_pair(
"Odometry/LocalKeyFrames/", odomInfo.
localKeyFrames));
497 externalStats.insert(std::make_pair(
"Odometry/LocalMapSize/", odomInfo.
localMapSize));
498 externalStats.insert(std::make_pair(
"Odometry/LocalScanMapSize/", odomInfo.
localScanMapSize));
502 covariance = cv::Mat();
506 if(!quiet || iteration == totalImages)
508 double slamTime = timer.
ticks();
522 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%f, kfs=%d)=%dms, slam=%dms, rmse=%fm",
527 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%f, kfs=%d)=%dms, slam=%dms",
537 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%d/%d, kfs=%d)=%dms, slam=%dms, rmse=%fm",
542 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%d/%d, kfs=%d)=%dms, slam=%dms",
552 else if(iteration % (totalImages/10) == 0)
563 printf(
"Total time=%fs\n", totalTime.
ticks());
569 printf(
"Saving trajectory ...\n");
570 std::map<int, Transform> poses;
571 std::multimap<int, Link> links;
572 rtabmap.
getGraph(poses, links,
true,
true);
573 std::string pathTrajectory = output+
"/"+outputName+
"_poses.txt";
576 printf(
"Saving %s... done!\n", pathTrajectory.c_str());
580 printf(
"Saving %s... failed!\n", pathTrajectory.c_str());
586 std::map<int, Transform> groundTruth;
588 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
594 std::vector<float> v;
597 rtabmap.
getMemory()->
getNodeInfo(iter->first, o, m, w, l, s, gtPose, v, gps, sensors,
true);
600 groundTruth.insert(std::make_pair(iter->first, gtPose));
608 printf(
"Ground truth comparison:\n");
609 printf(
" KITTI t_err = %f %%\n", t_err);
610 printf(
" KITTI r_err = %f deg/m\n", r_err);
613 float translational_rmse = 0.0f;
614 float translational_mean = 0.0f;
615 float translational_median = 0.0f;
616 float translational_std = 0.0f;
617 float translational_min = 0.0f;
618 float translational_max = 0.0f;
619 float rotational_rmse = 0.0f;
620 float rotational_mean = 0.0f;
621 float rotational_median = 0.0f;
622 float rotational_std = 0.0f;
623 float rotational_min = 0.0f;
624 float rotational_max = 0.0f;
630 translational_median,
641 printf(
" translational_rmse= %f m\n", translational_rmse);
642 printf(
" rotational_rmse= %f deg\n", rotational_rmse);
645 std::string pathErrors = output+
"/"+outputName+
"_rmse.txt";
646 pFile = fopen(pathErrors.c_str(),
"w");
649 UERROR(
"could not save RMSE results to \"%s\"", pathErrors.c_str());
651 fprintf(pFile,
"Ground truth comparison:\n");
652 fprintf(pFile,
" KITTI t_err = %f %%\n", t_err);
653 fprintf(pFile,
" KITTI r_err = %f deg/m\n", r_err);
654 fprintf(pFile,
" translational_rmse= %f\n", translational_rmse);
655 fprintf(pFile,
" translational_mean= %f\n", translational_mean);
656 fprintf(pFile,
" translational_median= %f\n", translational_median);
657 fprintf(pFile,
" translational_std= %f\n", translational_std);
658 fprintf(pFile,
" translational_min= %f\n", translational_min);
659 fprintf(pFile,
" translational_max= %f\n", translational_max);
660 fprintf(pFile,
" rotational_rmse= %f\n", rotational_rmse);
661 fprintf(pFile,
" rotational_mean= %f\n", rotational_mean);
662 fprintf(pFile,
" rotational_median= %f\n", rotational_median);
663 fprintf(pFile,
" rotational_std= %f\n", rotational_std);
664 fprintf(pFile,
" rotational_min= %f\n", rotational_min);
665 fprintf(pFile,
" rotational_max= %f\n", rotational_max);
671 UERROR(
"Camera init failed!");
674 printf(
"Saving rtabmap database (with all statistics) to \"%s\"\n", (output+
"/"+outputName+
".db").c_str());
676 " $ rtabmap-databaseViewer %s\n\n", (output+
"/"+outputName+
".db").c_str());
int UTILITE_EXP uStr2Int(const std::string &str)
static std::string homeDir()
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
static bool makeDir(const std::string &dirPath)
void setStereoExposureCompensation(bool enabled)
static const char * showUsage()
std::pair< std::string, std::string > ParametersPair
static ParametersMap parseArguments(int argc, char *argv[], bool onlyParameters=false)
static int erase(const std::string &filePath)
GLM_FUNC_DECL genType e()
std::map< std::string, std::string > ParametersMap
void init(const ParametersMap ¶meters, const std::string &databasePath="", bool loadDatabaseParameters=false)
const std::vector< cv::KeyPoint > & keypoints() const
Basic mathematics functions.
Some conversion functions.
const LaserScan & laserScanRaw() const
int localBundleConstraints
static void setLevel(ULogger::Level level)
Transform process(SensorData &data, OdometryInfo *info=0)
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
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")=0
SensorData takeImage(CameraInfo *info=0)
Wrappers of STL for convenient functions.
const std::map< std::string, float > & data() const
float timeStereoExposureCompensation
static Odometry * create(const ParametersMap ¶meters=ParametersMap())
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)
bool getNodeInfo(int signatureId, Transform &odomPose, int &mapId, int &weight, std::string &label, double &stamp, Transform &groundTruth, std::vector< float > &velocity, GPS &gps, EnvSensors &sensors, bool lookInDatabase=false) const
int getLoopClosureId() const
Transform RTABMAP_EXP calcRMSE(const std::map< int, Transform > &groundTruth, const std::map< int, Transform > &poses, float &translational_rmse, float &translational_mean, float &translational_median, float &translational_std, float &translational_min, float &translational_max, float &rotational_rmse, float &rotational_mean, float &rotational_median, float &rotational_std, float &rotational_min, float &rotational_max)
const Statistics & getStatistics() const
static void setType(Type type, const std::string &fileName=kDefaultLogFileName, bool append=true)
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.
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())
std::vector< V > uValues(const std::multimap< K, V > &mm)
std::string getNextFilePath()
void setStereoToDepth(bool enabled)
std::string getNextFileName()
void postUpdate(SensorData *data, CameraInfo *info=0) const
const Memory * getMemory() const
float timeImageDecimation
std::vector< float > velocity() const
std::map< EnvSensor::Type, EnvSensor > EnvSensors
int main(int argc, char *argv[])
float timeBilateralFiltering
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
void RTABMAP_EXP calcKittiSequenceErrors(const std::vector< Transform > &poses_gt, const std::vector< Transform > &poses_result, float &t_err, float &r_err)