00001
00038
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
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
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
00107 child = child->NextSiblingElement("Joint");
00108
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
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
00139 XmlCalibrationParser::Calibration calib;
00140 float fval;
00141
00142
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
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
00155 calibrations.push_back( calib );
00156
00157
00158 child = child->NextSiblingElement("calib");
00159
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
00190
00191
00192 std::cout << "lookup table : ";
00193
00194
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
00207 joints_calibrations_map[name] = lookup_table;
00208
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
00253
00254
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
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
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
00312 return (int)floor(number + 0.5);
00313
00314 }
00315
00316
00317 std::vector<XmlCalibrationParser::JointCalibration> XmlCalibrationParser::getJointsCalibrations()
00318 {
00319 return jointsCalibrations;
00320 }
00321 }