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
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
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
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
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
00265
00266
00267 JointVectorType actualTorques;
00268 kinematics.tensionToJointTorque(actualTensions, actualTorques);
00269
00270 JointVectorType desiredTorques;
00271
00272 if (useCartesian && actualSliders.rows() >= 4)
00273 {
00274
00275 JointVectorType xyActual;
00276 kinematics.jointToCartesian(actualJoints, isLeft, xyActual);
00277
00278
00279 JacobianType jacobian;
00280 kinematics.calcJacobian(actualJoints, xyActual, isLeft, jacobian);
00281
00282
00283 JointVectorType desiredForces = desiredPos;
00284
00285 if (desiredForces.rows() == 3)
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
00305 if (actualJoints.rows() == 3 && actualJoints[2] < 0.5)
00306 {
00307 desiredTorques[2] += 500.0 * (0.5 - actualJoints[2]);
00308 }
00309
00310
00311 if (actualJoints.rows() == 4)
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
00349 double tensErr = kinematics.findDesiredInternalTension(fmin, fmax, desiredTorques);
00350 tensErr -= kinematics.calculateInternalTension(actualTensions);
00351
00352
00353 desiredTorques -= actualTorques;
00354
00355 kinematics.jointSpaceTorqueFeedback(desiredTorques, jointKp, tensErr, tensionKp, desiredSliders);
00356
00357
00358 desiredSliders += actualSliders - kd * sliderVelocities;
00359
00360
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
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
00408
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
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