xml_calibration_parser.cpp
Go to the documentation of this file.
00001 
00038 //ROS include
00039 #include <ros/ros.h>
00040 
00041 #include "cyberglove/xml_calibration_parser.h"
00042 
00043 #include <stdio.h>
00044 
00045 namespace xml_calibration_parser{
00046 
00047   const float XmlCalibrationParser::lookup_precision = 1000.0f;
00048   const float XmlCalibrationParser::lookup_offset = 1.0f;
00049 
00058   XmlCalibrationParser::XmlCalibrationParser(std::string path_to_calibration)
00059   {
00060     TiXmlDocument doc(path_to_calibration.c_str());
00061     bool loadOkay = doc.LoadFile();
00062     if (loadOkay)
00063       {
00064         ROS_DEBUG("loading calibration %s", path_to_calibration.c_str());
00065         parse_calibration_file( doc.RootElement() );
00066 
00067         build_calibration_table();
00068       }
00069     else
00070       {
00071         ROS_ERROR("Failed to load file \"%s\"", path_to_calibration.c_str());
00072       }
00073   }
00074 
00082   void XmlCalibrationParser::parse_calibration_file( TiXmlNode* pParent )
00083   {
00084     if ( !pParent ) return;
00085 
00086     TiXmlElement* child = pParent->FirstChildElement("Joint");
00087 
00088     //no Joint elements => error
00089     if( !child )
00090       {
00091         ROS_ERROR( "The calibration file seems to be broken: there's no Joint elements." );
00092         return;
00093       }
00094 
00095     bool has_sibling = true;
00096     while( has_sibling )
00097       {
00098         // a Joint element was found
00099         XmlCalibrationParser::JointCalibration joint_calib;
00100         joint_calib.name = child->Attribute("name");
00101 
00102         joint_calib.calibrations = parse_joint_attributes(child);
00103 
00104         jointsCalibrations.push_back(joint_calib);
00105 
00106         //get the next Joint element
00107         child = child->NextSiblingElement("Joint");
00108         //no more Joint elements => stop
00109         if( !child )
00110             has_sibling = false;
00111       }
00112   }
00113 
00121   std::vector<XmlCalibrationParser::Calibration>
00122   XmlCalibrationParser::parse_joint_attributes( TiXmlNode* pParent )
00123   {
00124     std::vector<XmlCalibrationParser::Calibration> calibrations;
00125 
00126     TiXmlElement* child = pParent->FirstChildElement("calib");
00127 
00128     //no Joint elements => error
00129     if( !child )
00130       {
00131         ROS_ERROR( "The calibration file seems to be broken: there's no calibration elements." );
00132         return calibrations;
00133       }
00134     bool has_sibling = true;
00135 
00136     while( has_sibling )
00137       {
00138         // a Joint element was found
00139         XmlCalibrationParser::Calibration calib;
00140         float fval;
00141 
00142         // get the raw-value
00143         if( child->QueryFloatAttribute("raw_value", &fval) == TIXML_SUCCESS )
00144           calib.raw_value = fval;
00145         else
00146           ROS_ERROR("The calibration file seems to be broken: there's no raw_value attribute.");
00147 
00148         //get the calibrated-value
00149         if( child->QueryFloatAttribute("calibrated_value", &fval) == TIXML_SUCCESS )
00150           calib.calibrated_value = fval;
00151         else
00152           ROS_ERROR("The calibration file seems to be broken: there's no calibrated_value attribute.");
00153 
00154         //add the calibration to the vector
00155         calibrations.push_back( calib );
00156 
00157         //get the next Joint element
00158         child = child->NextSiblingElement("calib");
00159         //no more Joint elements => stop
00160         if( !child )
00161             has_sibling = false;
00162       }
00163 
00164     return calibrations;
00165   }
00166 
00167 
00175   int XmlCalibrationParser::build_calibration_table()
00176   {
00177     for (unsigned int index_calib = 0; index_calib < jointsCalibrations.size(); ++index_calib)
00178     {
00179       std::string name = jointsCalibrations[index_calib].name;
00180       std::cout << name << std::endl;
00181 
00182       std::vector<Calibration> calib = jointsCalibrations[index_calib].calibrations;
00183 
00184       std::vector<float> lookup_table((int)lookup_offset*(int)lookup_precision);
00185 
00186       if( calib.size() < 2 )
00187         ROS_ERROR("Not enough points were defined to set up the calibration.");
00188 
00189       //order the calibration vector by ascending values of raw_value
00190       //      ROS_ERROR("TODO: calibration vector not ordered yet");
00191 
00192       std::cout << "lookup table : ";
00193 
00194       //setup the lookup table
00195       for( unsigned int index_lookup = 0;
00196            index_lookup < lookup_table.size() ;
00197            ++ index_lookup )
00198         {
00199           float value = compute_lookup_value(index_lookup, calib);
00200           std::cout << index_lookup<<":"<<value << " ";
00201           lookup_table[index_lookup] = value;
00202         }
00203 
00204       std::cout << std::endl;
00205 
00206       //add the values to the map
00207       joints_calibrations_map[name] = lookup_table;
00208       //joints_calibrations_map.insert(std::pair <std::string, std::vector<float> >(name, lookup_table));
00209     }
00210 
00211     return 0;
00212   }
00213 
00225   float XmlCalibrationParser::compute_lookup_value(int index, std::vector<XmlCalibrationParser::Calibration> calib)
00226   {
00227     float raw_pos = return_raw_position_from_index(index);
00228 
00229     if(calib.size() == 2)
00230       return linear_interpolate( raw_pos,
00231                                  calib[0].raw_value,
00232                                  calib[0].calibrated_value,
00233                                  calib[1].raw_value,
00234                                  calib[1].calibrated_value
00235                              );
00236 
00237 
00238     for( unsigned int index_calib = 0; index_calib < calib.size() - 1;
00239          ++index_calib)
00240       {
00241         if(calib[index_calib].raw_value > raw_pos)
00242           {
00243             return linear_interpolate( raw_pos,
00244                                        calib[index_calib].raw_value,
00245                                        calib[index_calib].calibrated_value,
00246                                        calib[index_calib+1].raw_value,
00247                                        calib[index_calib+1].calibrated_value
00248                                      );
00249           }
00250       }
00251 
00252     //bigger than last calibrated value => extrapolate the value from
00253     //last 2 values
00254     //TODO: ca marche la formule si on est en dehors des points ? oui
00255     return linear_interpolate( raw_pos,
00256                                calib[calib.size()-1].raw_value,
00257                                calib[calib.size()-1].calibrated_value,
00258                                calib[calib.size()].raw_value,
00259                                calib[calib.size()].calibrated_value
00260                              );
00261 
00262   }
00263 
00264   float XmlCalibrationParser::get_calibration_value(float position, std::string joint_name)
00265   {
00266     mapType::iterator iter = joints_calibrations_map.find(joint_name);
00267 
00268     if( iter != joints_calibrations_map.end() )
00269       {
00270         //reads from the lookup table
00271         int index = return_index_from_raw_position(position);
00272         std::cout << index << std::endl;
00273         return iter->second[index];
00274       }
00275     else
00276       {
00277         ROS_ERROR("%s is not calibrated", joint_name.c_str());
00278         return 1.0f;
00279       }
00280   }
00281 
00282   float XmlCalibrationParser::linear_interpolate( float x ,
00283                                                   float x0, float y0,
00284                                                   float x1, float y1 )
00285   {
00286 
00287     //TODO ca marche qd c'est decroissant ca? oui
00288     float y = 0.0f;
00289     if( x1 - x0 == 0.0f )
00290       {
00291         ROS_WARN("Bad calibration: raw_calib[1] = raw_calib[0]");
00292         return 0.0f;
00293       }
00294 
00295     y = y0 + (x-x0)* ((y1-y0)/(x1-x0));
00296     return y;
00297   }
00298 
00299 
00300   int XmlCalibrationParser::return_index_from_raw_position(float raw_position)
00301   {
00302     if (raw_position < 0.0f)
00303       return 0;
00304     if(raw_position > 1.0f)
00305       return lookup_precision;
00306     return round(raw_position * lookup_precision);
00307   };
00308 
00309   int XmlCalibrationParser::round(float number)
00310   {
00311     //we only have positive numbers
00312     return (int)floor(number + 0.5);
00313     //return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
00314   }
00315 
00316 
00317   std::vector<XmlCalibrationParser::JointCalibration> XmlCalibrationParser::getJointsCalibrations()
00318   {
00319     return jointsCalibrations;
00320   }
00321 }//end namespace


cyberglove
Author(s): Ugo Cupcic
autogenerated on Fri Jan 3 2014 12:04:16