FingerController.h
Go to the documentation of this file.
00001 
00007 #ifndef FINGERCONTROLLER_H
00008 #define FINGERCONTROLLER_H
00009 
00010 #include "nasa_common_logging/Logger.h"
00011 #include <eigen3/Eigen/Dense>
00012 #include "robodyn_mechanisms/FingerKinematics.h"
00013 #include <boost/array.hpp>
00014 #include "robodyn_utilities/MultiLoopController.h"
00015 #include "robodyn_mechanisms/HallsToAngle.h"
00016 
00017 template<unsigned int N, unsigned int NHall = N>
00018 class FingerController
00019 {
00020 public:
00021     typedef typename FingerKinematics<N>::ReferenceMatrixType   ReferenceMatrixType;
00022     typedef typename FingerKinematics<N>::JointVectorType       JointVectorType;
00023     typedef typename FingerKinematics<N>::SliderVectorType      SliderVectorType;
00024     typedef typename FingerKinematics<N>::JacobianType          JacobianType;
00025     typedef Eigen::Matrix<double, NHall, 1> HallVectorType;
00026 
00027     typedef boost::array < MultiLoopController, N + 1 >              MultiLoopVectorType;
00028 
00029     FingerController();
00030     virtual ~FingerController() {}
00031 
00032     void setReferenceMatrix(const ReferenceMatrixType& refMatrix_in)
00033     {
00034         kinematics.setReferenceMatrix(refMatrix_in);
00035     }
00036 
00040     void reset();
00044     void getDesiredSliders(const JointVectorType& desiredJoints, const SliderVectorType& actualSliders, SliderVectorType& desiredSliders);
00048     void getDesiredSlidersStiffness(const JointVectorType& desiredPos, const JointVectorType& actualJoints, const SliderVectorType& actualSliders, const SliderVectorType& actualTensions, const SliderVectorType& sliderVelocities, const bool useCartesian, const bool isLeft, SliderVectorType& desiredSliders);
00052     void getMotComs(const SliderVectorType& desiredSliders, const SliderVectorType& kTendon, const SliderVectorType& actualSliders, const SliderVectorType& actualTensions, const SliderVectorType& sliderVelocities, SliderVectorType& sliderMotComs, SliderVectorType& desiredSliderVels, const SliderVectorType& fingerBoostMotCom);
00053 
00054     // set parameters
00055     void setMillimetersPerCount(double mmPerCount_in) {mmPerCount = mmPerCount_in;}
00056     void setHallAngleParameters(double scale, const HallVectorType& coeffs0, const HallVectorType& coeffs1, const HallVectorType& coeffs2, const HallVectorType& coeffs3);
00057     void setTensionParameters(const SliderVectorType& aGains, const SliderVectorType& bGains, const SliderVectorType& offsets, const SliderVectorType& calibratedStrain_in);
00065     void setTubeTareParameters(const SliderVectorType& sliderOffsets_in,
00066                                const SliderVectorType& sliderTarePos_in, const SliderVectorType& tensionOffsets_in);
00067     void setStiffnessGains(const JointVectorType& K_in, const double kd_in, const double fmin_in, const double fmax_in, const JointVectorType& jointKp_in, const double tensionKp_in, const double tFreq, const double deadband_in);
00068     void setMultiLoopController(const MultiLoopController& mlc_in, unsigned int controllerIndex);
00069     void setBusVoltage(double busVoltage_in) {busVoltage = busVoltage_in;}
00070 
00071     void getHallAngles(const HallVectorType& halls_in, HallVectorType& jointAngles);
00072     void getCalibratedTensions(const SliderVectorType& tensionA, const SliderVectorType& tensionB, double timestep, SliderVectorType& tensionsCalibrated);
00073     void getXYPos(const JointVectorType& jointAngles, const bool isLeft, JointVectorType& xy, JointVectorType& desiredTorques);
00074 
00075     inline void getSlidersFromJoints(const JointVectorType& jointAngles, SliderVectorType& sliderPositions)
00076     {
00077         kinematics.inverse(jointAngles, sliderPositions);
00078     }
00079 
00080     inline void getSlidersFromEncoders(const SliderVectorType& encoderPositions, SliderVectorType& sliderPositions)
00081     {
00082         sliderPositions = ((encoderPositions - sliderOffsets) * mmPerCount + sliderTarePos) ;
00083     }
00084 
00085     inline void getJointsFromSliders(const SliderVectorType& sliderPositions, JointVectorType& jointAngles)
00086     {
00087         kinematics.forward(sliderPositions, jointAngles);
00088     }
00089 
00090 private:
00091     FingerKinematics<N> kinematics;
00092     double              mmPerCount;
00093     double              hallScale;
00094     HallVectorType      hallCoeffs0;
00095     HallVectorType      hallCoeffs1;
00096     HallVectorType      hallCoeffs2;
00097     HallVectorType      hallCoeffs3;
00098     SliderVectorType    tensionAGains;
00099     SliderVectorType    tensionBGains;
00100     SliderVectorType    tensionSensorCalOffsets;
00101     SliderVectorType    calibratedStrain;
00102     SliderVectorType    sliderOffsets;
00103     SliderVectorType    sliderTarePos;
00104     SliderVectorType    tensionOffsets;
00105     MultiLoopVectorType multiLoopControllers;
00106     double              smoothingHz;
00107     SliderVectorType    smoothingFactors;
00108     double              busVoltage;
00109     JointVectorType     K;
00110     double              kd;
00111     double              fmin;
00112     double              fmax;
00113     JointVectorType     jointKp;
00114     double              tensionKp;
00115     SliderVectorType    tensionsPrev;
00116     double              tensionFilterCutoffFreq;
00117     double              deadbandSize;
00118     JointVectorType     desTorques;
00119 };
00120 
00121 template<unsigned int N, unsigned int NHall>
00122 FingerController<N, NHall>::FingerController()
00123     : mmPerCount(0.0174427)
00124     , hallScale(0.)
00125     , hallCoeffs0(HallVectorType::Zero())
00126     , hallCoeffs1(HallVectorType::Zero())
00127     , hallCoeffs2(HallVectorType::Zero())
00128     , hallCoeffs3(HallVectorType::Zero())
00129     , tensionAGains(SliderVectorType::Zero())
00130     , tensionBGains(SliderVectorType::Zero())
00131     , tensionSensorCalOffsets(SliderVectorType::Zero())
00132     , calibratedStrain(SliderVectorType::Zero())
00133     , sliderOffsets(SliderVectorType::Zero())
00134     , sliderTarePos(SliderVectorType::Zero())
00135     , tensionOffsets(SliderVectorType::Zero())
00136     , busVoltage(48)
00137     , K(JointVectorType::Zero())
00138     , kd(0.01)
00139     , fmin(1.0)
00140     , fmax(15.0)
00141     , jointKp(JointVectorType::Zero())
00142     , tensionKp(0.003)
00143     , tensionsPrev(SliderVectorType::Zero())
00144     , tensionFilterCutoffFreq(20.)
00145     , deadbandSize(0.5)
00146     , desTorques(JointVectorType::Zero())
00147 {
00148     reset();
00149 }
00150 
00151 template<unsigned int N, unsigned int NHall>
00152 void FingerController<N, NHall>::setHallAngleParameters(double scale, const HallVectorType& coeffs0, const HallVectorType& coeffs1, const HallVectorType& coeffs2, const HallVectorType& coeffs3)
00153 {
00154     hallScale = scale;
00155     hallCoeffs0 = coeffs0;
00156     hallCoeffs1 = coeffs1;
00157     hallCoeffs2 = coeffs2;
00158     hallCoeffs3 = coeffs3;
00159 }
00160 
00161 template<unsigned int N, unsigned int NHall>
00162 void FingerController<N, NHall>::setTensionParameters(const SliderVectorType& aGains, const SliderVectorType& bGains, const SliderVectorType& offsets, const SliderVectorType& calibratedStrain_in)
00163 {
00164     tensionAGains = aGains;
00165     tensionBGains = bGains;
00166     tensionSensorCalOffsets = offsets;
00167     calibratedStrain = calibratedStrain_in;
00168 }
00169 
00170 template<unsigned int N, unsigned int NHall>
00171 void FingerController<N, NHall>::setTubeTareParameters(const SliderVectorType& sliderOffsets_in,
00172         const SliderVectorType& sliderTarePos_in, const SliderVectorType& tensionOffsets_in)
00173 {
00174     sliderOffsets = sliderOffsets_in;
00175     tensionOffsets = tensionOffsets_in;
00176 
00178     double roundedSlider;
00179 
00180     for (unsigned int i = 0; i < sliderTarePos_in.size(); ++i)
00181     {
00182         roundedSlider = fmod(sliderTarePos_in[i], mmPerCount);
00183 
00184         if (roundedSlider < 0.5)
00185         {
00186             roundedSlider = sliderTarePos_in[i] - roundedSlider;
00187         }
00188         else
00189         {
00190             roundedSlider = sliderTarePos_in[i] + mmPerCount - roundedSlider;
00191         }
00192 
00193         sliderTarePos[i] = roundedSlider;
00194     }
00195 
00196 }
00197 
00198 template<unsigned int N, unsigned int NHall>
00199 void FingerController<N, NHall>::setMultiLoopController(const MultiLoopController& mlc_in, unsigned int controllerIndex)
00200 {
00201     if (controllerIndex > N)
00202     {
00203         std::stringstream err;
00204         err << "setMultiLoopController() controllerIndex out of range" << std::endl;
00205         NasaCommonLogging::Logger::log("gov.nasa.controllers.FingerController", log4cpp::Priority::ERROR, err.str());
00206         throw std::runtime_error(err.str());
00207         return;
00208     }
00209 
00210     multiLoopControllers[controllerIndex] = mlc_in;
00211 }
00212 
00213 template<unsigned int N, unsigned int NHall>
00214 void FingerController<N, NHall>::setStiffnessGains(const JointVectorType& K_in, const double kd_in, const double fmin_in, const double fmax_in, const JointVectorType& jointKp_in, const double tensionKp_in, const double tFreq, const double deadband_in)
00215 {
00216     K = K_in;
00217     kd = kd_in;
00218     fmin = fmin_in;
00219     fmax = fmax_in;
00220     jointKp = jointKp_in;
00221     tensionKp = tensionKp_in;
00222     tensionFilterCutoffFreq = tFreq;
00223     deadbandSize = deadband_in;
00224 }
00225 
00226 template<unsigned int N, unsigned int NHall>
00227 void FingerController<N, NHall>::reset()
00228 {
00229     for (unsigned int i = 0; i < multiLoopControllers.size(); ++i)
00230     {
00231         multiLoopControllers[i].reset();
00232     }
00233 }
00234 
00235 
00236 //Position control
00237 template<unsigned int N, unsigned int NHall>
00238 void FingerController<N, NHall>::getDesiredSliders(const JointVectorType& desiredJoints, const SliderVectorType& actualSliders, SliderVectorType& desiredSliders)
00239 {
00240     SliderVectorType rsSliders;
00241     getSlidersFromJoints(desiredJoints, desiredSliders);
00242 
00243     // limit desired
00244     kinematics.projectToRangeSpace(actualSliders, rsSliders);
00245 
00246     for (int i = 0; i < desiredSliders.rows(); ++i)
00247     {
00249         if (desiredSliders[i] > rsSliders[i] + 2.54)
00250         {
00251             desiredSliders[i] = rsSliders[i] + 2.54;
00252         }
00253         else if (desiredSliders[i] < rsSliders[i] - 2.54)
00254         {
00255             desiredSliders[i] = rsSliders[i] - 2.54;
00256         }
00257     }
00258 }
00259 
00260 //Stiffness Control
00261 template<unsigned int N, unsigned int NHall>
00262 void FingerController<N, NHall>::getDesiredSlidersStiffness(const JointVectorType& desiredPos, const JointVectorType& actualJoints, const SliderVectorType& actualSliders, const SliderVectorType& actualTensions, const SliderVectorType& sliderVelocities, const bool useCartesian, const bool isLeft, SliderVectorType& desiredSliders)
00263 {
00264     //Needed variables -> K, kd, fmin, fmax, jointKp, tensionKp
00265 
00266     //find actual torques from tension sensors
00267     JointVectorType actualTorques;
00268     kinematics.tensionToJointTorque(actualTensions, actualTorques);
00269 
00270     JointVectorType desiredTorques;
00271 
00272     if (useCartesian && actualSliders.rows() >= 4)      //limits operation to thumb and primaries (secondaries only have 3 sliders/actuators)
00273     {
00274         //find current XY position
00275         JointVectorType xyActual;
00276         kinematics.jointToCartesian(actualJoints, isLeft, xyActual);
00277 
00278         //calculate Jacobian
00279         JacobianType jacobian;
00280         kinematics.calcJacobian(actualJoints, xyActual, isLeft, jacobian);
00281 
00282         //limit desired positions to be within reach
00283         JointVectorType desiredForces = desiredPos;
00284 
00285         if (desiredForces.rows() == 3) //limit primary fingers
00286         {
00287             if (desiredForces[2] < 0)
00288             {
00289                 desiredForces[2] = 0;
00290             }
00291 
00292             double dist = sqrt(desiredForces[1] * desiredForces[1] + desiredForces[2] * desiredForces[2]);
00293 
00294             if (dist > 90.0)
00295             {
00296                 desiredForces.tail(2) *= 90.0 / dist;
00297             }
00298         }
00299 
00300         desiredForces = K.asDiagonal() * (desiredForces - xyActual);
00301 
00302         kinematics.forceToJointTorque(jacobian, desiredForces, desiredTorques);
00303 
00304         //add in repulsive torque to avoid singularity
00305         if (actualJoints.rows() == 3 && actualJoints[2] < 0.5)
00306         {
00307             desiredTorques[2] += 500.0 * (0.5 - actualJoints[2]);
00308         }
00309 
00310         //keep thumbs away from joint limits
00311         if (actualJoints.rows() == 4)                   //selects thumb (primaries only have 3 joints defined)
00312         {
00313             if (actualJoints[0] > -0.3)
00314             {
00315                 desiredTorques[0] -= 500.0 * (actualJoints[0] + 0.3);
00316             }
00317             else if (actualJoints[0] < -1.4)
00318             {
00319                 desiredTorques[0] += 500.0 * (-1.4 - actualJoints[0]);
00320             }
00321 
00322             if (actualJoints[1] < 0.2)
00323             {
00324                 desiredTorques[1] += 500.0 * (0.2 - actualJoints[1]);
00325             }
00326             else if (actualJoints[1] > 1.4)
00327             {
00328                 desiredTorques[1] -= 500.0 * (actualJoints[1] - 1.4);
00329             }
00330 
00331             if (actualJoints[2] < 0.5)
00332             {
00333                 desiredTorques[2] += 500.0 * (0.5 - actualJoints[2]);
00334             }
00335             else if (actualJoints[2] > 1.4)
00336             {
00337                 desiredTorques[2] -= 500.0 * (actualJoints[2] - 1.4);
00338             }
00339         }
00340     }
00341     else
00342     {
00343         desiredTorques = K.asDiagonal() * (desiredPos - actualJoints);
00344     }
00345 
00346     desTorques = desiredTorques;
00347 
00348     //find internal tension and scale desired torques if necessary
00349     double tensErr = kinematics.findDesiredInternalTension(fmin, fmax, desiredTorques);
00350     tensErr -= kinematics.calculateInternalTension(actualTensions);
00351 
00352     //subtract to make desiredTorques into torqueError to use in feedback
00353     desiredTorques -= actualTorques;
00354     //compute force feedback term -> xd = P^T K_p * torqueError
00355     kinematics.jointSpaceTorqueFeedback(desiredTorques, jointKp, tensErr, tensionKp, desiredSliders);
00356 
00357     //add in slider position and velocity terms
00358     desiredSliders += actualSliders - kd * sliderVelocities;
00359 
00360     //deadband to reduce vibrations
00361     for (unsigned int i = 0; i < desiredSliders.rows(); ++i)
00362         if (desiredSliders[i] < actualSliders[i] + deadbandSize && desiredSliders[i] > actualSliders[i] - deadbandSize)
00363         {
00364             desiredSliders[i] = actualSliders[i];
00365         }
00366 }
00367 
00368 
00369 template<unsigned int N, unsigned int NHall>
00370 void FingerController<N, NHall>::getMotComs(const SliderVectorType& desiredSliders, const SliderVectorType& kTendon, const SliderVectorType& actualSliders, const SliderVectorType& actualTensions, const SliderVectorType& sliderVelocities, SliderVectorType& sliderMotComs, SliderVectorType& desiredSliderVels, const SliderVectorType& fingerBoostMotCom)
00371 {
00372     // get motcoms
00373     double roundedSlider;
00374 
00375     for (unsigned int i = 0; i < multiLoopControllers.size(); ++i)
00376     {
00377         roundedSlider = fmod(desiredSliders[i], mmPerCount);
00378 
00379         if (roundedSlider < 0.5)
00380         {
00381             roundedSlider = desiredSliders[i] - roundedSlider;
00382         }
00383         else
00384         {
00385             roundedSlider = desiredSliders[i] + mmPerCount - roundedSlider;
00386         }
00387 
00388         if (fingerBoostMotCom[i] != 0)
00389         {
00390             sliderMotComs[i] = fingerBoostMotCom[i];
00391         }
00392         else
00393         {
00394             sliderMotComs[i] = multiLoopControllers[i].update(roundedSlider, kTendon[i], actualSliders[i], actualTensions[i], sliderVelocities[i], busVoltage, desiredSliderVels[i]);
00395         }
00396     }
00397 }
00398 
00399 template<unsigned int N, unsigned int NHall>
00400 void FingerController<N, NHall>::getHallAngles(const HallVectorType& halls_in, HallVectorType& jointAngles)
00401 {
00402     for (int i = 0; i < halls_in.rows(); ++i)
00403     {
00404         jointAngles[i] = HallsToAngle::getAngleFromHalls(halls_in[i], hallCoeffs0[i], hallCoeffs1[i], hallCoeffs2[i], hallCoeffs3[i], hallScale);
00405     }
00406 
00407     // Calculate distals from medial if not controlled
00408     // @todo calibrate raw distal halls to this equation RDEV-2334
00409     if (N == 2 && NHall == 6)
00410     {
00411         jointAngles[2 * N] = HallsToAngle::getAngleFromHalls(jointAngles[N], -0.01376, 0.005286, 0.00006108, -1.57e-7, 1.0);
00412         jointAngles[2 * N + 1] = HallsToAngle::getAngleFromHalls(jointAngles[N + 1], -0.01376, 0.005286, 0.00006108, -1.57e-7, 1.0);
00413     }
00414     else if (N == 3 && NHall == 4)
00415     {
00416         jointAngles[N] = HallsToAngle::getAngleFromHalls(jointAngles[N - 1], -0.01376, 0.005286, 0.00006108, -1.57e-7, 1.0);
00417     }
00418 }
00419 
00420 template<unsigned int N, unsigned int NHall>
00421 void FingerController<N, NHall>::getCalibratedTensions(const SliderVectorType& tensionA, const SliderVectorType& tensionB, double timestep, SliderVectorType& tensionsCalibrated)
00422 {
00423     for (int i = 0; i < tensionA.size(); i++)
00424     {
00425         double temp;
00426         temp = tensionA[i] * tensionAGains[i] + tensionB[i] * tensionBGains[i] + tensionSensorCalOffsets[i];
00427         tensionsCalibrated[i] = calibratedStrain[i] * (temp - tensionOffsets[i]);
00428 
00429         if (tensionsCalibrated[i] < 0)
00430         {
00431             tensionsCalibrated[i] = 0;
00432         }
00433 
00434         if (tensionFilterCutoffFreq != 0 && timestep != 0.)
00435         {
00436             //first-order filter
00437             temp = tensionFilterCutoffFreq * (tensionsCalibrated[i] - tensionsPrev[i]);
00438             tensionsCalibrated[i] = tensionsPrev[i] + temp * timestep;
00439             tensionsPrev[i] = tensionsCalibrated[i];
00440         }
00441     }
00442 }
00443 
00444 template<unsigned int N, unsigned int NHall>
00445 void FingerController<N, NHall>::getXYPos(const JointVectorType& jointAngles, const bool isLeft, JointVectorType& xy, JointVectorType& desiredTorques)
00446 {
00447     kinematics.jointToCartesian(jointAngles, isLeft, xy);
00448     desiredTorques = desTorques;
00449 }
00450 
00451 #endif


robodyn_mechanisms
Author(s):
autogenerated on Thu Jun 6 2019 21:22:48