Blender V2.61 - r43446
|
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 }