WristMechanism.cpp
Go to the documentation of this file.
00001 
00011 #include "robodyn_mechanisms/WristMechanism.h"
00012 #include "nasa_common_logging/Logger.h"
00013 #include <Eigen/LU>
00014 
00015 using namespace Eigen;
00016 using namespace std;
00017 using namespace log4cpp;
00018 
00019 WristMechanism::WristMechanism()
00020     : logCategory("gov.nasa.robodyn.WristMechanism")
00021 {
00022     maxIt        = 20;
00023     eps          = 0.001;
00024     isCalibrated = false;
00025 }
00026 
00027 WristMechanism::~WristMechanism()
00028 {
00029 }
00030 
00036 void WristMechanism::setSliderOffsetGain(Vector2d sliderOffset, Vector2d sliderGain)
00037 {
00038     this->sliderOffset = sliderOffset;
00039     this->sliderGain = sliderGain;
00040     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "Slider Offset: " << sliderOffset;
00041     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "Slider Gain: " << sliderGain;
00042 }
00043 
00049 void WristMechanism::setAngleOffsetGain(Vector2d angleOffset, Vector2d angleGain)
00050 {
00051     this->angleOffset = angleOffset;
00052     this->angleGain  = angleGain;
00053     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG
00054             << "Angle Offset: " << angleOffset << "\r\n"
00055             << "Angle Gain: " << angleGain;
00056 }
00057 
00077 void WristMechanism::loadDesignParams(Vector3d A, Vector3d A0, Vector3d B, Vector3d C, Vector3d D, Vector3d D0, Vector3d Pitch, Vector3d Yaw, Vector3d M, Vector3d N, double linkLength)
00078 {
00079     this->linkLength = linkLength;
00080 
00081     //shift origin to pitch center
00082     alpha = A0  - Pitch;
00083     beta  = B   - Yaw;
00084     gamma = C   - Yaw;
00085     delta = D0  - Pitch;
00086     p     = Yaw - Pitch;
00087 
00088     // find unit vector for 1st slider axis
00089     Vector3d uMag = A - A0;
00090     double uNorm   = uMag.norm();
00091 
00092     if (uNorm != 0)
00093     {
00094         u = uMag / uNorm;
00095     }
00096     else
00097     {
00098         std::stringstream err;
00099         err << "in loadDesignParams A and A0 cannot be the same or produce a normal of 0";
00100         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00101         throw std::runtime_error(err.str());
00102     }
00103 
00104     // find unit vector for 2nd slider axis
00105     Vector3d vMag = D - D0;
00106     double vNorm   = vMag.norm();
00107 
00108     if (vNorm != 0)
00109     {
00110         v = vMag / vNorm;
00111     }
00112     else
00113     {
00114         std::stringstream err;
00115         err << "in loadDesignParams D and D0 cannot be the same or produce a normal of 0";
00116         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00117         throw std::runtime_error(err.str());
00118     }
00119 
00120     // find length^2
00121     lengthSq = linkLength * linkLength;
00122 
00123     m = M;
00124     n = N;
00125 
00126     R1m = AA2Rot(m, ONE);
00127     R1n = AA2Rot(n, ONE);
00128     Rsm = AA2Rot(m, SIN);
00129     Rsn = AA2Rot(n, SIN);
00130     Rcm = AA2Rot(m, COS);
00131     Rcn = AA2Rot(n, COS);
00132 
00133     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG
00134             << "a: (" << alpha(0) << "," << alpha(1) << "," << alpha(2) << ")\r\n"
00135             << "b: (" << beta(0) << "," << beta(1) << "," << beta(2) << ")\r\n"
00136             << "c: (" << gamma(0) << "," << gamma(1) << "," << gamma(2) << ")\r\n"
00137             << "d: (" << delta(0) << "," << delta(1) << "," << delta(2) << ")\r\n"
00138             << "m: (" << m(0) << "," << m(1) << "," << m(2) << ")\r\n"
00139             << "n: (" << n(0) << "," << n(1) << "," << n(2) << ")\r\n"
00140             << "u: (" << u(0) << "," << u(1) << "," << u(2) << ")\r\n"
00141             << "v: (" << v(0) << "," << v(1) << "," << v(2) << ")\r\n"
00142             << "p: (" << p(0) << "," << p(1) << "," << p(2) << ")\r\n"
00143             << "link length: " << linkLength;
00144 
00145 }
00146 
00158 void WristMechanism::setLimits(const double& upperPitchMin,
00159                                const double& upperPitchMax,
00160                                const double& lowerPitchMin,
00161                                const double& lowerPitchMax,
00162                                const double& upperYawMin,
00163                                const double& upperYawMax,
00164                                const double& lowerYawMin,
00165                                const double& lowerYawMax)
00166 {
00167     this->upperPitchMin = upperPitchMin;
00168     this->upperPitchMax = upperPitchMax;
00169     this->lowerPitchMin = lowerPitchMin;
00170     this->lowerPitchMax = lowerPitchMax;
00171     this->upperYawMin = upperYawMin;
00172     this->upperYawMax = upperYawMax;
00173     this->lowerYawMin = lowerYawMin;
00174     this->lowerYawMax = lowerYawMax;
00175 
00176     getLineFromPoints(upperYawMax, upperYawMin, upperPitchMin, upperPitchMax, mUpperPitchUpperYaw, bUpperPitchUpperYaw);
00177     getLineFromPoints(upperYawMax, upperYawMin, lowerPitchMax, lowerPitchMin, mLowerPitchUpperYaw, bLowerPitchUpperYaw);
00178     getLineFromPoints(lowerYawMax, lowerYawMin, lowerPitchMin, lowerPitchMax, mLowerPitchLowerYaw, bLowerPitchLowerYaw);
00179     getLineFromPoints(lowerYawMin, lowerYawMax, upperPitchMin, upperPitchMax, mUpperPitchLowerYaw, bUpperPitchLowerYaw);
00180 
00181     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG
00182             << "Upper Pitch Max: " << upperPitchMax << "\r\n"
00183             << "Upper Pitch Min: " << upperPitchMin << "\r\n"
00184             << "Lower Pitch Max: " << lowerPitchMax << "\r\n"
00185             << "Lower Pitch Min: " << lowerPitchMin << "\r\n"
00186             << "  Upper Yaw Max: " << upperYawMax << "\r\n"
00187             << "  Upper Yaw Min: " << upperYawMin << "\r\n"
00188             << "  Lower Yaw Max: " << lowerYawMax << "\r\n"
00189             << "  Lower Yaw Min: " << lowerYawMin << "\r\n"
00190             << "UpperPitchUpperYaw equation: y=" << mUpperPitchUpperYaw << "x + " << bUpperPitchUpperYaw << "\r\n"
00191             << "UpperPitchLowerYaw equation: y=" << mUpperPitchLowerYaw << "x + " << bUpperPitchLowerYaw << "\r\n"
00192             << "LowerPitchUpperYaw equation: y=" << mLowerPitchUpperYaw << "x + " << bLowerPitchUpperYaw << "\r\n"
00193             << "LowerPitchLowerYaw equation: y=" << mLowerPitchLowerYaw << "x + " << bLowerPitchLowerYaw;
00194 }
00195 
00205 void WristMechanism::getLimits(double pitch, double yaw, double& upperPitch, double& lowerPitch, double& upperYaw, double& lowerYaw)
00206 {
00207     upperPitch = upperPitchMax;
00208     lowerPitch = lowerPitchMin;
00209     upperYaw = upperYawMax;
00210     lowerYaw = lowerYawMin;
00211 
00213     if (yaw > upperYawMax)
00214     {
00215         yaw = upperYawMax;
00216     }
00217     else if (yaw < lowerYawMin)
00218     {
00219         yaw = lowerYawMin;
00220     }
00221 
00222     if (pitch > upperPitchMax)
00223     {
00224         pitch = upperPitchMax;
00225     }
00226     else if (pitch < lowerPitchMin)
00227     {
00228         pitch = lowerPitchMin;
00229     }
00230 
00231     if (pitch > upperPitchMin && yaw > upperYawMin)
00232     {
00233         getNearest(mUpperPitchUpperYaw, bUpperPitchUpperYaw, yaw, pitch, upperYaw, upperPitch);
00234         upperYaw = std::max(upperYawMin, upperYaw);
00235         upperPitch = std::max(upperPitchMin, upperPitch);
00236     }
00237     else if (pitch > upperPitchMin && yaw < lowerYawMax)
00238     {
00239         getNearest(mUpperPitchLowerYaw, bUpperPitchLowerYaw, yaw, pitch, lowerYaw, upperPitch);
00240         lowerYaw = std::min(lowerYawMax, lowerYaw);
00241         upperPitch = std::max(upperPitchMin, upperPitch);
00242     }
00243     else if (pitch < lowerPitchMax && yaw > upperYawMin)
00244     {
00245         getNearest(mLowerPitchUpperYaw, bLowerPitchUpperYaw, yaw, pitch, upperYaw, lowerPitch);
00246         upperYaw = std::max(upperYawMin, upperYaw);
00247         lowerPitch = std::min(lowerPitchMax, lowerPitch);
00248     }
00249     else if (pitch < lowerPitchMax && yaw < lowerYawMax)
00250     {
00251         getNearest(mLowerPitchLowerYaw, bLowerPitchLowerYaw, yaw, pitch, lowerYaw, lowerPitch);
00252         lowerYaw = std::min(lowerYawMax, lowerYaw);
00253         lowerPitch = std::min(lowerPitchMax, lowerPitch);
00254     }
00255 }
00256 
00262 void WristMechanism::applyLimits(double& pitch, double& yaw)
00263 {
00264     double upperPitch, lowerPitch, upperYaw, lowerYaw;
00265     getLimits(pitch, yaw, upperPitch, lowerPitch, upperYaw, lowerYaw);
00266 
00267     if (pitch > upperPitch)
00268     {
00269         NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "limiting pitch from: " << pitch << " to: " << upperPitch;
00270         pitch = upperPitch;
00271     }
00272     else if (pitch < lowerPitch)
00273     {
00274         NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "limiting pitch from: " << pitch << " to: " << lowerPitch;
00275         pitch = lowerPitch;
00276     }
00277 
00278     if (yaw > upperYaw)
00279     {
00280         NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "limiting yaw from: " << yaw << " to: " << upperYaw;
00281         yaw = upperYaw;
00282     }
00283     else if (yaw < lowerYaw)
00284     {
00285         NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "limiting yaw from: " << yaw << " to: " << lowerYaw;
00286         yaw = lowerYaw;
00287     }
00288 }
00289 
00299 void WristMechanism::getNearest(double m, double b, double x_in, double y_in, double& x_out, double& y_out)
00300 {
00301     x_out = (m * y_in + x_in - m * b) / (m * m + 1);
00302     y_out = (m * m * y_in + m * x_in + b) / (m * m + 1);
00303 }
00304 
00308 void WristMechanism::getLineFromPoints(double x1, double x2, double y1, double y2, double& m, double& b)
00309 {
00310     if (fabs(x2 - x1) < eps)
00311     {
00312         throw std::runtime_error("in WristMechanism::getLineFromPoints denominator is zero!");
00313     }
00314 
00315     m = (y2 - y1) / (x2 - x1);
00316     b = y1 - m * x1;
00317 }
00318 
00326 int WristMechanism::doFwdKin(Vector2d& ang, Vector2d pos, Vector2d lastang)
00327 {
00328     if (angleGain(0) == 0.0)
00329     {
00330         stringstream err;
00331         err << "angleGain(0) must be non-zero. Provided value of [" << angleGain(0) << "] is invalid.";
00332         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00333         throw runtime_error(err.str());
00334     }
00335 
00336     if (angleGain(1) == 0.0)
00337     {
00338         stringstream err;
00339         err << "angleGain(0) must be non-zero. Provided value of [" << angleGain(1) << "] is invalid.";
00340         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00341         throw runtime_error(err.str());
00342     }
00343 
00344     lastang(0) = (lastang(0) - angleOffset(0)) / angleGain(0);
00345     lastang(1) = (lastang(1) - angleOffset(1)) / angleGain(1);
00346 
00347     ang = Vector2d::Zero();
00348 
00349     Matrix3d AB = findFwdKinMatrix(alpha, beta, this->u, pos(0));
00350     Matrix3d DC = findFwdKinMatrix(delta, gamma, this->v, pos(1));
00351 
00352     MatrixXd Cfk = MatrixXd::Zero(8, 8);
00353     MatrixXd Dfk = MatrixXd::Zero(8, 8);
00354     MatrixXd Efk = MatrixXd::Zero(8, 8);
00355     MatrixXd Ffk = MatrixXd::Zero(8, 8);
00356 
00357 
00358     Cfk <<  AB(0, 0), AB(0, 1), AB(0, 2), 0,       AB(1, 0), AB(1, 1), AB(2, 0), AB(2, 1),
00359         0,       0,       0,       0,       AB(0, 0), AB(0, 1), AB(1, 0), AB(1, 1),
00360         0,       AB(0, 0), AB(0, 1), AB(0, 2), 0,       AB(1, 0), 0,       AB(2, 0),
00361         0,       0,       0,       0,       0,       AB(0, 0), 0,       AB(1, 0),
00362         DC(0, 0), DC(0, 1), DC(0, 2), 0,       DC(1, 0), DC(1, 1), DC(2, 0), DC(2, 1),
00363         0,       0,       0,       0,       DC(0, 0), DC(0, 1), DC(1, 0), DC(1, 1),
00364         0,       DC(0, 0), DC(0, 1), DC(0, 2), 0,       DC(1, 0), 0,       DC(2, 0),
00365         0,       0,       0,       0,       0,       DC(0, 0), 0,       DC(1, 0);
00366 
00367 
00368 
00369     Dfk <<  AB(1, 2), 0,       AB(2, 2), 0,       0,       0,       0,       0,
00370         AB(0, 2), 0,       AB(1, 2), 0,       AB(2, 0), AB(2, 1), AB(2, 2), 0,
00371         AB(1, 1), AB(1, 2), AB(2, 1), AB(2, 2), 0,       0,       0,       0,
00372         AB(0, 1), AB(0, 2), AB(1, 1), AB(1, 2), 0,       AB(2, 0), AB(2, 1), AB(2, 2),
00373         DC(1, 2), 0,       DC(2, 2), 0,       0,       0,       0,       0,
00374         DC(0, 2), 0,       DC(1, 2), 0,       DC(2, 0), DC(2, 1), DC(2, 2), 0,
00375         DC(1, 1), DC(1, 2), DC(2, 1), DC(2, 2), 0,       0,       0,       0,
00376         DC(0, 1), DC(0, 2), DC(1, 1), DC(1, 2), 0,       DC(2, 0), DC(2, 1), DC(2, 2);
00377 
00378 
00379     Efk <<  0, 0, 0, 0, 1, 0, 0, 0,
00380         0, 0, 0, 0, 0, 1, 0, 0,
00381         0, 0, 0, 0, 0, 0, 0, 0,
00382         0, 0, 0, 0, 0, 0, 0, 0,
00383         0, 0, 0, 0, 0, 0, 1, 0,
00384         0, 0, 0, 0, 0, 0, 0, 1,
00385         0, 0, 0, 0, 0, 0, 0, 0,
00386         0, 0, 0, 0, 0, 0, 0, 0;
00387 
00388     Ffk <<  0, 0, 0, 0, 0, 0, 0, 0,
00389         0, 0, 0, 0, 0, 0, 0, 0,
00390         1, 0, 0, 0, 0, 0, 0, 0,
00391         0, 1, 0, 0, 0, 0, 0, 0,
00392         0, 0, 0, 0, 0, 0, 0, 0,
00393         0, 0, 0, 0, 0, 0, 0, 0,
00394         0, 0, 0, 0, 1, 0, 0, 0,
00395         0, 0, 0, 0, 0, 1, 0, 0;
00396 
00397 
00398     MatrixXd Dfki = Dfk.lu().inverse();
00399 
00400     MatrixXd Mfk = (Efk - (Ffk * Dfki * Cfk));
00401 
00402     EigenSolver<MatrixXd> es(Mfk);
00403 
00404     // the eigenvalues are solutions for x
00405     VectorXcd xtheta = es.eigenvalues();
00406 
00407     // the eigenvectors give y as y= m2'' / m1''
00408     MatrixXcd ephi = es.eigenvectors();
00409 
00410     VectorXcd yphi = VectorXcd::Zero(8);
00411 
00412     if (ephi.rows() != 8)
00413     {
00414         std::stringstream err;
00415         err << "in doFwdKin there should be 8 rows in ephi";
00416         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00417         throw std::runtime_error(err.str());
00418     }
00419 
00420     if (ephi.cols() != 8)
00421     {
00422         std::stringstream err;
00423         err << "in doFwdKin there should be 8 cols in ephi";
00424         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00425         throw std::runtime_error(err.str());
00426     }
00427 
00428     if (yphi.rows() != 8)
00429     {
00430         std::stringstream err;
00431         err << "in doFwdKin there should be 8 rows in yphi";
00432         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00433         throw std::runtime_error(err.str());
00434     }
00435 
00436     std::complex<double> zero(0, 0);
00437 
00438     for (unsigned int i = 0; i < ephi.rows(); i++)
00439     {
00440         if (ephi(0, i) != zero)
00441         {
00442             yphi(i) = ephi(1, i) / ephi(0, i);
00443         }
00444         else
00445         {
00446             std::stringstream err;
00447             err << "in doFwdKin -- divide by zero error in calculating yphi for " << ephi(i, 1) << ", M1'' is zero " << ephi(i, 0);
00448             NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00449             throw std::runtime_error(err.str());
00450         }
00451 
00452     }
00453 
00454     std::vector<double> ptheta;
00455     std::vector<double> pphi;
00456     double             tantheta, tanphi, sintheta, costheta, theta, sinphi, cosphi, phi, dist;
00457 
00458     ptheta.clear();
00459     pphi.clear();
00460 
00461     // remove complex solutions
00462     for (unsigned int i = 0; i < xtheta.rows(); i++)
00463     {
00464         if (xtheta(i).imag() == 0 && yphi(i).imag() == 0)
00465         {
00466             //solve for theta and phi
00467             tantheta = xtheta(i).real();
00468             tanphi   = yphi(i).real();
00469 
00470             sintheta = (2 * tantheta) / (1 + tantheta * tantheta);
00471             costheta = (1 - tantheta * tantheta) / (1 + tantheta * tantheta);
00472             theta    = atan2(sintheta, costheta);
00473 
00474             sinphi = 2 * tanphi / (1 + tanphi * tanphi);
00475             cosphi = (1 - tanphi * tanphi) / (1 + tanphi * tanphi);
00476             phi    = atan2(sinphi, cosphi);
00477 
00478             //remove solutions outside of joint space for manipulator (within 5 degrees of limits to account for accumulated error)
00479             if (theta > lowerPitchMin - .1 && theta < upperPitchMax + .1 &&
00480                     phi > lowerYawMin - .1 && phi < upperYawMax + .1)
00481             {
00482                 //std::cout<<"added (" <<theta <<","<<phi<<")"<<std::endl;
00483                 ptheta.push_back(theta);
00484                 pphi.push_back(phi);
00485             }
00486 
00487 
00488         }
00489     }
00490 
00491     if (ptheta.size() != pphi.size())
00492     {
00493         std::stringstream err;
00494         err << "in doFwdKin vectors ptheta and pphi should be the same size";
00495         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00496         return -1;
00497     }
00498 
00499 
00500     // choose solution nearest to previous solution
00501     if (ptheta.size() > 1 && pphi.size() > 1)
00502     {
00503         unsigned int i = 0;
00504 
00505         theta = ptheta.at(i);
00506         phi   = pphi.at(i);
00507 
00508         dist = sqrt(pow(theta - lastang(0), 2.0) + pow(phi - lastang(1), 2.0));
00509 
00510         ang(0) = theta;
00511         ang(1) = phi;
00512 
00513         i++;
00514 
00515         for (; i < ptheta.size(); i++)
00516         {
00517             theta = ptheta.at(i);
00518             phi   = pphi.at(i);
00519 
00520             if (dist > sqrt(pow((theta - lastang(0)), 2.0) + pow((phi - lastang(1)), 2.0)))
00521             {
00522                 dist = sqrt(pow((theta - lastang(0)), 2.0) + pow((phi - lastang(1)), 2.0));
00523 
00524                 ang(0) = theta;
00525                 ang(1) = phi;
00526             }
00527         }
00528     }
00529     else if (ptheta.size() == 1 && pphi.size() == 1)
00530     {
00531 
00532         ang(0) = ptheta.at(0);
00533         ang(1) = pphi.at(0);
00534     }
00535     else
00536     {
00537         return -1;
00538     }
00539 
00540 //    //do newton's method
00541 //    Vector2d dang = NewtonsMethod(ang, pos);
00542 //    int maxit = maxIt;
00543 //    while(maxit > 0 && (fabs(dang(0)) > eps || fabs(dang(1)) > eps))
00544 //    {
00545 //        ang = ang-dang;
00546 //        dang = NewtonsMethod(ang, pos);
00547 //        maxit--;
00548 
00549 //        //std::cout<<"iterating"<<std::endl;
00550 //    }
00551 
00552 //    std::cout<<"iterations: "<<maxIt-maxit<<std::endl;
00553 
00554 //    if(abs(dang(0))> eps || abs(dang(1)) > eps)
00555 //    {
00556 //        std::stringstream err;
00557 //        err << "Fwd Kinematics solution not good"<<std::endl;
00558 //        err << "ang: "<<std::endl<<ang<<std::endl;
00559 //        err << "dang: "<<std::endl<<dang<<std::endl;
00560 //        NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::WARN, err.str());
00561 //        return -1;
00562 //    }
00563 
00564     return 0;
00565 
00566 }
00567 
00568 Matrix3d WristMechanism::findFwdKinMatrix(Vector3d a, Vector3d b, Vector3d u, double q)
00569 {
00570     Matrix3d aOut;
00571 
00572     Vector3d    ahat  = a + q * u;
00573     RowVector3d pT    = p.transpose();
00574     RowVector3d ahatT = ahat.transpose();
00575 
00576     double a1, b1, c1, d1, e1, f1, g1, h1, k1;
00577 
00578     a1        = p.dot(p) + b.dot(b) + ahat.dot(ahat) - lengthSq + 2 * pT * R1n * b - 2 * ahatT * R1m * (p + R1n * b);
00579     double b11 = -2 * ahatT * R1m * Rsn * b;
00580     b1        = b11 + 2 * pT * Rsn * b ;
00581     double c11 = -2 * ahatT * R1m * Rcn * b;
00582     c1        = c11 + 2 * pT * Rcn * b ;
00583     d1        = -2 * ahatT * Rsm * (p + R1n * b);
00584     e1        = -2 * ahatT * Rsm * Rsn * b;
00585     f1        = -2 * ahatT * Rsm * Rcn * b;
00586     g1        = -2 * ahatT * Rcm * (p + R1n * b);
00587     h1        = -2 * ahatT * Rcm * Rsn * b;
00588     k1        = -2 * ahatT * Rcm * Rcn * b;
00589 
00590 
00591     aOut(0, 0) = a1 + c1 + g1 + k1;
00592     aOut(1, 0) = 2 * d1 + 2 * f1;
00593     aOut(2, 0) = a1 + c1 - g1 - k1;
00594 
00595     aOut(0, 1) = 2 * b1 + 2 * h1;
00596     aOut(1, 1) = 4 * e1;
00597     aOut(2, 1) = 2 * b1 - 2 * h1;
00598 
00599     aOut(0, 2) = a1 - c1 + g1 - k1;
00600     aOut(1, 2) = 2 * d1 - 2 * f1;
00601     aOut(2, 2) = a1 - c1 - g1 + k1;
00602 
00603     return aOut;
00604 }
00605 
00612 int WristMechanism::doInvKin(Vector2d& pos, Vector2d ang)
00613 {
00614     int   success = 0;
00615     double pitch   = ang(0);
00616     double yaw     = ang(1);
00617 
00618     //applyLimits(pitch, yaw);
00619 
00620     double    bravo, charlie, david;
00621     Vector3d r1, r2;
00622 
00623     // find rotation matrices around the pitch axis
00624     Matrix3d Rpitch = AA2Rot(m, pitch);
00625     // find rotation matrices around the yaw axis
00626     Matrix3d Ryaw = AA2Rot(n, yaw);
00627 
00628 
00629     r1 = Ryaw * beta;
00630     r2 = Rpitch * (p + r1);
00631 
00632     bravo   = -2 * u.dot(r2) + 2 * alpha.dot(u);
00633     charlie = p.dot(p) + 2 * p.dot(r1) + beta.dot(beta) - 2 * alpha.dot(r2) + alpha.dot(alpha) - lengthSq;
00634     david   = bravo * bravo - 4 * charlie;
00635 
00636     if (david >= 0)
00637     {
00638         pos(0) = -0.5 * bravo - 0.5 * sqrt(david);
00639     }
00640     else
00641     {
00642         success = -1;
00643     }
00644 
00645     r1 = Ryaw * gamma;
00646     r2 = Rpitch * (p + r1);
00647 
00648     bravo   = -2 * v.dot(r2) + 2 * delta.dot(v);
00649     charlie = p.dot(p) + 2 * p.dot(r1) + gamma.dot(gamma) - 2 * delta.dot(r2) + delta.dot(delta) - lengthSq;
00650     david   = bravo * bravo - 4 * charlie;
00651 
00652     if (david >= 0)
00653     {
00654         pos(1) = -0.5 * bravo - 0.5 * sqrt(david);
00655     }
00656     else
00657     {
00658         success = -1;
00659     }
00660 
00661     return success;
00662 }
00663 
00664 
00671 Vector2d WristMechanism::getAngleFromSlider(Vector2d slider)
00672 {
00673     Vector2d ang;
00674 
00675     if (doFwdKin(ang, slider, lastAng) != 0)
00676     {
00677         std::stringstream err;
00678         err << "Could not find fwd kinematic solution";
00679         throw std::runtime_error(err.str());
00680     }
00681 
00682     //std::cout<<"angle out of fwd kin: "<<std::endl<<ang<<std::endl;
00683     ang(0) = ang(0) * angleGain(0) + angleOffset(0);
00684     ang(1) = ang(1) * angleGain(1) + angleOffset(1);
00685     lastAng = ang;
00686 
00687     return ang;
00688 }
00689 
00695 Vector2d WristMechanism::getSliderFromWristEncoder(Vector2d encoder)
00696 {
00697     if (!isCalibrated)
00698     {
00699         throw std::runtime_error("wrist has not been calibrated");
00700     }
00701 
00702     Vector2d encoderTared = encoder - encoderTarePos;
00703 
00704     Vector2d taredSliderEncoderPos = encoderTared + calSliderPos;
00705 
00706     Vector2d sliderPos;
00707 
00708     sliderPos(0) = taredSliderEncoderPos(0) * sliderGain(0) + sliderOffset(0);
00709     sliderPos(1) = taredSliderEncoderPos(1) * sliderGain(1) + sliderOffset(1);
00710 
00711     return sliderPos;
00712 }
00713 
00719 Vector2d WristMechanism::getWristEncoderFromSlider(Vector2d sliderPos)
00720 {
00721     if (!isCalibrated)
00722     {
00723         throw std::runtime_error("wrist has not been calibrated");
00724     }
00725 
00726     Vector2d encoder, sliderEncoderPos, encoderTared;
00727 
00728     if (sliderGain(0) == 0.0)
00729     {
00730         stringstream err;
00731         err << "sliderGain(0) must be non-zero. Provided value of [" << sliderGain(0) << "] is invalid.";
00732         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00733         throw runtime_error(err.str());
00734     }
00735 
00736     if (sliderGain(1) == 0.0)
00737     {
00738         stringstream err;
00739         err << "sliderGain(1) must be non-zero. Provided value of [" << sliderGain(1) << "] is invalid.";
00740         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00741         throw runtime_error(err.str());
00742     }
00743 
00744     sliderEncoderPos(0) = (sliderPos(0) - sliderOffset(0)) / sliderGain(0);
00745     sliderEncoderPos(1) = (sliderPos(1) - sliderOffset(1)) / sliderGain(1);
00746 
00747     encoderTared = sliderEncoderPos - calSliderPos;
00748     encoder      = encoderTared + encoderTarePos;
00749 
00750     return encoder;
00751 }
00752 
00759 Vector2d WristMechanism::getSliderFromAngle(Vector2d ang)
00760 {
00761     Vector2d angle;
00762 
00763     if (angleGain(0) == 0.0)
00764     {
00765         stringstream err;
00766         err << "angleGain(0) must be non-zero. Provided value of [" << angleGain(0) << "] is invalid.";
00767         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00768         throw runtime_error(err.str());
00769     }
00770 
00771     if (angleGain(1) == 0.0)
00772     {
00773         stringstream err;
00774         err << "angleGain(1) must be non-zero. Provided value of [" << angleGain(1) << "] is invalid.";
00775         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00776         throw runtime_error(err.str());
00777     }
00778 
00779     angle(0) = (ang(0) - angleOffset(0)) / angleGain(0);
00780     angle(1) = (ang(1) - angleOffset(1)) / angleGain(1);
00781 
00782     Vector2d sliderPos;
00783 
00784     if (doInvKin(sliderPos, angle) != 0)
00785     {
00786         std::stringstream err;
00787         err << "Could not find inv kinematic solution: " << angle(0) << ", " << angle(1);
00788         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::DEBUG, err.str());
00789         throw std::runtime_error(err.str());
00790     }
00791 
00792     return sliderPos;
00793 }
00794 
00795 
00801 void WristMechanism::tareWristEncoders(Vector2d encoder)
00802 {
00803     this->encoderTarePos = encoder;
00804     return;
00805 }
00806 
00817 void WristMechanism::calWrist(Vector2d encoder, Vector2d sliderPos, Vector2d angle)
00818 {
00819     tareWristEncoders(encoder);
00820 
00821     if (sliderGain(0) == 0.0)
00822     {
00823         stringstream err;
00824         err << "sliderGain(0) must be non-zero. Provided value of [" << sliderGain(0) << "] is invalid.";
00825         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00826         throw runtime_error(err.str());
00827     }
00828 
00829     if (sliderGain(1) == 0.0)
00830     {
00831         stringstream err;
00832         err << "sliderGain(1) must be non-zero. Provided value of [" << sliderGain(1) << "] is invalid.";
00833         NasaCommonLogging::Logger::log("gov.nasa.robodyn.WristMechanism", Priority::ERROR, err.str());
00834         throw runtime_error(err.str());
00835     }
00836 
00837     this->calSliderPos(0) = (sliderPos(0) - sliderOffset(0)) / sliderGain(0);
00838     this->calSliderPos(1) = (sliderPos(1) - sliderOffset(1)) / sliderGain(1);
00839     //std::cout<<"calSliderPos: "<<std::endl<<calSliderPos<<std::endl;
00840     isCalibrated = true;
00841     lastAng = angle;
00842 
00843     return;
00844 }
00845 
00853 Matrix3d WristMechanism::AA2Rot(Vector3d axis, double theta)
00854 {
00855     Matrix3d rot = Matrix3d::Zero();
00856     //convert axis to unit vector
00857     double norm = axis.norm();
00858 
00859     if (norm == 0)
00860     {
00861         std::stringstream err;
00862         err << "in AA2Rot(axis, theta) could not find find unit vector for axis (axis.norm() = 0)";
00863         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00864         throw std::runtime_error(err.str());
00865     }
00866 
00867     Vector3d unitAxis = 1 / norm * axis;
00868 
00869     double c  = cos(theta);
00870     double s  = sin(theta);
00871     double v  = 1 - c;
00872     double kx = unitAxis(0);
00873     double ky = unitAxis(1);
00874     double kz = unitAxis(2);
00875 
00876     rot(0, 0) = (kx * kx * v) + c;
00877     rot(1, 0) = (kx * ky * v) + (kz * s);
00878     rot(2, 0) = (kx * kz * v) - (ky * s);
00879 
00880     rot(0, 1) = (kx * ky * v) - (kz * s);
00881     rot(1, 1) = (ky * ky * v) + c;
00882     rot(2, 1) = (ky * kz * v) + (kx * s);
00883 
00884     rot(0, 2) = (kx * kz * v) + (ky * s);
00885     rot(1, 2) = (ky * kz * v) - (kx * s);
00886     rot(2, 2) = (kz * kz * v) + c;
00887 
00888 
00889     return rot;
00890 }
00891 
00892 
00901 Matrix3d WristMechanism::AA2Rot(Vector3d axis, RotationType index)
00902 {
00903     Matrix3d rot = Matrix3d::Zero();
00904     //convert axis to unit vector
00905     double norm = axis.norm();
00906 
00907     if (norm == 0)
00908     {
00909         std::stringstream err;
00910         err << "in AA2Rot(axis, index) could not find find unit vector for axis (axis.norm() = 0)";
00911         NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00912         throw std::runtime_error(err.str());
00913     }
00914 
00915     Vector3d unitAxis = 1 / norm * axis;
00916 
00917     double c, s, v;
00918 
00919     switch (index)
00920     {
00921         case ONE:
00922             c = 0;
00923             s = 0;
00924             v = 1;
00925             break;
00926 
00927         case SIN:
00928             c = 0;
00929             s = 1;
00930             v = 0;
00931             break;
00932 
00933         case COS:
00934             c = 1;
00935             s = 0;
00936             v = -1;
00937             break;
00938 
00939         default:
00940             std::stringstream err;
00941             err << "AA2Rot Rotation type not defined ";
00942             NasaCommonLogging::Logger::log("gov.nasa.robonet.WristMechanism", log4cpp::Priority::ERROR, err.str());
00943             throw std::invalid_argument(err.str());
00944     }
00945 
00946     double kx = unitAxis(0);
00947     double ky = unitAxis(1);
00948     double kz = unitAxis(2);
00949 
00950     rot(0, 0) = (kx * kx * v) + c;
00951     rot(1, 0) = (kx * ky * v) + (kz * s);
00952     rot(2, 0) = (kx * kz * v) - (ky * s);
00953 
00954     rot(0, 1) = (kx * ky * v) - (kz * s);
00955     rot(1, 1) = (ky * ky * v) + c;
00956     rot(2, 1) = (ky * kz * v) + (kx * s);
00957 
00958     rot(0, 2) = (kx * kz * v) + (ky * s);
00959     rot(1, 2) = (ky * kz * v) - (kx * s);
00960     rot(2, 2) = (kz * kz * v) + c;
00961 
00962     return rot;
00963 }
00964 
00971 Vector2d WristMechanism::NewtonsMethod(Vector2d ang, Vector2d pos)
00972 {
00973     WristMechanism::Partials Pabpo = findPartialDerivatives(alpha, beta, u, pos(0), ang);
00974     WristMechanism::Partials Pdcpo = findPartialDerivatives(delta, gamma, v, pos(1), ang);
00975 
00976     Matrix2d Fy;
00977     Fy <<   Pabpo.ftheta, Pabpo.fphi,
00978     Pdcpo.ftheta, Pdcpo.fphi;
00979 
00980     Vector2d Fxy;
00981     Fxy <<  Pabpo.f - lengthSq,
00982         Pdcpo.f - lengthSq;
00983 
00984     Vector2d dy = Fy.inverse() * Fxy;
00985 
00986     return dy;
00987 }
00988 
00989 WristMechanism::Partials WristMechanism::findPartialDerivatives(Vector3d a, Vector3d b, Vector3d w, double q, Vector2d ang)
00990 {
00991     WristMechanism::Partials wrist;
00992 
00993     Matrix3d Rmtheta = AA2Rot(m, ang(0));
00994     Matrix3d Rnphi = AA2Rot(n, ang(1));
00995 
00996     Vector3d r1  = Rnphi * b;
00997     Vector3d r2  = Rmtheta * (p + r1);
00998     Vector3d r   = r2 - a - q * w;
00999     Vector3d r0  = r2 - a;
01000     wrist.f0     = r0.dot(r0);
01001     wrist.f      = r.dot(r);
01002     wrist.fq     = -2 * r.dot(w);
01003     wrist.ftheta = 2 * r.dot(m.cross(r2));
01004     wrist.fphi   = 2 * r.dot(Rmtheta * (n.cross(r1)));
01005 
01006     return wrist;
01007 }
01008 


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