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 #include <boost/typeof/typeof.hpp> 00039 00040 namespace PointMatcherSupport 00041 { 00042 using namespace std; 00043 00045 Parametrizable::InvalidParameter::InvalidParameter(const std::string& reason): 00046 runtime_error(reason) 00047 {} 00048 00050 std::ostream& operator<< (std::ostream& o, const Parametrizable::ParameterDoc& p) 00051 { 00052 o << p.name << " (default: " << p.defaultValue << ") - " << p.doc; 00053 if (!p.minValue.empty()) 00054 o << " - min: " << p.minValue; 00055 if (!p.maxValue.empty()) 00056 o << " - max: " << p.maxValue; 00057 return o; 00058 } 00059 00061 std::ostream& operator<< (std::ostream& o, const Parametrizable& p) 00062 { 00063 o << p.parametersDoc; 00064 return o; 00065 } 00066 00068 std::ostream& operator<< (std::ostream& o, const Parametrizable::ParametersDoc& p) 00069 { 00070 for (BOOST_AUTO(it,p.begin()); it != p.end(); ++it) 00071 o << "- " << *it << endl; 00072 return o; 00073 } 00074 00076 bool FalseLexicalComparison(std::string, std::string) 00077 { 00078 return false; 00079 } 00080 00081 /*template<typename S> 00082 bool ScalarLexicalComparison(std::string a, std::string b) 00083 { 00084 return boost::lexical_cast<S>(a) < boost::lexical_cast<S>(b); 00085 } 00086 00087 Uncomment once most people have gcc >= 4.5 00088 Shame on bug 9050 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9050) 00089 template<typename S> 00090 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const S defaultValue, const S minValue, const S maxValue): 00091 name(name), 00092 doc(doc), 00093 defaultValue(boost::lexical_cast<string>(defaultValue)), 00094 minValue(boost::lexical_cast<string>(minValue)), 00095 maxValue(boost::lexical_cast<string>(maxValue)), 00096 comp(ScalarLexicalComparison<S>) 00097 {} 00098 00099 template<typename S> 00100 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const S defaultValue): 00101 name(name), 00102 doc(doc), 00103 defaultValue(boost::lexical_cast<string>(defaultValue)), 00104 minValue(""), 00105 maxValue(""), 00106 comp(TrueLexicalComparison) 00107 {} 00108 */ 00109 00111 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): 00112 name(name), 00113 doc(doc), 00114 defaultValue(defaultValue), 00115 minValue(minValue), 00116 maxValue(maxValue), 00117 comp(comp) 00118 {} 00119 00121 Parametrizable::ParameterDoc::ParameterDoc(const std::string& name, const std::string& doc, const std::string& defaultValue): 00122 name(name), 00123 doc(doc), 00124 defaultValue(boost::lexical_cast<string>(defaultValue)), 00125 minValue(""), 00126 maxValue(""), 00127 comp(FalseLexicalComparison) 00128 {} 00129 00131 /*ParametersDoc(const std::vector<ParameterDoc>& list): 00132 std::vector<ParameterDoc>(list) 00133 {}*/ 00134 00135 /* 00136 Again, not used because fo gcc bug 9050 00137 00138 template<typename S> 00139 Parametrizable::Parameter::Parameter(const S value): 00140 std::string(boost::lexical_cast<string>(value)) 00141 {} 00142 00143 // force instantiation of constructors 00144 template Parametrizable::ParameterDoc::ParameterDoc<int>(const std::string, const std::string, const int); 00145 template Parametrizable::ParameterDoc::ParameterDoc<float>(const std::string, const std::string, const float); 00146 template Parametrizable::ParameterDoc::ParameterDoc<double>(const std::string, const std::string, const double); 00147 template Parametrizable::ParameterDoc::ParameterDoc<bool>(const std::string, const std::string, const bool); 00148 template Parametrizable::ParameterDoc::ParameterDoc<std::string>(const std::string, const std::string, const std::string); 00149 template Parametrizable::ParameterDoc::ParameterDoc<const char*>(const std::string, const std::string, const char*); 00150 00151 template Parametrizable::ParameterDoc::ParameterDoc<int>(const std::string, const std::string, const int, const int, const int); 00152 template Parametrizable::ParameterDoc::ParameterDoc<float>(const std::string, const std::string, const float, const float, const float); 00153 template Parametrizable::ParameterDoc::ParameterDoc<double>(const std::string, const std::string, const double, const double, const double); 00154 00155 template Parametrizable::Parameter::Parameter<int>(const int); 00156 template Parametrizable::Parameter::Parameter<float>(const float); 00157 template Parametrizable::Parameter::Parameter<double>(const double); 00158 template Parametrizable::Parameter::Parameter<bool>(const bool); 00159 template Parametrizable::Parameter::Parameter<std::string>(const std::string); 00160 00161 */ 00162 00164 Parametrizable::Parametrizable(): 00165 className("unknown") 00166 {} 00167 00169 Parametrizable::Parametrizable( 00170 const std::string& className, const ParametersDoc paramsDoc, const Parameters& params): 00171 className(className), 00172 parametersDoc(paramsDoc) 00173 { 00174 // fill current parameters from either values passed as argument, or default value 00175 for (BOOST_AUTO(it, parametersDoc.begin()); it != parametersDoc.end(); ++it) 00176 { 00177 const string& paramName(it->name); 00178 Parameters::const_iterator paramIt(params.find(paramName)); 00179 if (paramIt != params.end()) 00180 { 00181 const string& val(paramIt->second); 00182 if (it->comp(val, it->minValue)) 00183 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()); 00184 if (it->comp(it->maxValue, val)) 00185 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()); 00186 parameters[paramName] = val; 00187 } 00188 else 00189 parameters[paramName] = it->defaultValue; 00190 } 00191 } 00192 00194 Parametrizable::~Parametrizable() 00195 {} 00196 00198 std::string Parametrizable::getParamValueString(const std::string& paramName) 00199 { 00200 Parameters::const_iterator paramIt(parameters.find(paramName)); 00201 if (paramIt == parameters.end()) 00202 throw InvalidParameter((boost::format("Parameter %1% does not exist in class %2%") % paramName % className).str()); 00203 // TODO: use string distance to propose close one, copy/paste code from Aseba 00204 this->parametersUsed.insert(paramIt->first); 00205 return paramIt->second; 00206 } 00207 } // namespace PointMatcherSupport