00001
00059
00060
00061
00062
00063
00064
00065
00066 #define DEBUG_
00067 #define ATOM_TESTING_
00068
00069 #include <ros/ros.h>
00070 #include <pcl/point_types.h>
00071 #include <pcl/point_cloud.h>
00072 #include <pcl/io/pcd_io.h>
00073 #include <cob_3d_mapping_slam/dof/rotation.h>
00074 #include <cob_3d_mapping_slam/dof/tflink.h>
00075 #include <cob_3d_mapping_slam/dof/euler.h>
00076 #include <cob_3d_mapping_slam/dof/dof_variance.h>
00077 #include <cob_3d_mapping_slam/rotation_from_correspondences.h>
00078 #include <pcl/common/transformation_from_correspondences.h>
00079
00080 #include "gnuplot_i.hpp"
00081 #include <gtest/gtest.h>
00082
00083 #if 0
00084 #define TEST_EXPRESSION(a) EXPECT_EQ((a), meval::EvaluateMathExpression(#a))
00085
00086 TEST(MathExpressions, operatorRecognition){
00087 EXPECT_TRUE(meval::ContainsOperators("+"));
00088 EXPECT_TRUE(meval::ContainsOperators("-"));
00089 EXPECT_TRUE(meval::ContainsOperators("/"));
00090 EXPECT_TRUE(meval::ContainsOperators("*"));
00091 EXPECT_FALSE(meval::ContainsOperators("1234567890qwertyuiop[]asdfghjkl;'zxcvbnm,._=?8"));
00092 }
00093
00094 TEST(MathExpressions, basicOperations){
00095 EXPECT_EQ(5, meval::EvaluateMathExpression("2+3"));
00096 EXPECT_EQ(5, meval::EvaluateMathExpression("2 + 3"));
00097 EXPECT_EQ(10, meval::EvaluateMathExpression("20/2"));
00098 EXPECT_EQ(-4, meval::EvaluateMathExpression("6 - 10"));
00099 EXPECT_EQ(24, meval::EvaluateMathExpression("6 * 4"));
00100 }
00101
00102 TEST(MathExpressions, complexOperations){
00103 TEST_EXPRESSION(((3 + 4) / 2.0) + 10);
00104 TEST_EXPRESSION(7 * (1 + 2 + 3 - 2 + 3.4) / 12.7);
00105 TEST_EXPRESSION((1 + 2 + 3) - (8.0 / 10));
00106 }
00107
00108 TEST(MathExpressions, UnaryMinus){
00109 TEST_EXPRESSION(-5);
00110 }
00111
00112 TEST(MathExpressions, badInput){
00113
00114
00115
00116 }
00117
00118 TEST(MathUtils, basicOperations){
00119 EXPECT_EQ(math_utils::clamp<int>(-10, 10, 20), 10);
00120 EXPECT_EQ(math_utils::clamp<int>(15, 10, 20), 15);
00121 EXPECT_EQ(math_utils::clamp<int>(25, 10, 20), 20);
00122 }
00123 #endif
00124
00125 #define CYCLES 1000
00126 #define THR_ANGLE 0.05
00127 #define NOISE_MAX 0.3f
00128 #define NOISE_STEP (NOISE_MAX/20)
00129 #define NUM_SAMPLES 1000
00130
00131
00132 template<typename Matrix>
00133 float MATRIX_DISTANCE(const Matrix &a, const Matrix &b, const float thr=THR_ANGLE) {
00134 Matrix c=a-b;
00135 float d=c.norm();
00136 if(d>thr) {
00137 c=a-b.transpose();
00138 d=std::min(d,c.norm());
00139 }
00140 if(d>thr) {
00141 std::cout<<"A\n"<<a<<"\n";
00142 std::cout<<"B\n"<<b<<"\n";
00143 }
00144 EXPECT_NEAR(d,0,thr);
00145 return d;
00146 }
00147 #if 0
00148 Eigen::Matrix3f build_random_rotation(DOF6::Rotationf &rot, const int N=2, const float noise=0.f) {
00149 Eigen::Vector3f n, nn, v,n2;
00150 float a = M_PI*(rand()%1000)/1000.f;
00151
00152 v(0)=0.01f;v(2)=v(1)=1.f;
00153
00154 nn(0) = (rand()%1000)/1000.f;
00155 nn(1) = (rand()%1000)/1000.f;
00156 nn(2) = (rand()%1000)/1000.f;
00157 nn.normalize();
00158
00159 Eigen::AngleAxisf aa(a,nn);
00160
00161 std::cout<<"rot angle\n"<<a<<"\n";
00162 std::cout<<"rot axis\n"<<nn<<"\n";
00163
00164 std::vector<Eigen::Vector3f> normal;
00165 std::vector<Eigen::Vector3f> normal2;
00166 for(int j=0; j<std::max(2,N); j++) {
00167
00168 n(0) = (rand()%1000)/1000.f-0.5f;
00169 n(1) = (rand()%1000)/1000.f-0.5f;
00170 n(2) = (rand()%1000)/1000.f-0.5f;
00171 n.normalize();
00172
00173 n2 = aa.toRotationMatrix()*n;
00174 n2(0) += 2*noise*((rand()%1000)/1000.f-0.5f);
00175 n2(1) += 2*noise*((rand()%1000)/1000.f-0.5f);
00176 n2(2) += 2*noise*((rand()%1000)/1000.f-0.5f);
00177 n2.normalize();
00178
00179 normal.push_back(n);
00180 normal2.push_back(n2);
00181 }
00182
00183 for(size_t i=0; i<normal.size(); i++) {
00184 rot.add1(normal[i],normal2[i],v);
00185 }
00186
00187 rot.finish1();
00188
00189 pcl::RotationFromCorrespondences rfc;
00190 pcl::TransformationFromCorrespondences tfc;
00191 for(size_t i=0; i<normal.size(); i++) {
00192 rot.add2(normal[i],normal2[i],1);
00193
00194 tfc.add(normal[i],normal2[i]);
00195 }
00196
00197 static float dis1=0,dis2=0,dis3=0;
00198 float d1=0,d2=0,d3=0;
00199 d1=MATRIX_DISTANCE(rfc.getTransformation(),aa.toRotationMatrix());
00200 d2=MATRIX_DISTANCE(rot.toRotationMatrix(),aa.toRotationMatrix());
00201 Eigen::Matrix3f M=tfc.getTransformation().matrix().topLeftCorner<3,3>();
00202 d3=MATRIX_DISTANCE(M,aa.toRotationMatrix());
00203 dis1+=d1;
00204 dis2+=d2;
00205 dis3+=d3;
00206 std::cout<<"rfc: "<<d1<<"\n";
00207 std::cout<<"rot: "<<d2<<"\n";
00208 std::cout<<"tfc: "<<d3<<"\n";
00209 std::cout<<"dis1: "<<dis1<<"\n";
00210 std::cout<<"dis2: "<<dis2<<"\n";
00211 std::cout<<"dis3: "<<dis3<<"\n";
00212
00213 return aa.toRotationMatrix();
00214 }
00215
00216
00217 TEST(DOF6, rotation_basic){
00218 time_t ti = time(NULL);
00219 ROS_INFO("init rotation_basic with %d",(int)ti);
00220 srand(ti);
00221
00222 for(int i=0; i<CYCLES; i++) {
00223 DOF6::Rotationf rot;
00224 Eigen::Matrix3f tf = build_random_rotation(rot);
00225
00226
00227 MATRIX_DISTANCE(rot.toRotationMatrix(),tf);
00228
00229 }
00230 }
00231
00232 TEST(DOF6, rotation_noise){
00233 time_t ti = time(NULL);
00234 ROS_INFO("init rotation_noise with %d",(int)ti);
00235 srand(ti);
00236
00237 std::vector<double> x, y, dy;
00238 Gnuplot plot("rotation_noise");
00239 plot.savetops("doc/rotation_noise");
00240 plot.set_title("rotation_noise");
00241
00242 for(float n=0.f; n<NOISE_MAX; n+=NOISE_STEP) {
00243 float dis=0.f;
00244 for(int i=0; i<CYCLES; i++) {
00245 DOF6::Rotationf rot;
00246 Eigen::Matrix3f tf = build_random_rotation(rot, NUM_SAMPLES, n);
00247
00248
00249
00250 dis+=MATRIX_DISTANCE(rot.toRotationMatrix(),tf,sqrtf(3)*n+THR_ANGLE);
00251 }
00252
00253 x.push_back(n);
00254 y.push_back(dis);
00255 dy.push_back(1);
00256 }
00257
00258 plot.set_style("boxes").plot_x(y,"deviaton").showonscreen();
00259 }
00260 #endif
00261
00262 Eigen::AngleAxisf createRandomAA()
00263 {
00264 Eigen::Vector3f nn;
00265 float a = M_PI*(rand()%1000)/2000.f;
00266
00267 nn(0) = (rand()%1000)/1000.f;
00268 nn(1) = (rand()%1000)/1000.f;
00269 nn(2) = (rand()%1000)/1000.f;
00270 nn.normalize();
00271
00272
00273
00274
00275 return Eigen::AngleAxisf(a,nn);
00276 }
00277
00278 Eigen::Vector3f createRandomT()
00279 {
00280 Eigen::Vector3f t;
00281
00282 t(0) = (rand()%1000)/1000.f;
00283 t(1) = (rand()%1000)/1000.f;
00284 t(2) = (rand()%1000)/1000.f;
00285 t*=(rand()%1000)/1000.f;
00286
00287
00288 return t;
00289 }
00290
00291 Eigen::Matrix4f build_random_tflink(DOF6::TFLinkvf &tflink, const int N=2, const float noise=0.f, const Eigen::AngleAxisf aa=createRandomAA(), const Eigen::Vector3f t=createRandomT()) {
00292 Eigen::Vector3f n, v,n2;
00293
00294 v(0)=0.01f;v(2)=v(1)=1.f;
00295
00296
00297
00298 std::vector<Eigen::Vector3f> normal;
00299 std::vector<Eigen::Vector3f> normal2;
00300 for(int j=0; j<std::max(2,N); j++) {
00301
00302 n(0) = (rand()%1000)/1000.f-0.5f;
00303 n(1) = (rand()%1000)/1000.f-0.5f;
00304 n(2) = (rand()%1000)/1000.f-0.5f;
00305 n.normalize();
00306
00307 n2 = aa.toRotationMatrix()*n;
00308 n2(0) += 2*noise*((rand()%1000)/1000.f-0.5f);
00309 n2(1) += 2*noise*((rand()%1000)/1000.f-0.5f);
00310 n2(2) += 2*noise*((rand()%1000)/1000.f-0.5f);
00311 n2.normalize();
00312
00313 normal.push_back(n);
00314 normal2.push_back(n2);
00315 }
00316
00317 pcl::TransformationFromCorrespondences tfc;
00318 for(size_t i=0; i<normal.size(); i++) {
00319
00320
00321
00322 int s=rand()%3;
00323 float w = (rand()%100+1)/10.f;
00324 if((s==0 && normal2[i].dot(t)>0))
00325 {
00326 std::cout<<"PLANE\n";
00327 tflink(DOF6::TFLinkvf::TFLinkObj(normal[i],true,false,w),
00328 DOF6::TFLinkvf::TFLinkObj(normal2[i]*(1+(normal2[i].dot(t)))
00329 ,true,false,w));
00330 }
00331 else if((s==1 && normal2[i].dot(t)>0))
00332 {
00333 std::cout<<"NORMAL\n";
00334 tflink(DOF6::TFLinkvf::TFLinkObj(normal[i], true,true,w),
00335 DOF6::TFLinkvf::TFLinkObj(normal2[i],true,true,w));
00336 }
00337 else
00338 {
00339 std::cout<<"CUBE\n";
00340 tflink(DOF6::TFLinkvf::TFLinkObj(normal[i],false,false,w),
00341 DOF6::TFLinkvf::TFLinkObj(normal2[i]+t,false,false,w));
00342 }
00343
00344 tfc.add(normal[i],normal2[i]+t);
00345
00346 }
00347
00348 tflink.finish();
00349
00350
00351 Eigen::Matrix4f r=Eigen::Matrix4f::Identity();
00352 for(int i=0; i<3; i++) {
00353 for(int j=0; j<3; j++)
00354 r(i,j) = aa.toRotationMatrix()(i,j);
00355 r.col(3)(i)= t(i);
00356 }
00357
00358 static float dis2=0,dis3=0;
00359 float d2=0,d3=0;
00360
00361 d2=MATRIX_DISTANCE(tflink.getTransformation(),r,10000);
00362 d3=MATRIX_DISTANCE(tfc.getTransformation().matrix(),r,10000);
00363
00364 dis2+=d2;
00365 dis3+=d3;
00366
00367 std::cout<<tflink<<"\n";
00368
00369 std::cout<<"tfl: "<<d2<<"\n";
00370 std::cout<<"tfc: "<<d3<<"\n";
00371
00372 std::cout<<"dis2: "<<dis2<<"\n";
00373 std::cout<<"dis3: "<<dis3<<"\n";
00374
00375 return r;
00376 }
00377
00378
00379 void t5()
00380 {
00381 time_t ti = time(NULL);
00382 ROS_INFO("init tflink_basic with %d",(int)ti);
00383 srand(ti);
00384
00385 for(int i=0; i<CYCLES; i++) {
00386 DOF6::TFLinkvf rot;
00387 Eigen::Matrix4f tf = build_random_tflink(rot,10);
00388
00389
00390 MATRIX_DISTANCE(rot.getTransformation(),tf);
00391
00392 }
00393 }
00394
00395
00396 void t4()
00397 {
00398 time_t ti = time(NULL);
00399 ROS_INFO("init tflink_ with %d",(int)ti);
00400 srand(ti);
00401
00402 std::vector<double> x, y, dy;
00403 Gnuplot plot("rotation_noise");
00404 plot.savetops("doc/rotation_noise");
00405 plot.set_title("rotation_noise");
00406
00407 for(float n=0.f; n<NOISE_MAX; n+=NOISE_STEP) {
00408 float dis=0.f;
00409 for(int i=0; i<CYCLES; i++) {
00410 DOF6::TFLinkvf rot;
00411 Eigen::Matrix4f tf = build_random_tflink(rot, NUM_SAMPLES, n);
00412
00413
00414
00415 dis+=MATRIX_DISTANCE(rot.getTransformation(),tf,sqrtf(3)*n+THR_ANGLE);
00416 }
00417
00418 x.push_back(n);
00419 y.push_back(dis);
00420 dy.push_back(1);
00421 }
00422
00423 plot.set_style("boxes").plot_x(y,"deviaton").showonscreen();
00424 }
00425
00426
00427 void t3()
00428 {
00429 time_t ti = time(NULL);
00430 ROS_INFO("init tflink_adding with %d",(int)ti);
00431 srand(ti);
00432
00433
00434 }
00435
00436
00437 void t2()
00438 {
00439 time_t ti = time(NULL);
00440 ROS_INFO("init euler with %d",(int)ti);
00441 srand(ti);
00442
00443 for(int i=0; i<10000; i++) {
00444 Eigen::Vector3f nn;
00445 float a = (rand()%1000)/500.f-1;
00446 nn(0) = (rand()%1000)/1000.f;
00447 nn(1) = (rand()%1000)/1000.f;
00448 nn(2) = (rand()%1000)/1000.f;
00449 nn.normalize();
00450
00451 Eigen::AngleAxisf aa(a,nn);
00452
00453 DOF6::EulerAnglesf e1 = aa.toRotationMatrix();
00454
00455 MATRIX_DISTANCE((Eigen::Matrix3f)e1,aa.toRotationMatrix(),0.001);
00456 }
00457 }
00458
00459 TEST(DOF6, Source)
00460
00461 {
00462 time_t ti = time(NULL);
00463 ROS_INFO("init Source with %d",(int)ti);
00464 srand(ti);
00465
00466 for(int i=0; i<CYCLES; i++) {
00467 DOF6::TFLinkvf rot1, rot2;
00468 const Eigen::AngleAxisf aa=createRandomAA();
00469 const Eigen::Vector3f t=createRandomT();
00470
00471
00472 Eigen::Matrix4f tf1 = build_random_tflink(rot1,30,0.4,aa,t);
00473 Eigen::Matrix4f tf2 = build_random_tflink(rot2,30,0.2,aa,t);
00474
00475
00476 const float d1=MATRIX_DISTANCE(rot1.getTransformation(),tf1,0.4);
00477 const float d2=MATRIX_DISTANCE(rot2.getTransformation(),tf2,0.2);
00478
00479 DOF6::DOF6_Source<DOF6::TFLinkvf,DOF6::TFLinkvf> abc(rot1.makeShared(), rot2.makeShared());
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 float d3=MATRIX_DISTANCE((Eigen::Matrix3f)abc.getRotation(),aa.toRotationMatrix(),0.2);
00505 EXPECT_NEAR((abc.getTranslation()-t).norm(),0,0.2);
00506 d3+=(abc.getTranslation()-t).norm();
00507
00508
00509 }
00510 }
00511
00512
00513 void abc1()
00514 {
00515 time_t ti = time(NULL);
00516 ROS_INFO("init Source with %d",(int)ti);
00517 srand(ti);
00518
00519 for(int i=0; i<CYCLES; i++) {
00520 DOF6::TFLinkvf rot1, rot2, res;
00521 Eigen::AngleAxisf aa=createRandomAA();
00522 Eigen::Vector3f t=createRandomT();
00523 Eigen::Matrix4f tf1 = build_random_tflink(rot1,30,0,aa,t);
00524
00525 aa=createRandomAA();
00526 t=createRandomT();
00527 Eigen::Matrix4f tf2 = build_random_tflink(rot2,30,0,aa,t);
00528
00529 res = rot1+rot2;
00530
00531 std::cout<<"TF1\n"<<tf1<<"\n";
00532 std::cout<<"TF2\n"<<tf2<<"\n";
00533 std::cout<<"RES1\n"<<tf1*tf2<<"\n";
00534
00535 std::cout<<"RES2\n"<<res.getRotation()<<"\n";
00536 std::cout<<"RES2\n"<<res.getTranslation()<<"\n";
00537
00538 std::cout<<"T TF1\n"<<tf1.inverse()<<"\n";
00539 std::cout<<"T\n"<<rot1.transpose().getRotation()<<"\n";
00540 std::cout<<"T\n"<<rot1.transpose().getTranslation()<<"\n";
00541 }
00542 }
00543
00544 int main(int argc, char **argv){
00545
00546 #if 0
00547 DOF6::TFLinkvf rot1,rot2;
00548 Eigen::Matrix4f tf1 = build_random_tflink(rot1,3);
00549 Eigen::Matrix4f tf2 = build_random_tflink(rot2,3);
00550
00551 DOF6::DOF6_Source<DOF6::TFLinkvf,DOF6::TFLinkvf,float> abc(rot1.makeShared(), rot2.makeShared());
00552 abc.getRotation();
00553 abc.getTranslation();
00554
00555 std::cout<<"tf1\n"<<tf1<<"\n";
00556 std::cout<<"tf2\n"<<tf2<<"\n";
00557 std::cout<<"tf1*2\n"<<tf1*tf2<<"\n";
00558 std::cout<<"tf2*1\n"<<tf2*tf1<<"\n";
00559
00560 std::cout<<"tf1\n"<<rot1.getTransformation()<<"\n";
00561 std::cout<<"tf2\n"<<rot2.getTransformation()<<"\n";
00562 std::cout<<"tf1*2\n"<<(rot1+rot2).getTransformation()<<"\n";
00563
00564 rot1.check();
00565 rot2.check();
00566
00567 return 0;
00568
00569 pcl::RotationFromCorrespondences rfc;
00570 Eigen::Vector3f n, nn, v,n2,n3,z,y,tv;
00571 float a = 0.1f;
00572
00573 z.fill(0);y.fill(0);
00574 z(2)=1;y(1)=1;
00575 nn.fill(0);
00576 nn(0) = 1;
00577 Eigen::AngleAxisf aa(a,nn);
00578
00579 nn.fill(100);
00580
00581 n.fill(0);
00582 n(0) = 1;
00583 n2.fill(0);
00584 n2=n;
00585 n2(1) = 0.2;
00586 n3.fill(0);
00587 n3=n;
00588 n3(2) = 0.2;
00589
00590 n2.normalize();
00591 n3.normalize();
00592
00593 tv.fill(1);
00594 tv.normalize();
00595
00596 #if 0
00597
00598 #if 0
00599 rfc.add(n,aa.toRotationMatrix()*n+nn,
00600 1*n.cross(y),1*n.cross(z),
00601 1*(aa.toRotationMatrix()*n).cross(y),1*(aa.toRotationMatrix()*n).cross(z),
00602 1,1/sqrtf(3));
00603 #else
00604 rfc.add(n,aa.toRotationMatrix()*n,
00605 0*n.cross(y),0*n.cross(z),
00606 0*(aa.toRotationMatrix()*n).cross(y),0*(aa.toRotationMatrix()*n).cross(z),
00607 1,0);
00608 #endif
00609
00610 #if 1
00611 rfc.add(n2,aa.toRotationMatrix()*n2+nn,
00612 tv,tv,
00613 tv,tv,
00614 1,1);
00615 #else
00616 rfc.add(n2,aa.toRotationMatrix()*n2+nn,
00617 1*n2.cross(y),1*n2.cross(z),
00618 1*(aa.toRotationMatrix()*n2).cross(y),1*(aa.toRotationMatrix()*n2).cross(z),
00619 1,1/sqrtf(3));
00620 #endif
00621
00622 #else
00623 float f=1;
00624 Eigen::Vector3f cyl;
00625 cyl.fill(1);
00626 cyl(0)=1;
00627 Eigen::Matrix3f cylM;
00628 cylM.fill(0);
00629 cylM.diagonal() = cyl;
00630 rfc.add(n,aa.toRotationMatrix()*n,
00631 f*n.cross(y),f*n.cross(z),
00632 f*(aa.toRotationMatrix()*n).cross(y),f*(aa.toRotationMatrix()*n).cross(z),
00633 1,0);
00634 rfc.add(n2,aa.toRotationMatrix()*n2+nn,
00635 1*n2.cross(y),1*n2.cross(z),
00636 1*(aa.toRotationMatrix()*n2).cross(y),1*(aa.toRotationMatrix()*n2).cross(z),
00637 1,1);
00638 #endif
00639 rfc.add(n3,aa.toRotationMatrix()*n3+nn,
00640
00641
00642 n3.cross(y),n3.cross(z),
00643 1*(aa.toRotationMatrix()*n3).cross(y),1*(aa.toRotationMatrix()*n3).cross(z),
00644 1,1);
00645
00646 std::cout<<"comp matrix:\n"<<rfc.getTransformation()<<"\n\n";
00647 std::cout<<"real matrix:\n"<<aa.toRotationMatrix()<<"\n\n";
00648
00649 return 0;
00650
00651
00652 rfc.covariance_ = (rfc.var_*rfc.covariance_.inverse().transpose()*rfc.covariance_);
00653 std::cout<<"comp matrix: "<<rfc.getTransformation()<<"\n\n";
00654 std::cout<<"real matrix: "<<aa.toRotationMatrix()*aa.toRotationMatrix()<<"\n\n";
00655
00656 return 0;
00657 #endif
00658
00659 testing::InitGoogleTest(&argc, argv);
00660 return RUN_ALL_TESTS();
00661 }
00662
00663