frames.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                         frames.cxx -  description
00003                        -------------------------
00004     begin                : June 2006
00005     copyright            : (C) 2006 Erwin Aertbelien
00006     email                : firstname.lastname@mech.kuleuven.ac.be
00007 
00008  History (only major changes)( AUTHOR-Description ) :
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place,                                    *
00024  *   Suite 330, Boston, MA  02111-1307  USA                                *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #include "frames.hpp"
00029 
00030 namespace KDL {
00031 
00032 #ifndef KDL_INLINE
00033 #include "frames.inl"
00034 #endif
00035 
00036     void Frame::Make4x4(double * d)
00037     {
00038         int i;
00039         int j;
00040         for (i=0;i<3;i++) {
00041             for (j=0;j<3;j++)
00042                 d[i*4+j]=M(i,j);
00043             d[i*4+3] = p(i)/1000;
00044         }
00045         for (j=0;j<3;j++)
00046             d[12+j] = 0.;
00047         d[15] = 1;
00048     }
00049 
00050     Frame Frame::DH_Craig1989(double a,double alpha,double d,double theta)
00051     // returns Modified Denavit-Hartenberg parameters (According to Craig)
00052     {
00053         double ct,st,ca,sa;
00054         ct = cos(theta);
00055         st = sin(theta);
00056         sa = sin(alpha);
00057         ca = cos(alpha);
00058         return Frame(Rotation(
00059                               ct,       -st,     0,
00060                               st*ca,  ct*ca,   -sa,
00061                               st*sa,  ct*sa,    ca   ),
00062                      Vector(
00063                             a,      -sa*d,  ca*d   )
00064                      );
00065     }
00066 
00067     Frame Frame::DH(double a,double alpha,double d,double theta)
00068     // returns Denavit-Hartenberg parameters (Non-Modified DH)
00069     {
00070         double ct,st,ca,sa;
00071         ct = cos(theta);
00072         st = sin(theta);
00073         sa = sin(alpha);
00074         ca = cos(alpha);
00075         return Frame(Rotation(
00076                               ct,    -st*ca,   st*sa,
00077                               st,     ct*ca,  -ct*sa,
00078                               0,        sa,      ca   ),
00079                      Vector(
00080                             a*ct,      a*st,  d   )
00081                      );
00082     }
00083 
00084     double Vector2::Norm() const
00085     {
00086         if (fabs(data[0]) > fabs(data[1]) ) {
00087             return data[0]*sqrt(1+sqr(data[1]/data[0]));
00088         } else {
00089             return data[1]*sqrt(1+sqr(data[0]/data[1]));
00090         }
00091     }
00092     // makes v a unitvector and returns the norm of v.
00093     // if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
00094     // if this is not good, check the return value of this method.
00095     double Vector2::Normalize(double eps) {
00096         double v = this->Norm();
00097         if (v < eps) {
00098             *this = Vector2(1,0);
00099             return v;
00100         } else {
00101             *this = (*this)/v;
00102             return v;
00103         }
00104     }
00105 
00106 
00107     // do some effort not to lose precision
00108     double Vector::Norm() const
00109     {
00110         double tmp1;
00111         double tmp2;
00112         tmp1 = fabs(data[0]);
00113         tmp2 = fabs(data[1]);
00114         if (tmp1 >= tmp2) {
00115             tmp2=fabs(data[2]);
00116             if (tmp1 >= tmp2) {
00117                 if (tmp1 == 0) {
00118                     // only to everything exactly zero case, all other are handled correctly
00119                     return 0;
00120                 }
00121                 return tmp1*sqrt(1+sqr(data[1]/data[0])+sqr(data[2]/data[0]));
00122             } else {
00123                 return tmp2*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
00124             }
00125         } else {
00126             tmp1=fabs(data[2]);
00127             if (tmp2 > tmp1) {
00128                 return tmp2*sqrt(1+sqr(data[0]/data[1])+sqr(data[2]/data[1]));
00129             } else {
00130                 return tmp1*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
00131             }
00132         }
00133     }
00134 
00135     // makes v a unitvector and returns the norm of v.
00136     // if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
00137     // if this is not good, check the return value of this method.
00138     double Vector::Normalize(double eps) {
00139         double v = this->Norm();
00140         if (v < eps) {
00141             *this = Vector(1,0,0);
00142             return v;
00143         } else {
00144             *this = (*this)/v;
00145             return v;
00146         }
00147     }
00148 
00149 
00150     bool Equal(const Rotation& a,const Rotation& b,double eps) {
00151         return (Equal(a.data[0],b.data[0],eps) &&
00152                 Equal(a.data[1],b.data[1],eps) &&
00153                 Equal(a.data[2],b.data[2],eps) &&
00154                 Equal(a.data[3],b.data[3],eps) &&
00155                 Equal(a.data[4],b.data[4],eps) &&
00156                 Equal(a.data[5],b.data[5],eps) &&
00157                 Equal(a.data[6],b.data[6],eps) &&
00158                 Equal(a.data[7],b.data[7],eps) &&
00159                 Equal(a.data[8],b.data[8],eps)    );
00160     }
00161 
00162 
00163 
00164     Rotation operator *(const Rotation& lhs,const Rotation& rhs)
00165     // Complexity : 27M+27A
00166     {
00167         return Rotation(
00168                         lhs.data[0]*rhs.data[0]+lhs.data[1]*rhs.data[3]+lhs.data[2]*rhs.data[6],
00169                         lhs.data[0]*rhs.data[1]+lhs.data[1]*rhs.data[4]+lhs.data[2]*rhs.data[7],
00170                         lhs.data[0]*rhs.data[2]+lhs.data[1]*rhs.data[5]+lhs.data[2]*rhs.data[8],
00171                         lhs.data[3]*rhs.data[0]+lhs.data[4]*rhs.data[3]+lhs.data[5]*rhs.data[6],
00172                         lhs.data[3]*rhs.data[1]+lhs.data[4]*rhs.data[4]+lhs.data[5]*rhs.data[7],
00173                         lhs.data[3]*rhs.data[2]+lhs.data[4]*rhs.data[5]+lhs.data[5]*rhs.data[8],
00174                         lhs.data[6]*rhs.data[0]+lhs.data[7]*rhs.data[3]+lhs.data[8]*rhs.data[6],
00175                         lhs.data[6]*rhs.data[1]+lhs.data[7]*rhs.data[4]+lhs.data[8]*rhs.data[7],
00176                         lhs.data[6]*rhs.data[2]+lhs.data[7]*rhs.data[5]+lhs.data[8]*rhs.data[8]
00177                         );
00178 
00179     }
00180 
00181     Rotation Rotation::Quaternion(double x,double y,double z, double w)
00182     {
00183         double x2, y2, z2, w2;
00184         x2 = x*x;  y2 = y*y; z2 = z*z;  w2 = w*w;
00185         return Rotation(w2+x2-y2-z2, 2*x*y-2*w*z, 2*x*z+2*w*y,
00186                         2*x*y+2*w*z, w2-x2+y2-z2, 2*y*z-2*w*x,
00187                         2*x*z-2*w*y, 2*y*z+2*w*x, w2-x2-y2+z2);
00188     }
00189 
00190     /* From the following sources:
00191        http://web.archive.org/web/20041029003853/http:/www.j3d.org/matrix_faq/matrfaq_latest.html
00192        http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
00193        RobOOP::quaternion.cpp
00194     */
00195     void Rotation::GetQuaternion(double& x,double& y,double& z, double& w) const
00196     {
00197         double trace = (*this)(0,0) + (*this)(1,1) + (*this)(2,2) + 1.0f;
00198         if( trace > epsilon ){
00199             double s = 0.5f / sqrt(trace);
00200             w = 0.25f / s;
00201             x = ( (*this)(2,1) - (*this)(1,2) ) * s;
00202             y = ( (*this)(0,2) - (*this)(2,0) ) * s;
00203             z = ( (*this)(1,0) - (*this)(0,1) ) * s;
00204         }else{
00205             if ( (*this)(0,0) > (*this)(1,1) && (*this)(0,0) > (*this)(2,2) ){
00206                 float s = 2.0f * sqrtf( 1.0f + (*this)(0,0) - (*this)(1,1) - (*this)(2,2));
00207                 w = ((*this)(2,1) - (*this)(1,2) ) / s;
00208                 x = 0.25f * s;
00209                 y = ((*this)(0,1) + (*this)(1,0) ) / s;
00210                 z = ((*this)(0,2) + (*this)(2,0) ) / s;
00211             } else if ((*this)(1,1) > (*this)(2,2)) {
00212                 float s = 2.0f * sqrtf( 1.0f + (*this)(1,1) - (*this)(0,0) - (*this)(2,2));
00213                 w = ((*this)(0,2) - (*this)(2,0) ) / s;
00214                 x = ((*this)(0,1) + (*this)(1,0) ) / s;
00215                 y = 0.25f * s;
00216                 z = ((*this)(1,2) + (*this)(2,1) ) / s;
00217             }else {
00218                 float s = 2.0f * sqrtf( 1.0f + (*this)(2,2) - (*this)(0,0) - (*this)(1,1) );
00219                 w = ((*this)(1,0) - (*this)(0,1) ) / s;
00220                 x = ((*this)(0,2) + (*this)(2,0) ) / s;
00221                 y = ((*this)(1,2) + (*this)(2,1) ) / s;
00222                 z = 0.25f * s;
00223             }
00224         }    
00225     }
00226 
00227 Rotation Rotation::RPY(double roll,double pitch,double yaw)
00228     {
00229         double ca1,cb1,cc1,sa1,sb1,sc1;
00230         ca1 = cos(yaw); sa1 = sin(yaw);
00231         cb1 = cos(pitch);sb1 = sin(pitch);
00232         cc1 = cos(roll);sc1 = sin(roll);
00233         return Rotation(ca1*cb1,ca1*sb1*sc1 - sa1*cc1,ca1*sb1*cc1 + sa1*sc1,
00234                    sa1*cb1,sa1*sb1*sc1 + ca1*cc1,sa1*sb1*cc1 - ca1*sc1,
00235                    -sb1,cb1*sc1,cb1*cc1);
00236     }
00237 
00238 // Gives back a rotation matrix specified with RPY convention
00239 void Rotation::GetRPY(double& roll,double& pitch,double& yaw) const
00240     {
00241         if (fabs(data[6]) > 1.0 - epsilon ) {
00242             roll = -sign(data[6]) * atan2(data[1], data[4]);
00243             pitch= -sign(data[6]) * PI / 2;
00244             yaw  = 0.0 ;
00245         } else {
00246             roll  = atan2(data[7], data[8]);
00247             pitch = atan2(-data[6], sqrt( sqr(data[0]) +sqr(data[3]) )  );
00248             yaw   = atan2(data[3], data[0]);
00249         }
00250     }
00251 
00252 Rotation Rotation::EulerZYZ(double Alfa,double Beta,double Gamma) {
00253         double sa,ca,sb,cb,sg,cg;
00254         sa  = sin(Alfa);ca = cos(Alfa);
00255         sb  = sin(Beta);cb = cos(Beta);
00256         sg  = sin(Gamma);cg = cos(Gamma);
00257         return Rotation( ca*cb*cg-sa*sg,     -ca*cb*sg-sa*cg,        ca*sb,
00258                  sa*cb*cg+ca*sg,     -sa*cb*sg+ca*cg,        sa*sb,
00259                  -sb*cg ,                sb*sg,              cb
00260                 );
00261 
00262      }
00263 
00264 
00265 void Rotation::GetEulerZYZ(double& alfa,double& beta,double& gamma) const {
00266         if (fabs(data[6]) < epsilon ) {
00267             alfa=0.0;
00268             if (data[8]>0) {
00269                 beta = 0.0;
00270                 gamma= atan2(-data[1],data[0]);
00271             } else {
00272                 beta = PI;
00273                 gamma= atan2(data[1],-data[0]);
00274             }
00275         } else {
00276             alfa=atan2(data[5], data[2]);
00277             beta=atan2(sqrt( sqr(data[6]) +sqr(data[7]) ),data[8]);
00278             gamma=atan2(data[7], -data[6]);
00279         }
00280  }
00281 
00282 Rotation Rotation::Rot(const Vector& rotaxis,double angle) {
00283     // The formula is
00284     // V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
00285     // can be found by multiplying it with an arbitrary vector p
00286     // and noting that this vector is rotated.
00287     Vector rotvec = rotaxis;
00288         rotvec.Normalize();
00289         return Rotation::Rot2(rotvec,angle);
00290 }
00291 
00292 Rotation Rotation::Rot2(const Vector& rotvec,double angle) {
00293     // rotvec should be normalized !
00294     // The formula is
00295     // V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
00296     // can be found by multiplying it with an arbitrary vector p
00297     // and noting that this vector is rotated.
00298     double ct = cos(angle);
00299     double st = sin(angle);
00300     double vt = 1-ct;
00301     double m_vt_0=vt*rotvec(0);
00302     double m_vt_1=vt*rotvec(1);
00303     double m_vt_2=vt*rotvec(2);
00304     double m_st_0=rotvec(0)*st;
00305     double m_st_1=rotvec(1)*st;
00306     double m_st_2=rotvec(2)*st;
00307     double m_vt_0_1=m_vt_0*rotvec(1);
00308     double m_vt_0_2=m_vt_0*rotvec(2);
00309     double m_vt_1_2=m_vt_1*rotvec(2);
00310     return Rotation(
00311         ct      +  m_vt_0*rotvec(0),
00312         -m_st_2 +  m_vt_0_1,
00313         m_st_1  +  m_vt_0_2,
00314         m_st_2  +  m_vt_0_1,
00315         ct      +  m_vt_1*rotvec(1),
00316         -m_st_0 +  m_vt_1_2,
00317         -m_st_1 +  m_vt_0_2,
00318         m_st_0  +  m_vt_1_2,
00319         ct      +  m_vt_2*rotvec(2)
00320         );
00321 }
00322 
00323 
00324 
00325 Vector Rotation::GetRot() const
00326          // Returns a vector with the direction of the equiv. axis
00327          // and its norm is angle
00328      {
00329        Vector axis  = Vector((data[7]-data[5]),
00330                              (data[2]-data[6]),
00331                              (data[3]-data[1]) )/2;
00332 
00333        double sa    = axis.Norm();
00334        double ca    = (data[0]+data[4]+data[8]-1)/2.0;
00335        double alfa;
00336        if (sa > epsilon)
00337            alfa = ::atan2(sa,ca)/sa;
00338        else
00339            alfa = 1;
00340        return axis * alfa;
00341      }
00342 
00343 
00344 
00355 double Rotation::GetRotAngle(Vector& axis,double eps) const {
00356         double ca    = (data[0]+data[4]+data[8]-1)/2.0;
00357         if (ca>1-eps) {
00358                 // undefined choose the Z-axis, and angle 0
00359                 axis = Vector(0,0,1);
00360                 return 0;
00361         }
00362         if (ca < -1+eps) {
00363                 // two solutions, choose a positive Z-component of the axis
00364                 double z = sqrt( (data[8]+1)/2 );
00365                 double x = (data[2])/2/z;
00366                 double y = (data[5])/2/z;
00367                 axis = Vector( x,y,z  );
00368                 return PI;
00369         }
00370         double angle = acos(ca);
00371         double sa    = sin(angle);
00372         axis  = Vector((data[7]-data[5])/2/sa,
00373                        (data[2]-data[6])/2/sa,
00374                        (data[3]-data[1])/2/sa  );
00375         return angle;
00376 }
00377 
00378 bool operator==(const Rotation& a,const Rotation& b) {
00379 #ifdef KDL_USE_EQUAL
00380     return Equal(a,b);
00381 #else
00382     return ( a.data[0]==b.data[0] &&
00383              a.data[1]==b.data[1] &&
00384              a.data[2]==b.data[2] &&
00385              a.data[3]==b.data[3] &&
00386              a.data[4]==b.data[4] &&
00387              a.data[5]==b.data[5] &&
00388              a.data[6]==b.data[6] &&
00389              a.data[7]==b.data[7] &&
00390              a.data[8]==b.data[8]  );
00391 #endif
00392 }
00393 }

Generated on Wed Nov 23 19:00:14 2011 for FreeCAD by  doxygen 1.6.1