00001 #include "ndt_map/ndt_cell.h"
00002 #include "ndt_map/lazy_grid.h"
00003 #include "ndt_map/pointcloud_utils.h"
00004 #include "ndt_registration/ndt_matcher_d2d.h"
00005
00006 #include "Eigen/Eigen"
00007 #include <fstream>
00008 #include <omp.h>
00009 #include <sys/time.h>
00010 namespace lslgeneric
00011 {
00012
00013
00014
00015 void NDTMatcherD2D::init(bool _isIrregularGrid,
00016 bool useDefaultGridResolutions, std::vector<double> _resolutions)
00017 {
00018 Jest.setZero();
00019 Jest.block<3,3>(0,0).setIdentity();
00020 Hest.setZero();
00021 Zest.setZero();
00022 ZHest.setZero();
00023
00024 isIrregularGrid = _isIrregularGrid;
00025 if(useDefaultGridResolutions)
00026 {
00027 resolutions.push_back(0.2);
00028 resolutions.push_back(0.5);
00029 resolutions.push_back(1);
00030 resolutions.push_back(2);
00031 }
00032 else
00033 {
00034 resolutions = _resolutions;
00035 }
00036
00037 current_resolution = 0.1;
00038 lfd1 = 1;
00039 lfd2 = 0.05;
00040 ITR_MAX = 30;
00041 DELTA_SCORE = 10e-3*current_resolution;
00042 step_control = true;
00043
00044 regularize = true;
00045
00046 n_neighbours =2;
00047
00048 }
00049
00050 bool NDTMatcherD2D::match( pcl::PointCloud<pcl::PointXYZ>& target,
00051 pcl::PointCloud<pcl::PointXYZ>& source,
00052 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T ,
00053 bool useInitialGuess)
00054 {
00055
00056 struct timeval tv_start, tv_end;
00057 struct timeval tv_start0, tv_end0;
00058 double time_load =0, time_match=0, time_combined=0;
00059
00060 gettimeofday(&tv_start0,NULL);
00061
00062
00063 pcl::PointCloud<pcl::PointXYZ> sourceCloud = source;
00064 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> Temp, Tinit;
00065 Tinit.setIdentity();
00066 if(useInitialGuess)
00067 {
00068 lslgeneric::transformPointCloudInPlace(T,sourceCloud);
00069 Tinit = T;
00070 }
00071
00072 T.setIdentity();
00073 bool ret = false;
00074
00075 #if 0
00076 if(isIrregularGrid)
00077 {
00078
00079 OctTree<PointTarget> pr1;
00080 NDTMap<PointTarget> targetNDT( &pr1 );
00081 targetNDT.loadPointCloud( target );
00082 targetNDT.computeNDTCells();
00083
00084 OctTree<PointSource> pr2;
00085 NDTMap<PointSource> sourceNDT( &pr2 );
00086 sourceNDT.loadPointCloud( source );
00087 sourceNDT.computeNDTCells();
00088
00089 ret = this->match( targetNDT, sourceNDT, T );
00090
00091 }
00092 else
00093 #endif
00094 {
00095
00096
00097 for(int r_ctr = resolutions.size()-1; r_ctr >=0; r_ctr--)
00098 {
00099
00100 current_resolution = resolutions[r_ctr];
00101
00102 LazyGrid prototypeSource(current_resolution);
00103 LazyGrid prototypeTarget(current_resolution);
00104
00105 gettimeofday(&tv_start,NULL);
00106 NDTMap targetNDT( &prototypeTarget );
00107 targetNDT.loadPointCloud( target );
00108 targetNDT.computeNDTCells();
00109
00110 NDTMap sourceNDT( &prototypeSource );
00111 sourceNDT.loadPointCloud( sourceCloud );
00112 sourceNDT.computeNDTCells();
00113 gettimeofday(&tv_end,NULL);
00114
00115 time_load += (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
00116 Temp.setIdentity();
00117
00118 gettimeofday(&tv_start,NULL);
00119 ret = this->match( targetNDT, sourceNDT, Temp );
00120 lslgeneric::transformPointCloudInPlace(Temp,sourceCloud);
00121 gettimeofday(&tv_end,NULL);
00122
00123 time_match += (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
00124
00125
00126 T = Temp*T;
00127
00128
00129 #ifdef DO_DEBUG_PROC
00130 std::cout<<"RESOLUTION: "<<current_resolution<<std::endl;
00131 std::cout<<"rotation : "<<Temp.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00132 std::cout<<"translation: "<<Temp.translation().transpose()<<std::endl;
00133 std::cout<<"--------------------------------------------------------\nOverall Transform:\n";
00134 std::cout<<"rotation : "<<T.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00135 std::cout<<"translation: "<<T.translation().transpose()<<std::endl;
00136
00137 #endif
00138 }
00139 }
00140 if(useInitialGuess)
00141 {
00142 T = T*Tinit;
00143 }
00144 gettimeofday(&tv_end0,NULL);
00145 time_combined = (tv_end0.tv_sec-tv_start0.tv_sec)*1000.+(tv_end0.tv_usec-tv_start0.tv_usec)/1000.;
00146
00147 return ret;
00148 }
00149
00150 bool NDTMatcherD2D::match( NDTMap& targetNDT,
00151 NDTMap& sourceNDT,
00152 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T ,
00153 bool useInitialGuess)
00154 {
00155
00156
00157 bool convergence = false;
00158
00159 double score_best = INT_MAX;
00160
00161
00162 int itr_ctr = 0;
00163
00164 double step_size = 1;
00165 Eigen::Matrix<double,6,1> pose_increment_v, scg;
00166 Eigen::MatrixXd Hessian(6,6), score_gradient(6,1);
00167
00168 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR, Tbest;
00169 Eigen::Vector3d transformed_vec, mean;
00170 bool ret = true;
00171 if(!useInitialGuess)
00172 {
00173 T.setIdentity();
00174 }
00175 Tbest = T;
00176
00177
00178 Eigen::Array<double,6,1> weights;
00179 std::vector<NDTCell*> nextNDT = sourceNDT.pseudoTransformNDT(T);
00180
00181
00182 while(!convergence)
00183 {
00184 TR.setIdentity();
00185 Hessian.setZero();
00186 score_gradient.setZero();
00187
00188 double score_here = derivativesNDT(nextNDT,targetNDT,score_gradient,Hessian,true);
00189
00190 scg = score_gradient;
00191
00192 if(score_here < score_best)
00193 {
00194 Tbest = T;
00195 score_best = score_here;
00196
00197 }
00198
00199
00200 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
00201 Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
00202 double minCoeff = evals.minCoeff();
00203 double maxCoeff = evals.maxCoeff();
00204 if(minCoeff < 0)
00205 {
00206 if(regularize) {
00207 Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
00208 double regularizer = score_gradient.norm();
00209 regularizer = regularizer + minCoeff > 0 ? regularizer : 0.001*maxCoeff - minCoeff;
00210
00211 Eigen::Matrix<double,6,1> reg;
00212
00213 reg<<regularizer,regularizer,regularizer,regularizer,regularizer,regularizer;
00214 evals += reg;
00215 Eigen::Matrix<double,6,6> Lam;
00216 Lam = evals.asDiagonal();
00217 Hessian = evecs*Lam*(evecs.transpose());
00218 } else {
00219 if(score_here > score_best)
00220 {
00221 T = Tbest;
00222 }
00223
00224 for(unsigned int i=0; i<nextNDT.size(); i++)
00225 {
00226 if(nextNDT[i]!=NULL)
00227 delete nextNDT[i];
00228 }
00229 return true;
00230 }
00231
00232 }
00233
00234
00235
00236 if (score_gradient.norm()<= DELTA_SCORE)
00237 {
00238
00239
00240 if(score_here > score_best)
00241 {
00242
00243 T = Tbest;
00244 }
00245
00246 for(unsigned int i=0; i<nextNDT.size(); i++)
00247 {
00248 if(nextNDT[i]!=NULL)
00249 delete nextNDT[i];
00250 }
00251
00252 return true;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 pose_increment_v = -Hessian.ldlt().solve(score_gradient);
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 double dginit = pose_increment_v.dot(scg);
00302 if(dginit > 0)
00303 {
00304
00305
00306
00307
00308 if(score_here > score_best)
00309 {
00310
00311 T = Tbest;
00312 }
00313 for(unsigned int i=0; i<nextNDT.size(); i++)
00314 {
00315 if(nextNDT[i]!=NULL)
00316 delete nextNDT[i];
00317 }
00318
00319 return true;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 if(step_control) {
00362 step_size = lineSearchMT(pose_increment_v,nextNDT,targetNDT);
00363 } else {
00364 step_size = 1;
00365 }
00366 pose_increment_v = step_size*pose_increment_v;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 TR.setIdentity();
00377 TR = Eigen::Translation<double,3>(pose_increment_v(0),pose_increment_v(1),pose_increment_v(2))*
00378 Eigen::AngleAxis<double>(pose_increment_v(3),Eigen::Vector3d::UnitX()) *
00379 Eigen::AngleAxis<double>(pose_increment_v(4),Eigen::Vector3d::UnitY()) *
00380 Eigen::AngleAxis<double>(pose_increment_v(5),Eigen::Vector3d::UnitZ()) ;
00381
00382
00383
00384 T = TR*T;
00385
00386
00387
00388 for(unsigned int i=0; i<nextNDT.size(); i++)
00389 {
00390
00391 Eigen::Vector3d meanC = nextNDT[i]->getMean();
00392 Eigen::Matrix3d covC = nextNDT[i]->getCov();
00393 meanC = TR*meanC;
00394 covC = TR.rotation()*covC*TR.rotation().transpose();
00395 nextNDT[i]->setMean(meanC);
00396 nextNDT[i]->setCov(covC);
00397 }
00398
00399 if(itr_ctr>0)
00400 {
00401 convergence = ((pose_increment_v.norm()) < DELTA_SCORE);
00402
00403 }
00404 if(itr_ctr>ITR_MAX)
00405 {
00406 convergence = true;
00407 ret = false;
00408 }
00409 itr_ctr++;
00410
00411
00412 }
00413
00414
00415
00416 score_gradient.setZero();
00417 double score_here = derivativesNDT(nextNDT,targetNDT,score_gradient,Hessian,false);
00418 if(score_here > score_best)
00419 {
00420
00421 T = Tbest;
00422 }
00423 for(unsigned int i=0; i<nextNDT.size(); i++)
00424 {
00425 if(nextNDT[i]!=NULL)
00426 delete nextNDT[i];
00427 }
00428
00429
00430
00431
00432
00433
00434
00435 return ret;
00436 }
00437
00438
00439 bool NDTMatcherD2D::update_gradient_hessian_local(
00440 Eigen::MatrixXd &score_gradient,
00441 Eigen::MatrixXd &Hessian,
00442 const Eigen::Vector3d & x,
00443 const Eigen::Matrix3d & B,
00444 const double &likelihood,
00445 const Eigen::Matrix<double,3,6> &_Jest,
00446 const Eigen::Matrix<double,18,6> &_Hest,
00447 const Eigen::Matrix<double,3,18> &_Zest,
00448 const Eigen::Matrix<double,18,18> &_ZHest,
00449 bool computeHessian)
00450 {
00451
00452
00453
00454 Eigen::Matrix<double,6,1> _xtBJ, _xtBZBx, _Q;
00455
00456 Eigen::Matrix<double,6,6> _xtBZBJ, _xtBH, _xtBZBZBx, _xtBZhBx;
00457 Eigen::Matrix<double,1,3> _TMP1, _xtB;
00458
00459 _xtBJ.setZero();
00460 _xtBZBx.setZero();
00461 _Q.setZero();
00462 _xtBZBJ.setZero();
00463 _xtBH.setZero();
00464 _xtBZBZBx.setZero();
00465 _xtBZhBx.setZero();
00466 _TMP1.setZero();
00467 _xtB.setZero();
00468
00469 _xtB = x.transpose()*B;
00470 _xtBJ = _xtB*_Jest;
00471
00472 for(unsigned int i=0; i<6; i++)
00473 {
00474 _TMP1 = _xtB*_Zest.block<3,3>(0,3*i)*B;
00475 _xtBZBx(i) = _TMP1*x;
00476 if(computeHessian)
00477 {
00478 _xtBZBJ.col(i) = (_TMP1*_Jest).transpose();
00479 for(unsigned int j=0; j<6; j++)
00480 {
00481 _xtBH(i,j) = _xtB*_Hest.block<3,1>(3*i,j);
00482 _xtBZBZBx(i,j) = _TMP1*_Zest.block<3,3>(0,3*j)*B*x;
00483 _xtBZhBx(i,j) = _xtB*_ZHest.block<3,3>(3*i,3*j)*B*x;
00484 }
00485 }
00486 }
00487 _Q = 2*_xtBJ-_xtBZBx;
00488 double factor = -(lfd2/2)*likelihood;
00489 score_gradient += _Q*factor;
00490
00491 if(computeHessian)
00492 {
00493 Hessian += factor*(2*_Jest.transpose()*B*_Jest+2*_xtBH -_xtBZhBx -2*_xtBZBJ.transpose()
00494 -2*_xtBZBJ +_xtBZBZBx +_xtBZBZBx.transpose() -lfd2*_Q*_Q.transpose()/2 );
00495
00496 }
00497 return true;
00498 }
00499
00500 bool NDTMatcherD2D::update_gradient_hessian(
00501 Eigen::MatrixXd &score_gradient,
00502 Eigen::MatrixXd &Hessian,
00503 const Eigen::Vector3d & x,
00504 const Eigen::Matrix3d & B,
00505 const double &likelihood,
00506 bool computeHessian)
00507 {
00508
00509
00510
00511
00512
00513
00514
00515
00516 Eigen::MatrixXd Hloc(6,6), sg(6,1);
00517
00518 Hloc.setZero();
00519 sg.setZero();
00520 xtBJ.setZero();
00521 xtBZBx.setZero();
00522 Q.setZero();
00523 JtBJ.setZero();
00524 xtBZBJ.setZero();
00525 xtBH.setZero();
00526 xtBZBZBx.setZero();
00527 xtBZhBx.setZero();
00528 TMP1.setZero();
00529 xtB.setZero();
00530
00531 xtB = x.transpose()*B;
00532 xtBJ = xtB*Jest;
00533
00534 for(unsigned int i=0; i<6; i++)
00535 {
00536 TMP1 = xtB*Zest.block<3,3>(0,3*i)*B;
00537 xtBZBx(i) = TMP1*x;
00538 if(computeHessian)
00539 {
00540 xtBZBJ.col(i) = (TMP1*Jest).transpose();
00541 for(unsigned int j=0; j<6; j++)
00542 {
00543 xtBH(i,j) = xtB*Hest.block<3,1>(3*i,j);
00544 xtBZBZBx(i,j) = TMP1*Zest.block<3,3>(0,3*j)*B*x;
00545 xtBZhBx(i,j) = xtB*ZHest.block<3,3>(3*i,3*j)*B*x;
00546 }
00547 }
00548 }
00549 Q = 2*xtBJ-xtBZBx;
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 double factor = -(lfd2/2)*likelihood;
00565 sg = Q*factor;
00566
00567 score_gradient += sg;
00568
00569 if(computeHessian)
00570 {
00571 Hloc= factor*(2*Jest.transpose()*B*Jest+2*xtBH -xtBZhBx -2*xtBZBJ.transpose()
00572 -2*xtBZBJ +xtBZBZBx +xtBZBZBx.transpose() -lfd2*Q*Q.transpose()/2 );
00573 Hessian += Hloc;
00574
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584 return true;
00585
00586 }
00587
00588
00589 void NDTMatcherD2D::computeDerivativesLocal(Eigen::Vector3d &x, Eigen::Matrix3d C1,
00590 Eigen::Matrix<double,3,6> &_Jest,
00591 Eigen::Matrix<double,18,6> &_Hest,
00592 Eigen::Matrix<double,3,18> &_Zest,
00593 Eigen::Matrix<double,18,18> &_ZHest,
00594 bool computeHessian)
00595 {
00596
00597 _Jest(0,4) = x(2);
00598 _Jest(0,5) = -x(1);
00599 _Jest(1,3) = -x(2);
00600 _Jest(1,5) = x(0);
00601 _Jest(2,3) = x(1);
00602 _Jest(2,4) = -x(0);
00603
00604 Eigen::Matrix3d myBlock;
00605
00606 myBlock<<
00607 0, -C1(0,2), C1(0,1),
00608 -C1(0,2), -2*C1(1,2), -C1(2,2) + C1(1,1),
00609 C1(0,1), -C1(2,2) + C1(1,1), 2*C1(1,2);
00610 _Zest.block<3,3>(0,9) = myBlock;
00611 myBlock<<
00612 2*C1(0,2), C1(1,2), -C1(0,0) + C1(2,2),
00613 C1(1,2), 0, -C1(0,1),
00614 -C1(0,0) + C1(2,2), -C1(0,1), -2*C1(0,2);
00615 _Zest.block<3,3>(0,12) = myBlock;
00616 myBlock<<
00617 -2*C1(0,1), -C1(1,1) + C1(0,0), -C1(1,2),
00618 -C1(1,1) + C1(0,0), 2*C1(0,1), C1(0,2),
00619 -C1(1,2), C1(0,2), 0;
00620 _Zest.block<3,3>(0,15) = myBlock;
00621
00622 if(computeHessian)
00623 {
00624 Eigen::Vector3d a,b,c,d,e,f;
00625 a<<0,-x(1),-x(2);
00626 b<<0,x(0),0;
00627 c<<0,0,x(0);
00628 d<<-x(0),0,-x(2);
00629 e<<0,0,x(1);
00630 f<<-x(0),-x(1),0;
00631
00632 _Hest.block<3,1>(9,3) = a;
00633 _Hest.block<3,1>(12,3) = b;
00634 _Hest.block<3,1>(15,3) = c;
00635 _Hest.block<3,1>(9,4) = b;
00636 _Hest.block<3,1>(12,4) = d;
00637 _Hest.block<3,1>(15,4) = e;
00638 _Hest.block<3,1>(9,5) = c;
00639 _Hest.block<3,1>(12,5) = e;
00640 _Hest.block<3,1>(15,5) = f;
00641
00642
00643 myBlock<<
00644 0, -C1(0,1), -C1(0,2),
00645 -C1(0,1), 2*C1(2,2) - 2*C1(1,1), -4*C1(1,2),
00646 -C1(0,2), -4*C1(1,2), 2*C1(1,1) - 2*C1(2,2);
00647 _ZHest.block<3,3>(9,9) = myBlock;
00648
00649 myBlock<<
00650 0, C1(0,0) - C1(2,2), C1(1,2),
00651 C1(0,0) - C1(2,2), 2*C1(0,1), 2*C1(0,2),
00652 C1(1,2), 2*C1(0,2), -2*C1(0,1);
00653 _ZHest.block<3,3>(9,12) = myBlock;
00654
00655 myBlock<<
00656 0, C1(1,2), C1(0,0) - C1(1,1),
00657 C1(1,2), -2*C1(0,2), 2*C1(0,1),
00658 C1(0,0) - C1(1,1), 2*C1(0,1), 2*C1(0,2);
00659 _ZHest.block<3,3>(9,15) = myBlock;
00660
00661 myBlock<<
00662 2*C1(2,2) - 2*C1(0,0), -C1(0,1), -4*C1(0,2),
00663 -C1(0,1), 0, -C1(1,2),
00664 -4*C1(0,2), -C1(1,2), 2*C1(0,0) - 2*C1(2,2);
00665 _ZHest.block<3,3>(12,12) = myBlock;
00666
00667 myBlock<<
00668 -2*C1(1,2), C1(0,2), 2*C1(0,1),
00669 C1(0,2), 0, C1(1,1) - C1(0,0),
00670 2*C1(0,1), C1(1,1) - C1(0,0), 2*C1(1,2);
00671 _ZHest.block<3,3>(12,15) = myBlock;
00672
00673 myBlock<<
00674 2*C1(1,1) - 2*C1(0,0), -4*C1(0,1), -C1(0,2),
00675 -4*C1(0,1), 2*C1(0,0) - 2*C1(1,1), -C1(1,2),
00676 -C1(0,2), -C1(1,2), 0;
00677 _ZHest.block<3,3>(15,15)= myBlock;
00678
00679 _ZHest.block<3,3>(12,9) = _ZHest.block<3,3>(9,12);
00680 _ZHest.block<3,3>(15,9) = _ZHest.block<3,3>(9,15);
00681 _ZHest.block<3,3>(15,12)= _ZHest.block<3,3>(12,15);
00682 }
00683 }
00684
00685 void NDTMatcherD2D::computeDerivatives(Eigen::Vector3d &x, Eigen::Matrix3d C1, bool computeHessian)
00686 {
00687
00688 Jest(0,4) = x(2);
00689 Jest(0,5) = -x(1);
00690 Jest(1,3) = -x(2);
00691 Jest(1,5) = x(0);
00692 Jest(2,3) = x(1);
00693 Jest(2,4) = -x(0);
00694
00695 Eigen::Matrix3d myBlock;
00696
00697 myBlock<<
00698 0, -C1(0,2), C1(0,1),
00699 -C1(0,2), -2*C1(1,2), -C1(2,2) + C1(1,1),
00700 C1(0,1), -C1(2,2) + C1(1,1), 2*C1(1,2);
00701 Zest.block<3,3>(0,9) = myBlock;
00702 myBlock<<
00703 2*C1(0,2), C1(1,2), -C1(0,0) + C1(2,2),
00704 C1(1,2), 0, -C1(0,1),
00705 -C1(0,0) + C1(2,2), -C1(0,1), -2*C1(0,2);
00706 Zest.block<3,3>(0,12) = myBlock;
00707 myBlock<<
00708 -2*C1(0,1), -C1(1,1) + C1(0,0), -C1(1,2),
00709 -C1(1,1) + C1(0,0), 2*C1(0,1), C1(0,2),
00710 -C1(1,2), C1(0,2), 0;
00711 Zest.block<3,3>(0,15) = myBlock;
00712
00713 if(computeHessian)
00714 {
00715 Eigen::Vector3d a,b,c,d,e,f;
00716 a<<0,-x(1),-x(2);
00717 b<<0,x(0),0;
00718 c<<0,0,x(0);
00719 d<<-x(0),0,-x(2);
00720 e<<0,0,x(1);
00721 f<<-x(0),-x(1),0;
00722
00723 Hest.block<3,1>(9,3) = a;
00724 Hest.block<3,1>(12,3) = b;
00725 Hest.block<3,1>(15,3) = c;
00726 Hest.block<3,1>(9,4) = b;
00727 Hest.block<3,1>(12,4) = d;
00728 Hest.block<3,1>(15,4) = e;
00729 Hest.block<3,1>(9,5) = c;
00730 Hest.block<3,1>(12,5) = e;
00731 Hest.block<3,1>(15,5) = f;
00732
00733
00734 myBlock<<
00735 0, -C1(0,1), -C1(0,2),
00736 -C1(0,1), 2*C1(2,2) - 2*C1(1,1), -4*C1(1,2),
00737 -C1(0,2), -4*C1(1,2), 2*C1(1,1) - 2*C1(2,2);
00738 ZHest.block<3,3>(9,9) = myBlock;
00739
00740 myBlock<<
00741 0, C1(0,0) - C1(2,2), C1(1,2),
00742 C1(0,0) - C1(2,2), 2*C1(0,1), 2*C1(0,2),
00743 C1(1,2), 2*C1(0,2), -2*C1(0,1);
00744 ZHest.block<3,3>(9,12) = myBlock;
00745
00746 myBlock<<
00747 0, C1(1,2), C1(0,0) - C1(1,1),
00748 C1(1,2), -2*C1(0,2), 2*C1(0,1),
00749 C1(0,0) - C1(1,1), 2*C1(0,1), 2*C1(0,2);
00750 ZHest.block<3,3>(9,15) = myBlock;
00751
00752 myBlock<<
00753 2*C1(2,2) - 2*C1(0,0), -C1(0,1), -4*C1(0,2),
00754 -C1(0,1), 0, -C1(1,2),
00755 -4*C1(0,2), -C1(1,2), 2*C1(0,0) - 2*C1(2,2);
00756 ZHest.block<3,3>(12,12) = myBlock;
00757
00758 myBlock<<
00759 -2*C1(1,2), C1(0,2), 2*C1(0,1),
00760 C1(0,2), 0, C1(1,1) - C1(0,0),
00761 2*C1(0,1), C1(1,1) - C1(0,0), 2*C1(1,2);
00762 ZHest.block<3,3>(12,15) = myBlock;
00763
00764 myBlock<<
00765 2*C1(1,1) - 2*C1(0,0), -4*C1(0,1), -C1(0,2),
00766 -4*C1(0,1), 2*C1(0,0) - 2*C1(1,1), -C1(1,2),
00767 -C1(0,2), -C1(1,2), 0;
00768 ZHest.block<3,3>(15,15)= myBlock;
00769
00770 ZHest.block<3,3>(12,9) = ZHest.block<3,3>(9,12);
00771 ZHest.block<3,3>(15,9) = ZHest.block<3,3>(9,15);
00772 ZHest.block<3,3>(15,12)= ZHest.block<3,3>(12,15);
00773 }
00774 }
00775
00776 double NDTMatcherD2D::scoreNDT(std::vector<NDTCell*> &sourceNDT, NDTMap &targetNDT)
00777 {
00778 NUMBER_OF_ACTIVE_CELLS = 0;
00779 NDTCell *cell;
00780 Eigen::Vector3d transformed, eps;
00781 Eigen::Vector3d meanMoving, meanFixed;
00782 Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
00783
00784 bool exists = false;
00785 double det = 0;
00786 double score_here = 0;
00787
00788 pcl::PointXYZ point;
00789 for(unsigned int i=0; i<sourceNDT.size(); i++)
00790 {
00791 meanMoving = sourceNDT[i]->getMean();
00792 CMoving= sourceNDT[i]->getCov();
00793 point.x = meanMoving(0);
00794 point.y = meanMoving(1);
00795 point.z = meanMoving(2);
00796 std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(point,2);
00797 for(unsigned int j=0; j<cells.size(); j++)
00798 {
00799 cell = cells[j];
00800 if(cell == NULL)
00801 {
00802 continue;
00803 }
00804 if(cell->hasGaussian_)
00805 {
00806 transformed = meanMoving - cell->getMean();
00807 CFixed = cell->getCov();
00808 CSum = (CFixed+CMoving);
00809 CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
00810 if(!exists)
00811 {
00812 continue;
00813 }
00814 double l = (transformed).dot(Cinv*(transformed));
00815 if(l*0 != 0)
00816 {
00817 continue;
00818 }
00819
00820 double sh = -lfd1*(exp(-lfd2*l/2));
00821 NUMBER_OF_ACTIVE_CELLS++;
00822 score_here += sh;
00823 cell = NULL;
00824 }
00825 else
00826 {
00827
00828
00829 }
00830 }
00831 }
00832
00833 return score_here;
00834 }
00835
00836 double NDTMatcherD2D::scoreNDT_OM(NDTMap &sourceNDT, NDTMap &targetNDT)
00837 {
00838 NUMBER_OF_ACTIVE_CELLS = 0;
00839 Eigen::Vector3d transformed;
00840 Eigen::Vector3d meanMoving, meanFixed;
00841 Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
00842 bool exists = false;
00843 double det = 0;
00844 double score_here = 0;
00845 double importance_free = 0.1;
00846
00847 pcl::PointXYZ point;
00848 LazyGrid* lz = dynamic_cast<LazyGrid*> (sourceNDT.getMyIndex());
00849 if(lz==NULL) return INT_MAX;
00850 std::vector<NDTCell*>::iterator it = lz->begin();
00851
00852
00853
00854
00855 while(it!=lz->end()) {
00856 if(*it == NULL) {
00857 it++;
00858 continue;
00859 }
00860 NDTCell* source =(*it);
00861 if(source==NULL) {
00862 it++;
00863 continue;
00864 }
00865 source->consistency_score = 0;
00866 NDTCell* cell=NULL;
00867 point = source->getCenter();
00868
00869 std::vector<NDTCell*> all_cells = targetNDT.getCellsForPoint(point,2,false);
00870
00871 for(unsigned int j=0; j<all_cells.size(); j++) {
00872 cell = all_cells[j];
00873 if(cell == NULL) {
00874 it++;
00875 continue;
00876 }
00877 double o1,o2;
00878 o1 = source->getOccupancyRescaled();
00879 o2 = cell->getOccupancyRescaled();
00880
00881
00882 if(source->hasGaussian_) {
00883 meanMoving = source->getMean();
00884 CMoving= source->getCov();
00885
00886
00887 if(cell->hasGaussian_) {
00888
00889 transformed = meanMoving - cell->getMean();
00890 CFixed = cell->getCov();
00891 CSum = (CFixed+CMoving);
00892 CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
00893 if(!exists)
00894 {
00895 it++;
00896 continue;
00897 }
00898 double l = (transformed).dot(Cinv*(transformed));
00899 if(l*0 != 0) {
00900 it++;
00901 continue;
00902 }
00903 double sh = -lfd1*(exp(-lfd2*l/2));
00904
00905 score_here += o1*o2*sh;
00906
00907
00908 source->consistency_score += -o1*o2*sh;
00909 }
00910 }
00911
00912 pcl::PointXYZ cen1 = cell->getCenter();
00913 pcl::PointXYZ cen2 = source->getCenter();
00914 double cell_dist = std::sqrt(pow(cen1.x-cen2.x,2)+pow(cen1.y-cen2.y,2)+pow(cen1.z-cen2.z,2));
00915 double lambda = 1 - cell_dist/(cell->getDiagonal());
00916 lambda = lambda < 0 ? 0 : importance_free*lambda;
00917
00918 score_here += -lambda*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1));
00919
00920
00921
00922 double ll = cell->isInside(cen2) ? 1 : 0;
00923
00924 source->consistency_score += ll*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1));
00925 }
00926 it++;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 return score_here;
00939 }
00940
00947 double NDTMatcherD2D::scoreNDTPositive(std::vector<NDTCell*> &sourceNDT, NDTMap &targetNDT,
00948 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T)
00949 {
00950
00951 NUMBER_OF_ACTIVE_CELLS = 0;
00952 double score_here = 0;
00953 double det = 0;
00954 bool exists = false;
00955 NDTCell *cell;
00956 Eigen::Matrix3d covCombined, icov, R;
00957 Eigen::Vector3d meanFixed;
00958 Eigen::Vector3d meanMoving;
00959 pcl::PointXYZ point;
00960
00961 R = T.rotation();
00962 for(unsigned int i=0; i<sourceNDT.size(); i++)
00963 {
00964 meanMoving = T*sourceNDT[i]->getMean();
00965 point.x = meanMoving(0);
00966 point.y = meanMoving(1);
00967 point.z = meanMoving(2);
00968
00969 if(!targetNDT.getCellForPoint(point,cell))
00970 {
00971 score_here += 0.1;
00972 continue;
00973 }
00974
00975 if(cell == NULL)
00976 {
00977 score_here += 0.1;
00978 continue;
00979 }
00980 if(cell->hasGaussian_)
00981 {
00982 meanFixed = cell->getMean();
00983 covCombined = cell->getCov() + R.transpose()*sourceNDT[i]->getCov()*R;
00984 covCombined.computeInverseAndDetWithCheck(icov,det,exists);
00985 if(!exists)
00986 {
00987 score_here+=0.1;
00988 continue;
00989 }
00990 double l = (meanMoving-meanFixed).dot(icov*(meanMoving-meanFixed));
00991 if(l*0 != 0)
00992 {
00993 score_here+=0.1;
00994 continue;
00995 }
00996 if(l > 120)
00997 {
00998 score_here+=0.1;
00999 continue;
01000 }
01001
01002 double sh = lfd1*(exp(-lfd2*l/2));
01003
01004 if(fabsf(sh) > 1e-10)
01005 {
01006 NUMBER_OF_ACTIVE_CELLS++;
01007 }
01008 score_here += (1.0 - sh);
01009
01010 }
01011 else
01012 {
01013 score_here+=0.1;
01014 }
01015
01016 }
01017 return score_here;
01018 }
01019
01023
01024
01025
01026 #define USE_OMP
01027
01028
01029 double NDTMatcherD2D::derivativesNDT(
01030 const std::vector<NDTCell*> &sourceNDT,
01031 const NDTMap &targetNDT,
01032 Eigen::MatrixXd &score_gradient,
01033 Eigen::MatrixXd &Hessian,
01034 bool computeHessian
01035 )
01036 {
01037
01038
01039 double score_here = 0;
01040 int n_dimensions = score_gradient.rows();
01041
01042
01043 NUMBER_OF_ACTIVE_CELLS = 0;
01044 score_gradient.setZero();
01045 Hessian.setZero();
01046
01047 #ifdef USE_OMP
01048 Eigen::MatrixXd score_gradient_omp;
01049 Eigen::MatrixXd score_here_omp;
01050 Eigen::MatrixXd Hessian_omp;
01051
01052 #define n_threads 6
01053
01054
01055 score_gradient_omp.resize(n_dimensions,n_threads);
01056 score_here_omp.resize(1,n_threads);
01057 Hessian_omp.resize(n_dimensions,n_dimensions*n_threads);
01058
01059 score_gradient_omp.setZero();
01060 score_here_omp.setZero();
01061 Hessian_omp.setZero();
01062
01063
01064 #pragma omp parallel num_threads(n_threads)
01065 {
01066 #pragma omp for
01067 for(unsigned int i=0; i<sourceNDT.size(); i++)
01068 {
01069 if(sourceNDT[i] == NULL) continue;
01070 if(!sourceNDT[i]->hasGaussian_) continue;
01071 pcl::PointXYZ point;
01072 Eigen::Vector3d transformed;
01073 Eigen::Vector3d meanMoving, meanFixed;
01074 Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
01075 Eigen::MatrixXd score_gradient_omp_loc(n_dimensions,1);
01076 Eigen::MatrixXd Hessian_omp_loc(n_dimensions,n_dimensions);
01077 Eigen::Matrix<double,3,6> _Jest;
01078 Eigen::Matrix<double,18,6> _Hest;
01079 Eigen::Matrix<double,3,18> _Zest;
01080 Eigen::Matrix<double,18,18> _ZHest;
01081 double score_here_loc=0;
01082 int thread_id = omp_get_thread_num();
01083 NDTCell *cell;
01084 bool exists = false;
01085 double det = 0;
01086
01087
01088 score_gradient_omp_loc.setZero();
01089 Hessian_omp_loc.setZero();
01090 _Jest.setZero();
01091 _Jest.block<3,3>(0,0).setIdentity();
01092 _Hest.setZero();
01093 _Zest.setZero();
01094 _ZHest.setZero();
01095
01096 meanMoving = sourceNDT[i]->getMean();
01097 CMoving= sourceNDT[i]->getCov();
01098 computeDerivativesLocal(meanMoving, CMoving, _Jest, _Hest, _Zest, _ZHest, computeHessian);
01099
01100 point.x = meanMoving(0);
01101 point.y = meanMoving(1);
01102 point.z = meanMoving(2);
01103 std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(point,n_neighbours);
01104 for(unsigned int j=0; j<cells.size(); j++)
01105 {
01106 cell = cells[j];
01107 if(cell == NULL)
01108 {
01109 continue;
01110 }
01111 if(cell->hasGaussian_)
01112 {
01113 transformed = meanMoving - cell->getMean();
01114 CFixed = cell->getCov();
01115 CSum = (CFixed+CMoving);
01116 CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
01117 if(!exists)
01118 {
01119 continue;
01120 }
01121 double l = (transformed).dot(Cinv*(transformed));
01122 if(l*0 != 0)
01123 {
01124 continue;
01125 }
01126
01127 double sh = -lfd1*(exp(-lfd2*l/2));
01128 if(!update_gradient_hessian_local(score_gradient_omp_loc,Hessian_omp_loc,transformed, Cinv, sh,
01129 _Jest, _Hest, _Zest, _ZHest, computeHessian))
01130 {
01131 continue;
01132 }
01133 score_here_loc += sh;
01134 cell = NULL;
01135 }
01136 }
01137
01138 score_gradient_omp.col(thread_id) += score_gradient_omp_loc;
01139 Hessian_omp.block(0,n_dimensions*thread_id,n_dimensions,n_dimensions) += Hessian_omp_loc;
01140 score_here_omp(0,thread_id) += score_here_loc;
01141
01142 }
01143 }
01144
01145
01146
01147 score_gradient = score_gradient_omp.rowwise().sum();
01148 score_here = score_here_omp.sum();
01149 if(computeHessian)
01150 {
01151
01152 for(int i=0; i<n_threads; ++i)
01153 {
01154 Hessian += Hessian_omp.block(0,n_dimensions*i,n_dimensions,n_dimensions);
01155 }
01156 }
01157 #else
01158 pcl::PointXYZ point;
01159 Eigen::Vector3d transformed;
01160 Eigen::Vector3d meanMoving, meanFixed;
01161 Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
01162 NDTCell *cell;
01163 bool exists = false;
01164 double det = 0;
01165 for(unsigned int i=0; i<sourceNDT.size(); i++)
01166 {
01167 meanMoving = sourceNDT[i]->getMean();
01168 CMoving= sourceNDT[i]->getCov();
01169 computeDerivatives(meanMoving, CMoving, computeHessian);
01170
01171 point.x = meanMoving(0);
01172 point.y = meanMoving(1);
01173 point.z = meanMoving(2);
01174 std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(point,n_neighbours);
01175 for(int j=0; j<cells.size(); j++)
01176 {
01177 cell = cells[j];
01178 if(cell == NULL)
01179 {
01180 continue;
01181 }
01182 if(cell->hasGaussian_)
01183 {
01184 transformed = meanMoving - cell->getMean();
01185 CFixed = cell->getCov();
01186 CSum = (CFixed+CMoving);
01187 CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
01188 if(!exists)
01189 {
01190
01191 continue;
01192 }
01193 double l = (transformed).dot(Cinv*(transformed));
01194 if(l*0 != 0)
01195 {
01196
01197 continue;
01198 }
01199
01200 double sh = -lfd1*(exp(-lfd2*l/2));
01201
01202
01203
01204
01205
01206 if(!update_gradient_hessian(score_gradient,Hessian,transformed, Cinv, sh, computeHessian))
01207 {
01208
01209 continue;
01210 }
01211
01212 score_here += sh;
01213
01214 cell = NULL;
01215 }
01216 }
01217 }
01218 #endif
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 return score_here;
01265 }
01266
01267
01268
01269 double NDTMatcherD2D::lineSearchMT(
01270 Eigen::Matrix<double,6,1> &increment,
01271 std::vector<NDTCell*> &sourceNDT,
01272 NDTMap &targetNDT
01273 )
01274 {
01275
01276
01277 double stp = 1.0;
01278 double recoverystep = 0.1;
01279 double dginit = 0.0;
01280 double ftol = 0.11111;
01281 double gtol = 0.99999;
01282 double stpmax = 4.0;
01283 double stpmin = 0.001;
01284 int maxfev = 40;
01285 double xtol = 0.01;
01286
01287
01288 std::vector<NDTCell*> sourceNDTHere;
01289 double score_init = 0.0;
01290
01291 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> ps;
01292 ps.setIdentity();
01293
01294 Eigen::Matrix<double,6,1> scg_here;
01295 Eigen::MatrixXd pincr(6,1), score_gradient_here(6,1);
01296 Eigen::MatrixXd pseudoH(6,6);
01297 Eigen::Vector3d eulerAngles;
01299
01300 int info = 0;
01301 int infoc = 1;
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316 score_gradient_here.setZero();
01317 score_init = derivativesNDT(sourceNDT,targetNDT,score_gradient_here,pseudoH,false);
01318 scg_here = score_gradient_here;
01319 dginit = increment.dot(scg_here);
01320
01321
01322 if (dginit >= 0.0)
01323 {
01324 std::cout << "MoreThuente::cvsrch - wrong direction (dginit = " << dginit << ")" << std::endl;
01325
01326
01327
01328 increment = -increment;
01329 dginit = -dginit;
01330
01331 if (dginit >= 0.0)
01332 {
01333 for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01334 {
01335 if(sourceNDTHere[i]!=NULL)
01336 delete sourceNDTHere[i];
01337 }
01338 return recoverystep;
01339 }
01340 }
01341 else
01342 {
01343
01344 }
01345
01346
01347
01348 bool brackt = false;
01349 bool stage1 = true;
01350 int nfev = 0;
01351 double dgtest = ftol * dginit;
01352 double width = stpmax - stpmin;
01353 double width1 = 2 * width;
01354
01355
01356
01357 double finit = 0.0;
01358 finit = score_init;
01359
01360
01361
01362
01363
01364
01365
01366
01367 double stx = 0.0;
01368 double fx = finit;
01369 double dgx = dginit;
01370 double sty = 0.0;
01371 double fy = finit;
01372 double dgy = dginit;
01373
01374
01375
01376
01377
01378
01379
01380
01381 double stmin, stmax;
01382 double fm, fxm, fym, dgm, dgxm, dgym;
01383
01384 while (1)
01385 {
01386
01387
01388 if (brackt)
01389 {
01390 stmin = MoreThuente::min(stx, sty);
01391 stmax = MoreThuente::max(stx, sty);
01392 }
01393 else
01394 {
01395 stmin = stx;
01396 stmax = stp + 4 * (stp - stx);
01397 }
01398
01399
01400 stp = MoreThuente::max(stp, stpmin);
01401 stp = MoreThuente::min(stp, stpmax);
01402
01403
01404
01405
01406 if ((brackt && ((stp <= stmin) || (stp >= stmax))) ||
01407 (nfev >= maxfev - 1) || (infoc == 0) ||
01408 (brackt && (stmax - stmin <= xtol * stmax)))
01409 {
01410 stp = stx;
01411 }
01412
01413
01414
01416
01417 pincr = stp*increment;
01418
01419 ps = Eigen::Translation<double,3>(pincr(0),pincr(1),pincr(2))*
01420 Eigen::AngleAxisd(pincr(3),Eigen::Vector3d::UnitX())*
01421 Eigen::AngleAxisd(pincr(4),Eigen::Vector3d::UnitY())*
01422 Eigen::AngleAxisd(pincr(5),Eigen::Vector3d::UnitZ());
01423
01424 for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01425 {
01426 if(sourceNDTHere[i]!=NULL)
01427 delete sourceNDTHere[i];
01428 }
01429 sourceNDTHere.clear();
01430 for(unsigned int i=0; i<sourceNDT.size(); i++)
01431 {
01432 NDTCell *cell = sourceNDT[i];
01433 if(cell!=NULL)
01434 {
01435 Eigen::Vector3d mean = cell->getMean();
01436 Eigen::Matrix3d cov = cell->getCov();
01437 mean = ps*mean;
01438 cov = ps.rotation()*cov*ps.rotation().transpose();
01439 NDTCell* nd = (NDTCell*)cell->copy();
01440 nd->setMean(mean);
01441 nd->setCov(cov);
01442 sourceNDTHere.push_back(nd);
01443 }
01444 }
01445
01446 double f = 0.0;
01447 score_gradient_here.setZero();
01448
01449
01450
01451
01452
01453
01454
01455
01456 f = derivativesNDT(sourceNDTHere,targetNDT,score_gradient_here,pseudoH,false);
01457
01458
01459
01460
01461
01462
01463 double dg = 0.0;
01464 scg_here = score_gradient_here;
01465 dg = increment.dot(scg_here);
01466
01467
01468
01469
01470 nfev ++;
01471
01473
01474
01475
01476 double ftest1 = finit + stp * dgtest;
01477
01478
01479
01480
01481 if ((brackt && ((stp <= stmin) || (stp >= stmax))) || (infoc == 0))
01482 info = 6;
01483
01484 if ((stp == stpmax) && (f <= ftest1) && (dg <= dgtest))
01485 info = 5;
01486
01487 if ((stp == stpmin) && ((f > ftest1) || (dg >= dgtest)))
01488 info = 4;
01489
01490 if (nfev >= maxfev)
01491 info = 3;
01492
01493 if (brackt && (stmax-stmin <= xtol*stmax))
01494 info = 2;
01495
01496
01497 bool sufficientDecreaseTest = false;
01498 sufficientDecreaseTest = (f <= ftest1);
01499
01500
01501
01502
01503 if ((sufficientDecreaseTest) && (fabs(dg) <= gtol*(-dginit)))
01504 info = 1;
01505
01506 if (info != 0)
01507 {
01508 if (info != 1)
01509 {
01510
01511
01512
01513
01514 stp = recoverystep;
01515
01516
01517
01518
01519
01520 }
01521 else
01522 {
01523
01524 }
01525
01526
01527
01528
01529
01530 for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01531 {
01532 if(sourceNDTHere[i]!=NULL)
01533 delete sourceNDTHere[i];
01534 }
01535
01536 return stp;
01537
01538 }
01539
01540
01541
01542
01543
01544
01545
01546 if (stage1 && (f <= ftest1) && (dg >= MoreThuente::min(ftol, gtol) * dginit))
01547 {
01548 stage1 = false;
01549 }
01550
01551
01552
01553
01554
01555
01556
01557 if (stage1 && (f <= fx) && (f > ftest1))
01558 {
01559
01560
01561
01562 fm = f - stp * dgtest;
01563 fxm = fx - stx * dgtest;
01564 fym = fy - sty * dgtest;
01565 dgm = dg - dgtest;
01566 dgxm = dgx - dgtest;
01567 dgym = dgy - dgtest;
01568
01569
01570
01571
01572
01573 infoc = MoreThuente::cstep(stx,fxm,dgxm,sty,fym,dgym,stp,fm,dgm,
01574 brackt,stmin,stmax);
01575
01576
01577
01578 fx = fxm + stx*dgtest;
01579 fy = fym + sty*dgtest;
01580 dgx = dgxm + dgtest;
01581 dgy = dgym + dgtest;
01582
01583 }
01584
01585 else
01586 {
01587
01588
01589
01590
01591
01592 infoc = MoreThuente::cstep(stx,fx,dgx,sty,fy,dgy,stp,f,dg,
01593 brackt,stmin,stmax);
01594
01595 }
01596
01597
01598
01599
01600 if (brackt)
01601 {
01602 if (fabs(sty - stx) >= 0.66 * width1)
01603 stp = stx + 0.5 * (sty - stx);
01604 width1 = width;
01605 width = fabs(sty-stx);
01606 }
01607
01608 }
01609
01610 }
01611
01612 int NDTMatcherD2D::MoreThuente::cstep(double& stx, double& fx, double& dx,
01613 double& sty, double& fy, double& dy,
01614 double& stp, double& fp, double& dp,
01615 bool& brackt, double stmin, double stmax)
01616 {
01617 int info = 0;
01618
01619
01620
01621 if ((brackt && ((stp <= MoreThuente::min(stx, sty)) || (stp >= MoreThuente::max(stx, sty)))) ||
01622 (dx * (stp - stx) >= 0.0) || (stmax < stmin))
01623 return info;
01624
01625
01626
01627 double sgnd = dp * (dx / fabs(dx));
01628
01629
01630
01631
01632
01633
01634 bool bound;
01635 double theta;
01636 double s;
01637 double gamma;
01638 double p,q,r;
01639 double stpc, stpq, stpf;
01640
01641 if (fp > fx)
01642 {
01643 info = 1;
01644 bound = 1;
01645 theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01646
01647
01648
01649 s = MoreThuente::absmax(theta, dx, dp);
01650 gamma = s * sqrt(((theta / s) * (theta / s)) - (dx / s) * (dp / s));
01651 if (stp < stx)
01652 gamma = -gamma;
01653
01654 p = (gamma - dx) + theta;
01655 q = ((gamma - dx) + gamma) + dp;
01656 r = p / q;
01657 stpc = stx + r * (stp - stx);
01658 stpq = stx + ((dx / ((fx - fp) / (stp - stx) + dx)) / 2) * (stp - stx);
01659 if (fabs(stpc - stx) < fabs(stpq - stx))
01660 stpf = stpc;
01661 else
01662 stpf = stpc + (stpq - stpc) / 2;
01663
01664 brackt = true;
01665 }
01666
01667
01668
01669
01670
01671
01672 else if (sgnd < 0.0)
01673 {
01674 info = 2;
01675 bound = false;
01676 theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01677 s = MoreThuente::absmax(theta,dx,dp);
01678 gamma = s * sqrt(((theta/s) * (theta/s)) - (dx / s) * (dp / s));
01679 if (stp > stx)
01680 gamma = -gamma;
01681 p = (gamma - dp) + theta;
01682 q = ((gamma - dp) + gamma) + dx;
01683 r = p / q;
01684 stpc = stp + r * (stx - stp);
01685 stpq = stp + (dp / (dp - dx)) * (stx - stp);
01686 if (fabs(stpc - stp) > fabs(stpq - stp))
01687 stpf = stpc;
01688 else
01689 stpf = stpq;
01690 brackt = true;
01691 }
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702 else if (fabs(dp) < fabs(dx))
01703 {
01704 info = 3;
01705 bound = true;
01706 theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01707 s = MoreThuente::absmax(theta, dx, dp);
01708
01709
01710
01711
01712 gamma = s * sqrt(max(0,(theta / s) * (theta / s) - (dx / s) * (dp / s)));
01713 if (stp > stx)
01714 gamma = -gamma;
01715
01716 p = (gamma - dp) + theta;
01717 q = (gamma + (dx - dp)) + gamma;
01718 r = p / q;
01719 if ((r < 0.0) && (gamma != 0.0))
01720 stpc = stp + r * (stx - stp);
01721 else if (stp > stx)
01722 stpc = stmax;
01723 else
01724 stpc = stmin;
01725
01726 stpq = stp + (dp/ (dp - dx)) * (stx - stp);
01727 if (brackt)
01728 {
01729 if (fabs(stp - stpc) < fabs(stp - stpq))
01730 stpf = stpc;
01731 else
01732 stpf = stpq;
01733 }
01734 else
01735 {
01736 if (fabs(stp - stpc) > fabs(stp - stpq))
01737 stpf = stpc;
01738 else
01739 stpf = stpq;
01740 }
01741 }
01742
01743
01744
01745
01746
01747
01748 else
01749 {
01750 info = 4;
01751 bound = false;
01752 if (brackt)
01753 {
01754 theta = 3 * (fp - fy) / (sty - stp) + dy + dp;
01755 s = MoreThuente::absmax(theta, dy, dp);
01756 gamma = s * sqrt(((theta/s)*(theta/s)) - (dy / s) * (dp / s));
01757 if (stp > sty)
01758 gamma = -gamma;
01759 p = (gamma - dp) + theta;
01760 q = ((gamma - dp) + gamma) + dy;
01761 r = p / q;
01762 stpc = stp + r * (sty - stp);
01763 stpf = stpc;
01764 }
01765 else if (stp > stx)
01766 stpf = stmax;
01767 else
01768 stpf = stmin;
01769 }
01770
01771
01772
01773
01774 if (fp > fx)
01775 {
01776 sty = stp;
01777 fy = fp;
01778 dy = dp;
01779 }
01780 else
01781 {
01782 if (sgnd < 0.0)
01783 {
01784 sty = stx;
01785 fy = fx;
01786 dy = dx;
01787 }
01788 stx = stp;
01789 fx = fp;
01790 dx = dp;
01791 }
01792
01793
01794
01795 stpf = MoreThuente::min(stmax, stpf);
01796 stpf = MoreThuente::max(stmin, stpf);
01797 stp = stpf;
01798 if (brackt && bound)
01799 {
01800 if (sty > stx)
01801 stp = min(stx + 0.66 * (sty - stx), stp);
01802 else
01803 stp = max(stx + 0.66 * (sty - stx), stp);
01804 }
01805
01806 return info;
01807
01808 }
01809
01810 double NDTMatcherD2D::MoreThuente::min(double a, double b)
01811 {
01812 return (a < b ? a : b);
01813 }
01814
01815 double NDTMatcherD2D::MoreThuente::max(double a, double b)
01816 {
01817 return (a > b ? a : b);
01818 }
01819
01820 double NDTMatcherD2D::MoreThuente::absmax(double a, double b, double c)
01821 {
01822 a = fabs(a);
01823 b = fabs(b);
01824 c = fabs(c);
01825
01826 if (a > b)
01827 return (a > c) ? a : c;
01828 else
01829 return (b > c) ? b : c;
01830 }
01831
01832 double NDTMatcherD2D::normalizeAngle(double a)
01833 {
01834
01835 return atan2(sin(a), cos(a));
01836
01837 }
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994 bool NDTMatcherD2D::covariance( NDTMap& targetNDT,
01995 NDTMap& sourceNDT,
01996 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T,
01997 Eigen::MatrixXd &cov
01998 )
01999 {
02000
02001 double sigmaS = (0.03)*(0.03);
02002 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR;
02003 TR.setIdentity();
02004
02005 std::vector<NDTCell*> sourceNDTN = sourceNDT.pseudoTransformNDT(T);
02006 std::vector<NDTCell*> targetNDTN = targetNDT.pseudoTransformNDT(T);
02007
02008 Eigen::MatrixXd scg(6,1);
02009 int NM = sourceNDTN.size() + targetNDTN.size();
02010
02011 Eigen::MatrixXd Jdpdz(NM,6);
02012
02013 NDTCell *cell;
02014 Eigen::Vector3d transformed;
02015 Eigen::Vector3d meanMoving, meanFixed;
02016 Eigen::Matrix3d CMoving, CFixed, Cinv;
02017 bool exists = false;
02018 double det = 0;
02019 Eigen::Matrix<double,6,1> ones;
02020 ones<<1,1,1,1,1,1;
02021
02022 derivativesNDT(sourceNDTN,targetNDT,scg,cov,true);
02023
02024 Eigen::Matrix3d Q;
02025 Jdpdz.setZero();
02026 Q.setZero();
02027
02028 pcl::PointXYZ point;
02029
02030 for(int i=0; i<sourceNDTN.size(); i++)
02031 {
02032 meanMoving = sourceNDTN[i]->getMean();
02033 point.x = meanMoving(0);
02034 point.y = meanMoving(1);
02035 point.z = meanMoving(2);
02036
02037 if(!targetNDT.getCellForPoint(point,cell))
02038 {
02039 continue;
02040 }
02041 if(cell == NULL)
02042 {
02043 continue;
02044 }
02045 if(cell->hasGaussian_)
02046 {
02047
02048 meanFixed = cell->getMean();
02049 transformed = meanMoving-meanFixed;
02050 CFixed = cell->getCov();
02051 CMoving= sourceNDTN[i]->getCov();
02052
02053 (CFixed+CMoving).computeInverseAndDetWithCheck(Cinv,det,exists);
02054 if(!exists) continue;
02055
02056
02057 double factor = (-transformed.dot(Cinv*transformed)/2);
02058
02059 if(factor < -120)
02060 {
02061 continue;
02062 }
02063 factor = exp(lfd2*factor)/2;
02064 if(factor > 1 || factor < 0 || factor*0 !=0)
02065 {
02066 continue;
02067 }
02068
02069 Q = -sigmaS*Cinv*Cinv;
02070
02071 Eigen::Matrix<double,6,1> G, xtQJ;
02072
02073 G.setZero();
02074 for(int q=3; q<6; q++)
02075 {
02076 G(q) = -transformed.transpose()*Q*Zest.block<3,3>(0,3*q)*Cinv*transformed;
02077 G(q) = G(q) -transformed.transpose()*Cinv*Zest.block<3,3>(0,3*q)*Q*transformed;
02078 }
02079
02080 xtQJ = transformed.transpose()*Q*Jest;
02081
02082 double f1 = (transformed.transpose()*Q*transformed);
02083 G = G + xtQJ + (-lfd2/2)*f1*ones;
02084 G = G*factor*lfd1*lfd2/2;
02085
02086 Jdpdz.row(i) = G.transpose();
02087
02088 for(int j=0; j<targetNDTN.size(); j++)
02089 {
02090 if(targetNDTN[j]->getMean() == meanFixed)
02091 {
02092
02093 Jdpdz.row(j+sourceNDTN.size()) = Jdpdz.row(j+sourceNDTN.size())+G.transpose();
02094 continue;
02095 }
02096 }
02097
02098 cell = NULL;
02099 }
02100 }
02101
02102
02103
02104
02105 Eigen::MatrixXd JK(6,6);
02106 JK = sigmaS*Jdpdz.transpose()*Jdpdz;
02107
02108
02109
02110
02111 cov = cov.inverse()*JK*cov.inverse();
02112
02113
02114
02115 for(unsigned int q=0; q<sourceNDTN.size(); q++)
02116 {
02117 delete sourceNDTN[q];
02118 }
02119 sourceNDTN.clear();
02120
02121 return true;
02122 }
02123 bool NDTMatcherD2D::covariance( pcl::PointCloud<pcl::PointXYZ>& target,
02124 pcl::PointCloud<pcl::PointXYZ>& source,
02125 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T,
02126 Eigen::MatrixXd &cov
02127 )
02128 {
02129
02130 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR;
02131 TR.setIdentity();
02132
02133 pcl::PointCloud<pcl::PointXYZ> sourceCloud = lslgeneric::transformPointCloud(T,source);
02134
02135 LazyGrid prototypeSource(resolutions.front());
02136 LazyGrid prototypeTarget(resolutions.front());
02137
02138 NDTMap targetNDT( &prototypeTarget );
02139 targetNDT.loadPointCloud( target );
02140 targetNDT.computeNDTCells();
02141
02142 NDTMap sourceNDT( &prototypeSource );
02143 sourceNDT.loadPointCloud( sourceCloud );
02144 sourceNDT.computeNDTCells();
02145
02146 this->covariance(targetNDT,sourceNDT,TR,cov);
02147
02148 return true;
02149 }
02150
02151
02152 }