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