Increased version to 0.20.5

Refactored how features are stored in Signature (significative memory optimization, causing major refactoring in Memory, RegistrationVis, OdometryF2M)
FLANN: optimized memory usage when Kp/IncrementalFlann is false
Added memory usage functions
Added statistics Loop/Visual_inliers_ratio/ and Memory/RAM_estimated/MB
EpipolarGeometry: templated findPairs functions
graph::filterLinks: added inverted option
LocalBundleOnLoopClosure: Force to use only neighbor links
MainWindow: fixed max depth filtering for map's features
Rtabmap::getSignatureCopy() fixed links not returned
Added UPlot::getAllCurveDataAsText() function.
DbViewer: fixed features not rendered in right view when failing ro refine a constraint
report: added --export and --export_prefix options (to export figures data)
This commit is contained in:
matlabbe
2020-10-05 17:34:32 -04:00
parent bedc771fa4
commit bbccbd63e4
41 changed files with 1456 additions and 898 deletions

View File

@@ -275,7 +275,7 @@ int main(int argc, char * argv[])
if(reg.getNNType()==6 &&
!dataFrom.getWordsDescriptors().empty() &&
dataFrom.getWordsDescriptors().begin()->second.type()!=CV_32F)
dataFrom.getWordsDescriptors().type()!=CV_32F)
{
UWARN("PyMatcher is selected for matching but binary features "
"are not compatible. BruteForce with CrossCheck (%s=5) "
@@ -298,7 +298,7 @@ int main(int argc, char * argv[])
.arg(Parameters::kVisCorNNType().c_str())
.arg(reg.getNNType())
.arg(reg.getNNType()<VWDictionary::kNNUndef?VWDictionary::nnStrategyName((VWDictionary::NNStrategy)reg.getNNType()).c_str():
reg.getNNType()==5||(reg.getNNType()==6&&!dataFrom.getWordsDescriptors().empty()&& dataFrom.getWordsDescriptors().begin()->second.type()!=CV_32F)?"BFCrossCheck":
reg.getNNType()==5||(reg.getNNType()==6&&!dataFrom.getWordsDescriptors().empty()&& dataFrom.getWordsDescriptors().type()!=CV_32F)?"BFCrossCheck":
reg.getNNType()==6?QString(uSplit(UFile::getName(pyMatcherPath), '.').front().c_str()).replace("rtabmap_", ""):
reg.getNNType()==7?"GMS":"?")
.arg(reg.getNNType()<5?QString(" %1=%2").arg(Parameters::kVisCorNNDR().c_str()).arg(reg.getNNDR()):"")
@@ -322,9 +322,21 @@ int main(int argc, char * argv[])
if(reg.getEstimationType() == 2)
{
// triangulate 3D words based on the transform computed
std::map<int, int> wordsFrom = uMultimapToMapUnique(dataFrom.getWords());
std::map<int, int> wordsTo = uMultimapToMapUnique(dataTo.getWords());
std::map<int, cv::KeyPoint> kptsFrom;
std::map<int, cv::KeyPoint> kptsTo;
for(std::map<int, int>::iterator iter=wordsFrom.begin(); iter!=wordsFrom.end(); ++iter)
{
kptsFrom.insert(std::make_pair(iter->first, dataFrom.getWordsKpts()[iter->second]));
}
for(std::map<int, int>::iterator iter=wordsTo.begin(); iter!=wordsTo.end(); ++iter)
{
kptsTo.insert(std::make_pair(iter->first, dataTo.getWordsKpts()[iter->second]));
}
std::map<int, cv::Point3f> points3d = util3d::generateWords3DMono(
uMultimapToMapUnique(dataFrom.getWords()),
uMultimapToMapUnique(dataTo.getWords()),
kptsFrom,
kptsTo,
model.isValidForProjection()?model:stereoModel.left(),
t);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>);
@@ -353,11 +365,12 @@ int main(int argc, char * argv[])
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>);
cloudWordsFrom->resize(dataFrom.getWords3().size());
int i=0;
for(std::multimap<int, cv::Point3f>::const_iterator iter=dataFrom.getWords3().begin();
iter!=dataFrom.getWords3().end();
for(std::multimap<int, int>::const_iterator iter=dataFrom.getWords().begin();
iter!=dataFrom.getWords().end();
++iter)
{
cloudWordsFrom->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z);
const cv::Point3f & pt = dataFrom.getWords3()[iter->second];
cloudWordsFrom->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
}
if(cloudWordsFrom->size())
{
@@ -371,22 +384,23 @@ int main(int argc, char * argv[])
}
if(!dataTo.getWords3().empty())
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>);
cloudWordsFrom->resize(dataTo.getWords3().size());
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsTo(new pcl::PointCloud<pcl::PointXYZ>);
cloudWordsTo->resize(dataTo.getWords3().size());
int i=0;
for(std::multimap<int, cv::Point3f>::const_iterator iter=dataTo.getWords3().begin();
iter!=dataTo.getWords3().end();
for(std::multimap<int, int>::const_iterator iter=dataTo.getWords().begin();
iter!=dataTo.getWords().end();
++iter)
{
cloudWordsFrom->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z);
const cv::Point3f & pt = dataTo.getWords3()[iter->second];
cloudWordsTo->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
}
if(cloudWordsFrom->size())
if(cloudWordsTo->size())
{
cloudWordsFrom = rtabmap::util3d::removeNaNFromPointCloud(cloudWordsFrom);
cloudWordsTo = rtabmap::util3d::removeNaNFromPointCloud(cloudWordsTo);
}
if(cloudWordsFrom->size())
if(cloudWordsTo->size())
{
viewer->addCloud("wordsTo", cloudWordsFrom, t, Qt::cyan);
viewer->addCloud("wordsTo", cloudWordsTo, t, Qt::cyan);
viewer->setCloudPointSize("wordsTo", 5);
}
}
@@ -443,8 +457,24 @@ int main(int argc, char * argv[])
viewB->setImageDepth(uCvMat2QImage(toDepth, false, uCvQtDepthRedToBlue));
viewB->setImageDepthShown(true);
}
viewA->setFeatures(dataFrom.getWords());
viewB->setFeatures(dataTo.getWords());
std::multimap<int, cv::KeyPoint> keypointsFrom;
std::multimap<int, cv::KeyPoint> keypointsTo;
if(!dataFrom.getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=dataFrom.getWords().begin(); iter!=dataFrom.getWords().end(); ++iter)
{
keypointsFrom.insert(keypointsFrom.end(), std::make_pair(iter->first, dataFrom.getWordsKpts()[iter->second]));
}
}
if(!dataTo.getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=dataTo.getWords().begin(); iter!=dataTo.getWords().end(); ++iter)
{
keypointsTo.insert(keypointsTo.end(), std::make_pair(iter->first, dataTo.getWordsKpts()[iter->second]));
}
}
viewA->setFeatures(keypointsFrom);
viewB->setFeatures(keypointsTo);
std::set<int> inliersSet(info.inliersIDs.begin(), info.inliersIDs.end());
const QMultiMap<int, KeypointItem*> & wordsA = viewA->getFeatures();

View File

@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef WITH_QT
#include <rtabmap/utilite/UPlot.h>
#include <QApplication>
#include <QFile>
#endif
using namespace rtabmap;
@@ -69,6 +70,8 @@ void showUsage()
" database, the inverse will be done. \n"
" --ids Use IDs for x axis instead of time in the figures. \n"
" --start # Start from this node ID for the figures.\n"
" --export Export figures' data to txt files.\n"
" --export_prefix Prefix to filenames of exported figures' data (default is \"Stat\").\n"
#endif
" --report Export all evaluation statistics values in report.txt \n"
" --loc # Show localization statistics for each \"Statistic/Id\" per\n"
@@ -134,6 +137,8 @@ int main(int argc, char * argv[])
bool invertFigures = false;
bool useIds = false;
int startId = 0;
bool exportFigures = false;
std::string exportPrefix = "Stat";
int showLoc = 0;
float locDelay = 60;
std::vector<std::string> statsToShow;
@@ -186,6 +191,24 @@ int main(int argc, char * argv[])
{
useIds = true;
}
else if(strcmp(argv[i],"--export") == 0)
{
exportFigures = true;
}
else if(strcmp(argv[i],"--export_prefix") == 0)
{
++i;
if(i<argc-1)
{
exportPrefix = argv[i];
printf("Export prefix=%s (--export_prefix)\n", exportPrefix.c_str());
}
else
{
printf("Missing value for \"--export_prefix\" option.\n");
showUsage();
}
}
else if(strcmp(argv[i],"--loc") == 0)
{
++i;
@@ -518,14 +541,14 @@ int main(int argc, char * argv[])
if(uContains(stat, std::string("RtabmapROS/TotalTime/ms")))
{
if(w>=0)
if(w!=-1)
{
slamTime.push_back(stat.at("RtabmapROS/TotalTime/ms"));
}
}
else if(uContains(stat, Statistics::kTimingTotal()))
{
if(w>=0)
if(w!=-1)
{
slamTime.push_back(stat.at(Statistics::kTimingTotal()));
}
@@ -1171,9 +1194,34 @@ int main(int argc, char * argv[])
{
iter->second->frameData();
}
iter->second->show();
if(exportFigures)
{
QString data = iter->second->getAllCurveDataAsText();
if(!data.isEmpty())
{
QString filePath = QString(exportPrefix.c_str()) + (exportPrefix.empty()?"":"-") + iter->second->windowTitle().replace('/', "-") + ".txt";
QFile file(filePath);
if(file.open(QIODevice::Text | QIODevice::WriteOnly))
{
file.write(data.toUtf8());
file.close();
printf("Exported \"%s\".\n", filePath.toStdString().c_str());
}
else
{
printf("ERROR: could not open file \"%s\" for writing!\n", filePath.toStdString().c_str());
}
}
}
else
{
iter->second->show();
}
}
if(!exportFigures)
{
return app.exec();
}
return app.exec();
}
#endif
return 0;