mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-12 22:40:19 +08:00
Fixed build with OpenCV >= 3.4.11
This commit is contained in:
+182
-19
@@ -47,10 +47,8 @@ using namespace rtabmap;
|
||||
void showUsage()
|
||||
{
|
||||
printf("\nUsage:\n"
|
||||
#ifdef WITH_QT
|
||||
"rtabmap-report [\"Statistic/Id\"] [options] path\n"
|
||||
#else
|
||||
"rtabmap-report [options] path\n"
|
||||
#ifdef WITH_QT
|
||||
"[Not built with Qt, statistics cannot be plotted]\n"
|
||||
#endif
|
||||
" path Directory containing rtabmap databases or path of a database.\n"
|
||||
@@ -63,8 +61,8 @@ void showUsage()
|
||||
" and compute error based on the scaled path.\n"
|
||||
" --poses Export poses to [path]_poses.txt, ground truth to [path]_gt.txt\n"
|
||||
" and valid ground truth indices to [path]_indices.txt \n"
|
||||
" --stats Show available statistics \"Statistic/Id\" to plot or get localization statistics (if path is a file). \n"
|
||||
#ifdef WITH_QT
|
||||
" --stats Show available statistics to plot (if path is a file). \n"
|
||||
" --invert When reading many databases, put all curves from a same \n"
|
||||
" database in same figure, instead of all same curves from \n"
|
||||
" different database in same figure. When reading a single \n"
|
||||
@@ -72,11 +70,45 @@ void showUsage()
|
||||
" --ids Use IDs for x axis instead of time in the figures. \n"
|
||||
" --start # Start from this node ID for the figures.\n"
|
||||
#endif
|
||||
" --report Export all statistics values in report.txt \n"
|
||||
" --report Export all evaluation statistics values in report.txt \n"
|
||||
" --loc # Show localization statistics for each \"Statistic/Id\" per "
|
||||
" session for 1=min,2=max,4=mean,8=stddev,16=total,32=nonnull%% "
|
||||
" (it is a mask, we can combine those numbers, e.g., 63 for all) \n"
|
||||
" --help Show usage\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct LocStats
|
||||
{
|
||||
static LocStats from(const std::vector<float> & array)
|
||||
{
|
||||
LocStats values;
|
||||
values.mean = uMean(array);
|
||||
values.stddev = std::sqrt(uVariance(array, values.mean));
|
||||
uMinMax(array, values.min, values.max);
|
||||
values.total = array.size();
|
||||
values.nonNull = 0.0f;
|
||||
if(!array.empty())
|
||||
{
|
||||
for(size_t j=0; j<array.size(); ++j)
|
||||
{
|
||||
if(array[j] != 0)
|
||||
{
|
||||
values.nonNull+=1.0f;
|
||||
}
|
||||
}
|
||||
values.nonNull = values.nonNull/float(array.size());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
float mean;
|
||||
float stddev;
|
||||
float min;
|
||||
float max;
|
||||
int total;
|
||||
float nonNull;
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
@@ -101,6 +133,7 @@ int main(int argc, char * argv[])
|
||||
bool invertFigures = false;
|
||||
bool useIds = false;
|
||||
int startId = 0;
|
||||
int showLoc = 0;
|
||||
std::vector<std::string> statsToShow;
|
||||
#ifdef WITH_QT
|
||||
std::map<std::string, UPlot*> figures;
|
||||
@@ -151,7 +184,20 @@ int main(int argc, char * argv[])
|
||||
{
|
||||
useIds = true;
|
||||
}
|
||||
#ifdef WITH_QT
|
||||
else if(strcmp(argv[i],"--loc") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i<argc-1)
|
||||
{
|
||||
showLoc = atoi(argv[i]);
|
||||
printf("Localization statistics=%d (--loc)\n", showLoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Missing type for \"--showLoc\" option.\n");
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else if(strcmp(argv[i],"--start") == 0)
|
||||
{
|
||||
++i;
|
||||
@@ -171,22 +217,22 @@ int main(int argc, char * argv[])
|
||||
|
||||
statsToShow.push_back(argv[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string path = argv[argc-1];
|
||||
path = uReplaceChar(path, '~', UDirectory::homeDir());
|
||||
|
||||
#ifdef WITH_QT
|
||||
if(!UDirectory::exists(path) && UFile::getExtension(path).compare("db") == 0)
|
||||
{
|
||||
invertFigures = !invertFigures;
|
||||
}
|
||||
if(!invertFigures)
|
||||
std::map<std::string, std::map<std::string, std::vector<LocStats> > > localizationMultiStats; //<statsName, <Database<Session>> >
|
||||
for(size_t i=0; i<statsToShow.size(); ++i)
|
||||
{
|
||||
for(size_t i=0; i<statsToShow.size(); ++i)
|
||||
std::string figureTitle = statsToShow[i];
|
||||
if(!invertFigures)
|
||||
{
|
||||
std::string figureTitle = statsToShow[i];
|
||||
#ifdef WITH_QT
|
||||
printf("Plot %s\n", figureTitle.c_str());
|
||||
UPlot * fig = new UPlot();
|
||||
fig->resize(QSize(640,480));
|
||||
@@ -200,10 +246,17 @@ int main(int argc, char * argv[])
|
||||
fig->setXLabel("Time (s)");
|
||||
}
|
||||
figures.insert(std::make_pair(figureTitle, fig));
|
||||
#endif
|
||||
}
|
||||
if(showLoc & 0b111111)
|
||||
{
|
||||
localizationMultiStats.insert(std::make_pair(figureTitle, std::map<std::string, std::vector<LocStats> >()));
|
||||
}
|
||||
}
|
||||
if(!invertFigures)
|
||||
{
|
||||
statsToShow.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string fileName;
|
||||
std::list<std::string> paths;
|
||||
@@ -223,6 +276,7 @@ int main(int argc, char * argv[])
|
||||
if(UFile::getExtension(currentPath).compare("db") == 0)
|
||||
{
|
||||
currentPathIsDatabase=true;
|
||||
localizationMultiStats.clear();
|
||||
printf("Database: %s\n", currentPath.c_str());
|
||||
}
|
||||
else
|
||||
@@ -255,6 +309,7 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// For all databases in currentDir
|
||||
while(currentPathIsDatabase || !(fileName = currentDir.getNextFileName()).empty())
|
||||
{
|
||||
if(currentPathIsDatabase || UFile::getExtension(fileName).compare("db") == 0)
|
||||
@@ -327,6 +382,8 @@ int main(int argc, char * argv[])
|
||||
for(std::map<std::string, UPlot*>::iterator iter=figures.begin(); iter!=figures.end(); ++iter)
|
||||
{
|
||||
curves.insert(std::make_pair(iter->first, iter->second->addCurve(filePath.c_str())));
|
||||
if(!localizationMultiStats.empty())
|
||||
localizationMultiStats.at(iter->first).insert(std::make_pair(fileName, std::vector<LocStats>()));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -351,11 +408,31 @@ int main(int argc, char * argv[])
|
||||
for(size_t i=0; i<statsToShow.size(); ++i)
|
||||
{
|
||||
curves.insert(std::make_pair(statsToShow[i], fig->addCurve(statsToShow[i].c_str())));
|
||||
if(!localizationMultiStats.empty())
|
||||
localizationMultiStats.at(statsToShow[i]).insert(std::make_pair(fileName, std::vector<LocStats>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for(size_t i=0; i<statsToShow.size(); ++i)
|
||||
{
|
||||
if(!localizationMultiStats.empty())
|
||||
localizationMultiStats.at(statsToShow[i]).insert(std::make_pair(fileName, std::vector<LocStats>()));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find localization sessions and adjust startId
|
||||
if(!localizationMultiStats.empty() && startId ==0)
|
||||
{
|
||||
std::map<int, Transform> poses = driver->loadOptimizedPoses();
|
||||
if(!poses.empty())
|
||||
{
|
||||
startId = poses.rbegin()->first+1;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<float> > localizationSessionStats;
|
||||
double previousStamp = 0.0;
|
||||
for(std::set<int>::iterator iter=ids.begin(); iter!=ids.end(); ++iter)
|
||||
{
|
||||
Transform p, gt;
|
||||
@@ -432,22 +509,63 @@ int main(int argc, char * argv[])
|
||||
#ifdef WITH_QT
|
||||
for(std::map<std::string, UPlotCurve*>::iterator jter=curves.begin(); jter!=curves.end(); ++jter)
|
||||
{
|
||||
if(uContains(stat, jter->first) && *iter >= startId)
|
||||
#else
|
||||
for(std::map<std::string, std::map<std::string, std::vector<LocStats> > >::iterator jter=localizationMultiStats.begin();
|
||||
jter!=localizationMultiStats.end();
|
||||
++jter)
|
||||
{
|
||||
#endif
|
||||
if(*iter >= startId)
|
||||
{
|
||||
double x = s;
|
||||
if(useIds)
|
||||
if(uContains(stat, jter->first))
|
||||
{
|
||||
x = *iter;
|
||||
double y = stat.at(jter->first);
|
||||
#ifdef WITH_QT
|
||||
double x = s;
|
||||
if(useIds)
|
||||
{
|
||||
x = *iter;
|
||||
}
|
||||
jter->second->addValue(x,y);
|
||||
#endif
|
||||
|
||||
if(!localizationMultiStats.empty())
|
||||
{
|
||||
if(previousStamp > 0 && s - previousStamp > 10 && uContains(localizationSessionStats, jter->first))
|
||||
{
|
||||
// changed session
|
||||
LocStats values = LocStats::from(localizationSessionStats.at(jter->first));
|
||||
localizationMultiStats.at(jter->first).rbegin()->second.push_back(values);
|
||||
localizationSessionStats.at(jter->first).clear();
|
||||
}
|
||||
|
||||
if(!uContains(localizationSessionStats, jter->first))
|
||||
{
|
||||
localizationSessionStats.insert(std::make_pair(jter->first, std::vector<float>()));
|
||||
}
|
||||
localizationSessionStats.at(jter->first).push_back(y);
|
||||
}
|
||||
}
|
||||
double y = stat.at(jter->first);
|
||||
jter->second->addValue(x,y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
previousStamp = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(std::map<std::string, std::map<std::string, std::vector<LocStats> > >::iterator jter=localizationMultiStats.begin();
|
||||
jter!=localizationMultiStats.end();
|
||||
++jter)
|
||||
{
|
||||
if(uContains(localizationSessionStats, jter->first) &&
|
||||
!localizationSessionStats.at(jter->first).empty())
|
||||
{
|
||||
// changed session
|
||||
LocStats values = LocStats::from(localizationSessionStats.at(jter->first));
|
||||
localizationMultiStats.at(jter->first).rbegin()->second.push_back(values);
|
||||
}
|
||||
}
|
||||
|
||||
std::multimap<int, Link> links;
|
||||
std::multimap<int, Link> allLinks;
|
||||
driver->getAllLinks(allLinks, true, true);
|
||||
@@ -823,6 +941,51 @@ int main(int argc, char * argv[])
|
||||
currentPathIsDatabase = false;
|
||||
}
|
||||
|
||||
for(std::map<std::string, std::map<std::string, std::vector<LocStats> > >::iterator iter=localizationMultiStats.begin();
|
||||
iter!=localizationMultiStats.end();
|
||||
++iter)
|
||||
{
|
||||
printf("%s\n", iter->first.c_str());
|
||||
for(int k=0; k<6; ++k)
|
||||
{
|
||||
if(showLoc & (0x1 << k))
|
||||
{
|
||||
printf(" %s:\n",
|
||||
k==0?"min":
|
||||
k==1?"max":
|
||||
k==2?"mean":
|
||||
k==3?"stddev":
|
||||
k==4?"total":
|
||||
"nonnull%");
|
||||
for(std::map<std::string, std::vector<LocStats> >::iterator jter=iter->second.begin(); jter!=iter->second.end(); ++jter)
|
||||
{
|
||||
printf(" %s ", jter->first.c_str());
|
||||
for(size_t j=0; j<jter->second.size(); ++j)
|
||||
{
|
||||
if(k<4)
|
||||
{
|
||||
printf("%f ",
|
||||
k==0?jter->second[j].min:
|
||||
k==1?jter->second[j].max:
|
||||
k==2?jter->second[j].mean:
|
||||
jter->second[j].stddev);
|
||||
}
|
||||
else if(k==4)
|
||||
{
|
||||
printf("%d ",jter->second[j].total);
|
||||
}
|
||||
else if(k==5)
|
||||
{
|
||||
printf("%.2f ", (jter->second[j].nonNull*100));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
iter->second.clear();
|
||||
}
|
||||
|
||||
for(std::list<std::string>::iterator iter=subDirs.begin(); iter!=subDirs.end(); ++iter)
|
||||
{
|
||||
paths.push_front(*iter);
|
||||
|
||||
Reference in New Issue
Block a user