00001 // kate: replace-tabs off; indent-width 4; indent-mode normal 00002 // vim: ts=4:sw=4:noexpandtab 00003 /* 00004 00005 Copyright (c) 2010--2012, 00006 François Pomerleau and Stephane Magnenat, ASL, ETHZ, Switzerland 00007 You can contact the authors at <f dot pomerleau at gmail dot com> and 00008 <stephane at magnenat dot net> 00009 00010 All rights reserved. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright 00015 notice, this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright 00017 notice, this list of conditions and the following disclaimer in the 00018 documentation and/or other materials provided with the distribution. 00019 * Neither the name of the <organization> nor the 00020 names of its contributors may be used to endorse or promote products 00021 derived from this software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00026 DISCLAIMED. IN NO EVENT SHALL ETH-ASL BE LIABLE FOR ANY 00027 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00028 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00030 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "Parametrizable.h" 00037 #include <boost/format.hpp> 00038 00039 namespace PointMatcherSupport 00040 { 00041 using namespace std; 00042 00044 Parametrizable::InvalidParameter::InvalidParameter(const std::string& reason): 00045 runtime_error(reason) 00046 {} 00047 00049 std::ostream& operator<< (std::ostream& o, const Parametrizable::ParameterDoc& p) 00050 { 00051 o << p.name << " (default: " << p.defaultValue << ") - " << p.doc; 00052 if (!p.minValue.empty()) 00053 o << " - min: " << p.minValue; 00054 if (!p.maxValue.empty()) 00055 o << " - max: " << p.maxValue; 00056 return o; 00057 } 00058 00060 std::ostream& operator<< (std::ostream& o, const Parametrizable::ParametersDoc& p) 00061 { 00062 for (auto it = p.cbegin(); it != p.cend(); ++it) 00063 o << "- " << *it << endl; 00064 return o; 00065 } 00066 00068 bool FalseLexicalComparison(std::string, std::string) 00069 { 00070 return false; 00071 } 00072 00073 /*template<typename S> 00074 bool ScalarLexicalComparison(std::string a, std::string b) 00075 { 00076 return boost::lexical_cast<S>(a) < boost::lexical_cast<S>(b); 00077 } 00078 00079 Uncomment once most people have gcc >= 4.5 00080 Shame on bug 9050 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9050) 00081 template<typename S> 00082 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const S defaultValue, const S minValue, const S maxValue): 00083 name(name), 00084 doc(doc), 00085 defaultValue(boost::lexical_cast<string>(defaultValue)), 00086 minValue(boost::lexical_cast<string>(minValue)), 00087 maxValue(boost::lexical_cast<string>(maxValue)), 00088 comp(ScalarLexicalComparison<S>) 00089 {} 00090 00091 template<typename S> 00092 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const S defaultValue): 00093 name(name), 00094 doc(doc), 00095 defaultValue(boost::lexical_cast<string>(defaultValue)), 00096 minValue(""), 00097 maxValue(""), 00098 comp(TrueLexicalComparison) 00099 {} 00100 */ 00101 00103 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const std::string& defaultValue, const std::string& minValue, const std::string& maxValue, LexicalComparison comp): 00104 name(name), 00105 doc(doc), 00106 defaultValue(defaultValue), 00107 minValue(minValue), 00108 maxValue(maxValue), 00109 comp(comp) 00110 {} 00111 00113 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const std::string& defaultValue): 00114 name(name), 00115 doc(doc), 00116 defaultValue(boost::lexical_cast<string>(defaultValue)), 00117 minValue(""), 00118 maxValue(""), 00119 comp(FalseLexicalComparison) 00120 {} 00121 00123 Parametrizable::ParametersDoc::ParametersDoc(std::initializer_list<ParameterDoc> list): 00124 std::vector<ParameterDoc>(list) 00125 {} 00126 00128 Parametrizable::ParametersDoc::ParametersDoc() 00129 {} 00130 00131 /* 00132 Again, not used because fo gcc bug 9050 00133 00134 template<typename S> 00135 Parametrizable::Parameter::Parameter(const S value): 00136 std::string(boost::lexical_cast<string>(value)) 00137 {} 00138 00139 // force instantiation of constructors 00140 template Parametrizable::ParameterDoc::ParameterDoc<int>(const std::string, const std::string, const int); 00141 template Parametrizable::ParameterDoc::ParameterDoc<float>(const std::string, const std::string, const float); 00142 template Parametrizable::ParameterDoc::ParameterDoc<double>(const std::string, const std::string, const double); 00143 template Parametrizable::ParameterDoc::ParameterDoc<bool>(const std::string, const std::string, const bool); 00144 template Parametrizable::ParameterDoc::ParameterDoc<std::string>(const std::string, const std::string, const std::string); 00145 template Parametrizable::ParameterDoc::ParameterDoc<const char*>(const std::string, const std::string, const char*); 00146 00147 template Parametrizable::ParameterDoc::ParameterDoc<int>(const std::string, const std::string, const int, const int, const int); 00148 template Parametrizable::ParameterDoc::ParameterDoc<float>(const std::string, const std::string, const float, const float, const float); 00149 template Parametrizable::ParameterDoc::ParameterDoc<double>(const std::string, const std::string, const double, const double, const double); 00150 00151 template Parametrizable::Parameter::Parameter<int>(const int); 00152 template Parametrizable::Parameter::Parameter<float>(const float); 00153 template Parametrizable::Parameter::Parameter<double>(const double); 00154 template Parametrizable::Parameter::Parameter<bool>(const bool); 00155 template Parametrizable::Parameter::Parameter<std::string>(const std::string); 00156 00157 */ 00158 00160 Parametrizable::Parametrizable(): 00161 className("unknown") 00162 {} 00163 00165 Parametrizable::Parametrizable( 00166 const std::string& className, const ParametersDoc paramsDoc, const Parameters& params): 00167 className(className), 00168 parametersDoc(paramsDoc) 00169 { 00170 // fill current parameters from either values passed as argument, or default value 00171 for (auto it = parametersDoc.cbegin(); it != parametersDoc.cend(); ++it) 00172 { 00173 const string& paramName(it->name); 00174 Parameters::const_iterator paramIt(params.find(paramName)); 00175 if (paramIt != params.end()) 00176 { 00177 const string& val(paramIt->second); 00178 if (it->comp(val, it->minValue)) 00179 throw InvalidParameter((boost::format("Value %1% of parameter %2% in class %3% is smaller than minimum admissible value %4%") % val % paramName % className % it->minValue).str()); 00180 if (it->comp(it->maxValue, val)) 00181 throw InvalidParameter((boost::format("Value %1% of parameter %2% in class %3% is larger than maximum admissible value %4%") % val % paramName % className % it->maxValue).str()); 00182 parameters[paramName] = val; 00183 } 00184 else 00185 parameters[paramName] = it->defaultValue; 00186 } 00187 } 00188 00190 Parametrizable::~Parametrizable() 00191 {} 00192 00194 std::string Parametrizable::getParamValueString(const std::string& paramName) 00195 { 00196 Parameters::const_iterator paramIt(parameters.find(paramName)); 00197 if (paramIt == parameters.end()) 00198 throw InvalidParameter((boost::format("Parameter %1% does not exist in class %2%") % paramName % className).str()); 00199 // TODO: use string distance to propose close one, copy/paste code from Aseba 00200 this->parametersUsed.insert(paramIt->first); 00201 return paramIt->second; 00202 } 00203 } // namespace PointMatcherSupport