ndt_histogram.cpp
Go to the documentation of this file.
00001 #include <ndt_map/pointcloud_utils.h>
00002 #include <pcl/registration/transformation_estimation_svd.h>
00003 #include <ndt_map/ndt_histogram.h>
00004 
00005 namespace lslgeneric{
00006 
00007   NDTHistogram::NDTHistogram(){
00008     N_LINE_BINS = 1;
00009     N_FLAT_BINS = 40;
00010     N_SPHERE_BINS = 10;
00011 
00012     histogramBinsLine = std::vector<int>(N_LINE_BINS,0);
00013     histogramBinsFlat = std::vector<int>(N_FLAT_BINS,0);
00014     histogramBinsSphere = std::vector<int>(N_SPHERE_BINS,0);
00015 
00016     for(int i=0; i<3; i++)
00017       {
00018         dist_histogramBinsLine[i] = std::vector<int>(N_LINE_BINS,0);
00019         dist_histogramBinsFlat[i] = std::vector<int>(N_FLAT_BINS,0);
00020         dist_histogramBinsSphere[i] = std::vector<int>(N_SPHERE_BINS,0);
00021       }
00022 
00023     D1 = 5;
00024     D2 = 10;
00025 
00026     averageDirections = std::vector<Eigen::Vector3d,Eigen::aligned_allocator<Eigen::Vector3d> >(N_FLAT_BINS,Eigen::Vector3d(0,0,0));
00027     computeDirections();
00028 
00029     topThree.reserve(3);
00030     for(int r=0; r<3; r++)
00031       {
00032         topThree[r].setIdentity();
00033         topThreeS[r] = INT_MAX;
00034       }
00035     inited = true;
00036   }
00037 
00038   NDTHistogram::NDTHistogram (const NDTHistogram& other){
00039 
00040     histogramBinsLine =   other.histogramBinsLine;
00041     histogramBinsFlat =   other.histogramBinsFlat;
00042     histogramBinsSphere = other.histogramBinsSphere;
00043 
00044     for(int i=0; i<3; i++)
00045       {
00046         dist_histogramBinsLine[i] =   other.dist_histogramBinsLine[i];
00047         dist_histogramBinsFlat[i] =   other.dist_histogramBinsFlat[i];
00048         dist_histogramBinsSphere[i] = other.dist_histogramBinsSphere[i];
00049       }
00050 
00051     D1 = 5;
00052     D2 = 10;
00053 
00054     averageDirections = other.averageDirections;
00055     directions = other.directions;
00056 
00057     topThree.reserve(3);
00058     for(int r=0; r<3; r++){
00059       topThree[r].setIdentity();
00060       topThreeS[r] = INT_MAX;
00061     }
00062     inited = true;
00063   }
00064 
00065   NDTHistogram::NDTHistogram (NDTMap &map){
00066 
00067     N_LINE_BINS = 1;
00068     N_FLAT_BINS = 40;
00069     N_SPHERE_BINS = 10;
00070 
00071     histogramBinsLine = std::vector<int>(N_LINE_BINS,0);
00072     histogramBinsFlat = std::vector<int>(N_FLAT_BINS,0);
00073     histogramBinsSphere = std::vector<int>(N_SPHERE_BINS,0);
00074 
00075     for(int i=0; i<3; i++){
00076       dist_histogramBinsLine[i] = std::vector<int>(N_LINE_BINS,0);
00077       dist_histogramBinsFlat[i] = std::vector<int>(N_FLAT_BINS,0);
00078       dist_histogramBinsSphere[i] = std::vector<int>(N_SPHERE_BINS,0);
00079     }
00080 
00081     D1 = 5;
00082     D2 = 10;
00083 
00084     averageDirections = std::vector<Eigen::Vector3d,Eigen::aligned_allocator<Eigen::Vector3d> >(N_FLAT_BINS,Eigen::Vector3d(0,0,0));
00085     //populate directions
00086     computeDirections();
00087     constructHistogram(map);
00088 
00089     topThree.reserve(3);
00090     for(int r=0; r<3; r++){
00091       topThree[r].setIdentity();
00092       topThreeS[r] = INT_MAX;
00093     }
00094 
00095     inited = true;
00096   }
00097 
00098 
00099   void NDTHistogram::computeDirections(){
00100 
00101     double dlong = M_PI*(3-sqrt(5));  /* ~2.39996323 */
00102     double dz    = 2.0/N_FLAT_BINS;
00103     double longitude = 0;
00104     double z    = 1 - dz/2;
00105 
00106     for (int k = 0; k<N_FLAT_BINS; k++){
00107       double r    = sqrt(1-z*z);
00108       Eigen::Vector3d v;
00109       v<<cos(longitude)*r, sin(longitude)*r, z;
00110       directions.push_back(v);
00111       z    = z - dz;
00112       longitude = longitude + dlong;
00113     }
00114   }
00115 
00116 
00117   void NDTHistogram::constructHistogram(NDTMap &map){
00118 
00119     SpatialIndex *si = map.getMyIndex();
00120     if(si==NULL) return;
00121 
00122     double LINEAR_FACTOR = 50;
00123     double FLAT_FACTOR = 50;
00124 
00125     typename std::vector<NDTCell*>::iterator it = si->begin();
00126     while(it!=si->end())
00127       {
00128 
00129         //NDTCell *ndcell = dynamic_cast<NDTCell* >(*it);
00130         if(*it == NULL){
00131             it++;
00132             continue;
00133           }
00134         if(!(*it)->hasGaussian_){
00135             it++;
00136             continue;
00137           }
00138         Eigen::Matrix3d evecs = (*it)->getEvecs();
00139         Eigen::Vector3d evals = (*it)->getEvals();
00140 
00141         int idMin,idMax,idMid;
00142         double minEval = evals.minCoeff(&idMin);
00143         double maxEval = evals.maxCoeff(&idMax);
00144         double midEval = -1;
00145         idMid = -1;
00146         for(int j=0; j<3; j++){
00147           if(j!=idMin && j!=idMax){
00148             midEval = evals(j);
00149             idMid = j;
00150           }
00151         }
00152         double dist = (*it)->getMean().norm();
00153         //three cases:
00154         //maxEval >> midEval -> linear
00155         if(maxEval > midEval*LINEAR_FACTOR){
00156           incrementLineBin(dist);
00157           it++;
00158           continue;
00159         }
00160         //maxEval ~ midEval >> minEval -> planar
00161         if(midEval > minEval*FLAT_FACTOR){
00162             Eigen::Vector3d normal = evecs.col(idMin);
00163             Eigen::Vector3d mean = (*it)->getMean();
00164             if(normal.dot(mean) < 0){
00165               //                std::cout<<"switching normal direction\n";
00166               normal = -normal;
00167             }
00168             incrementFlatBin(normal,dist);
00169             it++;
00170             continue;
00171           }
00172 
00173         //maxEval ~ midEval ~ minEval -> spherical
00174         incrementSphereBin(dist);
00175 
00176         it++;
00177       }
00178 
00179     for(int i=0; i<averageDirections.size(); i++)
00180       {
00181         averageDirections[i].normalize();
00182       }
00183 
00184   }
00185 
00186   void NDTHistogram::incrementLineBin(double d){
00187     histogramBinsLine[0] ++;
00188     if(d<D1) dist_histogramBinsLine[0][0] ++;
00189     else if(d>D2) dist_histogramBinsLine[2][0] ++;
00190     else dist_histogramBinsLine[1][0] ++;
00191   }
00192 
00193   void NDTHistogram::incrementFlatBin(Eigen::Vector3d &normal, double d){
00194     //std::cout<<"n "<<normal.transpose()<<std::endl;
00195     normal.normalize();
00196     //bins are in 3D. go through directions, find smallest difference
00197     double mindist = INT_MAX;
00198     int idmin = -1;
00199     for(unsigned int i=0; i<directions.size(); i++)
00200       {
00201         double dist = (directions[i]-normal).norm();
00202         if(mindist > dist)
00203           {
00204             mindist = dist;
00205             idmin = i;
00206           }
00207       }
00208     //std::cout<<idmin<<std::endl;
00209     if(idmin >=0 && idmin < histogramBinsFlat.size())
00210       {
00211         histogramBinsFlat[idmin] ++;
00212         averageDirections[idmin] += normal;
00213         if(d<D1) dist_histogramBinsFlat[0][idmin] ++;
00214         else if(d>D2) dist_histogramBinsFlat[2][idmin] ++;
00215         else dist_histogramBinsFlat[1][idmin] ++;
00216       }
00217   }
00218 
00219   void NDTHistogram::incrementSphereBin(double d){
00220     histogramBinsSphere[0] ++;
00221     if(d<D1){
00222       int id = floor(((double)d*N_SPHERE_BINS)/(double)D1);
00223       dist_histogramBinsSphere[0][id] ++;
00224     }
00225     else if(d>D2){
00226       dist_histogramBinsSphere[2][0] ++;
00227     }
00228     else{
00229       int id = floor(((double)(d-D1)*N_SPHERE_BINS)/(double)D2);
00230       dist_histogramBinsSphere[1][id] ++;
00231     }
00232   }
00233 
00234 
00235   pcl::PointCloud<pcl::PointXYZ> NDTHistogram::getDominantDirections(int nDirections){
00236     
00237     pcl::PointCloud<pcl::PointXYZ> ret;
00238     std::vector<bool> dominated (directions.size(),false);
00239     double NORM_MIN = 0.2;
00240     int MIN_SUPPORT = 3;
00241     
00242     for(int i=0; i<nDirections; i++){
00243       //get the next direction
00244       pcl::PointXYZ current;
00245       //find max in histogram, that is not dominated
00246       bool found = false;
00247       int maxBin, idMax;
00248       while (!found){
00249         maxBin = -1;
00250         idMax = -1;
00251         for(int j=0; j<histogramBinsFlat.size(); j++){
00252           if(histogramBinsFlat[j] > maxBin && !dominated[j]){
00253             maxBin = histogramBinsFlat[j];
00254             idMax = j;
00255           }
00256         }
00257 
00258         found = !dominated[idMax];
00259         //check if any of the already found directions are "duals"
00260         /* for(int j=0; j<ret.points.size() && found; j++) {
00261            Eigen::Vector3d v(ret.points[j].x,ret.points[j].y,ret.points[j].z);
00262            v = v + directions[idMax];
00263            found = found && (v.norm() > NORM_MIN);
00264            }*/
00265         //suppress this max and neighbours --- independent of the value of found, this is necessarry
00266         dominated[idMax] = true;
00267         if(idMax-1 >=0) dominated[idMax-1] = true;
00268         if(idMax+1 <dominated.size()) dominated[idMax+1] = true;
00269         if(maxBin < MIN_SUPPORT) break;
00270       }
00271 
00272       if(maxBin < MIN_SUPPORT) break;
00273       //current.x = directions[idMax](0);
00274       //current.y = directions[idMax](1);
00275       //current.z = directions[idMax](2);
00276       current.x = averageDirections[idMax](0);
00277       current.y = averageDirections[idMax](1);
00278       current.z = averageDirections[idMax](2);
00279       //current.intensity = maxBin;
00280       //std::cout<<directions[idMax].transpose()<<" e "<<maxBin<<std::endl;
00281       //std::cout<<averageDirections[idMax].transpose()<<" e "<<maxBin<<std::endl;
00282       ret.points.push_back(current);
00283     }
00284     return ret;
00285   }
00286 
00287   void NDTHistogram::bestFitToHistogram(NDTHistogram &target, Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> &T, bool bound_transform)
00288   {
00289 
00290     //find the top N dominant directions
00291     int N = 3;
00292     //store vectors as pcl::points
00293     pcl::PointCloud<pcl::PointXYZ> dominantBinsMine, dominantBinsTarget;
00294 
00295     //    std::cout<<"d1 : \n";
00296     dominantBinsMine = this->getDominantDirections(N);
00297     //    std::cout<<"d2 : \n";
00298     dominantBinsTarget = target.getDominantDirections(N);
00299 
00300     /*    double N_THIS=0, N_OTHER=0;
00301           for(int i=0; i<histogramBinsFlat.size(); i++) {
00302           N_THIS += histogramBinsFlat[i];
00303           N_OTHER += target.histogramBinsFlat[i];
00304           }
00305     */    //estimate least-squares fit, assuming correspondence
00306     /*    pcl::registration::TransformationEstimationSVD<PointT,PointT> trEst;
00307           Eigen::Matrix4f TR;
00308           trEst.estimateRigidTransformation(dominantBinsMine, dominantBinsTarget, TR);
00309           T = TR.cast<double>();
00310     */
00311     //check for best fitting combination
00312 
00313     for(int r=0; r<3; r++)
00314       {
00315         topThree[r].setIdentity();
00316         topThreeS[r] = INT_MAX;
00317       }
00318     pcl::PointCloud<pcl::PointXYZ> mineNew, mineNew2;
00319     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> localT, localT2;
00320 
00321     //    double best = INT_MAX;
00322     //choose 3 out of N
00323     for(int a1 = 0; a1<dominantBinsMine.points.size(); a1++){
00324       //int a1 = 0; {
00325       for(int b1 = a1+1; b1<dominantBinsMine.points.size(); b1++){
00326         //if(a1 == b1) continue;
00327         //for(int c1 = 0; c1<dominantBinsMine.points.size(); c1++) {
00328         //if(b1 == c1 || a1 == c1) continue;
00329         //int a2 = 0; {
00330         for(int a2 = 0; a2<dominantBinsTarget.points.size(); a2++)
00331           {
00332             for(int b2 = 0; b2<dominantBinsTarget.points.size(); b2++)
00333               {
00334                 if(a2 == b2) continue;
00335                 //for(int c2 = 0; c2<dominantBinsTarget.points.size(); c2++) {
00336                 //    if(b2 == c2 || a2 == c2) continue;
00337                 pcl::PointCloud<pcl::PointXYZ> useMine, useTarget;
00338                 useMine.points.push_back(dominantBinsMine[a1]);
00339                 useMine.points.push_back(dominantBinsMine[b1]);
00340                 //useMine.points.push_back(dominantBinsMine[c1]);
00341                 useTarget.points.push_back(dominantBinsTarget[a2]);
00342                 useTarget.points.push_back(dominantBinsTarget[b2]);
00343                 //useTarget.points.push_back(dominantBinsTarget[c2]);
00344 
00345                 closedFormSolution(useMine, useTarget, localT2);
00346                 double good2 = this->getSimilarity(target,localT2);
00347                 //          std::cout<<good2<<std::endl;
00348                 //compute score of fitness "good2"
00349                 /*                          double good2 = 0, scale2 = 0;
00350                                 for(int q = 0; q<averageDirections.size(); q++) {
00351 
00352                                 Eigen::Vector3d tr = localT2*averageDirections[q];
00353                                 if( this->histogramBinsFlat[q] == 0) {
00354                                 tr = directions[q]; //fall back to bin direction
00355                                 }
00356                                 //find B = the bin in which tr falls
00357                                 tr.normalize();
00358                                 //std::cout<<"TR"<<tr.transpose()<<std::endl;
00359                                 double mindist = INT_MAX;
00360                                 int idmin = -1;
00361                                 for(unsigned int i=0; i<directions.size(); i++) {
00362                                 double dist = (directions[i]-tr).norm();
00363                                 if(mindist > dist) {
00364                                 mindist = dist;
00365                                 idmin = i;
00366                                 }
00367                                 }
00368                                 //std::cout<<idmin<<std::endl;
00369                                 if(!(idmin >=0 && idmin < histogramBinsFlat.size())) {
00370                                 continue;
00371                                 }
00372 
00373 
00374                                 //find the averageDirection other->average[B]
00375                                 Eigen::Vector3d other_tr = target.averageDirections[idmin];
00376                                 if (target.histogramBinsFlat[idmin] == 0) {
00377                                 other_tr = target.directions[idmin]; //fall back to bin direction
00378                                 }
00379 
00380                                 //compute norm of difference, scale by cardinality
00381                                 //double factor = fabsf((double)(this->histogramBinsFlat[q] - target.histogramBinsFlat[idmin]+1)/
00382                                 //                      (double)(this->histogramBinsFlat[q]+target.histogramBinsFlat[idmin]+1));
00383                                 //double factor = this->histogramBinsFlat[q]+target.histogramBinsFlat[idmin];
00384                                 //scale2 += factor;
00385                                 //good2 += factor*(tr-other_tr).norm();
00386                                 good2 += pow((double)this->histogramBinsFlat[q]/N_THIS - (double)target.histogramBinsFlat[idmin]/N_OTHER,2);
00387 
00388                                 }
00389                                 good2 = sqrt(good2);
00390                 */
00391 
00392                 /*
00393                 //don't use them for finding but just for verifying
00394                 useMine.points.push_back(dominantBinsMine[c1]);
00395                 useTarget.points.push_back(dominantBinsTarget[c2]);
00396                 //calculate goodness of fit
00397                 //                          mineNew = transformPointCloud(localT,useMine);
00398 
00399                 //now also considering last orientation....
00400                 //                          closedFormSolution(useMine, useTarget, localT2);
00401                 mineNew2 = transformPointCloud(localT2,useMine);
00402 
00403                 //                          double good = 0, scale = 0;
00404                 //                          for(int i=0; i<mineNew.points.size(); i++) {
00405                 //                              double factor = (mineNew.points[i].intensity+useTarget.points[i].intensity);
00406                 //                              good += factor*sqrt( pow(mineNew.points[i].x-useTarget.points[i].x,2) +
00407                 //                                      pow(mineNew.points[i].y-useTarget.points[i].y,2) +
00408                 //                                      pow(mineNew.points[i].z-useTarget.points[i].z,2));
00409                 //                              scale += factor;
00410                 //                          }
00411                 //                          good = good/scale;
00412 
00413 
00414                 double good2 = 0, scale2 = 0;
00415                 for(int i=0; i<mineNew2.points.size(); i++) {
00416                 double factor = (mineNew2.points[i].intensity+useTarget.points[i].intensity);
00417                 good2 += factor*sqrt( pow(mineNew2.points[i].x-useTarget.points[i].x,2) +
00418                 pow(mineNew2.points[i].y-useTarget.points[i].y,2) +
00419                 pow(mineNew2.points[i].z-useTarget.points[i].z,2));
00420                 scale2 += factor;
00421                 }
00422                 good2 = good2/scale2;
00423                 */
00424 
00425                 //                          std::cout<<"combo "<<a1<<" "<<b1<<" "<<" -- "
00426                 //                              <<a2<<" "<<b2<<" "<<" fit = "<<good2<<std::endl;
00427                 /*if(good < best) {
00428                   std::cout<<"local minimum at combo "<<a1<<" "<<b1<<" "<<c1<<" -- "
00429                   <<a2<<" "<<b2<<" "<<c2<<" fit = "<<good<<std::endl;
00430                   best = good;
00431                   T = localT;
00432                   }*/
00433                 Eigen::Quaternion<double> id, errorQ;
00434                 id.setIdentity();
00435                 errorQ = localT2.rotation();
00436                 double angle = fabsf(acos(id.dot(errorQ))/2);
00437                 if(angle > M_PI/8 && bound_transform)
00438                   {
00439                     //transform is too big!
00440                     continue;
00441                   }
00442                 if(good2 < topThreeS[2])
00443                   {
00444                     //                          std::cout<<"local minimum at combo "<<a1<<" "<<b1<<" "<<" -- "
00445                     //                              <<a2<<" "<<b2<<" "<<" fit = "<<good2<<std::endl;
00446                     if(good2 < topThreeS[1])
00447                       {
00448                         if(good2 < topThreeS[0])
00449                           {
00450                             topThree[2] = topThree[1];
00451                             topThree[1] = topThree[0];
00452                             topThree[0] = localT2;
00453                             topThreeS[2] = topThreeS[1];
00454                             topThreeS[1] = topThreeS[0];
00455                             topThreeS[0] = good2;
00456                           }
00457                         else
00458                           {
00459                             topThree[2] = topThree[1];
00460                             topThree[1] = localT2;
00461                             topThreeS[2] = topThreeS[1];
00462                             topThreeS[1] = good2;
00463                           }
00464                       }
00465                     else
00466                       {
00467                         topThree[2] = localT2;
00468                         topThreeS[2] = good2;
00469                       }
00470                   }
00471                 //                      }
00472               }
00473           }
00474         //    }
00475       }
00476     }
00477 
00478     T = topThree[0];
00479 
00480     if(dominantBinsMine.points.size() < 2 || dominantBinsTarget.points.size() < 2)
00481       {
00482         T.setIdentity();
00483       }
00484 
00485   }
00486 
00487   void NDTHistogram::closedFormSolution(pcl::PointCloud<pcl::PointXYZ> &src, pcl::PointCloud<pcl::PointXYZ> &tgt, Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> &T){
00488     T.setIdentity ();
00489     Eigen::Matrix3d H; // = (cloud_src_demean * cloud_tgt_demean.transpose ()).topLeftCorner<3, 3>();
00490     Eigen::MatrixXd P1, P2;         //temporary points for sets 1 and 2
00491     unsigned int itr=0;             //loop counters
00492     size_t size = src.points.size();
00493 
00494     // Assemble the correlation matrix H = source * target'
00495     P1 = Eigen::MatrixXd(size,3);
00496     P2 = Eigen::MatrixXd(size,3);
00497     //compute values needed for the N matrix and for scale
00498     for(itr=0; itr<size; itr++)
00499       {
00500         P1(itr,0) = src.points[itr].x;
00501         P1(itr,1) = src.points[itr].y;
00502         P1(itr,2) = src.points[itr].z;
00503         P2(itr,0) = tgt.points[itr].x;
00504         P2(itr,1) = tgt.points[itr].y;
00505         P2(itr,2) = tgt.points[itr].z;
00506       }
00507     H = P1.transpose()*P2;
00508 
00509     // Compute the Singular Value Decomposition
00510     Eigen::JacobiSVD<Eigen::Matrix3d> svd (H, Eigen::ComputeFullU | Eigen::ComputeFullV);
00511     Eigen::Matrix3d u = svd.matrixU ();
00512     Eigen::Matrix3d v = svd.matrixV ();
00513 
00514     // Compute R = V * U'
00515     if (u.determinant () * v.determinant () < 0)
00516       {
00517         for (int x = 0; x < 3; ++x)
00518           v (x, 2) *= -1;
00519       }
00520 
00521     Eigen::Matrix3d R = v * u.transpose ();
00522     // Return the correct transformation
00523     T = R;
00524 
00525   }
00526 
00527   void NDTHistogram::printHistogram(bool bMatlab){
00528     if(bMatlab){
00529       //prints in a format suitable for matlab plotting
00530       std::cout<<"L=[ ";
00531       for(unsigned int i=0; i<histogramBinsLine.size(); i++){
00532         std::cout<<histogramBinsLine[i]<<" ";
00533       }
00534       std::cout<<"];\n";
00535       std::cout<<"F=[";
00536       for(unsigned int i=0; i<histogramBinsFlat.size(); i++)
00537         {
00538           std::cout<<histogramBinsFlat[i]<<" ";
00539         }
00540       std::cout<<"];\n";
00541       for(unsigned int q=0; q<3; q++)
00542         {
00543           std::cout<<"F"<<q<<" = [";
00544           for(unsigned int i=0; i<dist_histogramBinsFlat[q].size(); i++)
00545             {
00546               std::cout<<dist_histogramBinsFlat[q][i]<<" ";
00547             }
00548           std::cout<<"];\n";
00549         }
00550 
00551       std::cout<<"];\nS=[";
00552       for(unsigned int i=0; i<histogramBinsSphere.size(); i++)
00553         {
00554           std::cout<<histogramBinsSphere[i]<<" ";
00555         }
00556       std::cout<<"];\n";
00557       for(unsigned int q=0; q<3; q++)
00558         {
00559           std::cout<<"S"<<q<<" = [";
00560           for(unsigned int i=0; i<dist_histogramBinsSphere[q].size(); i++)
00561             {
00562               std::cout<<dist_histogramBinsSphere[q][i]<<" ";
00563             }
00564           std::cout<<"];\n";
00565         }
00566       /*        std::cout<<"];\nD=[";
00567                 for(unsigned int i=0; i<directions.size(); i++) {
00568                 std::cout<<directions[i].transpose()<<"; ";
00569                 }
00570       */
00571 
00572     }
00573     else
00574       {
00575         std::cout<<"L: ";
00576         for(unsigned int i=0; i<histogramBinsLine.size(); i++)
00577           {
00578             std::cout<<histogramBinsLine[i]<<" ";
00579           }
00580 
00581         std::cout<<"\nF: ";
00582         for(unsigned int i=0; i<histogramBinsFlat.size(); i++)
00583           {
00584             std::cout<<histogramBinsFlat[i]<<" ";
00585           }
00586 
00587         std::cout<<"\nS: ";
00588         for(unsigned int i=0; i<histogramBinsSphere.size(); i++)
00589           {
00590             std::cout<<histogramBinsSphere[i]<<" ";
00591           }
00592         std::cout<<"\n";
00593       }
00594   }
00595 
00596 
00597   double NDTHistogram::getSimilarity(NDTHistogram &other)
00598   {
00599 
00600     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> T;
00601 
00602     this->bestFitToHistogram(other,T,false);
00603 
00604     return this->getSimilarity(other,T);
00605   }
00606 
00607 
00608   double NDTHistogram::getSimilarity(NDTHistogram &other, Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> &T){
00609     double score[3];
00610     double N_THIS[3], N_OTHER[3];
00611     for(unsigned int r = 0; r<3; r++){
00612       N_THIS[r] = 0;
00613       N_OTHER[r] = 0;
00614       score[r] = 0;
00615       for(int i=0; i<histogramBinsFlat.size(); i++)
00616         {
00617           N_THIS[r] += dist_histogramBinsFlat[r][i];
00618           N_OTHER[r] += other.dist_histogramBinsFlat[r][i];
00619         }
00620       for(int i=0; i<histogramBinsSphere.size(); i++)
00621         {
00622           N_THIS[r] += dist_histogramBinsSphere[r][i] ;
00623           N_OTHER[r] += other.dist_histogramBinsSphere[r][i] ;
00624         }
00625       N_THIS[r] += dist_histogramBinsLine[r][0];
00626       N_OTHER[r]+= other.dist_histogramBinsLine[r][0];
00627       N_THIS[r] = N_THIS[r]==0 ? INT_MAX : N_THIS[r];
00628       N_OTHER[r] = N_OTHER[r]==0 ? INT_MAX : N_OTHER[r];
00629     }
00630 
00631     for(int q = 0; q<averageDirections.size(); q++)
00632       {
00633 
00634         Eigen::Vector3d tr = T*averageDirections[q];
00635         if( this->histogramBinsFlat[q] == 0)
00636           {
00637             tr = directions[q]; //fall back to bin direction
00638           }
00639 
00640         //find B = the bin in which tr falls
00641         tr.normalize();
00642         double mindist = INT_MAX;
00643         int idmin = -1;
00644         for(unsigned int i=0; i<directions.size(); i++)
00645           {
00646             double dist = (directions[i]-tr).norm();
00647             if(mindist > dist)
00648               {
00649                 mindist = dist;
00650                 idmin = i;
00651               }
00652           }
00653         //std::cout<<idmin<<std::endl;
00654         if(!(idmin >=0 && idmin < histogramBinsFlat.size()))
00655           {
00656             continue;
00657           }
00658 
00659         for(unsigned int r = 0; r<3; r++)
00660           {
00661             score[r] += pow((double)this->dist_histogramBinsFlat[r][q]/N_THIS[r] - (double)other.dist_histogramBinsFlat[r][idmin]/N_OTHER[r],2);
00662           }
00663 
00664       }
00665     for(unsigned int r = 0; r<3; r++)
00666       {
00667         for(int i=0; i<histogramBinsSphere.size(); i++)
00668           {
00669             score[r] += pow( (double)this->dist_histogramBinsSphere[r][i]/N_THIS[r] - (double)other.dist_histogramBinsSphere[r][i]/N_OTHER[r] ,2);
00670           }
00671 
00672         score[r] += pow( (double)this->dist_histogramBinsLine[r][0]/N_THIS[r] - (double)other.dist_histogramBinsLine[r][0]/N_OTHER[r] ,2);
00673         double maxN, minN;
00674         maxN = (N_THIS[r] > N_OTHER[r]) ? N_THIS[r] : N_OTHER[r];
00675         minN = (N_THIS[r] < N_OTHER[r]) ? N_THIS[r] : N_OTHER[r];
00676         minN = (minN < 1) ? 1 : minN;
00677 
00678         score[r] = maxN*sqrt(score[r])/minN;
00679       }
00680 
00681 
00682     return score[0]+score[1];
00683   }
00684 
00685 }


ndt_map
Author(s): Todor Stoyanov, Jari Saarinen, Henrik Andreasson
autogenerated on Wed Aug 26 2015 15:24:40