00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "frames.hpp"
00029
00030 #define _USE_MATH_DEFINES // For MSVC
00031 #include <math.h>
00032 #include <algorithm>
00033
00034 namespace KDL {
00035
00036 #ifndef KDL_INLINE
00037 #include "frames.inl"
00038 #endif
00039
00040 void Frame::Make4x4(double * d)
00041 {
00042 int i;
00043 int j;
00044 for (i=0;i<3;i++) {
00045 for (j=0;j<3;j++)
00046 d[i*4+j]=M(i,j);
00047 d[i*4+3] = p(i);
00048 }
00049 for (j=0;j<3;j++)
00050 d[12+j] = 0.;
00051 d[15] = 1;
00052 }
00053
00054 Frame Frame::DH_Craig1989(double a,double alpha,double d,double theta)
00055
00056 {
00057 double ct,st,ca,sa;
00058 ct = cos(theta);
00059 st = sin(theta);
00060 sa = sin(alpha);
00061 ca = cos(alpha);
00062 return Frame(Rotation(
00063 ct, -st, 0,
00064 st*ca, ct*ca, -sa,
00065 st*sa, ct*sa, ca ),
00066 Vector(
00067 a, -sa*d, ca*d )
00068 );
00069 }
00070
00071 Frame Frame::DH(double a,double alpha,double d,double theta)
00072
00073 {
00074 double ct,st,ca,sa;
00075 ct = cos(theta);
00076 st = sin(theta);
00077 sa = sin(alpha);
00078 ca = cos(alpha);
00079 return Frame(Rotation(
00080 ct, -st*ca, st*sa,
00081 st, ct*ca, -ct*sa,
00082 0, sa, ca ),
00083 Vector(
00084 a*ct, a*st, d )
00085 );
00086 }
00087
00088 double Vector2::Norm() const
00089 {
00090 double tmp1 = fabs(data[0]);
00091 double tmp2 = fabs(data[1]);
00092
00093 if (tmp1 == 0.0 && tmp2 == 0.0)
00094 return 0.0;
00095
00096 if (tmp1 > tmp2) {
00097 return tmp1*sqrt(1+sqr(data[1]/data[0]));
00098 } else {
00099 return tmp2*sqrt(1+sqr(data[0]/data[1]));
00100 }
00101 }
00102
00103
00104
00105 double Vector2::Normalize(double eps) {
00106 double v = this->Norm();
00107 if (v < eps) {
00108 *this = Vector2(1,0);
00109 return v;
00110 } else {
00111 *this = (*this)/v;
00112 return v;
00113 }
00114 }
00115
00116
00117
00118 double Vector::Norm() const
00119 {
00120 double tmp1;
00121 double tmp2;
00122 tmp1 = fabs(data[0]);
00123 tmp2 = fabs(data[1]);
00124 if (tmp1 >= tmp2) {
00125 tmp2=fabs(data[2]);
00126 if (tmp1 >= tmp2) {
00127 if (tmp1 == 0) {
00128
00129 return 0;
00130 }
00131 return tmp1*sqrt(1+sqr(data[1]/data[0])+sqr(data[2]/data[0]));
00132 } else {
00133 return tmp2*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
00134 }
00135 } else {
00136 tmp1=fabs(data[2]);
00137 if (tmp2 > tmp1) {
00138 return tmp2*sqrt(1+sqr(data[0]/data[1])+sqr(data[2]/data[1]));
00139 } else {
00140 return tmp1*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
00141 }
00142 }
00143 }
00144
00145
00146
00147
00148 double Vector::Normalize(double eps) {
00149 double v = this->Norm();
00150 if (v < eps) {
00151 *this = Vector(1,0,0);
00152 return v;
00153 } else {
00154 *this = (*this)/v;
00155 return v;
00156 }
00157 }
00158
00159
00160 bool Equal(const Rotation& a,const Rotation& b,double eps) {
00161 return (Equal(a.data[0],b.data[0],eps) &&
00162 Equal(a.data[1],b.data[1],eps) &&
00163 Equal(a.data[2],b.data[2],eps) &&
00164 Equal(a.data[3],b.data[3],eps) &&
00165 Equal(a.data[4],b.data[4],eps) &&
00166 Equal(a.data[5],b.data[5],eps) &&
00167 Equal(a.data[6],b.data[6],eps) &&
00168 Equal(a.data[7],b.data[7],eps) &&
00169 Equal(a.data[8],b.data[8],eps) );
00170 }
00171
00172
00173
00174 Rotation operator *(const Rotation& lhs,const Rotation& rhs)
00175
00176 {
00177 return Rotation(
00178 lhs.data[0]*rhs.data[0]+lhs.data[1]*rhs.data[3]+lhs.data[2]*rhs.data[6],
00179 lhs.data[0]*rhs.data[1]+lhs.data[1]*rhs.data[4]+lhs.data[2]*rhs.data[7],
00180 lhs.data[0]*rhs.data[2]+lhs.data[1]*rhs.data[5]+lhs.data[2]*rhs.data[8],
00181 lhs.data[3]*rhs.data[0]+lhs.data[4]*rhs.data[3]+lhs.data[5]*rhs.data[6],
00182 lhs.data[3]*rhs.data[1]+lhs.data[4]*rhs.data[4]+lhs.data[5]*rhs.data[7],
00183 lhs.data[3]*rhs.data[2]+lhs.data[4]*rhs.data[5]+lhs.data[5]*rhs.data[8],
00184 lhs.data[6]*rhs.data[0]+lhs.data[7]*rhs.data[3]+lhs.data[8]*rhs.data[6],
00185 lhs.data[6]*rhs.data[1]+lhs.data[7]*rhs.data[4]+lhs.data[8]*rhs.data[7],
00186 lhs.data[6]*rhs.data[2]+lhs.data[7]*rhs.data[5]+lhs.data[8]*rhs.data[8]
00187 );
00188
00189 }
00190
00191 Rotation Rotation::Quaternion(double x,double y,double z, double w)
00192 {
00193 double x2, y2, z2, w2;
00194 x2 = x*x; y2 = y*y; z2 = z*z; w2 = w*w;
00195 return Rotation(w2+x2-y2-z2, 2*x*y-2*w*z, 2*x*z+2*w*y,
00196 2*x*y+2*w*z, w2-x2+y2-z2, 2*y*z-2*w*x,
00197 2*x*z-2*w*y, 2*y*z+2*w*x, w2-x2-y2+z2);
00198 }
00199
00200
00201
00202
00203
00204
00205 void Rotation::GetQuaternion(double& x,double& y,double& z, double& w) const
00206 {
00207 double trace = (*this)(0,0) + (*this)(1,1) + (*this)(2,2);
00208 double epsilon=1E-12;
00209 if( trace > epsilon ){
00210 double s = 0.5 / sqrt(trace + 1.0);
00211 w = 0.25 / s;
00212 x = ( (*this)(2,1) - (*this)(1,2) ) * s;
00213 y = ( (*this)(0,2) - (*this)(2,0) ) * s;
00214 z = ( (*this)(1,0) - (*this)(0,1) ) * s;
00215 }else{
00216 if ( (*this)(0,0) > (*this)(1,1) && (*this)(0,0) > (*this)(2,2) ){
00217 double s = 2.0 * sqrt( 1.0 + (*this)(0,0) - (*this)(1,1) - (*this)(2,2));
00218 w = ((*this)(2,1) - (*this)(1,2) ) / s;
00219 x = 0.25 * s;
00220 y = ((*this)(0,1) + (*this)(1,0) ) / s;
00221 z = ((*this)(0,2) + (*this)(2,0) ) / s;
00222 } else if ((*this)(1,1) > (*this)(2,2)) {
00223 double s = 2.0 * sqrt( 1.0 + (*this)(1,1) - (*this)(0,0) - (*this)(2,2));
00224 w = ((*this)(0,2) - (*this)(2,0) ) / s;
00225 x = ((*this)(0,1) + (*this)(1,0) ) / s;
00226 y = 0.25 * s;
00227 z = ((*this)(1,2) + (*this)(2,1) ) / s;
00228 }else {
00229 double s = 2.0 * sqrt( 1.0 + (*this)(2,2) - (*this)(0,0) - (*this)(1,1) );
00230 w = ((*this)(1,0) - (*this)(0,1) ) / s;
00231 x = ((*this)(0,2) + (*this)(2,0) ) / s;
00232 y = ((*this)(1,2) + (*this)(2,1) ) / s;
00233 z = 0.25 * s;
00234 }
00235 }
00236 }
00237
00238 Rotation Rotation::RPY(double roll,double pitch,double yaw)
00239 {
00240 double ca1,cb1,cc1,sa1,sb1,sc1;
00241 ca1 = cos(yaw); sa1 = sin(yaw);
00242 cb1 = cos(pitch);sb1 = sin(pitch);
00243 cc1 = cos(roll);sc1 = sin(roll);
00244 return Rotation(ca1*cb1,ca1*sb1*sc1 - sa1*cc1,ca1*sb1*cc1 + sa1*sc1,
00245 sa1*cb1,sa1*sb1*sc1 + ca1*cc1,sa1*sb1*cc1 - ca1*sc1,
00246 -sb1,cb1*sc1,cb1*cc1);
00247 }
00248
00249
00250 void Rotation::GetRPY(double& roll,double& pitch,double& yaw) const
00251 {
00252 double epsilon=1E-12;
00253 pitch = atan2(-data[6], sqrt( sqr(data[0]) +sqr(data[3]) ) );
00254 if ( fabs(pitch) > (M_PI/2.0-epsilon) ) {
00255 yaw = atan2( -data[1], data[4]);
00256 roll = 0.0 ;
00257 } else {
00258 roll = atan2(data[7], data[8]);
00259 yaw = atan2(data[3], data[0]);
00260 }
00261 }
00262
00263 Rotation Rotation::EulerZYZ(double Alfa,double Beta,double Gamma) {
00264 double sa,ca,sb,cb,sg,cg;
00265 sa = sin(Alfa);ca = cos(Alfa);
00266 sb = sin(Beta);cb = cos(Beta);
00267 sg = sin(Gamma);cg = cos(Gamma);
00268 return Rotation( ca*cb*cg-sa*sg, -ca*cb*sg-sa*cg, ca*sb,
00269 sa*cb*cg+ca*sg, -sa*cb*sg+ca*cg, sa*sb,
00270 -sb*cg , sb*sg, cb
00271 );
00272
00273 }
00274
00275
00276 void Rotation::GetEulerZYZ(double& alpha,double& beta,double& gamma) const {
00277 double epsilon = 1E-12;
00278 if (fabs(data[8]) > 1-epsilon ) {
00279 gamma=0.0;
00280 if (data[8]>0) {
00281 beta = 0.0;
00282 alpha= atan2(data[3],data[0]);
00283 } else {
00284 beta = PI;
00285 alpha= atan2(-data[3],-data[0]);
00286 }
00287 } else {
00288 alpha=atan2(data[5], data[2]);
00289 beta=atan2(sqrt( sqr(data[6]) +sqr(data[7]) ),data[8]);
00290 gamma=atan2(data[7], -data[6]);
00291 }
00292 }
00293
00294 Rotation Rotation::Rot(const Vector& rotaxis,double angle) {
00295
00296
00297
00298
00299 Vector rotvec = rotaxis;
00300 rotvec.Normalize();
00301 return Rotation::Rot2(rotvec,angle);
00302 }
00303
00304 Rotation Rotation::Rot2(const Vector& rotvec,double angle) {
00305
00306
00307
00308
00309
00310 double ct = cos(angle);
00311 double st = sin(angle);
00312 double vt = 1-ct;
00313 double m_vt_0=vt*rotvec(0);
00314 double m_vt_1=vt*rotvec(1);
00315 double m_vt_2=vt*rotvec(2);
00316 double m_st_0=rotvec(0)*st;
00317 double m_st_1=rotvec(1)*st;
00318 double m_st_2=rotvec(2)*st;
00319 double m_vt_0_1=m_vt_0*rotvec(1);
00320 double m_vt_0_2=m_vt_0*rotvec(2);
00321 double m_vt_1_2=m_vt_1*rotvec(2);
00322 return Rotation(
00323 ct + m_vt_0*rotvec(0),
00324 -m_st_2 + m_vt_0_1,
00325 m_st_1 + m_vt_0_2,
00326 m_st_2 + m_vt_0_1,
00327 ct + m_vt_1*rotvec(1),
00328 -m_st_0 + m_vt_1_2,
00329 -m_st_1 + m_vt_0_2,
00330 m_st_0 + m_vt_1_2,
00331 ct + m_vt_2*rotvec(2)
00332 );
00333 }
00334
00335
00336
00337 Vector Rotation::GetRot() const
00338
00339
00340 {
00341 Vector axis;
00342 double angle;
00343 angle = Rotation::GetRotAngle(axis,epsilon);
00344 return axis * angle;
00345 }
00346
00347
00348
00359 double Rotation::GetRotAngle(Vector& axis,double eps) const {
00360 double angle,x,y,z;
00361 double epsilon = eps;
00362 double epsilon2 = eps*10;
00363
00364
00365
00366
00367 if ((std::abs(data[1] - data[3]) < epsilon)
00368 && (std::abs(data[2] - data[6])< epsilon)
00369 && (std::abs(data[5] - data[7]) < epsilon))
00370 {
00371
00372
00373
00374 if ((std::abs(data[1] + data[3]) < epsilon2)
00375 && (std::abs(data[2] + data[6]) < epsilon2)
00376 && (std::abs(data[5] + data[7]) < epsilon2)
00377 && (std::abs(data[0] + data[4] + data[8]-3) < epsilon2))
00378 {
00379
00380
00381 axis = KDL::Vector(0,0,1);
00382 angle = 0.0;
00383 return angle;
00384 }
00385
00386
00387 angle = M_PI;
00388 double xx = (data[0] + 1) / 2;
00389 double yy = (data[4] + 1) / 2;
00390 double zz = (data[8] + 1) / 2;
00391 double xy = (data[1] + data[3]) / 4;
00392 double xz = (data[2] + data[6]) / 4;
00393 double yz = (data[5] + data[7]) / 4;
00394
00395 if ((xx > yy) && (xx > zz))
00396 {
00397
00398 x = sqrt(xx);
00399 y = xy/x;
00400 z = xz/x;
00401 }
00402 else if (yy > zz)
00403 {
00404
00405 y = sqrt(yy);
00406 x = xy/y;
00407 z = yz/y;
00408 }
00409 else
00410 {
00411
00412 z = sqrt(zz);
00413 x = xz/z;
00414 y = yz/z;
00415 }
00416 axis = KDL::Vector(x, y, z);
00417 return angle;
00418 }
00419
00420
00421
00422 double f = (data[0] + data[4] + data[8] - 1) / 2;
00423 angle = acos(std::max(-1.0, std::min(1.0, f)));
00424
00425 x = (data[7] - data[5]);
00426 y = (data[2] - data[6]);
00427 z = (data[3] - data[1]);
00428 axis = KDL::Vector(x, y, z);
00429 axis.Normalize();
00430 return angle;
00431 }
00432
00433 bool operator==(const Rotation& a,const Rotation& b) {
00434 #ifdef KDL_USE_EQUAL
00435 return Equal(a,b);
00436 #else
00437 return ( a.data[0]==b.data[0] &&
00438 a.data[1]==b.data[1] &&
00439 a.data[2]==b.data[2] &&
00440 a.data[3]==b.data[3] &&
00441 a.data[4]==b.data[4] &&
00442 a.data[5]==b.data[5] &&
00443 a.data[6]==b.data[6] &&
00444 a.data[7]==b.data[7] &&
00445 a.data[8]==b.data[8] );
00446 #endif
00447 }
00448 }