vecmath.cpp
Go to the documentation of this file.
00001 
00028 #include <stdio.h>
00029 #include <math.h>
00030 #include <iostream>
00031 
00032 
00033 #include "frame.h"
00034 #include "vecmath.h"
00035 
00036 #define SWAP(x,y) tmp = a[x];a[x]=a[y];a[y] = tmp;
00037 #define ROUND(x) rnd(x*10)/10.0)
00038 
00039 using namespace std;
00040 
00041 namespace robotLibPbD {
00042 
00043 
00044 boost::mt19937 pRngMt19937;
00045 boost::uniform_01<double> pRngDist;
00046 boost::variate_generator<boost::mt19937&, boost::uniform_01<double> > pRngUniform01(pRngMt19937, pRngDist);
00047 
00048 //static PRECISION tmpCMatrixMul[16];
00049 
00050 // sets vector to (x y z 1.0)
00051 void CVec::set(PRECISION x, PRECISION y, PRECISION z)
00052 {
00053      this->x = x;
00054          this->y = y;
00055          this->z = z;
00056          this->w = 1.0;
00057 }
00058         
00059 // prints vector value
00060 void CVec::print() const
00061 {
00062      printf("%f %f %f", x, y, z);
00063 }
00064     
00065 std::string CVec::toString()
00066 {
00067     char str[255];
00068     sprintf(str, "%f %f %f", x, y, z);
00069     return std::string(str);
00070 }
00071 
00072 // inits matrix with 1-Matrix
00073 CMatrix::CMatrix()
00074 {
00075      set( 1.0, 0.0, 0.0, 0.0, 
00076               0.0, 1.0, 0.0, 0.0, 
00077               0.0, 0.0, 1.0, 0.0, 
00078               0.0, 0.0, 0.0, 1.0);
00079 }
00080 
00081 void CMatrix::randomOrientation(double max)
00082 {
00083   CVec tmp;
00084   tmp.x = getGaussianProb(0.0, 1.0);
00085   tmp.y = getGaussianProb(0.0, 1.0);
00086   tmp.z = getGaussianProb(0.0, 1.0);
00087   tmp.normalize();
00088 
00089   CMathLib::getMatrixFromRotation(*this, tmp, getUniform() * max);
00090 }
00091 
00092 void CMatrix::unity()
00093 {
00094      set( 1.0, 0.0, 0.0, 0.0, 
00095               0.0, 1.0, 0.0, 0.0, 
00096               0.0, 0.0, 1.0, 0.0, 
00097               0.0, 0.0, 0.0, 1.0);
00098 }
00099 
00100 void CMatrix::printText()
00101 {
00102     double x,y,z,a,b,g;
00103     x = this->a[12];
00104     y = this->a[13];
00105     z = this->a[14];
00106 
00107     CVec tmp1, tmp2;
00108     CMathLib::getOrientation(*this, tmp1, tmp2);
00109 
00110     a = tmp1.x * 180.0/M_PI;
00111     b = tmp1.y * 180.0/M_PI;
00112     g = tmp1.z * 180.0/M_PI;
00113 
00114     printf("%g %g %g %g %g %g\n", x, y, z, a, b, g);
00115 }
00116 
00117 // transposes matrix    
00118 void CMatrix::transpose()
00119 {
00120      PRECISION tmp;
00121      SWAP(1,4);
00122      SWAP(2,8);
00123      SWAP(6,9);
00124      SWAP(3,12);
00125      SWAP(7,13);
00126      SWAP(11,14);
00127 }
00128 
00129 
00130 
00131 // sets matrix to supplied value        
00132 CMatrix::CMatrix( PRECISION a0, PRECISION a4, PRECISION a8,  PRECISION a12,
00133                   PRECISION a1, PRECISION a5, PRECISION a9,  PRECISION a13,
00134                   PRECISION a2, PRECISION a6, PRECISION a10, PRECISION a14,
00135                   PRECISION a3, PRECISION a7, PRECISION a11, PRECISION a15)
00136 {
00137      a[0] = a0;  a[4] = a4;  a[8]  = a8;   a[12] = a12;
00138      a[1] = a1;  a[5] = a5;  a[9]  = a9;   a[13] = a13;
00139      a[2] = a2;  a[6] = a6;  a[10] = a10;  a[14] = a14;
00140      a[3] = a3;  a[7] = a7;  a[11] = a11;  a[15] = a15;
00141 }
00142 
00143 // sets matrix to supplied value        
00144 void CMatrix::set( PRECISION a0, PRECISION a4, PRECISION a8,  PRECISION a12,
00145                    PRECISION a1, PRECISION a5, PRECISION a9,  PRECISION a13,
00146                    PRECISION a2, PRECISION a6, PRECISION a10, PRECISION a14,
00147                    PRECISION a3, PRECISION a7, PRECISION a11 , PRECISION a15)
00148 {
00149      a[0] = a0;  a[4] = a4;  a[8]  = a8;   a[12] = a12;
00150      a[1] = a1;  a[5] = a5;  a[9]  = a9;   a[13] = a13;
00151      a[2] = a2;  a[6] = a6;  a[10] = a10;  a[14] = a14;
00152      a[3] = a3;  a[7] = a7;  a[11] = a11;  a[15] = a15;
00153 }
00154 
00155 // creates denavit hartenberg transformation matrix     based on CDh struct
00156 void CMatrix::setDh(const CDh &dh)
00157 {
00158   if (dh.useAxis)
00159     {
00160       if (dh.rotationalDof)
00161         {
00162           CMathLib::getMatrixFromRotation(*this, dh.axis, dh.rot_z + dh.angle);
00163           a[12] = 0.0;
00164           a[13] = 0.0;
00165           a[14] = 0.0;
00166         } else
00167         {
00168           a[0] = 1.0;
00169           a[1] = 0.0;
00170           a[2] = 0.0;
00171           a[3] = 0.0;
00172           a[4] = 0.0;
00173           a[5] = 1.0;
00174           a[6] = 0.0;
00175           a[7] = 0.0;
00176           a[8] = 0.0;
00177           a[9] = 0.0;
00178           a[10] = 1.0;
00179           a[11] = 0.0;
00180           a[12] = dh.axis.x * (dh.rot_z + dh.angle);
00181           a[13] = dh.axis.y * (dh.rot_z + dh.angle);
00182           a[14] = dh.axis.z * (dh.rot_z + dh.angle);
00183           a[15] = 1.0;
00184         }
00185     } else if (dh.rotationalDof)
00186     {
00187       a[0] = cos(dh.rot_z + dh.angle);  a[4] = -sin(dh.rot_z + dh.angle)*cos(dh.rot_x);  a[8]  = sin(dh.rot_x)*sin(dh.rot_z + dh.angle);   a[12] = dh.trans_x*cos(dh.rot_z + dh.angle);
00188       a[1] = sin(dh.rot_z + dh.angle);  a[5] = cos(dh.rot_x)*cos(dh.rot_z + dh.angle);   a[9]  =  -cos(dh.rot_z + dh.angle)*sin(dh.rot_x); a[13] = dh.trans_x*sin(dh.rot_z + dh.angle);
00189       a[2] = 0.0;                       a[6] = sin(dh.rot_x);                            a[10] = cos(dh.rot_x);                            a[14] = dh.trans_z;
00190       a[3] = 0.0;                       a[7] = 0.0;                                      a[11] = 0.0;                                      a[15] = 1.0;
00191     } else
00192     {
00193       a[0] = cos(dh.rot_z);  a[4] = -sin(dh.rot_z)*cos(dh.rot_x);  a[8]  = sin(dh.rot_x) * sin(dh.rot_z);   a[12] = dh.trans_x*cos(dh.rot_z);
00194       a[1] = sin(dh.rot_z);  a[5] = cos(dh.rot_x)*cos(dh.rot_z);   a[9]  = -cos(dh.rot_z) * sin(dh.rot_x); a[13] = dh.trans_x*sin(dh.rot_z);
00195       a[2] = 0.0;            a[6] = sin(dh.rot_x);                 a[10] = cos(dh.rot_x);                 a[14] = dh.trans_z + dh.angle;
00196       a[3] = 0.0;            a[7] = 0.0;                           a[11] = 0.0;                           a[15] = 1.0;
00197     }
00198 }
00199 
00200 // trace of rotational 3x3 part of matrix       
00201 PRECISION CMatrix::trace()
00202 {
00203      return a[0] + a[5] + a[10];
00204 }
00205        
00206 // print matrix contents        
00207 void CMatrix::print(bool round) const
00208 {
00209    //char str[1024];
00210    
00211    #define RND(x) (round ? rnd(x*10)/10.0 : x)
00212    printf(      
00213                 "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", 
00214                 RND(a[0]), RND(a[4]), RND(a[8]), RND(a[12]), 
00215                 RND(a[1]), RND(a[5]), RND(a[9]), RND(a[13]), 
00216                 RND(a[2]), RND(a[6]), RND(a[10]), RND(a[14]), 
00217                 RND(a[3]), RND(a[7]), RND(a[11]), RND(a[15]));
00218 }
00219 
00220 
00221 std::string CMatrix::toString(bool round)
00222 {
00223     char str[1024];
00224 #define RND(x) (round ? rnd(x*10)/10.0 : x)
00225     sprintf(     str, 
00226                  "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", 
00227                  RND(a[0]), RND(a[4]), RND(a[8]), RND(a[12]), 
00228                  RND(a[1]), RND(a[5]), RND(a[9]), RND(a[13]), 
00229                  RND(a[2]), RND(a[6]), RND(a[10]), RND(a[14]), 
00230                  RND(a[3]), RND(a[7]), RND(a[11]), RND(a[15]));
00231     return std::string(str);
00232 }
00233 
00234 // scalar multiplication    
00235 CMatrix CMatrix::operator * ( PRECISION f) const  
00236 {       
00237     return CMatrix( a[0]*f, a[4]*f, a[8]*f, a[12]*f,
00238                     a[1]*f, a[5]*f, a[9]*f, a[13]*f,
00239                     a[2]*f, a[6]*f, a[10]*f, a[14]*f,
00240                     0.0, 0.0, 0.0, 1.0);        
00241 }
00242 
00243 // matrix add operator  
00244 CMatrix CMatrix::operator + (const  CMatrix &b) const 
00245 {       
00246     return CMatrix( a[0]+b.a[0], a[4]+b.a[4], a[8]+b.a[8], a[12]+b.a[12],
00247                     a[1]+b.a[1], a[5]+b.a[5], a[9]+b.a[9], a[13]+b.a[13],
00248                     a[2]+b.a[2], a[6]+b.a[6], a[10]+b.a[10], a[14]+b.a[14],
00249                     0.0, 0.0, 0.0, 1.0);        
00250 }
00251 
00252 // matrix sub operator  
00253 CMatrix CMatrix::operator - (const  CMatrix &b) const 
00254 {       
00255     return CMatrix( a[0]-b.a[0], a[4]-b.a[4], a[8]-b.a[8], a[12]-b.a[12],
00256                     a[1]-b.a[1], a[5]-b.a[5], a[9]-b.a[9], a[13]-b.a[13],
00257                     a[2]-b.a[2], a[6]-b.a[6], a[10]-b.a[10], a[14]-b.a[14],
00258                     0.0, 0.0, 0.0, 1.0);        
00259 }
00260 
00261 // matrix product operator      
00262 CMatrix CMatrix::operator * (const  CMatrix &m) const 
00263 {       
00264     CMatrix tmp;
00265     tmp.mul((*this), m);
00266     return tmp; 
00267 }
00268 
00269 // add a translation to homogenous matrix       
00270 CMatrix& CMatrix::operator += (const  CVec &v) 
00271 {       
00272     a[12] += v.x;
00273     a[13] += v.y;
00274     a[14] += v.z;
00275     return *this;       
00276 }
00277 
00278 // calculate matrix * vector    
00279 CVec CMatrix::operator * (const  CVec &v) const  
00280 {       
00281     PRECISION x, y, z;
00282     x = a[0]*v.x + a[4]*v.y + a[8]*v.z + a[12]*v.w;
00283     y = a[1]*v.x + a[5]*v.y + a[9]*v.z + a[13]*v.w;
00284     z = a[2]*v.x + a[6]*v.y + a[10]*v.z + a[14]*v.w;
00285     return CVec(x, y, z);       
00286 }
00287 
00288 
00289 // array operator, read only    
00290 const CVec& CMatrix::operator [] ( int i ) const 
00291 {       
00292     return *( const CVec*) &a[4*i];     
00293 }
00294 
00295 CVec& CMatrix::operator [] ( int i ) 
00296 {       
00297     return *(CVec*) &a[4*i];    
00298 }
00299         
00300 // assignment operator
00301 CMatrix& CMatrix::operator = ( const CMatrix& v)
00302 {
00303     memcpy(a,v.a, 16*sizeof(PRECISION));
00304     return *this;
00305 }
00306 
00307 // rounds a value       
00308 int rnd(PRECISION value)
00309 {
00310      return (int) (value < 0.0 ? ceil(value - 0.5) : floor(value +0.5));
00311 }
00312 
00313 void CMatrix::matrixToArray(std::vector<double> &values)
00314 {
00315   values.resize(12);
00316   values[0] = a[12];
00317   values[1] = a[13];
00318   values[2] = a[14];
00319 
00320   
00321   values[3]  = a[0];
00322   values[4]  = a[1];
00323   values[5]  = a[2];
00324   values[6]  = a[4];
00325   values[7]  = a[5];
00326   values[8]  = a[6];
00327   values[9]  = a[8];
00328   values[10] = a[9];
00329   values[11] = a[10];
00330 }
00331 
00332 void CMatrix::arrayToMatrix(std::vector<double> &values)
00333 {
00334     a[12] = values[0];
00335     a[13] = values[1];
00336     a[14] = values[2];
00337     a[15] = 1.0;
00338                
00339     a[0] = values[3];
00340     a[1] = values[4];
00341     a[2] = values[5];
00342     a[3] = 0.0;
00343                
00344     a[4] = values[6];
00345     a[5] = values[7];
00346     a[6] = values[8];
00347     a[7] = 0.0;
00348                
00349     a[8] = values[9];
00350     a[9] = values[10];
00351     a[10] = values[11];
00352     a[11] = 0.0;
00353 }
00354 
00355 PRECISION CMatrix::length() const
00356 {
00357     double dist = sqrt(a[12]*a[12]+a[13]*a[13]+a[14]*a[14]);
00358     CVec axis;
00359     double angle;
00360     CMathLib::getRotationFromMatrix(*this, axis, angle);
00361   
00362     if (2.0*M_PI - angle < angle)
00363       angle = 2.0*M_PI-angle;
00364 
00365     return dist + fabsf(angle) * 180.0/M_PI;
00366 }
00367 
00368 
00369 
00370 // calculates rotation matrix from quaternion
00371 // http://www.flipcode.com/documents/matrfaq.html
00372 void CMathLib::matrixFromQuaternion(CVec &quaternion, CMatrix &matrix)
00373 {
00374     double xx,xy,xz,xw,yy,yz,yw,zz,zw;
00375     double X = quaternion.x;
00376     double Y = quaternion.y;
00377     double Z = quaternion.z;
00378     double W = quaternion.w;
00379     xx      = X * X;
00380     xy      = X * Y;
00381     xz      = X * Z;
00382     xw      = X * W;
00383 
00384     yy      = Y * Y;
00385     yz      = Y * Z;
00386     yw      = Y * W;
00387 
00388     zz      = Z * Z;
00389     zw      = Z * W;
00390 
00391     matrix.a[0]  = 1.0 - 2.0 * ( yy + zz );
00392     matrix.a[4]  =     2.0 * ( xy - zw );
00393     matrix.a[8]  =     2.0 * ( xz + yw );
00394 
00395     matrix.a[1]  =     2.0 * ( xy + zw );
00396     matrix.a[5]  = 1.0 - 2.0 * ( xx + zz );
00397     matrix.a[9]  =     2.0 * ( yz - xw );
00398 
00399     matrix.a[2]  =     2.0 * ( xz - yw );
00400     matrix.a[6]  =     2.0 * ( yz + xw );
00401     matrix.a[10] = 1.0 - 2.0 * ( xx + yy );
00402 
00403     matrix.a[3]  = matrix.a[7] = matrix.a[11] = matrix.a[12] = matrix.a[13] = matrix.a[14] = 0.0;
00404     matrix.a[15] = 1.0;
00405 }
00406 
00407 // calculates matrix from rotation axis and rotation angle
00408 // http://www.flipcode.com/documents/matrfaq.html
00409 void CMathLib::getMatrixFromRotation(CMatrix &mat, const CVec &axis, double angle)
00410 {
00411     CVec tmp, quater;
00412     double sin_a = sin( angle / 2.0 );
00413     double cos_a = cos( angle / 2.0 );
00414 
00415     tmp.x = axis.x * sin_a;
00416     tmp.y = axis.y * sin_a;
00417     tmp.z = axis.z * sin_a;
00418     tmp.w = cos_a;
00419 
00420     // normalisieren
00421     double tmpf = 1.0/sqrt(tmp.x*tmp.x+
00422                 tmp.y*tmp.y+
00423                 tmp.z*tmp.z+
00424                 tmp.w*tmp.w); 
00425     
00426     //tmpf = 1.0;
00427                 
00428     quater.x = tmp.x * tmpf;
00429     quater.y = tmp.y * tmpf;
00430     quater.z = tmp.z * tmpf;
00431     quater.w = tmp.w * tmpf;   
00432 
00433     matrixFromQuaternion(quater, mat); 
00434 }
00435 
00436 void CMathLib::getQuaternionFromRotation(CVec &quater, CVec &axis, double angle)
00437 {
00438     CVec tmp;
00439     double sin_a = sin( angle / 2.0 );
00440     double cos_a = cos( angle / 2.0 );
00441 
00442     tmp.x = axis.x * sin_a;
00443     tmp.y = axis.y * sin_a;
00444     tmp.z = axis.z * sin_a;
00445     tmp.w = cos_a;
00446 
00447     // normalisieren
00448     double tmpf = 1.0/sqrt(tmp.x*tmp.x+
00449             tmp.y*tmp.y+
00450             tmp.z*tmp.z+
00451             tmp.w*tmp.w); 
00452     
00453     //tmpf = 1.0;
00454                 
00455     quater.x = tmp.x * tmpf;
00456     quater.y = tmp.y * tmpf;
00457     quater.z = tmp.z * tmpf;
00458     quater.w = tmp.w * tmpf;   
00459 }
00460 
00461 // calculates rotation axis and angle from rotation matrix
00462 // http://www.flipcode.com/documents/matrfaq.html
00463 void CMathLib::getRotationFromMatrix(const CMatrix &mat, CVec &result, double &angle)
00464 {
00465          CVec quat, tmp;
00466          double rotangle, tmpf, cos_a, sin_a;
00467          quaternionFromMatrix(mat, tmp); 
00468          
00469          // normalisieren
00470          tmpf = 1.0/sqrt(tmp.x*tmp.x+
00471                 tmp.y*tmp.y+
00472                 tmp.z*tmp.z+
00473                 tmp.w*tmp.w); 
00474                 
00475          quat = tmp * tmpf;
00476          quat.w = tmp.w * tmpf;      
00477       
00478          cos_a = quat.w;
00479          rotangle = acos( cos_a ) * 2;
00480          sin_a = sqrt( 1.0 - cos_a * cos_a );
00481          if ( fabs( sin_a ) < 0.0005 ) sin_a = 1;
00482          
00483          result.x = quat.x / sin_a;
00484          result.y = quat.y / sin_a;
00485          result.z = quat.z / sin_a;
00486 
00487          angle = rotangle;
00488          
00489          /*
00490          if (result.z < 0.0)
00491            {
00492              result = -result;
00493              angle = -angle;
00494            }
00495          */
00496 }
00497 
00498 // calculates matrix[n x m] * vector [m]
00499 void CMathLib::calcMatrixResult(double a[], double b[], int n, int m, double result[])
00500 {
00501      int i,j;
00502      for (i=0;i<n;i++)
00503      {
00504          result[i] = 0.0;    
00505          for (j=0;j<m; j++)
00506              result[i] += a[i*n+j]*b[j];
00507      }
00508 }
00509 
00510 // calculates dot product a[n] * b[n]
00511 double CMathLib::calcDotProduct(double a[], double b[], int n)
00512 {
00513      int i;
00514      double tmp = a[0]*b[0];
00515      for (i=1;i<n;i++)
00516          tmp += a[i]*b[i];
00517          
00518      return tmp;
00519 }
00520 
00521 
00522 
00523 // calculates quaternion from rotation matrix
00524 // http://www.flipcode.com/documents/matrfaq.html
00525 void CMathLib::quaternionFromMatrix(const CMatrix &mat, CVec &quaternion)
00526 {
00527   double T = 1 + mat.a[0] + mat.a[5] + mat.a[10];//mat.trace();
00528      double S,X,Y,Z,W;
00529      
00530      if (T > 0.00000001)
00531      {
00532       S = 2 * sqrt(T);
00533       X = (mat.a[6] - mat.a[9])/S;
00534       Y = (mat.a[8] - mat.a[2])/S;
00535       Z = (mat.a[1] - mat.a[4])/S;   
00536       W = S*0.25;
00537      } else
00538      if ( mat.a[0] > mat.a[5] && mat.a[0] > mat.a[10] )  {      // Column 0: 
00539         S  = sqrt( 1.0 + mat.a[0] - mat.a[5] - mat.a[10] ) * 2;
00540         X = 0.25 * S;
00541         Y = (mat.a[4] + mat.a[1] ) / S;
00542         Z = (mat.a[2] + mat.a[8] ) / S;
00543         W = (mat.a[6] - mat.a[9] ) / S;
00544     } else if ( mat.a[5] > mat.a[10] ) {                        // Column 1: 
00545         S  = sqrt( 1.0 + mat.a[5] - mat.a[0] - mat.a[10] ) * 2;
00546         X = (mat.a[4] + mat.a[1] ) / S;
00547         Y = 0.25 * S;
00548         Z = (mat.a[9] + mat.a[6] ) / S;
00549         W = (mat.a[8] - mat.a[2] ) / S;
00550     } else {                                            // Column 2:
00551         S  = sqrt( 1.0 + mat.a[10] - mat.a[0] - mat.a[5] ) * 2;
00552         X = (mat.a[2] + mat.a[8] ) / S;
00553         Y = (mat.a[9] + mat.a[6] ) / S;
00554         Z = 0.25 * S;
00555         W = (mat.a[1] - mat.a[4] ) / S;
00556     }
00557     
00558     quaternion.x = X;
00559     quaternion.y = Y;
00560     quaternion.z = Z;
00561     quaternion.w = W;
00562 }
00563 
00564 // transposes matrix a[n x n]
00565 void CMathLib::transposeMatrix(double *a, double *result, int n)
00566 {
00567      int i,j;
00568      double tmp;
00569      for (i=0;i<n;i++)
00570          for (j=0;j<i;j++)
00571          {
00572              tmp = a[i*n+j];
00573              result[i*n+j] = a[j*n+i];
00574              result[j*n+i] = tmp; 
00575          }
00576 }
00577 
00578 // multiplies two matrix a[n x m] * b [m x k]
00579 void CMathLib::multiplyMatrices(double *a, double *b, int n, int m, int k, double *res)
00580 {
00581      int i,j,l;
00582      for (i=0; i<n; i++)
00583          for (j=0; j<k; j++)
00584          {
00585              res[i*n + j] = 0.0;
00586              for (l=0; l<m; l++)
00587              res[i*n + j] += a[i*n + l] * b[l*m + j];
00588          }
00589 }
00590 
00591 // calculates euler angles representing rotation matrix
00592 /*void CMathLib::getOrientation(CMatrix &mat, CVec &first, CVec &second)
00593 {
00594      //g = roll, a = pitch, b = yaw
00595      double a, b, g;
00596      
00597      
00598      b = atan2(-mat.a[4], sqrt(mat.a[5]*mat.a[5]+mat.a[6]*mat.a[6]));
00599 
00600      if (fabs(b - M_PI/2.0) < 0.0001)
00601      {
00602         g = 0;
00603         a = atan2(mat.a[9], mat.a[10]);        
00604      } else if (fabs(b + M_PI/2.0) < 0.0001)
00605      {
00606         g = 0;
00607         a = atan2(-mat.a[9], mat.a[10]);        
00608      } else
00609      {
00610         a = atan2(mat.a[8]/cos(b), mat.a[0]/cos(b));
00611         g = atan2(mat.a[6]/cos(b), mat.a[5]/cos(b));   
00612      }
00613      
00614      first.set(g, a, b);
00615      second = first;
00616 }*/
00617 
00618 void CMathLib::getEulerZXZ(CMatrix &mat, CVec &first)
00619 {
00620   if (mat.a[10] < 1.0)
00621     {
00622       if (mat.a[10]>-1.0)
00623         {
00624           first.x = atan2(mat.a[8], -mat.a[9]);
00625           first.y = acos(mat.a[10]);
00626           first.z = atan2(mat.a[2], mat.a[6]);
00627         } else
00628         {
00629           first.x = -atan2(-mat.a[4], mat.a[0]);
00630           first.y = M_PI;
00631           first.z = 0;
00632         }
00633     } else
00634     {
00635       first.x = 0;
00636       first.y = atan2(-mat.a[4], mat.a[0]);
00637       first.z = 0;
00638     }
00639 }
00640 
00641 // calculates euler angles representing rotation matrix
00642 void CMathLib::getOrientation(CMatrix &mat, CVec &first, CVec &second, bool old)
00643 {
00644     double a, b, g;
00645      
00646     b = atan2(-mat.a[2], sqrt(mat.a[0]*mat.a[0]+mat.a[1]*mat.a[1]));
00647 
00648     if (fabsf(b - M_PI/2.0) < 0.000001)
00649     {
00650         a = 0;
00651         g = atan2(mat.a[4], mat.a[5]);        
00652     } else if (fabsf(b + M_PI/2.0) < 0.000001)
00653     {
00654         a = 0;
00655         g = -atan2(mat.a[4], mat.a[5]);        
00656     } else
00657     {
00658         a = atan2(mat.a[1]/cos(b), mat.a[0]/cos(b));
00659         g = atan2(mat.a[6]/cos(b), mat.a[10]/cos(b));   
00660     }
00661      
00662     if (old)
00663       first.set(a, b, g);
00664     else
00665       first.set(g, b, a);
00666 
00667     second = first;
00668 }
00669 
00670 
00671 // calculates rotation matrix representing euler angles
00672 /*void CMathLib::getRotation(CMatrix &mat, double aX, double aY, double aZ)
00673 {
00674      double a = aX;
00675      double b = aZ; 
00676      double g = aY;                                       
00677      mat.a[0] = cos(b)*cos(g);                          
00678      mat.a[1] = cos(a)*sin(b)*cos(g) + sin(a)*sin(g);        
00679      mat.a[2] = sin(a)*sin(b)*cos(g)-cos(a)*sin(g);      
00680      mat.a[4] = -sin(b);                                
00681      mat.a[5] = cos(a)*cos(b);                          
00682      mat.a[6] = sin(a)*cos(b);                           
00683     
00684      mat.a[8] = cos(b)*sin(g);                           
00685      mat.a[9] = cos(a)*sin(b)*sin(g)-sin(a)*cos(g);      
00686      mat.a[10] = sin(a)*sin(b)*sin(g)+cos(a)*cos(g); 
00687          
00688 }
00689 */
00690 
00691 // calculates rotation matrix representing euler angles
00692 void CMathLib::getRotation(CMatrix &mat, double aX, double aY, double aZ, bool old)
00693 {
00694     double g = aX;
00695     double b = aY; 
00696     double a = aZ; 
00697 
00698     if (old)
00699     {
00700       a = aX;
00701       b = aY;
00702       g = aZ;
00703     }                                
00704     if (fabsf(b - M_PI/2.0) < 0.0001)
00705     {
00706         mat.a[0] = 0.0;                          
00707         mat.a[1] = 0.0;        
00708         mat.a[2] = -1.0;      
00709         mat.a[4] = sin(g - a);                                
00710         mat.a[5] = cos(g - a);                          
00711         mat.a[6] = 0.0;                           
00712     
00713         mat.a[8] = cos(g - a);                           
00714         mat.a[9] = -sin(g - a);      
00715         mat.a[10] = 0.0;   
00716     } else
00717         if (fabsf(b + M_PI/2.0) < 0.0001)
00718         {
00719             mat.a[0] = 0.0;                          
00720             mat.a[1] = 0.0;        
00721             mat.a[2] = 1.0;      
00722             mat.a[4] = -sin(g + a);                                
00723             mat.a[5] = cos(g + a);                          
00724             mat.a[6] = 0.0;                           
00725     
00726             mat.a[8] = -cos(g + a);                           
00727             mat.a[9] = -sin(g + a);      
00728             mat.a[10] = 0.0;  
00729         } else
00730         {    
00731             mat.a[0] = cos(b)*cos(a);                          
00732             mat.a[1] = sin(a)*cos(b);        
00733             mat.a[2] = -sin(b);      
00734             mat.a[4] = cos(a)*sin(b)*sin(g) - sin(a)*cos(g);                                
00735             mat.a[5] = sin(a)*sin(b)*sin(g) + cos(a)*cos(g);                          
00736             mat.a[6] = cos(b)*sin(g);                           
00737     
00738             mat.a[8] = cos(a)*sin(b)*cos(g)+sin(a)*sin(g);                           
00739             mat.a[9] = sin(a)*sin(b)*cos(g)-cos(a)*sin(g);      
00740             mat.a[10] = cos(b)*cos(g); 
00741         }
00742 
00743         /* set to zero
00744         mat.a[12] = 0.0; mat.a[13] = 0.0; mat.a[14] = 0.0;
00745         mat.a[3] = 0.0;mat.a[7] = 0.0;mat.a[11] = 0.0;mat.a[15] = 1.0;
00746         */
00747 }
00748 
00749 // convenience function
00750 void CMathLib::getRotation(CMatrix &mat, CVec &vec, bool old)
00751 {
00752     getRotation(mat, vec.x, vec.y, vec.z, old);
00753 }
00754 
00755 // calculates inverse kinematics of a two bone leg
00756 void CMathLib::calcAngles(double leg1, double leg2, double x, double y, double &first, double &second)
00757 {
00758         double lambda;
00759         
00760     // normalize x and y
00761     const double factor = 0.9999;
00762     if ((x*x +y*y) >= factor*(leg1+leg2)*(leg1+leg2))
00763         {
00764        x = factor*x*sqrt((leg1+leg2)*(leg1+leg2) /(x*x +y*y));
00765        y = factor*y*sqrt((leg1+leg2)*(leg1+leg2) /(x*x +y*y));
00766        first = 0.0;
00767        second = atan2(-x,-y);
00768        return;
00769     }
00770     
00771     lambda = leg1;
00772     leg1 = leg2;
00773     leg2 = lambda;
00774     double cosb, sinb, sinab, cosab, cosa, sina;
00775     lambda = sqrt(x*x+y*y);
00776     sina = y / lambda;
00777     cosa = -x / lambda;
00778     cosb = (leg1*leg1 + lambda*lambda - leg2*leg2) / (2*leg1*lambda);
00779     sinb = sqrt(1-cosb*cosb);
00780     sinab = sina*cosb + cosa*sinb;
00781     cosab = cosa*cosb-sina*sinb;
00782     second = atan2(sinab, cosab)+0.5*M_PI;
00783     
00784     cosa = (leg1*leg1 + leg2*leg2 - lambda*lambda)/(2*leg1*leg2);
00785     sina = sqrt(1-cosa*cosa);
00786     first = 0.5*M_PI-atan2(-cosa, -sina);
00787     
00788     first = atan2(sina, cosa) - M_PI;
00789 }
00790 
00791 double vectorlength(std::vector<double> &v)
00792 {
00793   double sum = 0.0;
00794   for (unsigned int i=0; i<v.size(); i++)
00795     sum += v[i]*v[i];
00796   return sqrt(sum);
00797 }
00798 
00799 char rosenbrock_version[] = "rosenbrock 0.99";
00800 
00801 #define MIN(a,b) ((a)<(b)?(a):(b))
00802 #define MAX(a,b) ((a)>(b)?(a):(b))
00803 
00804 void simulatedannealing(int n, double *x, double *bl, double *bu,
00805                 double bigbnd, int maxiter, double eps, int verbose,
00806                 void obj(int,double *,double *,void *), void *extraparams)
00807 {
00808     double *best = (double*)calloc(n,sizeof(double));
00809     double besty, t0, beta, y, delta;;
00810     
00811     beta = 0.9999;
00812     t0 = 3000.0;
00813     
00814     memcpy(best,x,n*sizeof(double));
00815     
00816     (*obj)(n,best,&besty,extraparams);
00817     
00818     unsigned int steps, unchanged;
00819     
00820     steps = 0;
00821     unchanged = 0;
00822     while ((int)steps < maxiter && unchanged < 100)
00823     {
00824         for (int i=0; i<n;i++)
00825         {
00826             double rnd = getUniform();
00827             
00828             double lo, hi;
00829             
00830             if ((x[i] - eps) < bl[i])
00831             {
00832                 lo = bl[i];
00833                 hi = lo + 2*eps;
00834             } else
00835                 if ((x[i] + eps) > bu[i])
00836                 {
00837                     hi = bu[i];
00838                     lo = hi -2*eps;
00839                     
00840                 } else
00841                 {
00842                     lo = x[i] - eps;
00843                     hi = x[i] + eps;
00844                 }   
00845             
00846             x[i] = lo + (hi -lo) * rnd;
00847         }
00848         
00849         (*obj)(n,x,&y,extraparams);
00850         //if (y > 1000)
00851          //   continue;
00852         
00853         delta = y - besty;
00854         
00855         if (delta <= 0 || getUniform() <= exp(-delta/(t0 * pow(beta, steps))))
00856         {
00857             memcpy(best,x,n*sizeof(double));
00858             besty = y;
00859             
00860             unchanged = 0;
00861         } else unchanged++;
00862         
00863         steps++;
00864     }
00865     
00866     printf("steps: %d best: %g\n", steps, besty);
00867     
00868     memcpy(x,best,n*sizeof(double));
00869 }
00870 
00871 void rosenbrock(int n, double *x, double *bl, double *bu,
00872                 double bigbnd, int maxiter, double eps, int verbose,
00873                 void obj(int,double *,double *,void *), void *extraparams)
00874 {
00875     double **xi=(double**)calloc(n,sizeof(double*)),
00876     *temp1=(double*)calloc(n*n,sizeof(double)),
00877     **A=(double**)calloc(n,sizeof(double*)),
00878     *temp2=(double*)calloc(n*n,sizeof(double)),
00879     *d=(double*)calloc(n,sizeof(double)),
00880     *lambda=(double*)calloc(n,sizeof(double)),
00881     *xk=(double*)calloc(n,sizeof(double)),
00882     *xcurrent=(double*)calloc(n,sizeof(double)),
00883     *t=(double*)calloc(n,sizeof(double)),
00884     alpha=2,
00885     beta=0.5,
00886     yfirst,yfirstfirst,ybest,ycurrent,mini,div;
00887     int i,k,j,restart,numfeval=0;
00888 
00889     memset(temp1,0,n*n*sizeof(double));
00890     for(i=0; i<n; i++)
00891       { 
00892         temp1[i]=1; 
00893         xi[i]=temp1; 
00894         temp1+=n;
00895         A[i]=temp2; 
00896         temp2+=n;
00897       };
00898     // memcpy(destination,source,nbre_of_byte)
00899     memcpy(xk,x,n*sizeof(double));
00900     for (i=0; i<n; i++) 
00901       d[i]=.1;
00902     memset(lambda,0,n*sizeof(double));
00903     (*obj)(n,x,&yfirstfirst,extraparams); 
00904     numfeval++; 
00905 
00906     do
00907     {
00908         ybest=yfirstfirst; 
00909         do
00910         {
00911             yfirst=ybest;
00912             for (i=0; i<n; i++)
00913             {
00914                 for (j=0; j<n; j++) 
00915                   {
00916                     xcurrent[j]=xk[j]+d[i]*xi[i][j];
00917                     if (xcurrent[j] < bl[j])
00918                       xcurrent[j] = bl[j]; 
00919                     else if (xcurrent[j] > bu[j])
00920                       xcurrent[j] = bu[j]; 
00921                   }
00922                 (*obj)(n,xcurrent,&ycurrent,extraparams); 
00923                 numfeval++;
00924 
00925                 if (ycurrent<ybest) 
00926                 { 
00927                     lambda[i]+=d[i];        // success
00928                     d[i]*=alpha;
00929                     ybest=ycurrent;
00930                     memcpy(xk,xcurrent,n*sizeof(double));
00931                 } else
00932                 {
00933                     d[i]*=-beta;             // failure
00934                 }
00935 
00936                 if (numfeval > maxiter)
00937                   {
00938                     memcpy(x,xk,n*sizeof(double));
00939                     goto  LABEL_ROSENBROCK_DONE;
00940                   }
00941             }
00942         } while (ybest<yfirst);
00943 
00944         mini=bigbnd;
00945         for (i=0; i<n; i++) 
00946           mini=MIN(mini,fabs(d[i]));
00947         restart=mini>eps;
00948 
00949         memcpy(x,xk,n*sizeof(double));
00950 
00951         if (ybest<yfirstfirst)
00952         {
00953             mini=bigbnd;
00954             for (i=0; i<n; i++) 
00955               mini=MIN(mini,fabs(xk[i]-x[i]));
00956             restart=restart||(mini>eps);
00957 
00958             if (restart)
00959             {
00960                 // nous avons:
00961                 // xk[j]-x[j]=(somme sur i de) lambda[i]*xi[i][j];
00962 
00963                 for (i=0; i<n; i++) 
00964                   A[n-1][i]=lambda[n-1]*xi[n-1][i];
00965 
00966                 for (k=n-2; k>=0; k--)
00967                     for (i=0; i<n; i++) 
00968                       A[k][i]=A[k+1][i]+lambda[k]*xi[k][i];
00969 
00970                 t[n-1]=lambda[n-1]*lambda[n-1];
00971                 for (i=n-2; i>=0; i--) 
00972                   t[i]=t[i+1]+lambda[i]*lambda[i];
00973                 for (i=n-1; i>0; i--)
00974                 {
00975                     div=sqrt(t[i-1]*t[i]);
00976                     if (div!=0)
00977                         for (j=0; j<n; j++)
00978                             xi[i][j]=(lambda[i-1]*A[i][j]-xi[i-1][j]*t[i])/div;
00979                 }
00980                 div=sqrt(t[0]);
00981                 for (i=0; i<n; i++) 
00982                   xi[0][i]=A[0][i]/div;
00983 
00984                 memcpy(x,xk,n*sizeof(double));
00985                 memset(lambda,0,n*sizeof(double));
00986                 for (i=0; i<n; i++) 
00987                   d[i]=.1;
00988                 yfirstfirst=ybest;
00989             }
00990         }
00991 
00992     } while ((restart)&&(numfeval<maxiter));
00993 
00994  LABEL_ROSENBROCK_DONE:
00995     // the maximum number of evaluation is approximative
00996     // because in 1 iteration there is n function evaluations.
00997     if (verbose)
00998     {
00999         printf("ROSENBROCK method for local optimization (minimization)\n"
01000                 "number of evaluation of the objective function= %i\n",numfeval);
01001     }
01002     free(xi[0]);
01003     free(A[0]);
01004     free(d);
01005     free(lambda);
01006     free(xk);
01007     free(xcurrent);
01008     free(t);
01009 }
01010 
01011 void calculateTransformationFromPlane(CVec &plane, CMatrix &transformation)
01012 {
01013     CVec z;
01014     z.x = plane.x; // plane is 4d!
01015     z.y = plane.y;
01016     z.z = plane.z;
01017     
01018     CVec y;
01019 
01020     if (plane.x != 0.0)
01021     {
01022         y.x = (plane.y + plane.z) / plane.x;
01023         y.y = -1.0;
01024         y.z = -1.0;
01025     } else
01026     if (plane.y != 0.0)
01027     {
01028         y.y = (plane.x + plane.z) / plane.y;
01029         y.x = -1.0;
01030         y.z = -1.0;
01031     } else
01032     if (plane.z != 0.0)
01033     {
01034         y.z = (plane.y + plane.x) / plane.z;
01035         y.y = -1.0;
01036         y.x = -1.0;
01037     } else printf("error\n");
01038     
01039     CVec x = y ^ z;
01040     
01041     x.normalize();
01042     y.normalize();
01043     z.normalize();
01044 
01045     transformation.a[0] = x.x;
01046     transformation.a[1] = x.y;
01047     transformation.a[2] = x.z;
01048     
01049     transformation.a[4] = y.x;
01050     transformation.a[5] = y.y;
01051     transformation.a[6] = y.z;
01052     
01053     transformation.a[8] = z.x;
01054     transformation.a[9] = z.y;
01055     transformation.a[10] = z.z;
01056 }
01057 
01058 
01059 void setUniformSeed(unsigned int seed)
01060 { 
01061   pRngUniform01.engine().seed(seed);
01062   pRngUniform01.distribution().reset();
01063   //pRngMt19937.seed(seed);
01064 }
01065 
01066 double getSigmoid(double value, double offset, double factor)
01067 {
01068        return 1.0/(1.0+exp(-factor*(value - offset)));
01069 }
01070 
01071 double getGaussian(double value, double mean, double std)
01072 {
01073        // 0.063494 = 1.0 * sqrt(2 * M_PI)
01074        
01075        return 0.063494 / std * exp(-0.5 * (value - mean) * (value - mean) / (std * std) );
01076 }
01077 
01078 double getGaussianWithoutNormalization(double value, double mean, double std)
01079 {
01080        return exp(-0.5 * (value - mean) * (value - mean) / (std * std) );
01081 }
01082 
01083 
01084 
01085 double getLogisticProb(double alpha, double beta)
01086 {
01087   double u = getUniform();
01088     
01089     if (u==0.0)
01090        return 1E30;
01091        
01092     if (u==1.0)
01093        return -1E30;
01094     
01095     return alpha - beta * log(u/(1.0-u));
01096 }
01097 
01098 
01099 
01100 void convertMatrix(double (*R)[3], double *T, CMatrix &to)
01101 {
01102   to.a[12] = T[0];
01103   to.a[13] = T[1];
01104   to.a[14] = T[2];
01105 
01106   to.a[0] = R[0][0];
01107   to.a[4] = R[0][1];
01108   to.a[8] = R[0][2];
01109 
01110   to.a[1] = R[1][0];
01111   to.a[5] = R[1][1];
01112   to.a[9] = R[1][2];
01113 
01114   to.a[2] = R[2][0];
01115   to.a[6] = R[2][1];
01116   to.a[10] = R[2][2];
01117 }
01118 
01119 void convertMatrix(CMatrix &from, double (*R)[3], double *T)
01120 {
01121   R[0][0] = from.a[0];
01122   R[0][1] = from.a[4];
01123   R[0][2] = from.a[8];
01124 
01125   R[1][0] = from.a[1];
01126   R[1][1] = from.a[5];
01127   R[1][2] = from.a[9];
01128 
01129   R[2][0] = from.a[2];
01130   R[2][1] = from.a[6];
01131   R[2][2] = from.a[10];
01132 
01133   T[0] = from.a[12];
01134   T[1] = from.a[13];
01135   T[2] = from.a[14];
01136 }
01137 
01138 
01139 void getMeanFromVectors(std::vector<std::vector<double> > &values, std::vector<double> &mean)
01140 {
01141   if (values.size() == 0)
01142     return;
01143 
01144   mean.clear();
01145   mean.resize(values[0].size(), 0.0);
01146   unsigned int counter = 0;
01147   for (unsigned int i=0; i<values.size(); i++)
01148     {
01149       for (unsigned int j=0; j<mean.size() && j<values[i].size(); j++)
01150         mean[j] += values[i][j];
01151 
01152       counter++;
01153     }
01154 
01155   if (counter > 0)
01156     for (unsigned int j=0; j<mean.size(); j++)
01157       mean[j] /= (double) counter;
01158 }
01159 
01160 
01161 
01162 void orientation2scaledAxis(CMatrix &matrix, CVec &axis)
01163 {
01164   double angle;
01165   CMathLib::getRotationFromMatrix(matrix, axis, angle);
01166   axis *= angle;
01167 }
01168 
01169 void orientation2scaledAxis(CMatrix &matrix, std::vector<double> &axis2)
01170 {
01171   CVec axis;
01172   double angle;
01173   CMathLib::getRotationFromMatrix(matrix, axis, angle);
01174   axis2.resize(3);
01175   axis2[0] = axis.x * angle;
01176   axis2[1] = axis.y * angle;
01177   axis2[2] = axis.z * angle;
01178 }
01179 
01180 void scaledAxis2Orientation(CVec &axis2, CMatrix &matrix)
01181 {
01182   CVec axis;
01183   double angle = axis2.length();
01184   if (angle == 0.0)
01185     axis = axis2;
01186   else
01187     axis = axis2 / angle;
01188 
01189   CMathLib::getMatrixFromRotation(matrix, axis, angle);
01190 }
01191 
01192 void scaledAxis2Orientation(std::vector<double> &axis2, CMatrix &matrix)
01193 {
01194   CVec axis(axis2[0], axis2[1], axis2[2]);
01195   double angle = axis.length(); 
01196   axis.normalize();
01197 
01198   CMathLib::getMatrixFromRotation(matrix, axis, angle);
01199 }
01200 
01201 
01202 }


asr_kinematic_chain_optimizer
Author(s): Aumann Florian, Heller Florian, Jäkel Rainer, Wittenbeck Valerij
autogenerated on Sat Jun 8 2019 19:42:49