Go to the documentation of this file.00001
00002 #ifndef CANOPEN_MOTOR_NODE_UNIT_CONVERTER_H_
00003 #define CANOPEN_MOTOR_NODE_UNIT_CONVERTER_H_
00004
00005 #include <string>
00006 #include <list>
00007 #include <boost/function.hpp>
00008 #include <boost/shared_ptr.hpp>
00009 #include "muParser.h"
00010 #include <boost/math/special_functions/fpclassify.hpp>
00011
00012 namespace canopen {
00013 class UnitConverter{
00014 public:
00015 typedef boost::function<double * (const std::string &) > get_var_func_type;
00016
00017 UnitConverter(const std::string &expression, get_var_func_type var_func)
00018 : var_func_(var_func)
00019 {
00020 parser_.SetVarFactory(UnitConverter::createVariable, this);
00021
00022 parser_.DefineConst("pi", M_PI);
00023 parser_.DefineConst("nan", std::numeric_limits<double>::quiet_NaN());
00024
00025 parser_.DefineFun("rad2deg", UnitConverter::rad2deg);
00026 parser_.DefineFun("deg2rad", UnitConverter::deg2rad);
00027 parser_.DefineFun("norm", UnitConverter::norm);
00028 parser_.DefineFun("smooth", UnitConverter::smooth);
00029 parser_.DefineFun("avg", UnitConverter::avg);
00030
00031 parser_.SetExpr(expression);
00032 }
00033
00034 void reset(){
00035 for(variable_ptr_list::iterator it = var_list_.begin(); it != var_list_.end(); ++it){
00036 **it = std::numeric_limits<double>::quiet_NaN();
00037 }
00038 }
00039 double evaluate() { int num; return parser_.Eval(num)[0]; }
00040 private:
00041 typedef boost::shared_ptr<double> variable_ptr;
00042 typedef std::list<variable_ptr> variable_ptr_list;
00043
00044 static double* createVariable(const char *name, void * userdata) {
00045 UnitConverter * uc = static_cast<UnitConverter*>(userdata);
00046 double *p = uc->var_func_ ? uc->var_func_(name) : 0;
00047 if(!p){
00048 p = new double(std::numeric_limits<double>::quiet_NaN());
00049 uc->var_list_.push_back(variable_ptr(p));
00050 }
00051 return p;
00052 }
00053 variable_ptr_list var_list_;
00054 get_var_func_type var_func_;
00055
00056 mu::Parser parser_;
00057
00058 static double rad2deg(double r){
00059 return r*180.0/M_PI;
00060 }
00061 static double deg2rad(double d){
00062 return d*M_PI/180.0;
00063 }
00064 static double norm(double val, double min, double max){
00065 while(val >= max) val -= (max-min);
00066 while(val < min) val += (max-min);
00067 return val;
00068 }
00069 static double smooth(double val, double old_val, double alpha){
00070 if(boost::math::isnan(val)) return 0;
00071 if(boost::math::isnan(old_val)) return val;
00072 return alpha*val + (1.0-alpha)*old_val;
00073 }
00074 static double avg(const double *vals, int num)
00075 {
00076 double s = 0.0;
00077 int i=0;
00078 for (; i<num; ++i){
00079 const double &val = vals[i];
00080 if(boost::math::isnan(val)) break;
00081 s += val;
00082 }
00083 return s / double(i+1);
00084 }
00085 };
00086
00087 }
00088
00089 #endif