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 #include <base/MathTest>
00026
00027 #include <base/SVD>
00028 #include <base/Path>
00029
00030 using base::MathTest;
00031
00032 using base::consts;
00033 using base::Matrix;
00034 using base::Vector;
00035 using base::SVD;
00036 using base::Path;
00037
00038
00039
00040 MathTest::MathTest()
00041 : I(4,4), A(4,4), S(3,3),
00042 b(4), x(4)
00043 {
00044 }
00045
00046
00047 void MathTest::setUp()
00048 {
00049
00050 I = identityMatrix(4,4);
00051
00052
00053 A(0,0) = 1; A(0,1) = -1; A(0,2) = 0; A(0,3) = 0;
00054 A(1,0) = 2; A(1,1) = -2; A(1,2) = 1; A(1,3) = 2;
00055 A(2,0) = 0; A(2,1) = 1; A(2,2) = 0; A(2,3) = 1;
00056 A(3,0) = 0; A(3,1) = 0; A(3,2) = 2; A(3,3) = 1;
00057
00058 b[0] = 0; b[1] = 4; b[2] = 0; b[3] = 5;
00059
00060 x[0] = -1; x[1]=-1; x[2] = 2; x[3] = 1;
00061
00062 S(0,0) = 1; S(0,1) = 2; S(0,2) = 3;
00063 S(1,0) = 1; S(1,1) = 2; S(1,2) = 2;
00064 S(2,0) = 1; S(2,1) = 2; S(2,2) = 3;
00065
00066
00067 P.resize(3,9);
00068 P(0,0) = 1; P(0,1) = 0; P(0,2) = -0.71595; P(0,3) = -0.13884; P(0,4) = -0.46236; P(0,5) = -0.29068; P(0,6) = 0.06875; P(0,7) = -0.36885; P(0,8) = -0.24926;
00069 P(1,0) = 0; P(1,1) = 1; P(1,2) = 0.94988; P(1,3) = 0.20359; P(1,4) = -0.66261; P(1,5) = -0.98019; P(1,6) = -0.55012; P(1,7) = -0.10177; P(1,8) = 0.23327;
00070 P(2,0) = 0; P(2,1) = 0; P(2,2) = 0; P(2,3) = 0; P(2,4) = -0.11290; P(2,5) = -0.53204; P(2,6) = -0.54088; P(2,7) = -0.60098; P(2,8) = -0.20846;
00071
00072 }
00073
00074
00075 void MathTest::tearDown()
00076 {
00077 }
00078
00079
00080 void MathTest::testMatrixVector()
00081 {
00082
00083 Matrix m(3,3);
00084 m = identityMatrix(3,3);
00085 for(Int r=0; r<3; r++)
00086 for(Int c=0; c<3; c++)
00087 CPPUNIT_ASSERT( m(r,c) == ((r==c)?1:0) );
00088
00089 Vector u(3);
00090 u = unitVector(3,2);
00091 CPPUNIT_ASSERT( equals(norm_2(u),1) );
00092 CPPUNIT_ASSERT( u[2] == 1 );
00093 Vector mr(3), mc(3);
00094 mr = matrixRow(m,2);
00095 mc = matrixColumn(m,1);
00096
00097 CPPUNIT_ASSERT( mr[2] == 1 );
00098 CPPUNIT_ASSERT( mc[1] == 1 );
00099
00100 CPPUNIT_ASSERT( norm_2(zeroVector(3)) == 0 );
00101
00102 Matrix z(3,3);
00103 z = zeroMatrix(3,3);
00104 CPPUNIT_ASSERT( norm_2(matrixRow(z,0)) == 0 );
00105
00106 matrixRow(z,0) = unitVector(3,2);
00107 CPPUNIT_ASSERT( norm_2(matrixRow(z,0)) == 1 );
00108
00109 Vector v6(zeroVector(6));
00110 vectorRange(v6,Range(0,3)) = unitVector(3,0);
00111 CPPUNIT_ASSERT( v6[0] == 1 );
00112
00113 Matrix sm(2,2);
00114 sm = matrixRange(m,Range(0,2), Range(0,2));
00115 CPPUNIT_ASSERT( base::equals(sm, identityMatrix(2,2)) );
00116
00117 Matrix m1(3,3);
00118 m1(0,0) = 1; m1(0,1) = 2; m1(0,2) = 3;
00119 m1(1,0) = 4; m1(1,1) = 5; m1(1,2) = 6;
00120 m1(2,0) = 7; m1(2,1) = 8; m1(2,2) = 9;
00121
00122
00123 Matrix newm1(m1);
00124 matrixRange(newm1, Range(0,2), Range(0,2)) = identityMatrix(2,2);
00125 CPPUNIT_ASSERT( base::equals( matrixRange(newm1, Range(0,2), Range(0,2)), identityMatrix(2,2)) );
00126
00127
00128 Matrix m2(3,3);
00129 m2(0,0) = 0; m2(0,1) = 3; m2(0,2) = 6;
00130 m2(1,0) = 7; m2(1,1) = 3; m2(1,2) = 5;
00131 m2(2,0) = -4;m2(2,1) = 5; m2(2,2) = -3;
00132
00133
00134 Matrix m12(3,3);
00135 m12(0,0) = 2; m12(0,1) = 24; m12(0,2) = 7;
00136 m12(1,0) = 11;m12(1,1) = 57; m12(1,2) = 31;
00137 m12(2,0) = 20;m12(2,1) = 90; m12(2,2) = 55;
00138
00139 CPPUNIT_ASSERT( base::equals(m1*m2, m12) );
00140
00141
00142
00143 Vector v1(3);
00144 v1[0] = 2; v1[1] = 5; v1[2] = 7;
00145
00146 Vector m1v1(3);
00147 m1v1[0] = 33; m1v1[1] = 75; m1v1[2] = 117;
00148
00149 CPPUNIT_ASSERT( base::equals(m1*v1, m1v1) );
00150
00151
00152 Vector n(1); n[0]=1;
00153 -n;
00154 CPPUNIT_ASSERT( base::equals(n[0], 1) );
00155 n = -n;
00156 CPPUNIT_ASSERT( base::equals(n[0], -1) );
00157
00158 Matrix nm(1,1);
00159 nm(0,0) = 1;
00160 -nm;
00161 CPPUNIT_ASSERT( base::equals(nm(0,0), 1) );
00162 nm = -nm;
00163 CPPUNIT_ASSERT( base::equals(nm(0,0), -1) );
00164
00165 }
00166
00167
00168 void MathTest::testNullSpace()
00169 {
00170 Vector r(3); r[0]=1; r[1]=2; r[2]=3;
00171
00172 Matrix A(3,3);
00173 matrixRow(A,0) = r;
00174 matrixRow(A,1) = r;
00175 matrixRow(A,2) = r;
00176
00177 Int rank;
00178 Real k2;
00179 Matrix Z( Math::nullSpace(A,rank,k2) );
00180
00181 CPPUNIT_ASSERT( equals(rank,2) );
00182
00183 CPPUNIT_ASSERT( base::equals(A*Z, zeroMatrix(3,2), 0.00001) );
00184
00185 Vector x(3);
00186 for(Int i=0; i<10; i++) {
00187 Real r = Math::random();
00188 Real s = r-1;
00189 x = matrixColumn(Z,0)*r + matrixColumn(Z,1)*s;
00190 CPPUNIT_ASSERT( equals(A*x, zeroVector(3), 0.00001) );
00191 }
00192
00193 }
00194
00195
00196 void MathTest::testInverse()
00197 {
00198
00199 Assert( equals(A*x,b) );
00200 Assert( A.size1() == A.size2() );
00201
00202
00203 Matrix Ainv( Math::inverse(A) );
00204 CPPUNIT_ASSERT( Ainv.size1() == A.size1() );
00205 CPPUNIT_ASSERT( Ainv.size2() == A.size2() );
00206
00207
00208 Matrix AAinv( A*Ainv );
00209 CPPUNIT_ASSERT( AAinv.size1() == A.size1() );
00210 CPPUNIT_ASSERT( AAinv.size2() == Ainv.size2() );
00211
00212
00213 CPPUNIT_ASSERT( equals(AAinv, I) );
00214
00215
00216 CPPUNIT_ASSERT( equals(Ainv*b, x) );
00217 }
00218
00219
00220 void MathTest::testInverseSingular()
00221 {
00222
00223 Matrix Sinv( Math::inverse(S) );
00224 }
00225
00226
00227 void MathTest::testSVD()
00228 {
00229
00230 SVD svda(A);
00231
00232 Matrix U(svda.U());
00233 Matrix V(svda.V());
00234 Matrix S(svda.S());
00235
00236 Matrix NA( U * S * transpose(V) );
00237
00238 CPPUNIT_ASSERT( NA.equals(A,0.000001) );
00239
00240
00241 Vector so(4);
00242 so[3] = 3.95858;
00243 so[2] = 2.16562;
00244 so[1] = 1.24951;
00245 so[0] = 0.28007;
00246
00247
00248 bool swapped=false;
00249 do {
00250 swapped = false;
00251 for(Int i=0; i<3; i++)
00252 if (S(i,i) > S(i+1,i+1)) {
00253 base::swap( S(i,i), S(i+1,i+1) );
00254 swapped=true;
00255 }
00256 } while (swapped);
00257
00258 Assert(S.size1() == 4);
00259 for(Int i=0; i<S.size1(); i++) {
00260 CPPUNIT_ASSERT( Math::equals(S(i,i), so[i], 0.00001) );
00261 }
00262
00263
00264
00265 Matrix A1(A.rows(), A.cols()+2);
00266 matrixRange(A1, Range(0,A.rows()), Range(0,A.cols())) = A;
00267 Vector v1( zeroVector(A.rows()) );
00268 v1[0] = 1; v1[1] = 5; v1[2] = -0.2; v1[v1.size()-1] = -4;
00269 MatrixColumn(A1, A.cols()) = v1;
00270 v1[0] = 3; v1[1] = -6; v1[2] = -0.3; v1[v1.size()-1] = 2;
00271 MatrixColumn(A1, A.cols()+1) = v1;
00272
00273 const Int M1 = A1.rows();
00274 const Int N1 = A1.cols();
00275
00276 SVD svda1(A1);
00277
00278 Matrix U1(svda1.U());
00279 Matrix V1(svda1.V());
00280 Matrix S1(svda1.S());
00281
00282 CPPUNIT_ASSERT( U1.rows() == M1 );
00283 CPPUNIT_ASSERT( U1.cols() == M1 );
00284 CPPUNIT_ASSERT( S1.rows() == M1 );
00285 CPPUNIT_ASSERT( S1.cols() == N1 );
00286 CPPUNIT_ASSERT( V1.rows() == N1 );
00287 CPPUNIT_ASSERT( V1.cols() == N1 );
00288
00289 Matrix NA1( U1 * S1 * transpose(V1) );
00290
00291 CPPUNIT_ASSERT( NA1.equals(A1,0.00001) );
00292
00293
00294
00295 Matrix A2(A.rows()+2, A.cols());
00296 matrixRange(A2, Range(0,A.rows()), Range(0,A.cols())) = A;
00297 Vector v( zeroVector(A.cols()) );
00298 v[0] = 1; v[1] = 5; v[2] = -0.2; v[v.size()-1] = -4;
00299 MatrixRow(A2, A.rows()) = v;
00300 v[0] = 3; v[1] = -6; v[2] = -0.3; v[v.size()-1] = 2;
00301 MatrixRow(A2, A.rows()+1) = v;
00302
00303 const Int M = A2.rows();
00304 const Int N = A2.cols();
00305
00306 SVD svda2(A2);
00307
00308 Matrix U2(svda2.U());
00309 Matrix V2(svda2.V());
00310 Matrix S2(svda2.S());
00311
00312 CPPUNIT_ASSERT( U2.rows() == M );
00313 CPPUNIT_ASSERT( U2.cols() == M );
00314 CPPUNIT_ASSERT( S2.rows() == M );
00315 CPPUNIT_ASSERT( S2.cols() == N );
00316 CPPUNIT_ASSERT( V2.rows() == N );
00317 CPPUNIT_ASSERT( V2.cols() == N );
00318
00319 Matrix NA2( U2 * S2 * transpose(V2) );
00320
00321 CPPUNIT_ASSERT( NA2.equals(A2,0.00001) );
00322 }
00323
00324
00325
00326 void MathTest::testPseudoInverse()
00327 {
00328 Matrix PInv( Math::pseudoInverse(P) );
00329
00330 Matrix PIO(9,3);
00331
00332 PIO(0,0) = 0.5819252; PIO(0,1) = 0.1170694; PIO(0,2) = -0.3666462;
00333 PIO(1,0) = 0.1170694; PIO(1,1) = 0.3703392; PIO(1,2) = -0.3903029;
00334 PIO(2,0) = -0.3054275; PIO(2,1) = 0.2679620; PIO(2,2) = -0.1082405;
00335 PIO(3,0) = -0.0569603; PIO(3,1) = 0.0591435; PIO(3,2) = -0.0285566;
00336 PIO(4,0) = -0.3052359; PIO(4,1) = -0.2554535; PIO(4,2) = 0.2557433;
00337 PIO(5,0) = -0.0888338; PIO(5,1) = -0.1893758; PIO(5,2) = -0.3232752;
00338 PIO(6,0) = 0.1739168; PIO(6,1) = 0.0154245; PIO(6,2) = -0.6364151;
00339 PIO(7,0) = -0.0062102; PIO(7,1) = 0.1536938; PIO(7,2) = -0.7427355;
00340 PIO(8,0) = -0.0413108; PIO(8,1) = 0.1385709; PIO(8,2) = -0.3179733;
00341
00342 CPPUNIT_ASSERT( PInv.equals(PIO, 0.00001) );
00343 }
00344
00345
00346
00347
00348 void MathTest::testExpression()
00349 {
00350 Expression e("tan(0.1)*-2*sin(p[0])+-4.4e-1*((1+1.00)*0.5)/cos(p[0]+0.01+0*(100.0/-3.3e-8))");
00351 e.simplify();
00352
00353 Vector p(1);
00354 p[0] = consts::Pi/2.0;
00355
00356 CPPUNIT_ASSERT(Math::equals( e.evaluate(p), Math::tan(0.1)*-2.0*Math::sin(p[0])+-4.4e-1*((1+1)*0.5)/Math::cos(p[0]+0.01) ));
00357 }
00358
00359
00360
00361
00362 void MathTest::testPath()
00363 {
00364
00365 Path zp;
00366 for(Real t=0.0; t<=1.0; t+=0.05) {
00367 CPPUNIT_ASSERT( zp.position(t).equalsZero() );
00368 CPPUNIT_ASSERT( zp.orientation(t).getVector3(Orient::EulerRPY).equalsZero() );
00369 }
00370
00371
00372 Point3 p1(1,1,1);
00373 Point3 p2(2,2,2);
00374 Path up(p1,Orient(),p2,Orient());
00375 CPPUNIT_ASSERT( up.position(0.0).equals(p1) );
00376 CPPUNIT_ASSERT( up.position(1.0).equals(p2) );
00377 CPPUNIT_ASSERT( up.position(0.5).equals(Point3(1.5,1.5,1.5)) );
00378 CPPUNIT_ASSERT( up.orientation(0.5).getVector3(Orient::EulerRPY).equalsZero() );
00379
00380
00381 Quat4 q1(Vector3(0,0,1),consts::Pi/4.0);
00382 Quat4 q2(Vector3(0,0,1),consts::Pi/2.0);
00383 Orient o1(q1), o2(q2);
00384 Path path(p1,o1,p2,o2);
00385 CPPUNIT_ASSERT( path.position(0.0).equals(p1) );
00386 CPPUNIT_ASSERT( path.position(1.0).equals(p2) );
00387 CPPUNIT_ASSERT( path.position(0.5).equals(Point3(1.5,1.5,1.5)) );
00388 CPPUNIT_ASSERT( path.orientation(0.0).equals(o1) );
00389 CPPUNIT_ASSERT( path.orientation(1.0).equals(o2) );
00390 CPPUNIT_ASSERT( path.orientation(0.5).equals(Orient::interpolate(o1,o2,0.5)) );
00391
00392 array<Point3> ps(3);
00393 array<Orient> os(3);
00394 ps[0] = p1; ps[1] = Point3(1.5,3.0,-2.5); ps[2] = p2;
00395 Quat4 q3(Vector3(0,0,1),consts::Pi/3.0);
00396 Orient o3(q3);
00397 os[0] = o1; os[1] = o3; os[2] = o2;
00398 Path wpath(ps,os);
00399 CPPUNIT_ASSERT( wpath.position(0.0).equals(p1) );
00400 CPPUNIT_ASSERT( wpath.position(1.0).equals(p2) );
00401 CPPUNIT_ASSERT( wpath.position(0.5).equals(Point3(1.53099,2.93802,-2.22108),1e-4) );
00402 CPPUNIT_ASSERT( wpath.position(0.6).equals(Point3(1.62479,2.75042,-1.37687),1e-4) );
00403 CPPUNIT_ASSERT( wpath.position(0.8).equals(Point3(1.8124,2.37521,0.311566),1e-4) );
00404
00405 CPPUNIT_ASSERT( wpath.orientation(0.0).equals(o1) );
00406 CPPUNIT_ASSERT( wpath.orientation(1.0).equals(o2) );
00407
00408
00409 ps.clear();
00410 Path wpath2(ps,os);
00411 CPPUNIT_ASSERT( wpath2.orientation(0.0).equals(o1) );
00412 CPPUNIT_ASSERT( wpath2.orientation(1.0).equals(o2) );
00413 CPPUNIT_ASSERT( wpath2.orientation(0.5).getQuat4().equals(Quat4(Vector3(0,0,1),3.0*consts::Pi/8.0)) );
00414
00415
00416
00417 ExpressionVector v(3);
00418 v[0] = base::cos( Expression::p[0] * 2.0 * consts::Pi ); v[0].simplify();
00419 v[1] = base::sin( Expression::p[0] * 2.0 * consts::Pi ); v[1].simplify();
00420 v[2] = 0;
00421 Path unitcircle(v);
00422
00423 for(Real s=0.0; s<=1.0; s+=1/100.0) {
00424 Point3 p( Math::cos(s*2.0*consts::Pi), Math::sin(s*2.0*consts::Pi), 0);
00425 CPPUNIT_ASSERT( unitcircle.position(s).equals(p) );
00426 }
00427
00428 }
00429
00430
00431 #ifdef DEBUG
00432 CPPUNIT_TEST_SUITE_REGISTRATION( MathTest );
00433 #endif
00434