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 (use --scan_only to ignore image 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;
118 bool scanOnly =
false;
127 for(
int i=1; i<argc; ++i)
129 if(std::strcmp(argv[i],
"--output") == 0)
133 else if(std::strcmp(argv[i],
"--output_name") == 0)
135 outputName = argv[++i];
137 else if(std::strcmp(argv[i],
"--quiet") == 0)
141 else if(std::strcmp(argv[i],
"--scan_step") == 0)
143 scanStep = atoi(argv[++i]);
146 printf(
"scan_step should be > 0\n");
150 else if(std::strcmp(argv[i],
"--scan_voxel") == 0)
152 scanVoxel = atof(argv[++i]);
155 printf(
"scan_voxel should be >= 0.0\n");
159 else if(std::strcmp(argv[i],
"--scan_k") == 0)
161 scanNormalK = atoi(argv[++i]);
164 printf(
"scanNormalK should be >= 0\n");
168 else if(std::strcmp(argv[i],
"--scan_radius") == 0)
170 scanNormalRadius = atof(argv[++i]);
171 if(scanNormalRadius < 0.0
f)
173 printf(
"scanNormalRadius should be >= 0\n");
177 else if(std::strcmp(argv[i],
"--scan_only") == 0)
179 scan = scanOnly =
true;
181 else if(std::strcmp(argv[i],
"--gt") == 0)
185 else if(std::strcmp(argv[i],
"--color") == 0)
189 else if(std::strcmp(argv[i],
"--height") == 0)
193 else if(std::strcmp(argv[i],
"--scan") == 0)
197 else if(std::strcmp(argv[i],
"--disp") == 0)
201 else if(std::strcmp(argv[i],
"--exposure_comp") == 0)
203 exposureCompensation =
true;
219 parameters.insert(
ParametersPair(Parameters::kRtabmapWorkingDirectory(), output));
220 parameters.insert(
ParametersPair(Parameters::kRtabmapPublishRAMUsage(),
"true"));
223 seq =
uSplit(path,
'/').back();
226 UWARN(
"Sequence number \"%s\" should be between 0 and 21 (official KITTI datasets).", seq.c_str());
229 std::string pathLeftImages = path+(color?
"/image_2":
"/image_0");
230 std::string pathRightImages = path+(color?
"/image_3":
"/image_1");
231 std::string pathCalib = path+
"/calib.txt";
232 std::string pathTimes = path+
"/times.txt";
233 std::string pathScan;
236 " Sequence number: %s\n" 237 " Sequence path: %s\n" 241 " right images: %s\n" 248 pathLeftImages.c_str(),
249 pathRightImages.c_str(),
258 UWARN(
"Ground truth file path doesn't exist: \"%s\", benchmark values won't be computed.", gtPath.c_str());
263 printf(
" Ground Truth: %s\n", gtPath.c_str());
266 printf(
" Exposure Compensation: %s\n", exposureCompensation?
"true":
"false");
267 printf(
" Disparity: %s\n", disp?
"true":
"false");
270 pathScan = path+
"/velodyne";
271 printf(
" Scan: %s\n", pathScan.c_str());
272 printf(
" Scan only: %s\n", scanOnly?
"true":
"false");
273 printf(
" Scan step: %d\n", scanStep);
274 printf(
" Scan voxel: %fm\n", scanVoxel);
275 printf(
" Scan normal k: %d\n", scanNormalK);
276 printf(
" Scan normal radius: %f\n", scanNormalRadius);
281 pFile = fopen(pathCalib.c_str(),
"r");
284 UERROR(
"Cannot open calibration file \"%s\"", pathCalib.c_str());
287 cv::Mat_<double> P0(3,4);
288 cv::Mat_<double> P1(3,4);
289 cv::Mat_<double> P2(3,4);
290 cv::Mat_<double> P3(3,4);
291 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
292 &P0(0, 0), &P0(0, 1), &P0(0, 2), &P0(0, 3),
293 &P0(1, 0), &P0(1, 1), &P0(1, 2), &P0(1, 3),
294 &P0(2, 0), &P0(2, 1), &P0(2, 2), &P0(2, 3)) != 12)
296 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
299 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
300 &P1(0, 0), &P1(0, 1), &P1(0, 2), &P1(0, 3),
301 &P1(1, 0), &P1(1, 1), &P1(1, 2), &P1(1, 3),
302 &P1(2, 0), &P1(2, 1), &P1(2, 2), &P1(2, 3)) != 12)
304 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
307 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
308 &P2(0, 0), &P2(0, 1), &P2(0, 2), &P2(0, 3),
309 &P2(1, 0), &P2(1, 1), &P2(1, 2), &P2(1, 3),
310 &P2(2, 0), &P2(2, 1), &P2(2, 2), &P2(2, 3)) != 12)
312 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
315 if(fscanf (pFile,
"%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
316 &P3(0, 0), &P3(0, 1), &P3(0, 2), &P3(0, 3),
317 &P3(1, 0), &P3(1, 1), &P3(1, 2), &P3(1, 3),
318 &P3(2, 0), &P3(2, 1), &P3(2, 2), &P3(2, 3)) != 12)
320 UERROR(
"Failed to parse calibration file \"%s\"", pathCalib.c_str());
330 UERROR(
"Failed to read first image of \"%s\"", firstImage.c_str());
335 image.size(), P0.colRange(0,3), cv::Mat(), cv::Mat(), P0,
336 image.size(), P1.colRange(0,3), cv::Mat(), cv::Mat(), P1,
337 cv::Mat(), cv::Mat(), cv::Mat(), cv::Mat());
338 if(!
model.save(output,
true))
340 UERROR(
"Could not save calibration!");
343 printf(
"Saved calibration \"%s\" to \"%s\"\n", (outputName+
"_calib").c_str(), output.c_str());
345 if(!parameters.empty())
347 printf(
"Parameters:\n");
348 for(ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
350 printf(
" %s=%s\n", iter->first.c_str(), iter->second.c_str());
354 printf(
"RTAB-Map version: %s\n", RTABMAP_VERSION);
362 Transform opticalRotation(0,0,1,0, -1,0,0,color?-0.06:0, 0,-1,0,height?1.67:0.0);
378 if(exposureCompensation)
390 if(!pathScan.empty())
395 Transform(-0.27
f, 0.0
f, 0.08+(height?1.67
f:0.0
f), 0.0f, 0.0f, 0.0f));
407 float detectionRate = Parameters::defaultRtabmapDetectionRate();
408 bool intermediateNodes = Parameters::defaultRtabmapCreateIntermediateNodes();
409 int odomStrategy = Parameters::defaultOdomStrategy();
411 Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), detectionRate);
412 Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), intermediateNodes);
415 int mapUpdate = detectionRate>0?10 / detectionRate:1;
421 std::string databasePath = output+
"/"+outputName+
".db";
423 if(cameraThread.
camera()->
init(output, outputName+
"_calib"))
427 printf(
"Processing %d images...\n", totalImages);
430 odomParameters.erase(Parameters::kRtabmapPublishRAMUsage());
433 rtabmap.
init(parameters, databasePath);
445 int odomKeyFrames = 0;
462 if(odomStrategy == 2)
471 bool processData =
true;
472 if(iteration % mapUpdate != 0)
476 data.
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
477 processData = intermediateNodes;
479 if(covariance.empty() || odomInfo.
reg.
covariance.at<
double>(0,0) > covariance.at<
double>(0,0))
487 std::map<std::string, float> externalStats;
489 externalStats.insert(std::make_pair(
"Camera/BilateralFiltering/ms", cameraInfo.
timeBilateralFiltering*1000.0f));
490 externalStats.insert(std::make_pair(
"Camera/Capture/ms", cameraInfo.
timeCapture*1000.0f));
491 externalStats.insert(std::make_pair(
"Camera/Disparity/ms", cameraInfo.
timeDisparity*1000.0f));
492 externalStats.insert(std::make_pair(
"Camera/ImageDecimation/ms", cameraInfo.
timeImageDecimation*1000.0f));
493 externalStats.insert(std::make_pair(
"Camera/Mirroring/ms", cameraInfo.
timeMirroring*1000.0f));
495 externalStats.insert(std::make_pair(
"Camera/ScanFromDepth/ms", cameraInfo.
timeScanFromDepth*1000.0f));
496 externalStats.insert(std::make_pair(
"Camera/TotalTime/ms", cameraInfo.
timeTotal*1000.0f));
497 externalStats.insert(std::make_pair(
"Camera/UndistortDepth/ms", cameraInfo.
timeUndistortDepth*1000.0f));
499 externalStats.insert(std::make_pair(
"Odometry/LocalBundle/ms", odomInfo.
localBundleTime*1000.0f));
500 externalStats.insert(std::make_pair(
"Odometry/LocalBundleConstraints/", odomInfo.
localBundleConstraints));
501 externalStats.insert(std::make_pair(
"Odometry/LocalBundleOutliers/", odomInfo.
localBundleOutliers));
502 externalStats.insert(std::make_pair(
"Odometry/TotalTime/ms", odomInfo.
timeEstimation*1000.0f));
503 externalStats.insert(std::make_pair(
"Odometry/Registration/ms", odomInfo.
reg.
totalTime*1000.0f));
504 externalStats.insert(std::make_pair(
"Odometry/Speed/kph", speed));
505 externalStats.insert(std::make_pair(
"Odometry/Inliers/", odomInfo.
reg.
inliers));
506 externalStats.insert(std::make_pair(
"Odometry/Features/", odomInfo.
features));
507 externalStats.insert(std::make_pair(
"Odometry/DistanceTravelled/m", odomInfo.
distanceTravelled));
508 externalStats.insert(std::make_pair(
"Odometry/KeyFrameAdded/", odomInfo.
keyFrameAdded));
509 externalStats.insert(std::make_pair(
"Odometry/LocalKeyFrames/", odomInfo.
localKeyFrames));
510 externalStats.insert(std::make_pair(
"Odometry/LocalMapSize/", odomInfo.
localMapSize));
511 externalStats.insert(std::make_pair(
"Odometry/LocalScanMapSize/", odomInfo.
localScanMapSize));
515 covariance = cv::Mat();
519 if(!quiet || iteration == totalImages)
521 double slamTime = timer.
ticks();
535 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%f, kfs=%d)=%dms, slam=%dms, rmse=%fm",
540 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%f, kfs=%d)=%dms, slam=%dms",
550 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%d/%d, kfs=%d)=%dms, slam=%dms, rmse=%fm",
555 printf(
"Iteration %d/%d: speed=%dkm/h camera=%dms, odom(quality=%d/%d, kfs=%d)=%dms, slam=%dms",
565 else if(iteration % (totalImages/10) == 0)
576 printf(
"Total time=%fs\n", totalTime.
ticks());
582 printf(
"Saving trajectory ...\n");
583 std::map<int, Transform> poses;
584 std::multimap<int, Link> links;
585 rtabmap.
getGraph(poses, links,
true,
true);
586 std::string pathTrajectory = output+
"/"+outputName+
"_poses.txt";
589 printf(
"Saving %s... done!\n", pathTrajectory.c_str());
593 printf(
"Saving %s... failed!\n", pathTrajectory.c_str());
599 std::map<int, Transform> groundTruth;
601 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
607 std::vector<float> v;
610 rtabmap.
getMemory()->
getNodeInfo(iter->first, o, m, w, l, s, gtPose, v, gps, sensors,
true);
613 groundTruth.insert(std::make_pair(iter->first, gtPose));
621 printf(
"Ground truth comparison:\n");
622 printf(
" KITTI t_err = %f %%\n", t_err);
623 printf(
" KITTI r_err = %f deg/m\n", r_err);
626 float translational_rmse = 0.0f;
627 float translational_mean = 0.0f;
628 float translational_median = 0.0f;
629 float translational_std = 0.0f;
630 float translational_min = 0.0f;
631 float translational_max = 0.0f;
632 float rotational_rmse = 0.0f;
633 float rotational_mean = 0.0f;
634 float rotational_median = 0.0f;
635 float rotational_std = 0.0f;
636 float rotational_min = 0.0f;
637 float rotational_max = 0.0f;
643 translational_median,
654 printf(
" translational_rmse= %f m\n", translational_rmse);
655 printf(
" rotational_rmse= %f deg\n", rotational_rmse);
658 std::string pathErrors = output+
"/"+outputName+
"_rmse.txt";
659 pFile = fopen(pathErrors.c_str(),
"w");
662 UERROR(
"could not save RMSE results to \"%s\"", pathErrors.c_str());
664 fprintf(pFile,
"Ground truth comparison:\n");
665 fprintf(pFile,
" KITTI t_err = %f %%\n", t_err);
666 fprintf(pFile,
" KITTI r_err = %f deg/m\n", r_err);
667 fprintf(pFile,
" translational_rmse= %f\n", translational_rmse);
668 fprintf(pFile,
" translational_mean= %f\n", translational_mean);
669 fprintf(pFile,
" translational_median= %f\n", translational_median);
670 fprintf(pFile,
" translational_std= %f\n", translational_std);
671 fprintf(pFile,
" translational_min= %f\n", translational_min);
672 fprintf(pFile,
" translational_max= %f\n", translational_max);
673 fprintf(pFile,
" rotational_rmse= %f\n", rotational_rmse);
674 fprintf(pFile,
" rotational_mean= %f\n", rotational_mean);
675 fprintf(pFile,
" rotational_median= %f\n", rotational_median);
676 fprintf(pFile,
" rotational_std= %f\n", rotational_std);
677 fprintf(pFile,
" rotational_min= %f\n", rotational_min);
678 fprintf(pFile,
" rotational_max= %f\n", rotational_max);
684 UERROR(
"Camera init failed!");
687 printf(
"Saving rtabmap database (with all statistics) to \"%s\"\n", (output+
"/"+outputName+
".db").c_str());
689 " $ rtabmap-databaseViewer %s\n\n", (output+
"/"+outputName+
".db").c_str());
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 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()
const Statistics & getStatistics() const
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
const std::vector< cv::KeyPoint > & keypoints() const
void init(const ParametersMap ¶meters, const std::string &databasePath="", bool loadDatabaseParameters=false)
Basic mathematics functions.
Some conversion functions.
int localBundleConstraints
static void setLevel(ULogger::Level level)
Transform process(SensorData &data, OdometryInfo *info=0)
const std::map< std::string, float > & data() const
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")=0
SensorData takeImage(CameraInfo *info=0)
Wrappers of STL for convenient functions.
std::list< std::string > uSplit(const std::string &str, char separator=' ')
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)
const Memory * getMemory() 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)
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< float > velocity() const
void postUpdate(SensorData *data, CameraInfo *info=0) const
std::vector< V > uValues(const std::multimap< K, V > &mm)
std::string getNextFilePath()
void setStereoToDepth(bool enabled)
const LaserScan & laserScanRaw() const
std::string getNextFileName()
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
float timeImageDecimation
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)
int getLoopClosureId() const
void RTABMAP_EXP calcKittiSequenceErrors(const std::vector< Transform > &poses_gt, const std::vector< Transform > &poses_result, float &t_err, float &r_err)