JointPath.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, AIST, the University of Tokyo and General Robotix Inc.
00003  * All rights reserved. This program is made available under the terms of the
00004  * Eclipse Public License v1.0 which accompanies this distribution, and is
00005  * available at http://www.eclipse.org/legal/epl-v10.html
00006  * Contributors:
00007  * National Institute of Advanced Industrial Science and Technology (AIST)
00008  */
00009 
00016 #include "JointPath.h"
00017 #include "Link.h"
00018 #include <hrpUtil/MatrixSolvers.h>
00019 #include <algorithm>
00020 
00021 using namespace std;
00022 using namespace hrp;
00023 
00024 
00025 JointPath::JointPath()
00026 {
00027     initialize();
00028 }
00029 
00030 
00031 JointPath::JointPath(Link* base, Link* end)
00032     : linkPath(base, end), 
00033       joints(linkPath.size())
00034 {
00035     initialize();
00036     extractJoints();
00037 }
00038 
00039 
00040 JointPath::JointPath(Link* end)
00041     : linkPath(end), 
00042       joints(linkPath.size())
00043 {
00044     initialize();
00045     extractJoints();
00046 }
00047 
00048 
00049 void JointPath::initialize()
00050 {
00051     maxIKErrorSqr = 1.0e-6 * 1.0e-6;
00052     isBestEffortIKMode = false;
00053 }
00054         
00055 
00056 JointPath::~JointPath()
00057 {
00058 
00059 }
00060 
00061 
00062 bool JointPath::find(Link* base, Link* end)
00063 {
00064     if(linkPath.find(base, end)){
00065         extractJoints();
00066     }
00067     onJointPathUpdated();
00068 
00069     return (!joints.empty());
00070 }
00071 
00072 
00073 bool JointPath::find(Link* end)
00074 {
00075     linkPath.find(end);
00076     extractJoints();
00077     onJointPathUpdated();
00078         
00079     return !joints.empty();
00080 }
00081 
00082 
00083 void JointPath::extractJoints()
00084 {
00085     numUpwardJointConnections = 0;
00086 
00087     int n = linkPath.size();
00088     if(n <= 1){
00089         joints.clear();
00090     } else {
00091         int i = 0;
00092         if(linkPath.isDownward(i)){
00093             i++;
00094         }
00095         joints.resize(n); // reserve size n buffer
00096         joints.clear();
00097         int m = n - 1;
00098         while(i < m){
00099             Link* link = linkPath[i];
00100             if(link->jointId >= 0){
00101                 if(link->jointType == Link::ROTATIONAL_JOINT || link->jointType == Link::SLIDE_JOINT){
00102                     joints.push_back(link);
00103                     if(!linkPath.isDownward(i)){
00104                         numUpwardJointConnections++;
00105                     }
00106                 }
00107             }
00108             ++i;
00109         }
00110         if(linkPath.isDownward(m-1)){
00111             Link* link = linkPath[m];
00112             if(link->jointId >= 0){
00113                 if(link->jointType == Link::ROTATIONAL_JOINT || link->jointType == Link::SLIDE_JOINT){
00114                     joints.push_back(link);
00115                 }
00116             }
00117         }
00118     }
00119 }
00120 
00121 
00122 void JointPath::onJointPathUpdated()
00123 {
00124 
00125 }
00126 
00127 
00128 void JointPath::calcJacobian(dmatrix& out_J, const Vector3& local_p) const
00129 {
00130     const int n = joints.size();
00131     out_J.resize(6, n);
00132         
00133     if(n > 0){
00134                 
00135         Link* targetLink = linkPath.endLink();
00136                 
00137         for(int i=0; i < n; ++i){
00138                         
00139             Link* link = joints[i];
00140                         
00141             switch(link->jointType){
00142                                 
00143             case Link::ROTATIONAL_JOINT:
00144             {
00145                 Vector3 omega(link->R * link->a);
00146                 Vector3 arm(targetLink->p + targetLink->R * local_p - link->p);
00147                 if(!isJointDownward(i)){
00148                     omega *= -1.0;
00149                 } 
00150                 Vector3 dp(omega.cross(arm));
00151                 out_J.col(i) << dp, omega;
00152             }
00153             break;
00154                                 
00155             case Link::SLIDE_JOINT:
00156             {
00157                 Vector3 dp(link->R * link->d);
00158                 if(!isJointDownward(i)){
00159                     dp *= -1.0;
00160                 }
00161                 out_J.col(i) << dp, Vector3::Zero();
00162             }
00163             break;
00164                                 
00165             default:
00166                 out_J.col(i).setZero();
00167             }
00168         }
00169     }
00170 }
00171 
00172 
00173 void JointPath::calcJacobianDot(dmatrix& out_dJ, const Vector3& local_p) const
00174 {
00175     const int n = joints.size();
00176     out_dJ.resize(6, n);
00177 
00178     if (n > 0) {
00179 
00180         Link* targetLink = linkPath.endLink();
00181 
00182         for (int i=0; i < n; ++i) {
00183 
00184             Link* link = joints[i];
00185 
00186             switch (link->jointType) {
00187               
00188             case Link::ROTATIONAL_JOINT:
00189             {
00190                 Vector3 omega(link->R * link->a);
00191                 Vector3 arm(targetLink->p + targetLink->R * local_p - link->p);
00192 
00193                 Vector3 omegaDot(hat(link->w) * link->R * link->a);
00194                 Vector3 armDot(targetLink->v + hat(targetLink->w) * targetLink->R * local_p - link->v);
00195 
00196                 if (!isJointDownward(i)) {
00197                     omega *= -1.0;
00198                     omegaDot *= -1.0;
00199                 }
00200 
00201                 Vector3 ddp(omegaDot.cross(arm) + omega.cross(armDot));
00202 
00203                 out_dJ.col(i) << ddp, omegaDot;
00204             }
00205             break;
00206 
00207             case Link::SLIDE_JOINT:
00208             {
00209                 Vector3 ddp(hat(link->w) * link->R * link->d);
00210                 if (!isJointDownward(i)) {
00211                     ddp *= -1.0;
00212                 }
00213                 out_dJ.col(i) << ddp, Vector3::Zero();  
00214             }
00215             break;
00216 
00217             default:
00218                 out_dJ.col(i).setZero();
00219             }
00220         }
00221     }
00222 }
00223 
00224 
00225 void JointPath::setMaxIKError(double e)
00226 {
00227     maxIKErrorSqr = e * e;
00228 }
00229 
00230 
00231 void JointPath::setBestEffortIKMode(bool on)
00232 {
00233     isBestEffortIKMode = on;
00234 }
00235 
00236 
00237 bool JointPath::calcInverseKinematics
00238 (const Vector3& base_p, const Matrix33& base_R, const Vector3& end_p, const Matrix33& end_R)
00239 {
00240     Link* baseLink = linkPath.baseLink();
00241     baseLink->p = base_p;
00242     baseLink->R = base_R;
00243 
00244     if(!hasAnalyticalIK()){
00245         calcForwardKinematics();
00246     }
00247         
00248     return calcInverseKinematics(end_p, end_R);
00249 }
00250 
00251 
00252 bool JointPath::calcInverseKinematics(const Vector3& end_p, const Matrix33& end_R)
00253 {
00254     static const int MAX_IK_ITERATION = 50;
00255     static const double LAMBDA = 0.9;
00256     static const double JOINT_LIMIT_MARGIN = 0.05;
00257     
00258     if(joints.empty()){
00259         if(linkPath.empty()){
00260             return false;
00261         }
00262         if(baseLink() == endLink()){
00263             baseLink()->p = end_p;
00264             baseLink()->R = end_R;
00265             return true;
00266         } else {
00267             // \todo implement here
00268             return false;
00269         }
00270     }
00271     
00272     const int n = numJoints();
00273 
00274     Link* target = linkPath.endLink();
00275 
00276     std::vector<double> qorg(n);
00277     for(int i=0; i < n; ++i){
00278         qorg[i] = joints[i]->q;
00279     }
00280 
00281     dmatrix J(6, n);
00282     dvector dq(n);
00283     dvector v(6);
00284 
00285     double errsqr = maxIKErrorSqr * 100.0;
00286     bool converged = false;
00287 
00288     for(int i=0; i < MAX_IK_ITERATION; i++){
00289         
00290         calcJacobian(J);
00291         
00292         Vector3 dp(end_p - target->p);
00293         Vector3 omega(target->R * omegaFromRot(target->R.transpose() * end_R));
00294 
00295         if(isBestEffortIKMode){
00296             const double errsqr0 = errsqr;
00297             errsqr = dp.dot(dp) + omega.dot(omega);
00298             if(fabs(errsqr - errsqr0) < maxIKErrorSqr){
00299                 converged = true;
00300                 break;
00301             }
00302         } else {
00303             const double errsqr = dp.dot(dp) + omega.dot(omega);
00304             if(errsqr < maxIKErrorSqr){
00305                 converged = true;
00306                 break;
00307             }
00308         }
00309 
00310         v << dp, omega;
00311                 
00312         if(n == 6){ 
00313             solveLinearEquationLU(J, v, dq);
00314         } else {
00315             solveLinearEquationSVD(J, v, dq);  // dq = pseudoInverse(J) * v
00316         }
00317                 
00318         for(int j=0; j < n; ++j){
00319             joints[j]->q += LAMBDA * dq(j);
00320             if (joints[j]->q > joints[j]->ulimit){
00321               joints[j]->q = joints[j]->ulimit - JOINT_LIMIT_MARGIN;
00322             }else if(joints[j]->q < joints[j]->llimit){
00323               joints[j]->q = joints[j]->llimit + JOINT_LIMIT_MARGIN;
00324             }
00325         }
00326 
00327         calcForwardKinematics();
00328     }
00329 
00330     if(!converged){
00331         for(int i=0; i < n; ++i){
00332             joints[i]->q = qorg[i];
00333         }
00334         calcForwardKinematics();
00335     }
00336     
00337     return converged;
00338 }
00339 
00340 
00341 bool JointPath::hasAnalyticalIK()
00342 {
00343     return false;
00344 }
00345 
00346 
00347 std::ostream& operator<<(std::ostream& os, JointPath& path)
00348 {
00349     int n = path.numJoints();
00350     for(int i=0; i < n; ++i){
00351         Link* link = path.joint(i);
00352         os << link->name;
00353         if(i != n){
00354             os << (path.isJointDownward(i) ? " => " : " <= ");
00355         }
00356     }
00357     os << std::endl;
00358     return os;
00359 }


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Apr 11 2019 03:30:17