Skip to content

Commit

Permalink
Added script to reproduce results from loop closure detection paper. …
Browse files Browse the repository at this point in the history
…Added option to show Recall at 100% precision directly from rtabmap-console. Fixed retrieval not working on loop closure detection mode-only. Fixed showLogs.m error with Octave.
  • Loading branch information
matlabbe committed May 19, 2024
1 parent 812caee commit 256dcbd
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 64 deletions.
25 changes: 25 additions & 0 deletions archive/2010-LoopClosure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

To reproduce results (based on parameters of this [paper](https://introlab.3it.usherbrooke.ca/mediawiki-introlab/images/b/bc/TRO2013.pdf)):

```
rtabmap-console \
--Rtabmap/StatisticLogged true\
--Rtabmap/StatisticLoggedHeaders false\
--Kp/DetectorStrategy 0\
--Rtabmap/MemoryThr 300\
--Rtabmap/LoopRatio 0.9\
--SURF/HessianThreshold 150\
--Mem/STMSize 30\
--Vis/MaxFeatures 400\
--Kp/TfIdfLikelihoodUsed false\
--Kp/MaxFeatures 400\
--Kp/BadSignRatio 0.25\
--Mem/BadSignaturesIgnored true\
--Mem/RehearsalSimilarity 0.20\
--Mem/RecentWmRatio 0.2\
-gt "~/Downloads/UdeS_1Hz.png"\
~/Downloads/UdeS_1Hz
```
Adding the ground truth file here is optional to show recall at 100% precision at the end of the process directly without using the octave/MATLAB script below. For NewCollege and CityCentre datasets, `rtabmap-imagesJoiner` can be used to assemble the left and right images together.

To analyze with Octave/MATLAB, drop `LogF.txt` and `LogI.txt` generated files from command above in ShowLogs directly, then execute `showLogs.m`.
4 changes: 0 additions & 4 deletions archive/2010-LoopClosure/README.txt

This file was deleted.

7 changes: 3 additions & 4 deletions archive/2010-LoopClosure/ShowLogs/getPrecisionRecall.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
if size(GroundTruth, 1) ~= length(LogF(:,1)) || size(GroundTruth, 1) ~= length(LogI(:,1))
error(['The ground truth size doesn''t match the log files (LogI=' num2str(length(LogI(:,1))) ', LogF=' num2str(length(LogF(:,1))) ', GT=' num2str(size(GroundTruth, 1)) ')'])
end



%[highestHypot, CorrespondingID, GT, Accepted, Good, Index, UnderLoopRatio] descending order
if(sum(LogI(:,8) == 10) > 0)
%OLD
Expand Down Expand Up @@ -111,14 +110,14 @@
index = find(PR(:,1) == 1);
if ~isempty(index)
maxRecall = PR(index(end),2) * 100;
display(['Recall max (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(index(end),1)) '), accepted=' num2str(sum(lc(1:index(end),5) & ~lc(1:index(end),7) & lc(1:index(end),2)))])
display(['Recall max (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(index(end),1)) '), accepted=' num2str(sum(lc(1:index(end),5) & ~lc(1:index(end),7) & lc(1:index(end),2))) '/' num2str(GT_total_positives)])
else
display('Recall max (Precision=100%) = 0')
end
indexAccepted = find(PR(:,3) == 1);
if ~isempty(indexAccepted)
maxRecall = PR(indexAccepted(end),2) * 100;
display(['Recall max accepted (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(indexAccepted(end),1)) '), accepted=' num2str(sum(lc(1:indexAccepted(end),5) & ~lc(1:indexAccepted(end),7) & lc(1:indexAccepted(end),2)))])
display(['Recall max accepted (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(indexAccepted(end),1)) '), accepted=' num2str(sum(lc(1:indexAccepted(end),5) & ~lc(1:indexAccepted(end),7) & lc(1:indexAccepted(end),2))) '/' num2str(GT_total_positives)])
else
display('Recall max accepted (Precision=100%) = 0')
end
Expand Down
4 changes: 3 additions & 1 deletion archive/2010-LoopClosure/ShowLogs/showlogs.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
set(0,'defaultAxesFontName', 'Times')
set(0,'defaultTextFontName', 'Times')

close all

if nargin < 2, GT_file = ''; end
if nargin < 1, PathPrefix = '.'; end

Expand Down Expand Up @@ -325,7 +327,7 @@
x(LogI(:, 1) == 0) = [];
plot(x,y, 'g.')

set(datacursormode,'UpdateFcn',@(Y,X){sprintf('X: %0.2f',X.Position(1)),sprintf('Y: %0.2f',X.Position(2))})
%set(datacursormode,'UpdateFcn',@(Y,X){sprintf('X: %0.2f',X.Position(1)),sprintf('Y: %0.2f',X.Position(2))})
% %matched sign words
% y = LogI(:,2);
% x = 1:length(y);
Expand Down
8 changes: 8 additions & 0 deletions archive/2010-LoopClosure/run_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

$SCRIPT_DIR/run_bow.sh ~/loop_closure_detection_datasets/NewCollege ~/loop_closure_detection_datasets/NewCollege.png
$SCRIPT_DIR/run_bow.sh ~/loop_closure_detection_datasets/CityCentre ~/loop_closure_detection_datasets/CityCentre.png
$SCRIPT_DIR/run_bow.sh ~/loop_closure_detection_datasets/UdeS_1Hz ~/loop_closure_detection_datasets/UdeS_1Hz.png

32 changes: 32 additions & 0 deletions archive/2010-LoopClosure/run_bow.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash

DATASET_FOLDER=""
GT_FILE=""
if [ $# -eq 2 ]
then
DATASET_FOLDER=$1
GT_FILE=$2
else
echo "Usage: run_bow.sh \"dataset folder\" \"ground truth file\""
exit
fi

rtabmap-console \
-quiet \
--Rtabmap/StatisticLogged true\
--Rtabmap/StatisticLoggedHeaders false\
--Kp/DetectorStrategy 0\
--SURF/HessianThreshold 150\
--Rtabmap/MemoryThr 300\
--Rtabmap/LoopRatio 0.9\
--Mem/STMSize 30\
--Vis/MaxFeatures 400\
--Kp/TfIdfLikelihoodUsed false\
--Kp/MaxFeatures 400\
--Kp/BadSignRatio 0.25\
--Mem/BadSignaturesIgnored true\
--Mem/RehearsalSimilarity 0.20\
--Mem/RecentWmRatio 0.20\
-gt "$GT_FILE"\
"$DATASET_FOLDER"

2 changes: 2 additions & 0 deletions corelib/include/rtabmap/core/Rtabmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class RTABMAP_CORE_EXPORT Rtabmap

float getTimeThreshold() const {return _maxTimeAllowed;} // in ms
void setTimeThreshold(float maxTimeAllowed); // in ms
int getMemoryThreshold() const {return _maxMemoryAllowed;} // in nodes
void setMemoryThreshold(int maxMemoryAllowed); // in nodes

void setInitialPose(const Transform & initialPose);
int triggerNewMap();
Expand Down
58 changes: 34 additions & 24 deletions corelib/src/Rtabmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2532,37 +2532,37 @@ bool Rtabmap::process(
// insert them first to make sure they are loaded.
reactivatedIds.insert(reactivatedIds.begin(), retrievalLocalIds.begin(), retrievalLocalIds.end());
}
}

//============================================================
// RETRIEVAL 3/3 : Load signatures from the database
//============================================================
if(reactivatedIds.size())
{
// Not important if the loop closure hypothesis don't have all its neighbors loaded,
// only a loop closure link is added...
signaturesRetrieved = _memory->reactivateSignatures(
reactivatedIds,
_maxRetrieved+(unsigned int)retrievalLocalIds.size(), // add path retrieved
timeRetrievalDbAccess);
//============================================================
// RETRIEVAL 3/3 : Load signatures from the database
//============================================================
if(reactivatedIds.size())
{
// Not important if the loop closure hypothesis don't have all its neighbors loaded,
// only a loop closure link is added...
signaturesRetrieved = _memory->reactivateSignatures(
reactivatedIds,
_maxRetrieved+(unsigned int)retrievalLocalIds.size(), // add path retrieved
timeRetrievalDbAccess);

ULOGGER_INFO("retrieval of %d (db time = %fs)", (int)signaturesRetrieved.size(), timeRetrievalDbAccess);
ULOGGER_INFO("retrieval of %d (db time = %fs)", (int)signaturesRetrieved.size(), timeRetrievalDbAccess);

timeRetrievalDbAccess += timeGetNeighborsTimeDb + timeGetNeighborsSpaceDb;
UINFO("total timeRetrievalDbAccess=%fs", timeRetrievalDbAccess);
timeRetrievalDbAccess += timeGetNeighborsTimeDb + timeGetNeighborsSpaceDb;
UINFO("total timeRetrievalDbAccess=%fs", timeRetrievalDbAccess);

// Immunize just retrieved signatures
immunizedLocations.insert(signaturesRetrieved.begin(), signaturesRetrieved.end());
// Immunize just retrieved signatures
immunizedLocations.insert(signaturesRetrieved.begin(), signaturesRetrieved.end());

if(!signaturesRetrieved.empty() && !_globalScanMap.empty())
{
UWARN("Some signatures have been retrieved from memory management, clearing global scan map...");
_globalScanMap.clear();
_globalScanMapPoses.clear();
}
if(!signaturesRetrieved.empty() && !_globalScanMap.empty())
{
UWARN("Some signatures have been retrieved from memory management, clearing global scan map...");
_globalScanMap.clear();
_globalScanMapPoses.clear();
}
timeReactivations = timer.ticks();
ULOGGER_INFO("timeReactivations=%fs", timeReactivations);
}
timeReactivations = timer.ticks();
ULOGGER_INFO("timeReactivations=%fs", timeReactivations);

//============================================================
// Proximity detections
Expand Down Expand Up @@ -4739,6 +4739,16 @@ void Rtabmap::setTimeThreshold(float maxTimeAllowed)
ULOGGER_WARN("Time threshold set to %fms, it is not in seconds!", _maxTimeAllowed);
}
}
void Rtabmap::setMemoryThreshold(int maxMemoryAllowed)
{
//must be positive, 0 mean inf memory allowed (no memory limit)
_maxMemoryAllowed = maxMemoryAllowed;
if(_maxMemoryAllowed < 0)
{
ULOGGER_WARN("maxMemoryAllowed < 0, then setting it to 0 (inf).");
_maxMemoryAllowed = 0;
}
}

void Rtabmap::setWorkingDirectory(std::string path)
{
Expand Down
Loading

0 comments on commit 256dcbd

Please sign in to comment.