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
00049
00050
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
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
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
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
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
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
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
00201 PRECISION CMatrix::trace()
00202 {
00203 return a[0] + a[5] + a[10];
00204 }
00205
00206
00207 void CMatrix::print(bool round) const
00208 {
00209
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
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
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
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
00262 CMatrix CMatrix::operator * (const CMatrix &m) const
00263 {
00264 CMatrix tmp;
00265 tmp.mul((*this), m);
00266 return tmp;
00267 }
00268
00269
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
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
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
00301 CMatrix& CMatrix::operator = ( const CMatrix& v)
00302 {
00303 memcpy(a,v.a, 16*sizeof(PRECISION));
00304 return *this;
00305 }
00306
00307
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
00371
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
00408
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
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
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
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
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
00462
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
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
00491
00492
00493
00494
00495
00496 }
00497
00498
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
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
00524
00525 void CMathLib::quaternionFromMatrix(const CMatrix &mat, CVec &quaternion)
00526 {
00527 double T = 1 + mat.a[0] + mat.a[5] + mat.a[10];
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] ) {
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] ) {
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 {
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
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
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
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
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
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
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
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
00744
00745
00746
00747 }
00748
00749
00750 void CMathLib::getRotation(CMatrix &mat, CVec &vec, bool old)
00751 {
00752 getRotation(mat, vec.x, vec.y, vec.z, old);
00753 }
00754
00755
00756 void CMathLib::calcAngles(double leg1, double leg2, double x, double y, double &first, double &second)
00757 {
00758 double lambda;
00759
00760
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
00851
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
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];
00928 d[i]*=alpha;
00929 ybest=ycurrent;
00930 memcpy(xk,xcurrent,n*sizeof(double));
00931 } else
00932 {
00933 d[i]*=-beta;
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
00961
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
00996
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;
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
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
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 }