Blender V2.61 - r43446

frames.cpp

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