Files
rtabmap/corelib/src/Parameters.cpp

791 lines
34 KiB
C++
Raw Normal View History

/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "rtabmap/core/Parameters.h"
#include <rtabmap/utilite/UDirectory.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UStl.h>
2016-01-19 18:18:53 -05:00
#include <cmath>
#include <stdlib.h>
#include <sstream>
#include <iostream>
#include <iomanip>
#include "SimpleIni.h"
namespace rtabmap
{
ParametersMap Parameters::parameters_;
ParametersMap Parameters::parametersType_;
ParametersMap Parameters::descriptions_;
Parameters Parameters::instance_;
std::map<std::string, std::pair<bool, std::string> > Parameters::removedParameters_;
ParametersMap Parameters::backwardCompatibilityMap_;
Parameters::Parameters()
{
}
Parameters::~Parameters()
{
}
2016-02-15 19:35:24 -05:00
std::string Parameters::createDefaultWorkingDirectory()
{
std::string path = UDirectory::homeDir();
if(!path.empty())
{
UDirectory::makeDir(path += UDirectory::separator() + "Documents");
UDirectory::makeDir(path += UDirectory::separator() + "RTAB-Map");
}
else
{
UFATAL("Can't get the HOME variable environment!");
}
return path;
}
std::string Parameters::getVersion()
{
return RTABMAP_VERSION;
return ""; // Second return only to avoid compiler warning with RTABMAP_VERSION not yet set.
}
std::string Parameters::getDefaultDatabaseName()
{
return "rtabmap.db";
}
std::string Parameters::serialize(const ParametersMap & parameters)
{
std::stringstream output;
for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
{
if(iter != parameters.begin())
{
output << ";";
}
// make sure there are no commas instead of dots
output << iter->first << ":" << uReplaceChar(iter->second, ',', '.');
}
UDEBUG("output=%s", output.str().c_str());
return output.str();
}
ParametersMap Parameters::deserialize(const std::string & parameters)
{
UDEBUG("parameters=%s", parameters.c_str());
ParametersMap output;
std::list<std::string> tuplets = uSplit(parameters, ';');
for(std::list<std::string>::iterator iter=tuplets.begin(); iter!=tuplets.end(); ++iter)
{
std::list<std::string> p = uSplit(*iter, ':');
if(p.size() == 2)
{
std::string key = p.front();
std::string value = p.back();
// look for old parameter name
bool addParameter = true;
std::map<std::string, std::pair<bool, std::string> >::const_iterator oldIter = Parameters::getRemovedParameters().find(key);
if(oldIter!=Parameters::getRemovedParameters().end())
{
addParameter = oldIter->second.first;
if(addParameter)
{
key = oldIter->second.second;
UWARN("Parameter migration from \"%s\" to \"%s\" (value=%s).",
oldIter->first.c_str(), oldIter->second.second.c_str(), value.c_str());
}
else if(oldIter->second.second.empty())
{
UWARN("Parameter \"%s\" doesn't exist anymore.",
oldIter->first.c_str());
}
else
{
UWARN("Parameter \"%s\" doesn't exist anymore, you may want to use this similar parameter \"%s\":\"%s\".",
oldIter->first.c_str(), oldIter->second.second.c_str(), Parameters::getDescription(oldIter->second.second).c_str());
}
}
if(Parameters::getDefaultParameters().find(key) == Parameters::getDefaultParameters().end())
{
UWARN("Unknown parameter \"%s\"=\"%s\"! The parameter is still added to output map.", key.c_str(), value.c_str());
}
uInsert(output, ParametersPair(key, value));
}
}
return output;
}
bool Parameters::isFeatureParameter(const std::string & parameter)
{
std::string group = uSplit(parameter, '/').front();
return group.compare("SURF") == 0 ||
group.compare("SIFT") == 0 ||
group.compare("ORB") == 0 ||
group.compare("FAST") == 0 ||
group.compare("FREAK") == 0 ||
group.compare("BRIEF") == 0 ||
group.compare("GFTT") == 0 ||
group.compare("BRISK") == 0;
}
rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, bool vis, bool icp)
{
rtabmap::ParametersMap odomParameters;
rtabmap::ParametersMap defaultParameters = rtabmap::Parameters::getDefaultParameters();
for(rtabmap::ParametersMap::iterator iter=defaultParameters.begin(); iter!=defaultParameters.end(); ++iter)
{
std::string group = uSplit(iter->first, '/').front();
if(uStrContains(group, "Odom") ||
(stereo && group.compare("Stereo") == 0) ||
(icp && group.compare("Icp") == 0) ||
(vis && Parameters::isFeatureParameter(iter->first)) ||
group.compare("Reg") == 0 ||
(vis && group.compare("Vis") == 0))
{
if(stereo)
{
if(iter->first.compare(Parameters::kVisEstimationType()) == 0)
{
iter->second = "1"; // 3D->2D (PNP)
}
}
odomParameters.insert(*iter);
}
}
return odomParameters;
}
ParametersMap Parameters::getDefaultParameters(const std::string & groupIn)
{
rtabmap::ParametersMap parameters;
const rtabmap::ParametersMap & defaultParameters = rtabmap::Parameters::getDefaultParameters();
for(rtabmap::ParametersMap::const_iterator iter=defaultParameters.begin(); iter!=defaultParameters.end(); ++iter)
{
UASSERT(uSplit(iter->first, '/').size() == 2);
std::string group = uSplit(iter->first, '/').front();
if(group.compare(groupIn) == 0)
{
parameters.insert(*iter);
}
}
UASSERT_MSG(parameters.size(), uFormat("No parameters found for group %s!", groupIn.c_str()).c_str());
return parameters;
}
ParametersMap Parameters::filterParameters(const ParametersMap & parameters, const std::string & groupIn)
{
ParametersMap output;
for(rtabmap::ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
{
UASSERT(uSplit(iter->first, '/').size() == 2);
std::string group = uSplit(iter->first, '/').front();
if(group.compare(groupIn) == 0)
{
output.insert(*iter);
}
}
return output;
}
const std::map<std::string, std::pair<bool, std::string> > & Parameters::getRemovedParameters()
{
if(removedParameters_.empty())
{
// removed parameters
// 0.11.12
removedParameters_.insert(std::make_pair("Optimizer/Slam2D", std::make_pair(true, Parameters::kRegForce3DoF())));
removedParameters_.insert(std::make_pair("OdomF2M/FixedMapPath", std::make_pair(false, "")));
// 0.11.10 typos
removedParameters_.insert(std::make_pair("Grid/FlatObstaclesDetected", std::make_pair(true, Parameters::kGridFlatObstacleDetected())));
// 0.11.8
removedParameters_.insert(std::make_pair("Reg/Force2D", std::make_pair(true, Parameters::kRegForce3DoF())));
removedParameters_.insert(std::make_pair("OdomF2M/ScanSubstractRadius", std::make_pair(true, Parameters::kOdomF2MScanSubtractRadius())));
// 0.11.6
removedParameters_.insert(std::make_pair("RGBD/ProximityPathScansMerged", std::make_pair(false, "")));
// 0.11.3
removedParameters_.insert(std::make_pair("Mem/ImageDecimation", std::make_pair(true, Parameters::kMemImagePostDecimation())));
// 0.11.2
removedParameters_.insert(std::make_pair("OdomLocalMap/HistorySize", std::make_pair(true, Parameters::kOdomF2MMaxSize())));
removedParameters_.insert(std::make_pair("OdomLocalMap/FixedMapPath", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("OdomF2F/GuessMotion", std::make_pair(true, Parameters::kOdomGuessMotion())));
removedParameters_.insert(std::make_pair("OdomF2F/KeyFrameThr", std::make_pair(false, Parameters::kOdomKeyFrameThr())));
// 0.11.0
removedParameters_.insert(std::make_pair("OdomBow/LocalHistorySize", std::make_pair(true, Parameters::kOdomF2MMaxSize())));
removedParameters_.insert(std::make_pair("OdomBow/FixedLocalMapPath", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("OdomFlow/KeyFrameThr", std::make_pair(false, Parameters::kOdomKeyFrameThr())));
removedParameters_.insert(std::make_pair("OdomFlow/GuessMotion", std::make_pair(true, Parameters::kOdomGuessMotion())));
removedParameters_.insert(std::make_pair("Kp/WordsPerImage", std::make_pair(true, Parameters::kKpMaxFeatures())));
removedParameters_.insert(std::make_pair("Mem/LaserScanVoxelSize", std::make_pair(false, Parameters::kMemLaserScanDownsampleStepSize())));
removedParameters_.insert(std::make_pair("Mem/LocalSpaceLinksKeptInWM", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("RGBD/PoseScanMatching", std::make_pair(true, Parameters::kRGBDNeighborLinkRefining())));
removedParameters_.insert(std::make_pair("Odom/ParticleFiltering", std::make_pair(false, Parameters::kOdomFilteringStrategy())));
removedParameters_.insert(std::make_pair("Odom/FeatureType", std::make_pair(true, Parameters::kVisFeatureType())));
removedParameters_.insert(std::make_pair("Odom/EstimationType", std::make_pair(true, Parameters::kVisEstimationType())));
removedParameters_.insert(std::make_pair("Odom/MaxFeatures", std::make_pair(true, Parameters::kVisMaxFeatures())));
removedParameters_.insert(std::make_pair("Odom/InlierDistance", std::make_pair(true, Parameters::kVisInlierDistance())));
removedParameters_.insert(std::make_pair("Odom/MinInliers", std::make_pair(true, Parameters::kVisMinInliers())));
removedParameters_.insert(std::make_pair("Odom/Iterations", std::make_pair(true, Parameters::kVisIterations())));
removedParameters_.insert(std::make_pair("Odom/RefineIterations", std::make_pair(true, Parameters::kVisRefineIterations())));
removedParameters_.insert(std::make_pair("Odom/MaxDepth", std::make_pair(true, Parameters::kVisMaxDepth())));
removedParameters_.insert(std::make_pair("Odom/RoiRatios", std::make_pair(true, Parameters::kVisRoiRatios())));
removedParameters_.insert(std::make_pair("Odom/Force2D", std::make_pair(true, Parameters::kRegForce3DoF())));
removedParameters_.insert(std::make_pair("Odom/VarianceFromInliersCount", std::make_pair(true, Parameters::kRegVarianceFromInliersCount())));
removedParameters_.insert(std::make_pair("Odom/PnPReprojError", std::make_pair(true, Parameters::kVisPnPReprojError())));
removedParameters_.insert(std::make_pair("Odom/PnPFlags", std::make_pair(true, Parameters::kVisPnPFlags())));
removedParameters_.insert(std::make_pair("OdomBow/NNType", std::make_pair(true, Parameters::kVisCorNNType())));
removedParameters_.insert(std::make_pair("OdomBow/NNDR", std::make_pair(true, Parameters::kVisCorNNDR())));
removedParameters_.insert(std::make_pair("OdomFlow/WinSize", std::make_pair(true, Parameters::kVisCorFlowWinSize())));
removedParameters_.insert(std::make_pair("OdomFlow/Iterations", std::make_pair(true, Parameters::kVisCorFlowIterations())));
removedParameters_.insert(std::make_pair("OdomFlow/Eps", std::make_pair(true, Parameters::kVisCorFlowEps())));
removedParameters_.insert(std::make_pair("OdomFlow/MaxLevel", std::make_pair(true, Parameters::kVisCorFlowMaxLevel())));
removedParameters_.insert(std::make_pair("OdomSubPix/WinSize", std::make_pair(true, Parameters::kVisSubPixWinSize())));
removedParameters_.insert(std::make_pair("OdomSubPix/Iterations", std::make_pair(true, Parameters::kVisSubPixIterations())));
removedParameters_.insert(std::make_pair("OdomSubPix/Eps", std::make_pair(true, Parameters::kVisSubPixEps())));
removedParameters_.insert(std::make_pair("LccReextract/Activated", std::make_pair(true, Parameters::kRGBDLoopClosureReextractFeatures())));
removedParameters_.insert(std::make_pair("LccReextract/FeatureType", std::make_pair(false, Parameters::kVisFeatureType())));
removedParameters_.insert(std::make_pair("LccReextract/MaxWords", std::make_pair(false, Parameters::kVisMaxFeatures())));
removedParameters_.insert(std::make_pair("LccReextract/MaxDepth", std::make_pair(false, Parameters::kVisMaxDepth())));
removedParameters_.insert(std::make_pair("LccReextract/RoiRatios", std::make_pair(false, Parameters::kVisRoiRatios())));
removedParameters_.insert(std::make_pair("LccReextract/NNType", std::make_pair(false, Parameters::kVisCorNNType())));
removedParameters_.insert(std::make_pair("LccReextract/NNDR", std::make_pair(false, Parameters::kVisCorNNDR())));
removedParameters_.insert(std::make_pair("LccBow/EstimationType", std::make_pair(false, Parameters::kVisEstimationType())));
removedParameters_.insert(std::make_pair("LccBow/InlierDistance", std::make_pair(false, Parameters::kVisInlierDistance())));
removedParameters_.insert(std::make_pair("LccBow/MinInliers", std::make_pair(false, Parameters::kVisMinInliers())));
removedParameters_.insert(std::make_pair("LccBow/Iterations", std::make_pair(false, Parameters::kVisIterations())));
removedParameters_.insert(std::make_pair("LccBow/RefineIterations", std::make_pair(false, Parameters::kVisRefineIterations())));
removedParameters_.insert(std::make_pair("LccBow/Force2D", std::make_pair(false, Parameters::kRegForce3DoF())));
removedParameters_.insert(std::make_pair("LccBow/VarianceFromInliersCount", std::make_pair(false, Parameters::kRegVarianceFromInliersCount())));
removedParameters_.insert(std::make_pair("LccBow/PnPReprojError", std::make_pair(false, Parameters::kVisPnPReprojError())));
removedParameters_.insert(std::make_pair("LccBow/PnPFlags", std::make_pair(false, Parameters::kVisPnPFlags())));
removedParameters_.insert(std::make_pair("LccBow/EpipolarGeometryVar", std::make_pair(true, Parameters::kVisEpipolarGeometryVar())));
removedParameters_.insert(std::make_pair("LccIcp/Type", std::make_pair(false, Parameters::kRegStrategy())));
removedParameters_.insert(std::make_pair("LccIcp3/Decimation", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("LccIcp3/MaxDepth", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("LccIcp3/VoxelSize", std::make_pair(false, Parameters::kIcpVoxelSize())));
removedParameters_.insert(std::make_pair("LccIcp3/Samples", std::make_pair(false, Parameters::kIcpDownsamplingStep())));
removedParameters_.insert(std::make_pair("LccIcp3/MaxCorrespondenceDistance", std::make_pair(false, Parameters::kIcpMaxCorrespondenceDistance())));
removedParameters_.insert(std::make_pair("LccIcp3/Iterations", std::make_pair(false, Parameters::kIcpIterations())));
removedParameters_.insert(std::make_pair("LccIcp3/CorrespondenceRatio", std::make_pair(false, Parameters::kIcpCorrespondenceRatio())));
removedParameters_.insert(std::make_pair("LccIcp3/PointToPlane", std::make_pair(true, Parameters::kIcpPointToPlane())));
removedParameters_.insert(std::make_pair("LccIcp3/PointToPlaneNormalNeighbors", std::make_pair(true, Parameters::kIcpPointToPlaneNormalNeighbors())));
removedParameters_.insert(std::make_pair("LccIcp2/MaxCorrespondenceDistance", std::make_pair(true, Parameters::kIcpMaxCorrespondenceDistance())));
removedParameters_.insert(std::make_pair("LccIcp2/Iterations", std::make_pair(true, Parameters::kIcpIterations())));
removedParameters_.insert(std::make_pair("LccIcp2/CorrespondenceRatio", std::make_pair(true, Parameters::kIcpCorrespondenceRatio())));
removedParameters_.insert(std::make_pair("LccIcp2/VoxelSize", std::make_pair(true, Parameters::kIcpVoxelSize())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionByTime", std::make_pair(true, Parameters::kRGBDProximityByTime())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionBySpace", std::make_pair(true, Parameters::kRGBDProximityBySpace())));
2016-02-19 15:10:28 -05:00
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionTime", std::make_pair(true, Parameters::kRGBDProximityByTime())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionSpace", std::make_pair(true, Parameters::kRGBDProximityBySpace())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathScansMerged", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionMaxGraphDepth", std::make_pair(true, Parameters::kRGBDProximityMaxGraphDepth())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathFilteringRadius", std::make_pair(true, Parameters::kRGBDProximityPathFilteringRadius())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathRawPosesUsed", std::make_pair(true, Parameters::kRGBDProximityPathRawPosesUsed())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeStrategy", std::make_pair(true, Parameters::kOptimizerStrategy())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeEpsilon", std::make_pair(true, Parameters::kOptimizerEpsilon())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeIterations", std::make_pair(true, Parameters::kOptimizerIterations())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeRobust", std::make_pair(true, Parameters::kOptimizerRobust())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeSlam2D", std::make_pair(true, Parameters::kRegForce3DoF())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeSlam2d", std::make_pair(true, Parameters::kRegForce3DoF())));
removedParameters_.insert(std::make_pair("RGBD/OptimizeVarianceIgnored", std::make_pair(true, Parameters::kOptimizerVarianceIgnored())));
removedParameters_.insert(std::make_pair("Stereo/WinSize", std::make_pair(true, Parameters::kStereoWinWidth())));
// before 0.11.0
removedParameters_.insert(std::make_pair("GFTT/MaxCorners", std::make_pair(true, Parameters::kVisMaxFeatures())));
removedParameters_.insert(std::make_pair("LccBow/MaxDepth", std::make_pair(true, Parameters::kVisMaxDepth())));
removedParameters_.insert(std::make_pair("LccReextract/LoopClosureFeatures", std::make_pair(true, Parameters::kRGBDLoopClosureReextractFeatures())));
removedParameters_.insert(std::make_pair("Rtabmap/DetectorStrategy", std::make_pair(true, Parameters::kKpDetectorStrategy())));
removedParameters_.insert(std::make_pair("RGBD/ScanMatchingSize", std::make_pair(true, Parameters::kRGBDNeighborLinkRefining())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionRadius", std::make_pair(true, Parameters::kRGBDLocalRadius())));
removedParameters_.insert(std::make_pair("RGBD/ToroIterations", std::make_pair(true, Parameters::kOptimizerIterations())));
removedParameters_.insert(std::make_pair("Mem/RehearsedNodesKept", std::make_pair(true, Parameters::kMemNotLinkedNodesKept())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionMaxDiffID", std::make_pair(true, Parameters::kRGBDProximityMaxGraphDepth())));
removedParameters_.insert(std::make_pair("RGBD/PlanVirtualLinksMaxDiffID", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionMaxDiffID", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("Odom/Type", std::make_pair(true, Parameters::kVisFeatureType())));
removedParameters_.insert(std::make_pair("Odom/MaxWords", std::make_pair(true, Parameters::kVisMaxFeatures())));
removedParameters_.insert(std::make_pair("Odom/LocalHistory", std::make_pair(true, Parameters::kOdomF2MMaxSize())));
removedParameters_.insert(std::make_pair("Odom/NearestNeighbor", std::make_pair(true, Parameters::kVisCorNNType())));
removedParameters_.insert(std::make_pair("Odom/NNDR", std::make_pair(true, Parameters::kVisCorNNDR())));
}
return removedParameters_;
}
const ParametersMap & Parameters::getBackwardCompatibilityMap()
{
if(backwardCompatibilityMap_.empty())
{
getRemovedParameters(); // make sure removedParameters is filled
// compatibility
for(std::map<std::string, std::pair<bool, std::string> >::iterator iter=removedParameters_.begin();
iter!=removedParameters_.end();
++iter)
{
if(iter->second.first)
{
backwardCompatibilityMap_.insert(ParametersPair(iter->second.second, iter->first));
}
}
}
return backwardCompatibilityMap_;
}
std::string Parameters::getType(const std::string & paramKey)
{
std::string type;
ParametersMap::iterator iter = parametersType_.find(paramKey);
if(iter != parametersType_.end())
{
type = iter->second;
}
else
{
UERROR("Parameters \"%s\" doesn't exist!", paramKey.c_str());
}
return type;
}
std::string Parameters::getDescription(const std::string & paramKey)
{
std::string description;
ParametersMap::iterator iter = descriptions_.find(paramKey);
if(iter != descriptions_.end())
{
description = iter->second;
}
else
{
UERROR("Parameters \"%s\" doesn't exist!", paramKey.c_str());
}
return description;
}
bool Parameters::parse(const ParametersMap & parameters, const std::string & key, bool & value)
{
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
value = uStr2Bool(iter->second.c_str());
return true;
}
return false;
}
bool Parameters::parse(const ParametersMap & parameters, const std::string & key, int & value)
{
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
value = uStr2Int(iter->second.c_str());
return true;
}
return false;
}
bool Parameters::parse(const ParametersMap & parameters, const std::string & key, unsigned int & value)
{
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
value = uStr2Int(iter->second.c_str());
return true;
}
return false;
}
bool Parameters::parse(const ParametersMap & parameters, const std::string & key, float & value)
{
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
value = uStr2Float(iter->second);
return true;
}
return false;
}
bool Parameters::parse(const ParametersMap & parameters, const std::string & key, double & value)
{
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
value = uStr2Double(iter->second);
return true;
}
return false;
}
bool Parameters::parse(const ParametersMap & parameters, const std::string & key, std::string & value)
{
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
value = iter->second;
return true;
}
return false;
}
void Parameters::parse(const ParametersMap & parameters, ParametersMap & parametersOut)
{
for(ParametersMap::iterator iter=parametersOut.begin(); iter!=parametersOut.end(); ++iter)
{
ParametersMap::const_iterator jter = parameters.find(iter->first);
if(jter != parameters.end())
{
iter->second = jter->second;
}
}
}
const char * Parameters::showUsage()
{
return "Logger options:\n"
" --nolog Disable logger\n"
" --logconsole Set logger console type\n"
" --logfile \"path\" Set logger file type\n"
" --logfilea \"path\" Set logger file type with appending mode if the file already exists\n"
" --udebug Set logger level to debug\n"
" --uinfo Set logger level to info\n"
" --uwarn Set logger level to warn\n"
" --uerror Set logger level to error\n"
" --logtime \"bool\" Print time when logging\n"
" --logwhere \"bool\" Print where when logging\n"
" --logthread \"bool\" Print thread id when logging\n"
"RTAB-Map options:\n"
" --params Show all parameters with their default value and description\n"
" --\"parameter name\" \"value\" Overwrite a specific RTAB-Map's parameter :\n"
" --SURF/HessianThreshold 150\n"
" For parameters in table format, add ',' between values :\n"
" --Kp/RoiRatios 0,0,0.1,0\n"
;
}
ParametersMap Parameters::parseArguments(int argc, char * argv[], bool onlyParameters)
{
ParametersMap out;
const ParametersMap & parameters = getDefaultParameters();
const std::map<std::string, std::pair<bool, std::string> > & removedParams = getRemovedParameters();
for(int i=0;i<argc;++i)
{
bool checkParameters = onlyParameters;
if(!checkParameters)
{
if(strcmp(argv[i], "--nolog") == 0)
{
ULogger::setType(ULogger::kTypeNoLog);
}
else if(strcmp(argv[i], "--logconsole") == 0)
{
ULogger::setType(ULogger::kTypeConsole);
}
else if(strcmp(argv[i], "--logfile") == 0)
{
++i;
if(i < argc)
{
ULogger::setType(ULogger::kTypeFile, argv[i], false);
}
else
{
UERROR("\"--logfile\" argument requires following file path");
}
}
else if(strcmp(argv[i], "--logfilea") == 0)
{
++i;
if(i < argc)
{
ULogger::setType(ULogger::kTypeFile, argv[i], true);
}
else
{
UERROR("\"--logfilea\" argument requires following file path");
}
}
else if(strcmp(argv[i], "--udebug") == 0)
{
ULogger::setLevel(ULogger::kDebug);
}
else if(strcmp(argv[i], "--uinfo") == 0)
{
ULogger::setLevel(ULogger::kInfo);
}
else if(strcmp(argv[i], "--uwarn") == 0)
{
ULogger::setLevel(ULogger::kWarning);
}
else if(strcmp(argv[i], "--uerror") == 0)
{
ULogger::setLevel(ULogger::kError);
}
else if(strcmp(argv[i], "--ulogtime") == 0)
{
++i;
if(i < argc)
{
ULogger::setPrintTime(uStr2Bool(argv[i]));
}
else
{
UERROR("\"--ulogtime\" argument requires a following boolean value");
}
}
else if(strcmp(argv[i], "--ulogwhere") == 0)
{
++i;
if(i < argc)
{
ULogger::setPrintWhere(uStr2Bool(argv[i]));
}
else
{
UERROR("\"--ulogwhere\" argument requires a following boolean value");
}
}
else if(strcmp(argv[i], "--ulogthread") == 0)
{
++i;
if(i < argc)
{
ULogger::setPrintThreadId(uStr2Bool(argv[i]));
}
else
{
UERROR("\"--ulogthread\" argument requires a following boolean value");
}
}
else
{
checkParameters = true;
}
}
if(checkParameters) // check for parameters
{
if(strcmp(argv[i], "--params") == 0)
{
for(rtabmap::ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
{
std::string str = "Param: " + iter->first + " = \"" + iter->second + "\"";
std::cout <<
str <<
std::setw(60 - str.size()) <<
" [" <<
rtabmap::Parameters::getDescription(iter->first).c_str() <<
"]" <<
std::endl;
}
UWARN("App will now exit after showing default RTAB-Map parameters because "
"argument \"--params\" is detected!");
exit(0);
}
else
{
std::string key = uReplaceChar(argv[i], '-', "");
ParametersMap::const_iterator iter = parameters.find(key);
if(iter != parameters.end())
{
++i;
if(i < argc)
{
uInsert(out, ParametersPair(iter->first, argv[i]));
}
}
else
{
// backward compatibility
std::map<std::string, std::pair<bool, std::string> >::const_iterator jter = removedParams.find(key);
if(jter!=removedParams.end())
{
if(jter->second.first)
{
++i;
if(i < argc)
{
std::string value = argv[i];
if(!value.empty())
{
value = uReplaceChar(value, ',', ' '); // for table
key = jter->second.second;
UWARN("Parameter migration from \"%s\" to \"%s\" (value=%s).",
jter->first.c_str(), jter->second.second.c_str(), value.c_str());
uInsert(out, ParametersPair(key, value));
}
}
else
{
UERROR("Value missing for argument \"%s\"", argv[i-1]);
}
}
else if(jter->second.second.empty())
{
UERROR("Parameter \"%s\" doesn't exist anymore.", jter->first.c_str());
}
else
{
UERROR("Parameter \"%s\" doesn't exist anymore, check this similar parameter \"%s\".", jter->first.c_str(), jter->second.second.c_str());
}
}
}
}
}
}
return out;
}
void Parameters::readINI(const std::string & configFile, ParametersMap & parameters)
{
CSimpleIniA ini;
ini.LoadFile(configFile.c_str());
const CSimpleIniA::TKeyVal * keyValMap = ini.GetSection("Core");
if(keyValMap)
{
for(CSimpleIniA::TKeyVal::const_iterator iter=keyValMap->begin(); iter!=keyValMap->end(); ++iter)
{
std::string key = (*iter).first.pItem;
if(key.compare("Version") == 0)
{
// Compare version in ini with the current RTAB-Map version
std::vector<std::string> version = uListToVector(uSplit((*iter).second, '.'));
if(version.size() == 3)
{
if(!RTABMAP_VERSION_COMPARE(std::atoi(version[0].c_str()), std::atoi(version[1].c_str()), std::atoi(version[2].c_str())))
{
if(configFile.find(".rtabmap") != std::string::npos)
{
UWARN("Version in the config file \"%s\" is more recent (\"%s\") than "
"current RTAB-Map version used (\"%s\"). The config file will be upgraded "
"to new version.",
configFile.c_str(),
(*iter).second,
RTABMAP_VERSION);
}
else
{
UERROR("Version in the config file \"%s\" is more recent (\"%s\") than "
"current RTAB-Map version used (\"%s\"). New parameters (if there are some) will "
"be ignored.",
configFile.c_str(),
(*iter).second,
RTABMAP_VERSION);
}
}
}
}
else
{
key = uReplaceChar(key, '\\', '/'); // Ini files use \ by default for separators, so replace them
// look for old parameter name
bool addParameter = true;
std::map<std::string, std::pair<bool, std::string> >::const_iterator oldIter = Parameters::getRemovedParameters().find(key);
if(oldIter!=Parameters::getRemovedParameters().end())
{
addParameter = oldIter->second.first;
if(addParameter)
{
key = oldIter->second.second;
UWARN("Parameter migration from \"%s\" to \"%s\" (value=%s, default=%s).",
oldIter->first.c_str(), oldIter->second.second.c_str(), iter->second, Parameters::getDefaultParameters().at(oldIter->second.second).c_str());
}
else if(oldIter->second.second.empty())
{
UWARN("Parameter \"%s\" doesn't exist anymore.",
oldIter->first.c_str());
}
else
{
UWARN("Parameter \"%s\" (value=%s) doesn't exist anymore, you may want to use this similar parameter \"%s (default=%s): %s\".",
oldIter->first.c_str(), iter->second, oldIter->second.second.c_str(), Parameters::getDefaultParameters().at(oldIter->second.second).c_str(), Parameters::getDescription(oldIter->second.second).c_str());
}
}
if(Parameters::getDefaultParameters().find(key) != Parameters::getDefaultParameters().end())
{
uInsert(parameters, ParametersPair(key, iter->second));
}
}
}
}
else
{
ULOGGER_WARN("Section \"Core\" in %s doesn't exist... "
"Ignore this warning if the ini file does not exist yet. "
"The ini file will be automatically created when this node will close.", configFile.c_str());
}
}
void Parameters::writeINI(const std::string & configFile, const ParametersMap & parameters)
{
CSimpleIniA ini;
ini.LoadFile(configFile.c_str());
// Save current version
ini.SetValue("Core", "Version", RTABMAP_VERSION, NULL, true);
for(ParametersMap::const_iterator i=parameters.begin(); i!=parameters.end(); ++i)
{
std::string key = (*i).first;
key = uReplaceChar(key, '/', '\\'); // Ini files use \ by default for separators, so replace the /
std::string value = (*i).second.c_str();
value = uReplaceChar(value, '\\', '/'); // use always slash for values
ini.SetValue("Core", key.c_str(), value.c_str(), NULL, true);
}
ini.SaveFile(configFile.c_str());
}
}