sr_friction_compensation.cpp
Go to the documentation of this file.
00001 
00026 #include "sr_mechanism_controllers/sr_friction_compensation.hpp"
00027 
00028 #include <sstream>
00029 #include <math.h>
00030 #include "sr_utilities/sr_math_utils.hpp"
00031 #include "sr_utilities/sr_deadband.hpp"
00032 
00033 using namespace std;
00034 
00035 namespace sr_friction_compensation
00036 {
00037 const double SrFrictionCompensator::velocity_for_static_friction = 0.01;
00038 
00039 SrFrictionCompensator::SrFrictionCompensator(const string &joint_name) :
00040   joint_name_(joint_name)
00041 {
00042   pair<vector<joint_calibration::Point>, vector<joint_calibration::Point> > both_maps = read_friction_map();
00043   friction_interpoler_forward.reset(new shadow_robot::JointCalibration(both_maps.first));
00044   friction_interpoler_backward.reset(new shadow_robot::JointCalibration(both_maps.second));
00045 }
00046 
00047 SrFrictionCompensator::~SrFrictionCompensator()
00048 {
00049 }
00050 
00051 double SrFrictionCompensator::friction_compensation(double position, double velocity, int force_demand, int deadband)
00052 {
00053   double compensation = 0.0;
00054 
00055   if (force_demand > 0.0)
00056     compensation = friction_interpoler_forward->compute(position);
00057   else
00058     compensation = friction_interpoler_backward->compute(position);
00059 
00060   //A value by which we'll multiply the compensation computed by the
00061   // friction map.
00062   double mult = 1.0;
00063   //we're out of the "finger is stopped" zone ->
00064   //   progressively decrease the amount of compensation
00065   if (fabs(velocity) > velocity_for_static_friction)
00066   {
00067     if (velocity < 0.0)
00068       mult = exp(-fabs(velocity + velocity_for_static_friction)*20);
00069     else
00070       mult = exp(-fabs(velocity - velocity_for_static_friction)*20);
00071   }
00072 
00073   //decrease the compensation around the force sign change
00074   // to have less discontinuity. Use the deadband for this.
00075   if (abs(force_demand) < deadband)
00076   {
00077     //we want the multiplier to be 1 if force_demand = deadband
00078     // and 0 if force_demand = 0
00079     mult *= sr_math_utils::linear_interpolate_(static_cast<double> (abs(force_demand)),
00080                                                0.0, 0.0,
00081                                                static_cast<double> (deadband), 1.0);
00082   }
00083 
00084   //amend the compensation value
00085   compensation *= mult;
00086 
00087   return compensation;
00088 }
00089 
00090 pair<vector<joint_calibration::Point>, vector<joint_calibration::Point> > SrFrictionCompensator::read_friction_map()
00091 {
00092   vector<joint_calibration::Point> friction_map_forward, friction_map_backward;
00093   string param_name = "/sr_friction_map";
00094 
00095   bool joint_not_found_forward = true;
00096   bool joint_not_found_backward = true;
00097 
00098   XmlRpc::XmlRpcValue calib;
00099   if (node_.hasParam(param_name))
00100   {
00101     node_.getParam(param_name, calib);
00102 
00103     ROS_DEBUG_STREAM("  Reading friction for: " << joint_name_);
00104     ROS_DEBUG_STREAM(" value: " << calib);
00105 
00106     ROS_ASSERT(calib.getType() == XmlRpc::XmlRpcValue::TypeArray);
00107     //iterate on all the joints
00108     for (int32_t index_cal = 0; index_cal < calib.size(); ++index_cal)
00109     {
00110       //check the calibration is well formatted:
00111       // first joint name, then calibration table
00112       ROS_ASSERT(calib[index_cal][0].getType() == XmlRpc::XmlRpcValue::TypeString);
00113       ROS_ASSERT(calib[index_cal][1].getType() == XmlRpc::XmlRpcValue::TypeInt);
00114       ROS_ASSERT(calib[index_cal][2].getType() == XmlRpc::XmlRpcValue::TypeArray);
00115 
00116       string joint_name_tmp = static_cast<string> (calib[index_cal][0]);
00117 
00118       ROS_DEBUG_STREAM("  Checking joint name: " << joint_name_tmp << " / " << joint_name_);
00119       if (joint_name_tmp.compare(joint_name_) != 0)
00120         continue;
00121 
00122       //reading the forward map:
00123       if (static_cast<int> (calib[index_cal][1]) == 1)
00124       {
00125         joint_not_found_forward = false;
00126 
00127         friction_map_forward = read_one_way_map(calib[index_cal][2]);
00128       }
00129       else
00130       {
00131         joint_not_found_backward = false;
00132 
00133         friction_map_backward = read_one_way_map(calib[index_cal][2]);
00134       }
00135     }
00136   }
00137 
00138   if (joint_not_found_forward)
00139   {
00140     ROS_INFO_STREAM("  No forward  friction compensation map for: " << joint_name_);
00141 
00142     friction_map_forward = generate_flat_map();
00143   }
00144 
00145   if (joint_not_found_backward)
00146   {
00147     ROS_INFO_STREAM("  No backward friction compensation map for: " << joint_name_);
00148 
00149     friction_map_backward = generate_flat_map();
00150   }
00151 
00152   /*
00153     ROS_INFO_STREAM(" Friction map forward: [" << joint_name_ << "]");
00154     for( unsigned int i=0; i<friction_map_forward.size(); ++i )
00155     ROS_INFO_STREAM("    -> position=" << friction_map_forward[i].raw_value << " compensation: " << friction_map_forward[i].calibrated_value);
00156     ROS_INFO_STREAM(" Friction map backward: [" << joint_name_ << "]");
00157     for( unsigned int i=0; i<friction_map_backward.size(); ++i )
00158     ROS_INFO_STREAM("    -> position=" << friction_map_backward[i].raw_value << " compensation: " << friction_map_backward[i].calibrated_value);
00159    */
00160 
00161   pair<vector<joint_calibration::Point>, vector<joint_calibration::Point> > both_maps;
00162   both_maps.first = friction_map_forward;
00163   both_maps.second = friction_map_backward;
00164 
00165   return both_maps;
00166 } //end read_friction_map
00167 
00168 vector<joint_calibration::Point> SrFrictionCompensator::read_one_way_map(XmlRpc::XmlRpcValue &raw_map)
00169 {
00170   vector<joint_calibration::Point> friction_map;
00171 
00172   //now iterates on the calibration table for the current joint
00173   for (int32_t index_table = 0; index_table < raw_map.size(); ++index_table)
00174   {
00175     ROS_ASSERT(raw_map[index_table].getType() == XmlRpc::XmlRpcValue::TypeArray);
00176     //only 2 values per calibration point: raw and calibrated (doubles)
00177     ROS_ASSERT(raw_map[index_table].size() == 2);
00178     ROS_ASSERT(raw_map[index_table][0].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00179     ROS_ASSERT(raw_map[index_table][1].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00180 
00181 
00182     joint_calibration::Point point_tmp;
00183     point_tmp.raw_value = sr_math_utils::to_rad(static_cast<double> (raw_map[index_table][0]));
00184     point_tmp.calibrated_value = static_cast<double> (raw_map[index_table][1]);
00185     friction_map.push_back(point_tmp);
00186   }
00187 
00188   return friction_map;
00189 }
00190 
00191 vector<joint_calibration::Point> SrFrictionCompensator::generate_flat_map()
00192 {
00193   vector<joint_calibration::Point> friction_map;
00194 
00195   joint_calibration::Point point_tmp;
00196   point_tmp.raw_value = 0.0;
00197   point_tmp.calibrated_value = 0.0;
00198   friction_map.push_back(point_tmp);
00199   point_tmp.raw_value = 1.0;
00200   friction_map.push_back(point_tmp);
00201 
00202   return friction_map;
00203 }
00204 }
00205 
00206 
00207 
00208 /* For the emacs weenies in the crowd.
00209    Local Variables:
00210    c-basic-offset: 2
00211    End:
00212  */
00213 
00214 


sr_mechanism_controllers
Author(s): Ugo Cupcic
autogenerated on Fri Aug 21 2015 12:26:14