Updated illumination invariant paper documentation
@@ -1,22 +0,0 @@
|
||||
|
||||
## Multi-Session Visual SLAM for Illumination Invariant Localization in Indoor Environments
|
||||
|
||||
* Paper: https://arxiv.org/abs/2103.03827
|
||||
|
||||
* The setup: we did 6 mapping sessions at dusk to evaluate how well RTAB-Map can localize (only by vision) on maps taken at different illumination conditions. The data has been collected with [RTAB-Map Tango](https://play.google.com/store/apps/details?id=com.introlab.rtabmap&hl=en_CA&gl=US).
|
||||
]
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
This folder contains scripts to re-generate results from the paper. The main idea behind this work is that using Multi-Session mapping can help to localize visually in illumination changing environments even with features that are not very robust to such conditions. We compared common hand-made visual features like SIFT, SURF, BRIEF, BRISK, FREAK, DAISY, KAZE with learned descriptor SuperPoint. The following picture show how robust are the visual features tested when localizing against single session recorded at different time. For example, the bottom-left and top-right cells are when the robot tries to localize the night on a map taken the day or vice-versa. The diagonal is localization performance when the localization session is about the same time than when the map was recorded. SuperPoint has clearly an advantage on this single-session experiment.
|
||||
|
||||
]
|
||||
|
||||
The following image shows when we do the same localization experiment at different hours, but against maps created by assembling maps taken at different hours. In this case, we can see that even binary features like BRIEF can work relatively well in illumination-variant environments. See the paper for more detailled results and comments. The line `1+2+3+4+5+6` refers to the assembled map shown below containing all mapping sessions linked together in same database.
|
||||
|
||||
]
|
||||
|
||||
|
||||
]
|
||||
|
||||
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 110 KiB |
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
SKIP=$1
|
||||
fi
|
||||
|
||||
DETECTOR=(0 1 6 7 9 11 12 14) #0 1 6 7 8 9 11 12 13 14
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPORT_TOOL="${PREFIX}rtabmap-report"
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
$REPORT_TOOL --export --export_prefix "Stat$d" --loc 32 Loop/Odom_correction_norm/m Loop/Visual_inliers/ Timing/Total/ms Loop/Map_id/ Keypoint/Current_frame/words Memory/RAM_usage/MB Memory/RAM_estimated/MB Memory/Distance_travelled/m "$SKIP/$d/loc"
|
||||
$REPORT_TOOL --export --export_prefix "Consecutive$d" --loc 32 Loop/Map_id/ "$SKIP/$d/consecutive_loc"
|
||||
done
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 2 ]
|
||||
then
|
||||
SKIP=$2
|
||||
fi
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
|
||||
DETECT_MORE_LOOP_CLOSURE_TOOL="${PREFIX}rtabmap-detectMoreLoopClosures"
|
||||
|
||||
[ ! -d "$SKIP" ] && mkdir $SKIP
|
||||
[ ! -d "$SKIP/$TYPE" ] && mkdir $SKIP/$TYPE
|
||||
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db'
|
||||
DATABASES=( 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' )
|
||||
|
||||
PARAMS="--Kp/DetectorStrategy $TYPE --Vis/FeatureType $TYPE"
|
||||
|
||||
if [ $TYPE -eq 2 ] || [ $TYPE -eq 3 ] || [ $TYPE -eq 4 ] || [ $TYPE -eq 5 ] || [ $TYPE -eq 6 ] || [ $TYPE -eq 7 ] || [ $TYPE -eq 8 ] || [ $TYPE -eq 10 ] || [ $TYPE -eq 12 ]
|
||||
then
|
||||
# binary descriptors
|
||||
PARAMS="--Vis/CorNNDR 0.8 $PARAMS"
|
||||
else
|
||||
# float descriptors
|
||||
PARAMS="--Vis/CorNNDR 0.6 $PARAMS"
|
||||
if
|
||||
|
||||
echo $PARAMS
|
||||
for db in "${DATABASES[@]}"
|
||||
do
|
||||
$REPROCESS_TOOL --skip $SKIP --RGBD/MarkerDetection false --RGBD/ProximityBySpace true --RGBD/LocalRadius 1 --Mem/InitWMWithAllNodes true --Rtabmap/TimeThr 0 --Mem/UseOdomFeatures false --Optimizer/GravitySigma 0.1 --Mem/UseOdomGravity true --RGBD/OptimizeFromGraphEnd false --Mem/DepthAsMask false --RGBD/OptimizeMaxError 4 --RGBD/ProximityOdomGuess false --Vis/MaxFeatures 1000 --Kp/MaxFeatures 400 --Vis/EpipolarGeometryVar 0.1 --Vis/EstimationType 1 --Vis/MinInliers 20 --Rtabmap/MaxRetrieved 2 --Optimizer/Iterations 20 --Mem/CompressionParallelized true --Kp/Parallelized true --Kp/MaxDepth 0 --Kp/BadSignRatio 0.2 --BRIEF/Bytes 32 --Kp/ByteToFloat true --SURF/HessianThreshold 100 --SIFT/ContrastThreshold 0.02 --BRISK/Thresh 10 --SuperPoint/ModelPath superpoint.pt --Rtabmap/PublishRAMUsage true --ORB/EdgeThreshold 19 --ORB/ScaleFactor 2 --ORB/NLevels 3 --uerror $PARAMS $db $SKIP/$TYPE/$db
|
||||
$DETECT_MORE_LOOP_CLOSURE_TOOL --uwarn $SKIP/$TYPE/$db
|
||||
done
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
SKIP=$1
|
||||
fi
|
||||
|
||||
DETECTOR=(0 1 6 7 9 11 12 14)
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
./reprocess_maps.sh $d $SKIP
|
||||
./run_merge.sh $d $SKIP
|
||||
done
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
SKIP=$1
|
||||
fi
|
||||
|
||||
./reprocess_maps_all.sh $SKIP
|
||||
./run_merge.sh $SKIP
|
||||
./run_localization_single_all.sh $SKIP
|
||||
./run_consecutive_localization_all.sh $SKIP
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 2 ]
|
||||
then
|
||||
SKIP=$2
|
||||
fi
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
|
||||
|
||||
SOURCE=('map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db')
|
||||
TARGETS=($SKIP/$TYPE'/map_190321-172717.db;'$SKIP/$TYPE'/map_190321-175428.db;'$SKIP/$TYPE'/map_190321-193556.db' $SKIP/$TYPE'/map_190321-175428.db;'$SKIP/$TYPE'/map_190321-182709.db;' $SKIP/$TYPE'/map_190321-182709.db;'$SKIP/$TYPE'/map_190321-185608.db' $SKIP/$TYPE'/map_190321-185608.db;'$SKIP/$TYPE'/map_190321-193556.db' $SKIP/$TYPE'/map_190321-193556.db' )
|
||||
|
||||
|
||||
[ ! -d "$SKIP/$TYPE/consecutive_loc" ] && mkdir $SKIP/$TYPE/consecutive_loc
|
||||
|
||||
for i in ${!SOURCE[@]}
|
||||
do
|
||||
db=${SOURCE[$i]}
|
||||
loc_dbs=${TARGETS[$i]}
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --uwarn "$SKIP/$TYPE/$db;$loc_dbs" $SKIP/$TYPE/consecutive_loc/loc_$db
|
||||
done
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
SKIP=$1
|
||||
fi
|
||||
|
||||
DETECTOR=(0 1 6 7 9 11 12 14)
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
./run_consecutive_localization.sh $d $SKIP
|
||||
done
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 2 ]
|
||||
then
|
||||
SKIP=$2
|
||||
fi
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
|
||||
|
||||
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
|
||||
LOCALIZATION_DATABASES="loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db"
|
||||
|
||||
[ ! -d "$SKIP/$TYPE/loc" ] && mkdir $SKIP/$TYPE/accuracy
|
||||
|
||||
db=merged_9999.db
|
||||
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOn_$db
|
||||
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 1 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOn_$db
|
||||
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOff_$db
|
||||
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 0 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOff_$db
|
||||
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOn_$db
|
||||
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOff_$db
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 2 ]
|
||||
then
|
||||
SKIP=$2
|
||||
fi
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
|
||||
|
||||
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_9999.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' 'merged_9999_reduced.db'
|
||||
DATABASES=( 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_9999.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' )
|
||||
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
|
||||
LOCALIZATION_DATABASES="loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db"
|
||||
|
||||
[ ! -d "$SKIP/$TYPE/loc" ] && mkdir $SKIP/$TYPE/loc
|
||||
|
||||
echo $PARAMS
|
||||
for db in "${DATABASES[@]}"
|
||||
do
|
||||
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/loc/loc_$db
|
||||
done
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
SKIP=$1
|
||||
fi
|
||||
|
||||
DETECTOR=(0 1 6 7 9 11 12 14)
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
./run_localization_single.sh $d $SKIP
|
||||
done
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 2 ]
|
||||
then
|
||||
SKIP=$2
|
||||
fi
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
|
||||
DETECT_MORE_LOOP_CLOSURE_TOOL="${PREFIX}rtabmap-detectMoreLoopClosures"
|
||||
|
||||
DATABASES="$SKIP/$TYPE/map_190321-164651.db;$SKIP/$TYPE/map_190321-172717.db;$SKIP/$TYPE/map_190321-175428.db;$SKIP/$TYPE/map_190321-182709.db;$SKIP/$TYPE/map_190321-185608.db;$SKIP/$TYPE/map_190321-193556.db"
|
||||
|
||||
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$DATABASES" $SKIP/$TYPE/merged_9999.db
|
||||
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_9999.db
|
||||
|
||||
#$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 --Mem/ReduceGraph true --Vis/MinInliers 60 "$DATABASES" $SKIP/$TYPE/merged_9999_reduced.db
|
||||
#$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_9999_reduced.db
|
||||
|
||||
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$SKIP/$TYPE/map_190321-164651.db;$SKIP/$TYPE/map_190321-193556.db" $SKIP/$TYPE/merged_16.db
|
||||
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_16.db
|
||||
|
||||
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$SKIP/$TYPE/map_190321-164651.db;$SKIP/$TYPE/map_190321-175428.db;$SKIP/$TYPE/map_190321-185608.db" $SKIP/$TYPE/merged_135.db
|
||||
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_135.db
|
||||
|
||||
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$SKIP/$TYPE/map_190321-172717.db;$SKIP/$TYPE/map_190321-182709.db;$SKIP/$TYPE/map_190321-193556.db" $SKIP/$TYPE/merged_246.db
|
||||
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_246.db
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SKIP=0
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
SKIP=$1
|
||||
fi
|
||||
|
||||
DETECTOR=(0 1 6 7 8 9 11 12 14)
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPORT_TOOL="${PREFIX}rtabmap-report"
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
valgrind --tool=massif --time-unit=ms --detailed-freq=1 --max-snapshots=100 ${PREFIX}rtabmap-reprocess --Mem/IncrementalMemory false --Kp/IncrementalFlann false "${SKIP}/${d}/merged_9999.db;map_190321-164651.db" output.db
|
||||
rm output.db
|
||||
done
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
## Multi-Session Visual SLAM for Illumination Invariant Re-Localization in Indoor Environments
|
||||
|
||||
* Paper: https://doi.org/10.3389/frobt.2022.801886
|
||||
|
||||
* The setup: we did 6 mapping sessions at dusk to evaluate how well RTAB-Map can localize (only by vision) on maps taken at different illumination conditions. The data has been collected with [RTAB-Map Tango](https://play.google.com/store/apps/details?id=com.introlab.rtabmap&hl=en_CA&gl=US).
|
||||
]
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
This folder contains scripts to re-generate results from the paper. The main idea behind this work is that using Multi-Session mapping can help to localize visually in illumination changing environments even with features that are not very robust to such conditions. We compared common hand-made visual features like SIFT, SURF, BRIEF, BRISK, FREAK, DAISY, KAZE with learned descriptor SuperPoint. The following picture show how robust are the visual features tested when localizing against single session recorded at different time. For example, the bottom-left and top-right cells are when the robot tries to localize the night on a map taken the day or vice-versa. The diagonal is localization performance when the localization session is about the same time than when the map was recorded. SuperPoint has clearly an advantage on this single-session experiment.
|
||||
|
||||
]
|
||||
|
||||
The following image shows when we do the same localization experiment at different hours, but against maps created by assembling maps taken at different hours. In this case, we can see that even binary features like BRIEF can work relatively well in illumination-variant environments. See the paper for more detailled results and comments. The line `1+2+3+4+5+6` refers to the assembled map shown below containing all mapping sessions linked together in same database.
|
||||
|
||||
]
|
||||
|
||||
|
||||
]
|
||||
|
||||
|
||||
## Dataset
|
||||
|
||||
We provide two formats: the first one is more general and the second one is used to produce the results in this paper with RTAB-Map. Please open issue if the links are outdated.
|
||||
|
||||
* [Images](https://usherbrooke-my.sharepoint.com/:u:/g/personal/labm2414_usherbrooke_ca/EV8F4PZUxOxLhwAyEehlzKwBjF-9xNuxR32Q4mUjx5u-rA?e=eCJ3TW):
|
||||
* `rgb`: folder containing *.jpg color camera images
|
||||
* `depth`: folder containing *.png 16bits mm depth images
|
||||
* `calib`: folder containing calibration for each color image. Each calibration contains also the transform between `device` and `camera` frames as `local_transform`.
|
||||
* `device_poses.txt`: poses of of each image in `device` frame
|
||||
* `camera_poses.txt`: poses of of each image in `camera` frame
|
||||
* [RTAB-Map Databases](https://usherbrooke-my.sharepoint.com/:u:/g/personal/labm2414_usherbrooke_ca/EU5fb0jEKzlGhPK3OWjMGLUBnDo1BRAoZwtB2czyeVLE_A?e=Y0JyXY)
|
||||
|
||||
|
||||
|
||||
## How reproduce results shown in the paper
|
||||
|
||||
1. RTAB-Map should be built from source with those dependencies (don't need to "install" it, we will launch it from build directory in the scripts below to avoid conflicting with another rtabmap already installed):
|
||||
* OpenCV built with xfeatures2d and nonfree modules
|
||||
* torchlib c++ to enable SuperPoint (superpoint.pt can be downloaded [here](https://github.com/KinglittleQ/SuperPoint_SLAM/blob/master/superpoint.pt))
|
||||
* Python3 to use SuperGlue
|
||||
|
||||
2. Download database version of the dataset and extract the databases in the `script` directory.
|
||||
3. Adjust the path inside `rtabmap_latest.sh` script to match where you just built rtabmap with right dependencies.
|
||||
4. Run `run_all.sh OUTPUT_PATH`, this script will do (warning, this could take hours to do...):
|
||||
* Recreate the map databases for each feature type
|
||||
* Create the merged databases
|
||||
* Run localization databases over all map/merged databases
|
||||
* Run consecutive localization experiment
|
||||
|
||||
5. Export statistics with `export_stats.sh` script.
|
||||
|
||||
6. Use the MatLab/Octave scripts in this folder to show results you want. Set `dataDir` to directory containing the exported statistics.
|
||||
|
||||
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 282 KiB |
@@ -2,24 +2,35 @@
|
||||
clear all
|
||||
close all
|
||||
|
||||
# sudo apt install octave-signal
|
||||
pkg load signal
|
||||
|
||||
# rtabmap-report --loc 32 Loop/Odom_correction_norm/m Loop/Visual_inliers/ Timing/Total/ms . Keypoint/Current_frame/words
|
||||
# Right-click on thr legend of the figure, copy all data to clipboard
|
||||
# Paste in correction#.txt, inliers#.txt and time#.txt where # is the
|
||||
# number of the descriptor used
|
||||
# Use with files generated by export_stats.sh
|
||||
|
||||
skipFrameDir = '0';
|
||||
prefix = 'Stat';
|
||||
RAMaddOverhead = 1;
|
||||
dataDir = '2'; % '0'=old, '1'=new, 2=revised(2022)
|
||||
resultsToShow = 1; % 1=single 2=Consecutive
|
||||
|
||||
prefix = 'Stat';
|
||||
RAMaddOverhead = 0;
|
||||
% Inliers_ratio = 'Loop/Visual_inliers/' ./ 'Keypoint/Current_frame/words'
|
||||
% Odometry_average = 'Memory/Distance_travelled/m'(2:end) - 'Memory/Distance_travelled/m'(1:end-1)
|
||||
statNames = {'Loop/Odom_correction_norm/m', 'Inliers_ratio_%', 'Timing/Total/ms', 'Memory/RAM_usage/MB', 'Memory/RAM_estimated/MB', 'Keypoint/Current_frame/words', 'Loop/Map_id/'}; % 'Odometry_average'
|
||||
|
||||
datasets = [ 0 1 6 7 9 12 14 11]; % 0 1 6 7 8 9 11 12
|
||||
statNames = {'Loop/Odom_correction_norm/m', 'Loop/Visual_inliers/', 'Inliers_ratio_%', 'Timing/Total/ms', 'Memory/RAM_usage/MB', 'Memory/RAM_estimated/MB', 'Keypoint/Current_frame/words', 'Loop/Map_id/', 'Memory/Local_graph_size/', 'Keypoint/Dictionary_size/words', 'Loop/Distance_since_last_loc/'}; % 'Odometry_average'
|
||||
|
||||
|
||||
datasets = [ 0 1 6 7 9 14 11 111 ]; % 0 1 6 7 9 12 14 11
|
||||
sep = [0, 1000, 3000, 5000, 7000, 9000, 12000];
|
||||
sepName = {'16:51', '17:31', '17:58', '18:30', '18:59', '19:42'};
|
||||
|
||||
if resultsToShow == 2
|
||||
sep = [0, 1000, 3000, 5000, 7000, 9000];
|
||||
sepName = {'17:27', '17:54', '18:27', '18:56', '19:35'};
|
||||
prefix = 'Consecutive';
|
||||
statNames = {'Loop/Distance_since_last_loc/', 'Distance_since_last_loc_under_50cm'};
|
||||
endif
|
||||
|
||||
MapsN = length(sepName);
|
||||
|
||||
allCumResults = {};
|
||||
allMaxResults = {};
|
||||
|
||||
@@ -35,13 +46,15 @@ statName = strrep(statNames{s},'/','-');
|
||||
for d=1:length(datasets)
|
||||
|
||||
if strcmp(statName,'Inliers_ratio_%')
|
||||
data = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' 'Loop-Visual_inliers-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
dataWords = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' 'Keypoint-Current_frame-words' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Loop-Visual_inliers-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
dataWords = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Keypoint-Current_frame-words' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
data(:, 2:end) = data(:, 2:end) ./ dataWords(:, 2:end) * 100;
|
||||
elseif strcmp(statName, 'Odometry_average')
|
||||
data = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' 'Memory-Distance_travelled-m' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Memory-Distance_travelled-m' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
elseif strcmp(statName, 'Distance_since_last_loc_under_50cm')
|
||||
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Loop-Distance_since_last_loc-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
else
|
||||
data = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' statName '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' statName '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
endif
|
||||
sessions = size(data,2)-1;
|
||||
|
||||
@@ -69,7 +82,7 @@ for i = 1:sessions
|
||||
if datasets(d) == 7
|
||||
%% 135 MB overhead for BRISK kernel
|
||||
y = y + 135;
|
||||
elseif datasets(d) == 11
|
||||
elseif datasets(d) == 11 || datasets(d) == 111
|
||||
%% 645 MB (library cuda) + 800 MB (network) for SuperPoint
|
||||
y = y + 645+800;
|
||||
elseif datasets(d) == 13 || datasets(d) == 14
|
||||
@@ -81,6 +94,12 @@ for i = 1:sessions
|
||||
if strcmp(statName, 'Loop-Map_id-')
|
||||
nonzeros = y;
|
||||
end
|
||||
if strcmp(statName, 'Distance_since_last_loc_under_50cm')
|
||||
y(y>0.55) = 0;
|
||||
y(isnan(y)) = 0;
|
||||
y(y>0) = 1;
|
||||
nonzeros = y;
|
||||
end
|
||||
if length(nonzeros) > 0
|
||||
avgValue = sum(nonzeros)/length(nonzeros);
|
||||
avgResultsTmp(i,j) = avgValue;
|
||||
@@ -103,7 +122,7 @@ for d=1:length(datasets)
|
||||
if sum(totalResults{1,d}, 2)
|
||||
cumResults(2:end-1,d+1) = sum(absResults{1,d}, 2) ./ sum(totalResults{1,d}, 2);
|
||||
endif
|
||||
cumResults(end,d+1) = sum(sum(absResults{1,d}(1:6,1:6).*eye(6,6))) / sum(sum(totalResults{1,d}(1:6,1:6).*eye(6,6)));
|
||||
cumResults(end,d+1) = sum(sum(absResults{1,d}(1:MapsN,1:MapsN).*eye(MapsN,MapsN))) / sum(sum(totalResults{1,d}(1:MapsN,1:MapsN).*eye(MapsN,MapsN)));
|
||||
end
|
||||
cumResults(2:end-1,1) = 1:sessions;
|
||||
|
||||
@@ -123,7 +142,7 @@ for d=1:length(datasets)
|
||||
if sum(totalResults{1,d}, 2)
|
||||
cumMaxResults(2:end-1,d+1) = max(maxResults{1,d}, [], 2);
|
||||
endif
|
||||
cumMaxResults(end,d+1) = max(max(maxResults{1,d}(1:6,1:6).*eye(6,6)));
|
||||
cumMaxResults(end,d+1) = max(max(maxResults{1,d}(1:MapsN,1:MapsN).*eye(MapsN,MapsN)));
|
||||
end
|
||||
cumMaxResults(2:end-1,1) = 1:sessions;
|
||||
|
||||
@@ -133,3 +152,18 @@ allMaxResults{2,s} = cumMaxResults;
|
||||
endfor % statNames
|
||||
|
||||
|
||||
if resultsToShow == 2
|
||||
disp('30min')
|
||||
for d=1:length(datasets)
|
||||
round(sum(absResults{1,d} .* eye(5,5)) / sum(totalResults{1,d} .*eye(5,5)) * 100)
|
||||
endfor
|
||||
disp('60min')
|
||||
for d=1:length(datasets)
|
||||
round(sum(absResults{1,d} .* [[0;0;0;0] eye(4,4) ; [0 0 0 0 0]]) / sum(totalResults{1,d} .*[[0;0;0;0] eye(4,4) ; [0 0 0 0 0]]) * 100)
|
||||
endfor
|
||||
disp('120min')
|
||||
for d=1:length(datasets)
|
||||
round(avgResults{1,d}(1,5) * 100)
|
||||
endfor
|
||||
endif
|
||||
|
||||
@@ -4,16 +4,15 @@ clear all
|
||||
|
||||
pkg load signal
|
||||
|
||||
# rtabmap-report --loc 32 Loop/Map_id/ loc
|
||||
# Right-click on thr legend of the figure, copy all data to clipboard
|
||||
# Paste in data#.txt where # is the number of the descriptor used
|
||||
# Use with files generated by export_stats.sh
|
||||
|
||||
dataDir = '2'; % '0'(old) '1'(new) '2' (revised april 2022)
|
||||
resultsToShow = 1; % 1=single loc, 2=merged loc, 3=consecutive
|
||||
skipFrameDir = '0';
|
||||
|
||||
datasetPrefix = 'Stat';
|
||||
datasets = [0 1 6 7 9 12 14 11]; % 0 1 6 7 8 9 11 12
|
||||
datasets = [0 1 6 7 9 14 11 111]; % 0 1 6 7 8 9 11 12
|
||||
datasetsName = {'SURF' 'SIFT' 'ORB' 'FAST/FREAK' 'FAST/BRIEF' 'GFTT/FREAK' 'GFTT/BRIEF' 'BRISK' 'GFTT/ORB' 'KAZE' 'ORB-OCTREE' 'SuperPoint' 'SURF/FREAK' 'GFTT/DAISY' 'SURF/DAISY'};
|
||||
datasetsName{112} = 'SuperGlue'
|
||||
sep = [0, 1000, 3000, 5000, 7000, 9000, 12000];
|
||||
sepName = {'16:51', '17:31', '17:58', '18:30', '18:59', '19:42'};
|
||||
|
||||
@@ -41,13 +40,13 @@ globalc = [];
|
||||
|
||||
for d=1:length(datasets)
|
||||
|
||||
data = dlmread([skipFrameDir '/' datasetPrefix num2str(datasets(d)) '-Loop-Map_id-' '.txt'], '\t', 1, 0, "emptyvalue", NaN);
|
||||
data = dlmread([dataDir '/' datasetPrefix num2str(datasets(d)) '-Loop-Map_id-' '.txt'], '\t', 1, 0, "emptyvalue", NaN);
|
||||
|
||||
curvesBeg = 2;
|
||||
curvesEnd = size(data,2)-4;
|
||||
curvesEnd = size(data,2)-5; % -4 for '0', -5 for '1'
|
||||
|
||||
if resultsToShow == 2
|
||||
curvesBeg = 8;
|
||||
curvesBeg = 8; % 2 if only 4 merged_reduced in stats, 8 to skip first 6
|
||||
curvesEnd = size(data,2);
|
||||
elseif resultsToShow == 3
|
||||
curvesEnd = size(data,2);
|
||||
@@ -198,7 +197,24 @@ for d=1:length(datasets)
|
||||
data=percentResults{1,d}*100;
|
||||
data(isnan(data)) = 0;
|
||||
hAxes = gca;
|
||||
imagesc( hAxes, data, [0, 100])
|
||||
% Upscaling the image to reduce anti-aliasing effect in pfd viewers
|
||||
scale = 50;
|
||||
tickXStep = zeros(1, size(data, 2));
|
||||
tickYStep = zeros(1, size(data, 1));
|
||||
dataUp = upsample(upsample(data',scale)',scale);
|
||||
for x=0:size(data, 2)-1
|
||||
for y=1:scale-1
|
||||
dataUp(:,(x*scale+1)+y) = dataUp(:,x*scale+1);
|
||||
endfor
|
||||
tickXStep(1,x+1) = scale/2 + scale*x;
|
||||
endfor
|
||||
for x=0:size(data, 1)-1
|
||||
for y=1:scale-1
|
||||
dataUp((x*scale+1)+y,:) = dataUp(x*scale+1,:);
|
||||
endfor
|
||||
tickYStep(1,x+1) = scale/2 + scale*x;
|
||||
endfor
|
||||
imagesc( hAxes, dataUp, [0, 100])
|
||||
%title({"",datasetsName{datasets(d)+1}})
|
||||
colors = [ones(100,1) [1:100]'*0.01 [1:100]'*0];
|
||||
colors(1,:) = 1;
|
||||
@@ -211,12 +227,14 @@ for d=1:length(datasets)
|
||||
ylabel("Map")
|
||||
endif
|
||||
xlabel([datasetsName{datasets(d)+1} " Localization"])
|
||||
set (gca, "xaxislocation", "top");
|
||||
set(gca, "xaxislocation", "top");
|
||||
set(gca, 'XTick', tickXStep)
|
||||
set(gca, 'XTickLabel', sepName, 'fontsize',7)
|
||||
set(gca, 'YTick', tickYStep)
|
||||
if resultsToShow == 3
|
||||
set(gca, 'YTickLabel', {'16:46', '17:27', '17:54', '18:27', '18:56'}, 'fontsize',7)
|
||||
elseif resultsToShow == 2
|
||||
set(gca, 'YTickLabel', {'1+6', '1+3+5', '2+4+6', '1+2+3+4+6', 'bundle', 'reduced'}, 'fontsize',7)
|
||||
set(gca, 'YTickLabel', {'1+6', '1+3+5', '2+4+6', '1+2+3+4+5+6', '1-2-3-4-5-6', 'not set'}, 'fontsize',7)
|
||||
else
|
||||
set(gca, 'YTickLabel', {'16:46', '17:27', '17:54', '18:27', '18:56', '19:35'}, 'fontsize',7)
|
||||
endif
|
||||
@@ -232,4 +250,4 @@ for d=1:length(datasets)
|
||||
endif
|
||||
end
|
||||
cumResults(2:end-1,1) = 1:curves;
|
||||
cumResults
|
||||
cumResults
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
clear all
|
||||
close all
|
||||
|
||||
# sudo apt install octave-signal
|
||||
pkg load signal
|
||||
|
||||
# Use with files generated by export_stats.sh
|
||||
|
||||
dataDir = '2'; % '0'(old) '1'(new) '2' (revised april 2022)
|
||||
prefix = 'Stat';
|
||||
|
||||
dataset = 6
|
||||
sep = [0, 1000, 3000, 5000, 7000, 9000, 12000];
|
||||
sepName = {'16:51', '17:31', '17:58', '18:30', '18:59', '19:42'};
|
||||
|
||||
statName = strrep('Loop/Distance_since_last_loc/','/','-');
|
||||
|
||||
data = dlmread([dataDir '/' prefix num2str(dataset) '-' statName '.txt'], '\t', 1, 0, "emptyvalue", 0);
|
||||
|
||||
sessions = size(data,2)-1
|
||||
|
||||
j = 1 % session #
|
||||
x3 = data(:,1);
|
||||
y3 = data(:,11);
|
||||
y3 = y3(x3>=sep(j) & x3<=sep(j+1), :);
|
||||
x3 = x3(x3>=sep(j) & x3<=sep(j+1), :);
|
||||
|
||||
max = 0;
|
||||
for i=2:length(y3)
|
||||
if isfinite(y3(i)) && isfinite(y3(i-1)) && (x3(i) - x3(i-1) < 1.5)
|
||||
v = y3(i);
|
||||
if v>max
|
||||
max = v
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
xb = max/2:max:5;
|
||||
[nn3, xx3] = hist (y3, xb);
|
||||
nn3 = nn3/length(x3);
|
||||
nn3(nn3==0) = NaN;
|
||||
|
||||
for j=1:6
|
||||
|
||||
x{j} = data(:,1);
|
||||
y{j} = data(:,2);
|
||||
y{j} = y{j}(x{j}>=sep(j) & x{j}<=sep(j+1), :);
|
||||
x{j} = x{j}(x{j}>=sep(j) & x{j}<=sep(j+1), :);
|
||||
[nn{j}, xx{j}] = hist (y{j}, xb);
|
||||
%nn{j} = nn{j}/length(x{j});
|
||||
%nn{j} = nn{j}/sum(nn{j});
|
||||
|
||||
for k=length(nn{j}):-1:1
|
||||
if nn{j}(k) != 0
|
||||
break;
|
||||
else
|
||||
nn{j}(k) = NaN;
|
||||
endif
|
||||
endfor
|
||||
|
||||
endfor
|
||||
|
||||
j = 6 % session #
|
||||
x4 = data(:,1);
|
||||
y4 = data(:,12);
|
||||
y4 = y4(x4>=sep(j) & x4<=sep(j+1), :);
|
||||
x4 = x4(x4>=sep(j) & x4<=sep(j+1), :);
|
||||
[nn4, xx4] = hist (y4, xb);
|
||||
nn4 = nn4/length(x4);
|
||||
nn4(nn4==0) = NaN;
|
||||
|
||||
figure
|
||||
hold on
|
||||
%plot(x1,y1, '.-');
|
||||
%plot(x2-x2(1),y2, '.-');
|
||||
plot(x3-x3(1),y3, '.-');
|
||||
%plot(x4-x4(1),y4, '.-');
|
||||
%legend('Map1 -> LocA', 'Map1 -> LocF', 'Map1+2+3+4+5+6 -> LocF', 'Map1-2-3-4-5-6 -> LocF')
|
||||
legend('Map1+2+3+4+5+6 -> LocA')
|
||||
xlabel('Time')
|
||||
ylabel('m')
|
||||
title('Distance since last loc')
|
||||
|
||||
figure
|
||||
hold on
|
||||
%plot(x1,y1, '.-');
|
||||
%plot(x2-x2(1),y2, '.-');
|
||||
plot(x{6}-x{6}(1),y{6}, '.-');
|
||||
%plot(x4-x4(1),y4, '.-');
|
||||
%legend('Map1 -> LocA', 'Map1 -> LocF', 'Map1+2+3+4+5+6 -> LocF', 'Map1-2-3-4-5-6 -> LocF')
|
||||
legend('Map1 -> LocF')
|
||||
xlabel('Time')
|
||||
ylabel('m')
|
||||
title('Distance since last loc')
|
||||
|
||||
figure
|
||||
hold on
|
||||
for j=1:6
|
||||
plot(xx{j},nn{j}, '-', 'linewidth', 3)
|
||||
endfor
|
||||
%plot(xx3,nn3, '.-', 'linewidth', 3)
|
||||
%plot(xx4,nn4, '.-', 'linewidth', 3)
|
||||
%legend('Loc-F', 'Loc-E', 'Loc-D', 'Loc-C', 'Loc-B', 'Loc-A')
|
||||
legend('A-16:51', 'B-17:31', 'C-17:58', 'D-18:30', 'E-18:59', 'F-19:42', 'Map1+2+3+4+5+6 -> LocF', 'Map1-2-3-4-5-6 -> LocF')
|
||||
%h = get(gca,'Children');
|
||||
%set(gca,'Children',[h(6) h(5) h(4) h(3) h(2) h(1)])
|
||||
%set(gca, 'YScale', 'log')
|
||||
xlabel(['Distance not localized (m) Step ' num2str(max) ' m'])
|
||||
ylabel('Re-Localization Probability on Map 1 (16:46)')
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases are saved)."
|
||||
exit
|
||||
fi
|
||||
DATA=$1
|
||||
|
||||
DETECTOR=(0 1 6 7 9 14 11 111)
|
||||
|
||||
source rtabmap_latest.bash
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
rtabmap-report --export --export_prefix "Stat$d" --loc 32 Loop/Odom_correction_norm/m Loop/Visual_inliers/ Timing/Total/ms Timing/Proximity_by_space_visual/ms Timing/Likelihood_computation/ms Timing/Posterior_computation/ms TimingMem/Keypoints_detection/ms TimingMem/Descriptors_extraction/ms TimingMem/Add_new_words/ms Loop/Map_id/ Keypoint/Current_frame/words Memory/RAM_usage/MB Memory/RAM_estimated/MB Memory/Distance_travelled/m Loop/Distance_since_last_loc/ Memory/Local_graph_size/ Keypoint/Dictionary_size/words "$DATA/$d/loc"
|
||||
rtabmap-report --export --export_prefix "Consecutive$d" --loc 32 Loop/Map_id/ Loop/Distance_since_last_loc/ "$DATA/$d/consecutive_loc"
|
||||
done
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint) and the data directory (where reprocessed map databases will be saved)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
DATA=$2
|
||||
|
||||
source rtabmap_latest.bash
|
||||
|
||||
[ ! -d "$DATA" ] && mkdir $DATA
|
||||
[ ! -d "$DATA/$TYPE" ] && mkdir $DATA/$TYPE
|
||||
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db'
|
||||
DATABASES=( 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' )
|
||||
|
||||
PARAMS="--Kp/DetectorStrategy $TYPE --Vis/FeatureType $TYPE"
|
||||
|
||||
if [ $TYPE -eq 2 ] || [ $TYPE -eq 3 ] || [ $TYPE -eq 4 ] || [ $TYPE -eq 5 ] || [ $TYPE -eq 6 ] || [ $TYPE -eq 7 ] || [ $TYPE -eq 8 ] || [ $TYPE -eq 10 ] || [ $TYPE -eq 12 ]
|
||||
then
|
||||
# binary descriptors
|
||||
PARAMS="--Vis/CorNNDR 0.8 $PARAMS"
|
||||
else
|
||||
# float descriptors
|
||||
PARAMS="--Vis/CorNNDR 0.6 $PARAMS"
|
||||
fi
|
||||
|
||||
if [ $TYPE -eq 111 ]
|
||||
then
|
||||
PARAMS="--Vis/CorNNType 6 --SuperGlue/Path ~/workspace/SuperGluePretrainedNetwork/rtabmap_superglue.py --Reg/RepeatOnce false --Vis/CorGuessWinSize 0 $PARAMS --Kp/DetectorStrategy 11 --Vis/FeatureType 11"
|
||||
fi
|
||||
|
||||
echo $PARAMS
|
||||
for db in "${DATABASES[@]}"
|
||||
do
|
||||
rtabmap-reprocess --RGBD/MarkerDetection false --RGBD/ProximityBySpace true --RGBD/LocalRadius 1 --Mem/InitWMWithAllNodes true --Rtabmap/TimeThr 0 --Mem/UseOdomFeatures false --Optimizer/GravitySigma 0.1 --Mem/UseOdomGravity true --RGBD/OptimizeFromGraphEnd false --Mem/DepthAsMask false --RGBD/OptimizeMaxError 10 --RGBD/ProximityOdomGuess false --Vis/MaxFeatures 1000 --Kp/MaxFeatures 400 --Vis/EpipolarGeometryVar 0.1 --Vis/EstimationType 1 --Vis/MinInliers 20 --Rtabmap/MaxRetrieved 2 --Optimizer/Iterations 20 --Mem/CompressionParallelized true --Kp/Parallelized true --Kp/MaxDepth 0 --Kp/BadSignRatio 0.2 --BRIEF/Bytes 32 --Kp/ByteToFloat true --SURF/HessianThreshold 100 --SIFT/ContrastThreshold 0.02 --BRISK/Thresh 10 --SuperPoint/ModelPath superpoint.pt --Rtabmap/PublishRAMUsage true --ORB/EdgeThreshold 19 --ORB/ScaleFactor 2 --ORB/NLevels 3 --Db/TargetVersion "" --Icp/CorrespondenceRatio 0.1 --RGBD/MaxOdomCacheSize 0 --uerror $PARAMS $db $DATA/$TYPE/$db
|
||||
rtabmap-detectMoreLoopClosures --uwarn $DATA/$TYPE/$db
|
||||
done
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases will be saved)."
|
||||
exit
|
||||
fi
|
||||
DATA=$1
|
||||
|
||||
DETECTOR=(0 1 6 7 9 14 11 111)
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
./reprocess_maps.sh $d $DATA
|
||||
./run_merge.sh $d $DATA
|
||||
done
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PATH=~/workspace/rtabmap/build/bin:$PATH
|
||||
export LD_LIBRARY_PATH=~/workspace/rtabmap/build/lib:$LD_LIBRARY_PATH
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases will be saved)."
|
||||
exit
|
||||
fi
|
||||
DATA=$1
|
||||
|
||||
./reprocess_maps_all.sh $DATA
|
||||
./run_localization_single_all.sh $DATA
|
||||
./run_consecutive_localization_all.sh $DATA
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint) and the data directory (where map databases have been reprocessed)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
DATA=$2
|
||||
|
||||
source rtabmap_latest.bash
|
||||
|
||||
SOURCE=('map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db')
|
||||
TARGETS=($DATA/$TYPE'/map_190321-172717.db;'$DATA/$TYPE'/map_190321-175428.db;'$DATA/$TYPE'/map_190321-193556.db' $DATA/$TYPE'/map_190321-175428.db;'$DATA/$TYPE'/map_190321-182709.db;' $DATA/$TYPE'/map_190321-182709.db;'$DATA/$TYPE'/map_190321-185608.db' $DATA/$TYPE'/map_190321-185608.db;'$DATA/$TYPE'/map_190321-193556.db' $DATA/$TYPE'/map_190321-193556.db' )
|
||||
|
||||
|
||||
[ ! -d "$DATA/$TYPE/consecutive_loc" ] && mkdir $DATA/$TYPE/consecutive_loc
|
||||
|
||||
for i in ${!SOURCE[@]}
|
||||
do
|
||||
db=${SOURCE[$i]}
|
||||
loc_dbs=${TARGETS[$i]}
|
||||
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --RGBD/ProximityMaxPaths 1 --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --uwarn "$DATA/$TYPE/$db;$loc_dbs" $DATA/$TYPE/consecutive_loc/loc_$db
|
||||
done
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases will be saved)."
|
||||
exit
|
||||
fi
|
||||
DATA=$1
|
||||
|
||||
DETECTOR=(0 1 6 7 9 14 11 111)
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
./run_consecutive_localization.sh $d $DATA
|
||||
done
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
|
||||
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
|
||||
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
|
||||
|
||||
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
|
||||
LOCALIZATION_DATABASES="loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db"
|
||||
|
||||
[ ! -d "results/$TYPE/loc" ] && mkdir results/$TYPE/accuracy
|
||||
|
||||
db=merged_9999.db
|
||||
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "results/$TYPE/$db;$LOCALIZATION_DATABASES" results/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOn_$db
|
||||
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 1 --uwarn "results/$TYPE/$db;$LOCALIZATION_DATABASES" results/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOn_$db
|
||||
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "results/$TYPE/$db;$LOCALIZATION_DATABASES" results/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOff_$db
|
||||
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 0 --uwarn "results/$TYPE/$db;$LOCALIZATION_DATABASES" results/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOff_$db
|
||||
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "results/$TYPE/$db;$LOCALIZATION_DATABASES" results/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOn_$db
|
||||
|
||||
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "results/$TYPE/$db;$LOCALIZATION_DATABASES" results/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOff_$db
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint) and the data directory (where map databases have been reprocessed)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
DATA=$2
|
||||
|
||||
source rtabmap_latest.bash
|
||||
|
||||
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_123456.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' 'merged_123456_reduced.db'
|
||||
DATABASES=('map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_123456.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' 'merged_123456_reduced.db')
|
||||
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
|
||||
LOCALIZATION_DATABASES="loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db"
|
||||
|
||||
[ ! -d "$DATA/$TYPE/loc" ] && mkdir $DATA/$TYPE/loc
|
||||
|
||||
echo $PARAMS
|
||||
for db in "${DATABASES[@]}"
|
||||
do
|
||||
rtabmap-reprocess -loc_null --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --RGBD/ProximityMaxPaths 1 --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --uwarn "$DATA/$TYPE/$db;$LOCALIZATION_DATABASES" $DATA/$TYPE/loc/loc_$db
|
||||
done
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases will be saved)."
|
||||
exit
|
||||
fi
|
||||
DATA=$1
|
||||
|
||||
DETECTOR=(0 1 6 7 9 14 11 111)
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
./run_localization_single.sh $d $DATA
|
||||
done
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint) and the data directory (where map databases have been reprocessed)."
|
||||
exit
|
||||
fi
|
||||
TYPE=$1
|
||||
DATA=$2
|
||||
|
||||
MIN_INLIERS=20 #20 40 60 80
|
||||
|
||||
source rtabmap_latest.bash
|
||||
|
||||
DATABASES="$DATA/$TYPE/map_190321-164651.db;$DATA/$TYPE/map_190321-172717.db;$DATA/$TYPE/map_190321-175428.db;$DATA/$TYPE/map_190321-182709.db;$DATA/$TYPE/map_190321-185608.db;$DATA/$TYPE/map_190321-193556.db"
|
||||
|
||||
# To compute "Ground truth"
|
||||
rtabmap-reprocess --uwarn --RGBD/OptimizeMaxError 10 "$DATABASES" $DATA/$TYPE/merged_123456.db
|
||||
|
||||
cp $DATA/$TYPE/merged_123456.db $DATA/$TYPE/merged_123456_gt.db
|
||||
rtabmap-detectMoreLoopClosures -r 0.5 -i 5 $DATA/$TYPE/merged_123456_gt.db
|
||||
|
||||
rtabmap-reprocess --uwarn --RGBD/OptimizeMaxError 10 -gt $DATA/$TYPE/merged_123456_gt.db $DATA/$TYPE/merged_123456.db
|
||||
|
||||
rtabmap-reprocess --uwarn --RGBD/OptimizeMaxError 10 "$DATA/$TYPE/map_190321-164651.db;$DATA/$TYPE/map_190321-193556.db" $DATA/$TYPE/merged_16.db
|
||||
|
||||
rtabmap-reprocess --uwarn --RGBD/OptimizeMaxError 10 "$DATA/$TYPE/map_190321-164651.db;$DATA/$TYPE/map_190321-175428.db;$DATA/$TYPE/map_190321-185608.db" $DATA/$TYPE/merged_135.db
|
||||
|
||||
rtabmap-reprocess --uwarn --RGBD/OptimizeMaxError 10 "$DATA/$TYPE/map_190321-172717.db;$DATA/$TYPE/map_190321-182709.db;$DATA/$TYPE/map_190321-193556.db" $DATA/$TYPE/merged_246.db
|
||||
|
||||
# Reduced graph
|
||||
rtabmap-reprocess --uwarn --RGBD/OptimizeMaxError 10 -gt --Mem/ReduceGraph true --Vis/MinInliers $MIN_INLIERS $DATA/$TYPE/merged_123456_gt.db $DATA/$TYPE/merged_123456_reduced.db
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases are saved)."
|
||||
exit
|
||||
fi
|
||||
DATA=$1
|
||||
|
||||
DETECTOR=(0 1 6 7 9 14 11 111)
|
||||
|
||||
source rtabmap_latest.bash
|
||||
|
||||
for d in "${DETECTOR[@]}"
|
||||
do
|
||||
valgrind --tool=massif --time-unit=ms --detailed-freq=1 --max-snapshots=100 rtabmap-reprocess --Mem/IncrementalMemory false --Kp/IncrementalFlann false "${DATA}/${d}/map_190321-164651.db;loc_190321-165128.db" output.db
|
||||
rm output.db
|
||||
done
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
##close all
|
||||
##clear all
|
||||
|
||||
%% Use Export Poses in TORO format, then copy columns
|
||||
load vertexes.txt;
|
||||
load edges.txt;
|
||||
|
||||
set(0,'defaultAxesFontName', 'Times')
|
||||
set(0,'defaultTextFontName', 'Times')
|
||||
|
||||
%matlab indexes % rtabmap indexes
|
||||
endMap1 = 201; % ID=206
|
||||
endMap2 = 401; % ID=411
|
||||
endMap3 = 604; % ID=621
|
||||
endMap4 = 794; % ID=814
|
||||
endMap5 = 968; % ID=990
|
||||
endMap6 = 1201; % ID=1230
|
||||
|
||||
%% 3D
|
||||
|
||||
t = vertexes(:,1);
|
||||
|
||||
##figure
|
||||
##plot3(vertexes(1:endMap1,2), vertexes(1:endMap1,3), vertexes(1:endMap1,1))
|
||||
##hold on
|
||||
##plot3(vertexes(endMap1+1:endMap2,2), vertexes(endMap1+1:endMap2,3), vertexes(endMap1+1:endMap2,1))
|
||||
##plot3(vertexes(endMap2+1:endMap3,2), vertexes(endMap2+1:endMap3,3), vertexes(endMap2+1:endMap3,1))
|
||||
##plot3(vertexes(endMap3+1:endMap4,2), vertexes(endMap3+1:endMap4,3), vertexes(endMap3+1:endMap4,1))
|
||||
##plot3(vertexes(endMap4+1:endMap5,2), vertexes(endMap4+1:endMap5,3), vertexes(endMap4+1:endMap5,1))
|
||||
##plot3(vertexes(endMap5+1:end,2), vertexes(endMap5+1:end,3), vertexes(endMap5+1:end,1))
|
||||
|
||||
mapIds = zeros(vertexes(end,1), 2); % matlab index to vertexes, map id
|
||||
for i=1:size(vertexes,1)
|
||||
mapIds(vertexes(i,1),1) = i;
|
||||
if i <= endMap1
|
||||
mapIds(vertexes(i,1),2) = 1;
|
||||
elseif i<=endMap2
|
||||
mapIds(vertexes(i,1),2) = 2;
|
||||
elseif i<=endMap3
|
||||
mapIds(vertexes(i,1),2) = 3;
|
||||
elseif i<=endMap4
|
||||
mapIds(vertexes(i,1),2) = 4;
|
||||
elseif i<=endMap5
|
||||
mapIds(vertexes(i,1),2) = 5;
|
||||
else
|
||||
mapIds(vertexes(i,1),2) = 6;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##interLoopClosures = 0;
|
||||
##intraLoopClosures = 0;
|
||||
##
|
||||
##for i=1:size(edges, 1)
|
||||
## if edges(i,2) > edges(i,1)+1
|
||||
## x = [vertexes(mapIds(edges(i,1),1), 2) vertexes(mapIds(edges(i,2),1), 2)];
|
||||
## y = [vertexes(mapIds(edges(i,1),1), 3) vertexes(mapIds(edges(i,2),1), 3)];
|
||||
## t = [vertexes(mapIds(edges(i,1),1), 1) vertexes(mapIds(edges(i,2),1), 1)];
|
||||
## if mapIds(edges(i,1),2) ~= mapIds(edges(i,2),2)
|
||||
## plot3(x,y,t, 'g')
|
||||
## interLoopClosures = interLoopClosures+1;
|
||||
## else
|
||||
## plot3(x,y,t, 'r')
|
||||
## intraLoopClosures = intraLoopClosures + 1;
|
||||
## end
|
||||
## end
|
||||
##end
|
||||
##xlabel('x')
|
||||
##ylabel('y')
|
||||
##zlabel('Node indexes')
|
||||
##
|
||||
##interLoopClosures
|
||||
##intraLoopClosures
|
||||
|
||||
%% 2D
|
||||
figure
|
||||
hold on
|
||||
plot([-8 6], [vertexes(endMap1,1) vertexes(endMap1,1)], 'k:')
|
||||
plot([-8 6], [vertexes(endMap2,1) vertexes(endMap2,1)], 'k:')
|
||||
plot([-8 6], [vertexes(endMap3,1) vertexes(endMap3,1)], 'k:')
|
||||
plot([-8 6], [vertexes(endMap4,1) vertexes(endMap4,1)], 'k:')
|
||||
plot([-8 6], [vertexes(endMap5,1) vertexes(endMap5,1)], 'k:')
|
||||
|
||||
colors = {'r:', 'g:', 'c:', 'y:', 'm:', 'c'};
|
||||
|
||||
for i=1:size(edges, 1)
|
||||
if edges(i,2) > edges(i,1)+1
|
||||
y = [vertexes(mapIds(edges(i,1),1), 3) vertexes(mapIds(edges(i,2),1), 3)];
|
||||
t = [vertexes(mapIds(edges(i,1),1), 1) vertexes(mapIds(edges(i,2),1), 1)];
|
||||
mapId = mapIds(edges(i,1),2);
|
||||
if mapId ~= mapIds(edges(i,2),2) && (mapId == 1 || mapIds(edges(i,2),2) == 1)
|
||||
plot(y,t, 'r')
|
||||
else
|
||||
%plot(y,t, 'r')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
curveColor = 'b'
|
||||
plot(vertexes(1:endMap1,3), vertexes(1:endMap1,1), curveColor)
|
||||
plot(vertexes(endMap1+1:endMap2,3), vertexes(endMap1+1:endMap2,1), curveColor)
|
||||
plot(vertexes(endMap2+1:endMap3,3), vertexes(endMap2+1:endMap3,1), curveColor)
|
||||
plot(vertexes(endMap3+1:endMap4,3), vertexes(endMap3+1:endMap4,1), curveColor)
|
||||
plot(vertexes(endMap4+1:endMap5,3), vertexes(endMap4+1:endMap5,1), curveColor)
|
||||
plot(vertexes(endMap5+1:end,3), vertexes(endMap5+1:end,1), 'k')
|
||||
|
||||
xlabel('y')
|
||||
ylabel('Node indexes')
|
||||
@@ -54,7 +54,8 @@ public:
|
||||
int cameraIndex = -1,
|
||||
int stopId = 0,
|
||||
bool intermediateNodesIgnored = false,
|
||||
bool landmarksIgnored = false);
|
||||
bool landmarksIgnored = false,
|
||||
bool featuresIgnored = false);
|
||||
DBReader(const std::list<std::string> & databasePaths,
|
||||
float frameRate = 0.0f, // -1 = use Database stamps, 0 = inf
|
||||
bool odometryIgnored = false,
|
||||
@@ -64,7 +65,8 @@ public:
|
||||
int cameraIndex = -1,
|
||||
int stopId = 0,
|
||||
bool intermediateNodesIgnored = false,
|
||||
bool landmarksIgnored = false);
|
||||
bool landmarksIgnored = false,
|
||||
bool featuresIgnored = false);
|
||||
virtual ~DBReader();
|
||||
|
||||
virtual bool init(
|
||||
@@ -91,6 +93,7 @@ private:
|
||||
int _cameraIndex;
|
||||
bool _intermediateNodesIgnored;
|
||||
bool _landmarksIgnored;
|
||||
bool _featuresIgnored;
|
||||
|
||||
DBDriver * _dbDriver;
|
||||
UTimer _timer;
|
||||
|
||||
@@ -51,7 +51,8 @@ DBReader::DBReader(const std::string & databasePath,
|
||||
int cameraIndex,
|
||||
int stopId,
|
||||
bool intermediateNodesIgnored,
|
||||
bool landmarksIgnored) :
|
||||
bool landmarksIgnored,
|
||||
bool featuresIgnored) :
|
||||
Camera(frameRate),
|
||||
_paths(uSplit(databasePath, ';')),
|
||||
_odometryIgnored(odometryIgnored),
|
||||
@@ -62,6 +63,7 @@ DBReader::DBReader(const std::string & databasePath,
|
||||
_cameraIndex(cameraIndex),
|
||||
_intermediateNodesIgnored(intermediateNodesIgnored),
|
||||
_landmarksIgnored(landmarksIgnored),
|
||||
_featuresIgnored(featuresIgnored),
|
||||
_dbDriver(0),
|
||||
_currentId(_ids.end()),
|
||||
_previousMapId(-1),
|
||||
@@ -84,7 +86,8 @@ DBReader::DBReader(const std::list<std::string> & databasePaths,
|
||||
int cameraIndex,
|
||||
int stopId,
|
||||
bool intermediateNodesIgnored,
|
||||
bool landmarksIgnored) :
|
||||
bool landmarksIgnored,
|
||||
bool featuresIgnored) :
|
||||
Camera(frameRate),
|
||||
_paths(databasePaths),
|
||||
_odometryIgnored(odometryIgnored),
|
||||
@@ -95,6 +98,7 @@ DBReader::DBReader(const std::list<std::string> & databasePaths,
|
||||
_cameraIndex(cameraIndex),
|
||||
_intermediateNodesIgnored(intermediateNodesIgnored),
|
||||
_landmarksIgnored(landmarksIgnored),
|
||||
_featuresIgnored(featuresIgnored),
|
||||
_dbDriver(0),
|
||||
_currentId(_ids.end()),
|
||||
_previousMapId(-1),
|
||||
@@ -569,13 +573,14 @@ SensorData DBReader::getNextData(CameraInfo * info)
|
||||
cv::Mat descriptors = s->getWordsDescriptors().clone();
|
||||
const std::vector<cv::KeyPoint> & keypoints = s->getWordsKpts();
|
||||
const std::vector<cv::Point3f> & keypoints3D = s->getWords3();
|
||||
if(!keypoints.empty() &&
|
||||
if(!_featuresIgnored &&
|
||||
!keypoints.empty() &&
|
||||
(keypoints3D.empty() || keypoints.size() == keypoints3D.size()) &&
|
||||
(descriptors.empty() || (int)keypoints.size() == descriptors.rows))
|
||||
{
|
||||
data.setFeatures(keypoints, keypoints3D, descriptors);
|
||||
}
|
||||
else if(!keypoints.empty() && (!keypoints3D.empty() || !descriptors.empty()))
|
||||
else if(!_featuresIgnored && !keypoints.empty() && (!keypoints3D.empty() || !descriptors.empty()))
|
||||
{
|
||||
UERROR("Missing feature data, features won't be published.");
|
||||
}
|
||||
|
||||
@@ -215,6 +215,16 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
||||
_model.fy(),
|
||||
_model.cx(),
|
||||
_model.cy());
|
||||
|
||||
cv::FileStorage fs(calibrationFolder+"/"+cameraName+".yaml", 0);
|
||||
cv::FileNode poseNode = fs["local_transform"];
|
||||
if(!poseNode.isNone())
|
||||
{
|
||||
UWARN("Using local transform from calibration file (%s) instead of the parameter one (%s).",
|
||||
_model.localTransform().prettyPrint().c_str(),
|
||||
this->getLocalTransform().prettyPrint().c_str());
|
||||
this->setLocalTransform(_model.localTransform());
|
||||
}
|
||||
}
|
||||
}
|
||||
_model.setName(cameraName);
|
||||
@@ -243,36 +253,18 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
||||
if(dirJson.getFileNames().size() == _dir->getFileNames().size())
|
||||
{
|
||||
bool modelsWarned = false;
|
||||
bool firstFrame = true;
|
||||
bool localTWarned = false;
|
||||
for(std::list<std::string>::const_iterator iter=dirJson.getFileNames().begin(); iter!=dirJson.getFileNames().end() && success; ++iter)
|
||||
{
|
||||
// Assuming 3DScannerApp(iOS) format (only this one supported...)
|
||||
std::string filePath = _path+"/"+*iter;
|
||||
cv::FileStorage fs(filePath, 0);
|
||||
cv::FileNode poseNode = fs["cameraPoseARFrame"];
|
||||
cv::FileNode timeNode = fs["time"];
|
||||
cv::FileNode intrinsicsNode = fs["intrinsics"];
|
||||
if(poseNode.isNone() || poseNode.size() != 16)
|
||||
cv::FileNode poseNode = fs["cameraPoseARFrame"]; // Check if it is 3DScannerApp(iOS) format
|
||||
if(poseNode.isNone())
|
||||
{
|
||||
UERROR("Failed reading \"cameraPoseARFrame\" parameter, it should have 16 values (file=%s)", filePath.c_str());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else if(timeNode.isNone() || !timeNode.isReal())
|
||||
{
|
||||
UERROR("Failed reading \"time\" parameter (file=%s)", filePath.c_str());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else if(intrinsicsNode.isNone() || intrinsicsNode.size()!=9)
|
||||
{
|
||||
UERROR("Failed reading \"intrinsics\" parameter (file=%s)", filePath.c_str());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_stamps.push_back((double)timeNode);
|
||||
cv::FileNode n = fs["local_transform"];
|
||||
bool hasLocalTransform = !n.isNone();
|
||||
|
||||
fs.release();
|
||||
if(_model.isValidForProjection() && !modelsWarned)
|
||||
{
|
||||
UWARN("Camera model loaded for each frame is overridden by "
|
||||
@@ -283,31 +275,74 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
||||
}
|
||||
else
|
||||
{
|
||||
_models.push_back(CameraModel(
|
||||
(double)intrinsicsNode[0], //fx
|
||||
(double)intrinsicsNode[4], //fy
|
||||
(double)intrinsicsNode[2], //cx
|
||||
(double)intrinsicsNode[5], //cy
|
||||
CameraModel::opticalRotation()));
|
||||
CameraModel model;
|
||||
model.load(filePath);
|
||||
|
||||
if(!hasLocalTransform)
|
||||
{
|
||||
if(!localTWarned)
|
||||
{
|
||||
UWARN("Loaded calibration file doesn't have local_transform field, "
|
||||
"the global local_transform parameter is used by default (%s).",
|
||||
this->getLocalTransform().prettyPrint().c_str());
|
||||
localTWarned = true;
|
||||
}
|
||||
model.setLocalTransform(this->getLocalTransform());
|
||||
}
|
||||
|
||||
_models.push_back(model);
|
||||
}
|
||||
// we need to rotate from opengl world to rtabmap world
|
||||
Transform pose(
|
||||
(float)poseNode[0], (float)poseNode[1], (float)poseNode[2], (float)poseNode[3],
|
||||
(float)poseNode[4], (float)poseNode[5], (float)poseNode[6], (float)poseNode[7],
|
||||
(float)poseNode[8], (float)poseNode[9], (float)poseNode[10], (float)poseNode[11]);
|
||||
pose = Transform::rtabmap_T_opengl() * pose * Transform::opengl_T_rtabmap();
|
||||
odometry_.push_back(pose);
|
||||
// linear cov = 0.0001
|
||||
cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.0001);
|
||||
if(!firstFrame)
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::FileNode timeNode = fs["time"];
|
||||
cv::FileNode intrinsicsNode = fs["intrinsics"];
|
||||
if(poseNode.isNone() || poseNode.size() != 16)
|
||||
{
|
||||
// angular cov = 0.000001
|
||||
covariance.at<double>(3,3) *= 0.01;
|
||||
covariance.at<double>(4,4) *= 0.01;
|
||||
covariance.at<double>(5,5) *= 0.01;
|
||||
UERROR("Failed reading \"cameraPoseARFrame\" parameter, it should have 16 values (file=%s)", filePath.c_str());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else if(timeNode.isNone() || !timeNode.isReal())
|
||||
{
|
||||
UERROR("Failed reading \"time\" parameter (file=%s)", filePath.c_str());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else if(intrinsicsNode.isNone() || intrinsicsNode.size()!=9)
|
||||
{
|
||||
UERROR("Failed reading \"intrinsics\" parameter (file=%s)", filePath.c_str());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_stamps.push_back((double)timeNode);
|
||||
if(_model.isValidForProjection() && !modelsWarned)
|
||||
{
|
||||
UWARN("Camera model loaded for each frame is overridden by "
|
||||
"general calibration file provided. Remove general calibration "
|
||||
"file to use camera model of each frame. This warning will "
|
||||
"be shown only one time.");
|
||||
modelsWarned = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_models.push_back(CameraModel(
|
||||
(double)intrinsicsNode[0], //fx
|
||||
(double)intrinsicsNode[4], //fy
|
||||
(double)intrinsicsNode[2], //cx
|
||||
(double)intrinsicsNode[5], //cy
|
||||
CameraModel::opticalRotation()));
|
||||
}
|
||||
// we need to rotate from opengl world to rtabmap world
|
||||
Transform pose(
|
||||
(float)poseNode[0], (float)poseNode[1], (float)poseNode[2], (float)poseNode[3],
|
||||
(float)poseNode[4], (float)poseNode[5], (float)poseNode[6], (float)poseNode[7],
|
||||
(float)poseNode[8], (float)poseNode[9], (float)poseNode[10], (float)poseNode[11]);
|
||||
pose = Transform::rtabmap_T_opengl() * pose * Transform::opengl_T_rtabmap();
|
||||
odometry_.push_back(pose);
|
||||
}
|
||||
firstFrame = false;
|
||||
covariances_.push_back(covariance);
|
||||
}
|
||||
}
|
||||
if(!success)
|
||||
@@ -315,7 +350,6 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
||||
odometry_.clear();
|
||||
_stamps.clear();
|
||||
_models.clear();
|
||||
covariances_.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -334,106 +368,110 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else if(_filenamesAreTimestamps)
|
||||
|
||||
if(_stamps.empty())
|
||||
{
|
||||
std::list<std::string> filenames = _dir?_dir->getFileNames():_scanDir->getFileNames();
|
||||
for(std::list<std::string>::const_iterator iter=filenames.begin(); iter!=filenames.end(); ++iter)
|
||||
if(_filenamesAreTimestamps)
|
||||
{
|
||||
// format is text_1223445645.12334_text.png or text_122344564512334_text.png
|
||||
// If no decimals, 10 first number are the seconds
|
||||
std::list<std::string> list = uSplit(*iter, '.');
|
||||
if(list.size() == 3 || list.size() == 2)
|
||||
std::list<std::string> filenames = _dir?_dir->getFileNames():_scanDir->getFileNames();
|
||||
for(std::list<std::string>::const_iterator iter=filenames.begin(); iter!=filenames.end(); ++iter)
|
||||
{
|
||||
list.pop_back(); // remove extension
|
||||
double stamp = 0.0;
|
||||
if(list.size() == 1)
|
||||
// format is text_1223445645.12334_text.png or text_122344564512334_text.png
|
||||
// If no decimals, 10 first number are the seconds
|
||||
std::list<std::string> list = uSplit(*iter, '.');
|
||||
if(list.size() == 3 || list.size() == 2)
|
||||
{
|
||||
std::list<std::string> numberList = uSplitNumChar(list.front());
|
||||
for(std::list<std::string>::iterator iter=numberList.begin(); iter!=numberList.end(); ++iter)
|
||||
list.pop_back(); // remove extension
|
||||
double stamp = 0.0;
|
||||
if(list.size() == 1)
|
||||
{
|
||||
if(uIsNumber(*iter))
|
||||
std::list<std::string> numberList = uSplitNumChar(list.front());
|
||||
for(std::list<std::string>::iterator iter=numberList.begin(); iter!=numberList.end(); ++iter)
|
||||
{
|
||||
std::string decimals;
|
||||
std::string sec;
|
||||
if(iter->length()>10)
|
||||
if(uIsNumber(*iter))
|
||||
{
|
||||
decimals = iter->substr(10, iter->size()-10);
|
||||
sec = iter->substr(0, 10);
|
||||
std::string decimals;
|
||||
std::string sec;
|
||||
if(iter->length()>10)
|
||||
{
|
||||
decimals = iter->substr(10, iter->size()-10);
|
||||
sec = iter->substr(0, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = *iter;
|
||||
}
|
||||
stamp = uStr2Double(sec + "." + decimals);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = *iter;
|
||||
}
|
||||
stamp = uStr2Double(sec + "." + decimals);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string decimals = uSplitNumChar(list.back()).front();
|
||||
list.pop_back();
|
||||
std::string sec = uSplitNumChar(list.back()).back();
|
||||
stamp = uStr2Double(sec + "." + decimals);
|
||||
}
|
||||
if(stamp > 0.0)
|
||||
{
|
||||
_stamps.push_back(stamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
UERROR("Conversion filename to timestamp failed! (filename=%s)", iter->c_str());
|
||||
else
|
||||
{
|
||||
std::string decimals = uSplitNumChar(list.back()).front();
|
||||
list.pop_back();
|
||||
std::string sec = uSplitNumChar(list.back()).back();
|
||||
stamp = uStr2Double(sec + "." + decimals);
|
||||
}
|
||||
if(stamp > 0.0)
|
||||
{
|
||||
_stamps.push_back(stamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
UERROR("Conversion filename to timestamp failed! (filename=%s)", iter->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_stamps.size() != this->imagesCount())
|
||||
{
|
||||
UERROR("The stamps count is not the same as the images (%d vs %d)! "
|
||||
"Converting filenames to timestamps is activated.",
|
||||
(int)_stamps.size(), this->imagesCount());
|
||||
_stamps.clear();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else if(_timestampsPath.size())
|
||||
{
|
||||
std::ifstream file;
|
||||
file.open(_timestampsPath.c_str(), std::ifstream::in);
|
||||
while(file.good())
|
||||
{
|
||||
std::string str;
|
||||
std::getline(file, str);
|
||||
|
||||
if(str.empty() || str.at(0) == '#' || str.at(0) == '%')
|
||||
if(_stamps.size() != this->imagesCount())
|
||||
{
|
||||
continue;
|
||||
UERROR("The stamps count is not the same as the images (%d vs %d)! "
|
||||
"Converting filenames to timestamps is activated.",
|
||||
(int)_stamps.size(), this->imagesCount());
|
||||
_stamps.clear();
|
||||
success = false;
|
||||
}
|
||||
|
||||
std::list<std::string> strList = uSplit(str, ' ');
|
||||
std::string stampStr = strList.front();
|
||||
if(strList.size() == 2)
|
||||
{
|
||||
// format "seconds millisec"
|
||||
// the millisec str needs 0-padding if size < 6
|
||||
std::string millisecStr = strList.back();
|
||||
while(millisecStr.size() < 6)
|
||||
{
|
||||
millisecStr = "0" + millisecStr;
|
||||
}
|
||||
stampStr = stampStr+'.'+millisecStr;
|
||||
}
|
||||
_stamps.push_back(uStr2Double(stampStr));
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
if(_stamps.size() != this->imagesCount())
|
||||
else if(_timestampsPath.size())
|
||||
{
|
||||
UERROR("The stamps count (%d) is not the same as the images (%d)! Please remove "
|
||||
"the timestamps file path if you don't want to use them (current file path=%s).",
|
||||
(int)_stamps.size(), this->imagesCount(), _timestampsPath.c_str());
|
||||
_stamps.clear();
|
||||
success = false;
|
||||
std::ifstream file;
|
||||
file.open(_timestampsPath.c_str(), std::ifstream::in);
|
||||
while(file.good())
|
||||
{
|
||||
std::string str;
|
||||
std::getline(file, str);
|
||||
|
||||
if(str.empty() || str.at(0) == '#' || str.at(0) == '%')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::list<std::string> strList = uSplit(str, ' ');
|
||||
std::string stampStr = strList.front();
|
||||
if(strList.size() == 2)
|
||||
{
|
||||
// format "seconds millisec"
|
||||
// the millisec str needs 0-padding if size < 6
|
||||
std::string millisecStr = strList.back();
|
||||
while(millisecStr.size() < 6)
|
||||
{
|
||||
millisecStr = "0" + millisecStr;
|
||||
}
|
||||
stampStr = stampStr+'.'+millisecStr;
|
||||
}
|
||||
_stamps.push_back(uStr2Double(stampStr));
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
if(_stamps.size() != this->imagesCount())
|
||||
{
|
||||
UERROR("The stamps count (%d) is not the same as the images (%d)! Please remove "
|
||||
"the timestamps file path if you don't want to use them (current file path=%s).",
|
||||
(int)_stamps.size(), this->imagesCount(), _timestampsPath.c_str());
|
||||
_stamps.clear();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,6 +484,23 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
||||
{
|
||||
success = readPoses(groundTruth_, _stamps, _groundTruthPath, _groundTruthFormat, _maxPoseTimeDiff);
|
||||
}
|
||||
|
||||
if(!odometry_.empty())
|
||||
{
|
||||
for(size_t i=0; i<odometry_.size(); ++i)
|
||||
{
|
||||
// linear cov = 0.0001
|
||||
cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1) * (i==0?9999.0:0.0001);
|
||||
if(i!=0)
|
||||
{
|
||||
// angular cov = 0.000001
|
||||
covariance.at<double>(3,3) *= 0.01;
|
||||
covariance.at<double>(4,4) *= 0.01;
|
||||
covariance.at<double>(5,5) *= 0.01;
|
||||
}
|
||||
covariances_.push_back(covariance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_captureTimer.restart();
|
||||
|
||||
@@ -1464,7 +1464,7 @@ void DatabaseViewer::extractImages()
|
||||
QString ext = format.split('.').back();
|
||||
bool useStamp = format.split('.').front().compare("timestamp") == 0;
|
||||
bool directoriesCreated = false;
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Select directory where to save images..."), QDir::homePath());
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Select directory where to save images..."), pathDatabase_);
|
||||
if(!path.isEmpty())
|
||||
{
|
||||
rtabmap::ProgressDialog * progressDialog = new rtabmap::ProgressDialog(this);
|
||||
|
||||
@@ -673,6 +673,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
connect(_ui->source_checkBox_ignoreGoalDelay, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->source_checkBox_ignoreGoals, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->source_checkBox_ignoreLandmarks, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->source_checkBox_ignoreFeatures, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->source_spinBox_databaseStartId, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->source_spinBox_databaseStopId, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->source_checkBox_useDbStamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
@@ -1919,6 +1920,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
|
||||
_ui->source_checkBox_ignoreGoalDelay->setChecked(true);
|
||||
_ui->source_checkBox_ignoreGoals->setChecked(true);
|
||||
_ui->source_checkBox_ignoreLandmarks->setChecked(false);
|
||||
_ui->source_checkBox_ignoreFeatures->setChecked(false);
|
||||
_ui->source_spinBox_databaseStartId->setValue(0);
|
||||
_ui->source_spinBox_databaseStopId->setValue(0);
|
||||
_ui->source_spinBox_database_cameraIndex->setValue(-1);
|
||||
@@ -2599,6 +2601,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
|
||||
_ui->source_checkBox_ignoreGoalDelay->setChecked(settings.value("ignoreGoalDelay", _ui->source_checkBox_ignoreGoalDelay->isChecked()).toBool());
|
||||
_ui->source_checkBox_ignoreGoals->setChecked(settings.value("ignoreGoals", _ui->source_checkBox_ignoreGoals->isChecked()).toBool());
|
||||
_ui->source_checkBox_ignoreLandmarks->setChecked(settings.value("ignoreLandmarks", _ui->source_checkBox_ignoreLandmarks->isChecked()).toBool());
|
||||
_ui->source_checkBox_ignoreFeatures->setChecked(settings.value("ignoreFeatures", _ui->source_checkBox_ignoreFeatures->isChecked()).toBool());
|
||||
_ui->source_spinBox_databaseStartId->setValue(settings.value("startId", _ui->source_spinBox_databaseStartId->value()).toInt());
|
||||
_ui->source_spinBox_databaseStopId->setValue(settings.value("stopId", _ui->source_spinBox_databaseStopId->value()).toInt());
|
||||
_ui->source_spinBox_database_cameraIndex->setValue(settings.value("cameraIndex", _ui->source_spinBox_database_cameraIndex->value()).toInt());
|
||||
@@ -3118,6 +3121,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
|
||||
settings.setValue("ignoreGoalDelay", _ui->source_checkBox_ignoreGoalDelay->isChecked());
|
||||
settings.setValue("ignoreGoals", _ui->source_checkBox_ignoreGoals->isChecked());
|
||||
settings.setValue("ignoreLandmarks", _ui->source_checkBox_ignoreLandmarks->isChecked());
|
||||
settings.setValue("ignoreFeatures", _ui->source_checkBox_ignoreFeatures->isChecked());
|
||||
settings.setValue("startId", _ui->source_spinBox_databaseStartId->value());
|
||||
settings.setValue("stopId", _ui->source_spinBox_databaseStopId->value());
|
||||
settings.setValue("cameraIndex", _ui->source_spinBox_database_cameraIndex->value());
|
||||
@@ -6333,7 +6337,8 @@ Camera * PreferencesDialog::createCamera(
|
||||
_ui->source_spinBox_database_cameraIndex->value(),
|
||||
_ui->source_spinBox_databaseStopId->value(),
|
||||
!_ui->general_checkBox_createIntermediateNodes->isChecked(),
|
||||
_ui->source_checkBox_ignoreLandmarks->isChecked());
|
||||
_ui->source_checkBox_ignoreLandmarks->isChecked(),
|
||||
_ui->source_checkBox_ignoreFeatures->isChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6349,7 +6354,7 @@ Camera * PreferencesDialog::createCamera(
|
||||
{
|
||||
calibrationFile.remove("_left.yaml").remove("_right.yaml").remove("_pose.yaml").remove("_rgb.yaml").remove("_depth.yaml");
|
||||
}
|
||||
QString name = QFileInfo(calibrationFile.remove(".yaml")).baseName();
|
||||
QString name = QFileInfo(calibrationFile.remove(".yaml")).fileName();
|
||||
if(!calibrationPath.isEmpty())
|
||||
{
|
||||
QDir d = QFileInfo(calibrationPath).dir();
|
||||
|
||||
@@ -63,9 +63,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<y>-1042</y>
|
||||
<width>756</width>
|
||||
<height>3623</height>
|
||||
<height>3640</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
@@ -95,7 +95,7 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>18</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_22">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,0">
|
||||
@@ -3109,7 +3109,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget_src">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_41">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_64">
|
||||
@@ -3220,7 +3220,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget_rgbd">
|
||||
<property name="currentIndex">
|
||||
<number>4</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_32">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_63">
|
||||
@@ -6116,66 +6116,6 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9" columnstretch="0,0,0">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_90">
|
||||
<property name="text">
|
||||
<string>Use database stamps as input rate.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="label_315">
|
||||
<property name="text">
|
||||
<string>Camera index. If the database contains multi-camera data, you can choose which camera to use. -1 means that all cameras are streamed.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QSpinBox" name="source_spinBox_databaseStartId">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_stereoToDepthDB">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_ignoreGoals">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QSpinBox" name="source_spinBox_databaseStopId">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_72">
|
||||
<property name="text">
|
||||
@@ -6189,13 +6129,6 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_useDbStamps">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QToolButton" name="source_database_toolButton_selectSource">
|
||||
<property name="text">
|
||||
@@ -6203,17 +6136,36 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="toolButton_dbViewer">
|
||||
<property name="toolTip">
|
||||
<string>Open database viewer</string>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_90">
|
||||
<property name="text">
|
||||
<string>Use database stamps as input rate.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_ignoreGoals">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../GuiLib.qrc">
|
||||
<normaloff>:/images/mag_glass.png</normaloff>:/images/mag_glass.png</iconset>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="label_315">
|
||||
<property name="text">
|
||||
<string>Camera index. If the database contains multi-camera data, you can choose which camera to use. -1 means that all cameras are streamed.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -6231,33 +6183,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QSpinBox" name="source_spinBox_database_cameraIndex">
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="source_database_lineEdit_path"/>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="label_557">
|
||||
<property name="text">
|
||||
<string>If the database contains stereo data, generate disparity image and convert it to depth. The resulting output is a RGB-D image instead of stereo images. Dense disparity parameters can be found under StereoBM tab.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="label_58">
|
||||
<property name="text">
|
||||
<string>Start position (node ID).</string>
|
||||
@@ -6267,7 +6193,68 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="source_database_lineEdit_path"/>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_stereoToDepthDB">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QSpinBox" name="source_spinBox_databaseStopId">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="toolButton_dbViewer">
|
||||
<property name="toolTip">
|
||||
<string>Open database viewer</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../GuiLib.qrc">
|
||||
<normaloff>:/images/mag_glass.png</normaloff>:/images/mag_glass.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_useDbStamps">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QSpinBox" name="source_spinBox_databaseStartId">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QSpinBox" name="source_spinBox_database_cameraIndex">
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="label_529">
|
||||
<property name="text">
|
||||
<string>Stop position (node ID) is the last node to process. If 0, all nodes after start position are published.</string>
|
||||
@@ -6280,45 +6267,6 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_80">
|
||||
<property name="text">
|
||||
<string>Ignore goal delay.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<spacer name="verticalSpacer_35">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_263">
|
||||
<property name="text">
|
||||
<string>Ignore goals saved in the database.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_546">
|
||||
<property name="text">
|
||||
@@ -6339,6 +6287,78 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_80">
|
||||
<property name="text">
|
||||
<string>Ignore goal delay.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_263">
|
||||
<property name="text">
|
||||
<string>Ignore goals saved in the database.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="label_557">
|
||||
<property name="text">
|
||||
<string>If the database contains stereo data, generate disparity image and convert it to depth. The resulting output is a RGB-D image instead of stereo images. Dense disparity parameters can be found under StereoBM tab.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<spacer name="verticalSpacer_35">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_644">
|
||||
<property name="text">
|
||||
<string>Ignore features.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="source_checkBox_ignoreFeatures">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -6879,7 +6899,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_605">
|
||||
<property name="text">
|
||||
<string>Load config file for each frame (intrinsics, pose and stamp). Config files should be in the same directory than RGB frames and they should have the same name than the corresponding frame file. Currently supporting only 3DScannerApp for iOS export config format (JSON).</string>
|
||||
<string>Load config file for each frame. For calibration, global calibration path above should be empty. Config files should be in the same directory than RGB frames and they should have the same name than the corresponding frame file. Currently supporting 3DScannerApp for iOS export config format (JSON, intrinsics, pose and stamp) and RTAB-Map calibration file format.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
||||