ndt_cell.cpp
Go to the documentation of this file.
00001 #include <ndt_map/ndt_cell.h>
00002 #include <cstring>
00003 #include <cstdio>
00004 
00005 namespace lslgeneric
00006 {
00007 
00008 
00009 bool NDTCell::parametersSet_ = false;
00010 double NDTCell::EVAL_ROUGH_THR;
00011 double NDTCell::EVEC_INCLINED_THR;
00012 double NDTCell::EVAL_FACTOR;
00013 
00014 void NDTCell::setParameters(double _EVAL_ROUGH_THR   ,
00015                                     double _EVEC_INCLINED_THR,
00016                                     double _EVAL_FACTOR
00017                                    )
00018 {
00019 
00020     NDTCell::EVAL_ROUGH_THR    = _EVAL_ROUGH_THR   ;
00021     NDTCell::EVEC_INCLINED_THR = cos(_EVEC_INCLINED_THR);
00022     NDTCell::EVAL_FACTOR       = _EVAL_FACTOR      ;
00023     parametersSet_ = true;
00024 }
00025 
00029 NDTCell* NDTCell::clone() const
00030 {
00031     NDTCell *ret = new NDTCell();
00032     ret->setDimensions(this->xsize_,this->ysize_,this->zsize_);
00033     ret->setCenter(this->center_);
00034     ret->setRGB(this->R,this->G,this->B);
00035     ret->setOccupancy(occ);
00036     ret->setEmptyval(emptyval);
00037     ret->setEventData(edata);
00038     ret->setN(this->N);
00039     ret->isEmpty = this->isEmpty;
00040     ret->hasGaussian_ = this->hasGaussian_;
00041     return ret;
00042 }
00046 NDTCell* NDTCell::copy() const
00047 {
00048     NDTCell *ret = new NDTCell();
00049 
00050     ret->setDimensions(this->xsize_,this->ysize_,this->zsize_);
00051     ret->setCenter(this->center_);
00052 
00053     for(unsigned int i=0; i<this->points_.size(); i++)
00054     {
00055         ret->points_.push_back(this->points_[i]);
00056     }
00057 
00058     ret->setMean(this->getMean());
00059     ret->setCov(this->getCov());
00060     ret->setRGB(this->R,this->G,this->B);
00061     ret->setOccupancy(this->occ);
00062     ret->setEmptyval(emptyval);
00063     ret->setEventData(edata);
00064     ret->setN(this->N);
00065     ret->isEmpty = this->isEmpty;
00066     ret->hasGaussian_ = this->hasGaussian_;
00067     ret->consistency_score = this->consistency_score;
00068     ret->cost = this->cost;
00069     return ret;
00070 }
00076 void NDTCell::updateSampleVariance(const Eigen::Matrix3d &cov2,const Eigen::Vector3d &m2, unsigned int numpointsindistribution, 
00077         bool updateOccupancyFlag, float max_occu, unsigned int maxnumpoints)
00078 {
00079 
00080     if(numpointsindistribution<=2){
00081         fprintf(stderr,"updateSampleVariance:: INVALID NUMBER OF POINTS\n");
00082         return;
00083     }
00084     if(this->hasGaussian_)
00085     {
00086         Eigen::Vector3d msum1 = mean_ * (double) N;
00087         Eigen::Vector3d msum2 = m2 * (double) numpointsindistribution;
00088 
00089         Eigen::Matrix3d csum1 = cov_ * (double) (N-1);
00090         Eigen::Matrix3d csum2 = cov2 * (double) (numpointsindistribution-1);
00091 
00092         if( fabsf(N) < 1e-5) {
00093             fprintf(stderr,"Divider error (%u %u)!\n",N,numpointsindistribution);
00094             hasGaussian_ = false;
00095             return;
00096         }
00097         double divider = (double)numpointsindistribution+(double)N;
00098         if(fabs(divider) < 1e-5)
00099         {
00100             fprintf(stderr,"Divider error (%u %u)!\n",N,numpointsindistribution);
00101             return;
00102         }
00103         mean_ = (msum1 + msum2) / (divider);
00104 
00105         double w1 =  ((double) N / (double)(numpointsindistribution*(N+numpointsindistribution)));
00106         double w2 = (double) (numpointsindistribution)/(double) N;
00107         Eigen::Matrix3d csum3 = csum1 + csum2 + w1 * (w2 * msum1 - msum2) * ( w2 * msum1 - msum2).transpose();
00108         N = N + numpointsindistribution;
00109         cov_ = 1.0/((double)N-1.0)  * csum3;
00110         if(updateOccupancyFlag){
00111             double likoccval = 0.6;
00112             double logoddlikoccu = numpointsindistribution * log((likoccval)/(1.0-likoccval));
00113             updateOccupancy(logoddlikoccu, max_occu); 
00114         }
00115     }
00116     else
00117     {
00118         mean_ = m2;
00119         cov_ = cov2;
00120         N = numpointsindistribution;
00121         hasGaussian_ = true;
00122         if(updateOccupancyFlag){
00123             double likoccval = 0.6;
00124             double logoddlikoccu = numpointsindistribution * log((likoccval)/(1.0-likoccval));
00125             updateOccupancy(logoddlikoccu,max_occu); 
00126         }
00127     }
00128     if(N>maxnumpoints) N=maxnumpoints;
00129     if(this->occ<0){
00130         this->hasGaussian_ = false;
00131         return;
00132     }
00133     rescaleCovariance();
00134 }
00135 
00137 void NDTCell::computeGaussianSimple(){
00138         Eigen::Vector3d meanSum_;
00139         Eigen::Matrix3d covSum_;
00140                         
00141                                 if(points_.size()<6){
00142                                         points_.clear();
00143                                         return;
00144                                 }
00145                                 
00146         mean_<<0,0,0;
00147         for(unsigned int i=0; i< points_.size(); i++)
00148         {
00149             Eigen::Vector3d tmp;
00150             tmp<<points_[i].x,points_[i].y,points_[i].z;
00151             mean_ += tmp;
00152         }
00153         meanSum_ = mean_;
00154         mean_ /= (points_.size());
00155         Eigen::MatrixXd mp;
00156         mp.resize(points_.size(),3);
00157         for(unsigned int i=0; i< points_.size(); i++)
00158         {
00159             mp(i,0) = points_[i].x - mean_(0);
00160             mp(i,1) = points_[i].y - mean_(1);
00161             mp(i,2) = points_[i].z - mean_(2);
00162         }
00163         covSum_ = mp.transpose()*mp;
00164         cov_ = covSum_/(points_.size()-1);
00165         this->rescaleCovariance();
00166         N = points_.size();     
00167                                 R = 0; G = 0; B = 0;
00168                                 updateColorInformation();
00169 }
00175 void NDTCell::studentT(){
00176         Eigen::Vector3d meanSum_, meantmp_;
00177         Eigen::Matrix3d covSum_, covTmp_;
00178 
00179         double nu = 5; // degrees of freedom of the t-distribution
00180         unsigned int maxIter = 10; // maximum number of iterations
00181         //mean_<<0,0,0;
00182         // weights for each sample point. Initialize each weight to 1
00183         std::vector<double> lambda;
00184         unsigned int pnts = points_.size();
00185         lambda.reserve(pnts);
00186         for(unsigned int i=0;i<pnts;i++) lambda[i] = 1.0; 
00187         
00188                 
00189         for (unsigned int j=0; j<maxIter; j++)
00190         {
00191                         // update mean
00192                         double lambdaSum=0;
00193                         meantmp_<<0,0,0;
00194                         for(unsigned int i=0; i< pnts; i++)
00195                         {
00196                                         Eigen::Vector3d tmp;
00197                                         tmp<<points_[i].x,points_[i].y,points_[i].z;
00198                                         meantmp_ += lambda[i]*tmp;
00199                                         lambdaSum += lambda[i];
00200                         
00201                         }
00202                         
00203                         meanSum_ = meantmp_;
00204                         meantmp_ /= lambdaSum;
00205                         
00206                         // update scalematrix
00207                         Eigen::MatrixXd mp;
00208                         mp.resize(points_.size(),3);
00209                         for(unsigned int i=0; i< pnts; i++)
00210                         {
00211                                         double sqrtLambda = sqrt(lambda[i]);
00212                                         mp(i,0) = sqrtLambda*(points_[i].x - meantmp_(0));
00213                                         mp(i,1) = sqrtLambda*(points_[i].y - meantmp_(1));
00214                                         mp(i,2) = sqrtLambda*(points_[i].z - meantmp_(2));
00215                         }
00216                         covSum_ = mp.transpose()*mp;
00217                         
00218                         covTmp_ = covSum_/(points_.size());
00219                         
00220                         // compute inverse scalematrix
00221                         Eigen::Matrix3d invCov;
00222                         double det=0;
00223                         bool exists=false;
00224                         covTmp_.computeInverseAndDetWithCheck(invCov,det,exists);
00225                         if(!exists){
00227                                 return;
00228                         }
00229                         
00230                         Eigen::Vector3d tempVec;
00231                         // update the weights
00232                         for (unsigned int i=0; i< points_.size(); i++){
00233                                         tempVec(0) = points_[i].x - meantmp_(0);
00234                                         tempVec(1) = points_[i].y - meantmp_(1);
00235                                         tempVec(2) = points_[i].z - meantmp_(2);
00236                                         double temp = nu;
00237                                         temp += squareSum(invCov, tempVec);
00238                                         lambda[i] = (nu+3)/(temp);
00239                         }
00240         }
00241         double temp;
00242         temp = nu/(nu-2.0);
00243         covTmp_ = temp*covTmp_;
00244         
00245         if(!hasGaussian_){
00246                 mean_ = meantmp_;
00247                 cov_ = covTmp_;
00248                 N = pnts;
00249                 this->rescaleCovariance();
00250         }else{
00251                 updateSampleVariance(covTmp_, meantmp_, pnts, false);
00252         }
00253         
00254         points_.clear();
00255 }
00256 
00261 void NDTCell::computeGaussian(int mode, unsigned int maxnumpoints, float occupancy_limit, Eigen::Vector3d origin, double sensor_noise)
00262 {
00266         
00268     double likoccval = 0.6;
00269     
00270     
00271     double logoddlikoccu = points_.size() * log((likoccval)/(1.0-likoccval));
00272 //              if(mode != CELL_UPDATE_MODE_ERROR_REFINEMENT){
00273                         if(logoddlikoccu > 0.4)  
00274                         {
00275                                         updateOccupancy(logoddlikoccu, occupancy_limit);
00276                         }
00277                         else
00278                         {
00279         #ifdef ICRA_2013_NDT_OM_SIMPLE_MODE
00280                                 double logoddlikempty = emptyval * log((0.49)/(1.0-0.49));
00281                                 updateOccupancy(logoddlikempty, occupancy_limit);       
00282         #else
00283                                 //updateOccupancy(logoddlikoccu+emptylik, occupancy_limit); << MUST BE ENABLED FOR OMG-NR
00284                                 updateOccupancy(logoddlikoccu, occupancy_limit);
00285                                 
00286         #endif
00287                         }
00288 //              }
00289     //occ++;
00290                 isEmpty = -1;
00291                 emptyval = 0;
00292                 emptylik = 0;
00293                 emptydist = 0;
00294                 
00295                 if(occ<=0){
00296       hasGaussian_ = false;
00297       return;
00298                 }
00299                 
00342                 if((hasGaussian_==false && points_.size()< 3) || points_.size()==0){
00343                         points_.clear();
00344                         return; 
00345                 }
00346                 
00347                 if(mode==CELL_UPDATE_MODE_STUDENT_T){
00348                         studentT();
00349                         return;
00350                 }
00351 
00352 
00353     if(!hasGaussian_)
00354     {
00355         Eigen::Vector3d meanSum_;
00356         Eigen::Matrix3d covSum_;
00357 
00358         mean_<<0,0,0;
00359         for(unsigned int i=0; i< points_.size(); i++)
00360         {
00361             Eigen::Vector3d tmp;
00362             tmp<<points_[i].x,points_[i].y,points_[i].z;
00363             mean_ += tmp;
00364         }
00365         meanSum_ = mean_;
00366         mean_ /= (points_.size());
00367         Eigen::MatrixXd mp;
00368         mp.resize(points_.size(),3);
00369         for(unsigned int i=0; i< points_.size(); i++)
00370         {
00371             mp(i,0) = points_[i].x - mean_(0);
00372             mp(i,1) = points_[i].y - mean_(1);
00373             mp(i,2) = points_[i].z - mean_(2);
00374         }
00375         covSum_ = mp.transpose()*mp;
00376         cov_ = covSum_/(points_.size()-1);
00377         this->rescaleCovariance();
00378         N = points_.size();
00379         
00380 
00383     }
00384     else if(mode == CELL_UPDATE_MODE_COVARIANCE_INTERSECTION)   
00385     {
00388         Eigen::Vector3d m2;
00389         m2<<0,0,0;
00390         for(unsigned int i=0; i< points_.size(); i++)
00391         {
00392             Eigen::Vector3d tmp;
00393             tmp<<points_[i].x,points_[i].y,points_[i].z;
00394             m2 += tmp;
00395         }
00396         m2 /= (points_.size());
00397 
00398 
00399         Eigen::MatrixXd mp;
00400         mp.resize(points_.size(),3);
00401         for(unsigned int i=0; i< points_.size(); i++)
00402         {
00403             mp(i,0) = points_[i].x - m2(0);
00404             mp(i,1) = points_[i].y - m2(1);
00405             mp(i,2) = points_[i].z - m2(2);
00406         }
00407         Eigen::Matrix3d c2;
00408         c2 = mp.transpose()*mp/(points_.size()-1);
00409         double w1 = 0.98;
00410         Eigen::Matrix3d c3,icov2,icov3;
00411         bool exists = false;
00412         double det=0;
00413         exists = rescaleCovariance(c2, icov2);
00414 
00415         if(exists)
00416         {
00417             c3 = w1 * icov_ + (1.0-w1) * icov2;
00418             c3.computeInverseAndDetWithCheck(icov3,det,exists);
00419             if(exists)
00420             {
00421                 cov_ = icov3;
00422                 mean_ = icov3 * (w1*icov_*mean_ + (1.0-w1)*icov2*m2);
00423 
00424                 this->rescaleCovariance();
00425                 N += points_.size();
00426             }
00427             else
00428             {
00429                 fprintf(stderr,"Covariance Intersection failed - Inverse does not exist (2)\n");
00430             }
00431         }
00432         else
00433         {
00434             points_.clear();
00435             fprintf(stderr,"Covariance Intersection failed - Inverse does not exist (1)\n");
00436         }
00439     }
00440     else if(mode == CELL_UPDATE_MODE_SAMPLE_VARIANCE)
00441     {
00444         Eigen::Vector3d meanSum_ = mean_ * N;
00445         Eigen::Matrix3d covSum_ = cov_ * (N-1);
00446 
00447         Eigen::Vector3d m2;
00448         m2<<0,0,0;
00449         for(unsigned int i=0; i< points_.size(); i++)
00450         {
00451             Eigen::Vector3d tmp;
00452             tmp<<points_[i].x,points_[i].y,points_[i].z;
00453             m2 += tmp;
00454         }
00455         Eigen::Vector3d T2 = m2;
00456 
00457         m2 /= (points_.size());
00458 
00459         Eigen::MatrixXd mp;
00460         mp.resize(points_.size(),3);
00461         for(unsigned int i=0; i< points_.size(); i++)
00462         {
00463             mp(i,0) = points_[i].x - m2(0);
00464             mp(i,1) = points_[i].y - m2(1);
00465             mp(i,2) = points_[i].z - m2(2);
00466         }
00467 
00468         Eigen::Matrix3d c2;
00469         c2 = mp.transpose()*mp;
00470         Eigen::Matrix3d c3;
00471 
00472         double w1 =  ((double) N / (double)(points_.size()*(N+points_.size())));
00473         double w2 = (double) (points_.size())/(double) N;
00474 
00475         c3 = covSum_ + c2 + w1 * (w2 * meanSum_ - (T2)) * ( w2 * meanSum_ - (T2)).transpose();
00476 
00477         meanSum_ = meanSum_ + T2;
00478         covSum_ = c3;
00479         N = N + points_.size();
00480 
00485         if(maxnumpoints > 0)
00486         {
00487             if(maxnumpoints < N)
00488             {
00489                 meanSum_ = meanSum_ * ((double)maxnumpoints / (double)N);
00490                 covSum_ = covSum_ * ((double)(maxnumpoints-1) / (double)(N-1));
00491                 N = maxnumpoints;
00492             }
00493         }
00494         mean_ = meanSum_ / (double) N;
00495         cov_ = covSum_ / (double) (N-1);
00496         this->rescaleCovariance();
00497 
00500     }
00501     else if(mode == CELL_UPDATE_MODE_ERROR_REFINEMENT)
00502     {
00505         
00506         double e_min = 5.0e-4;
00507         double e_max = 5.0e-2;
00508         double o_max = 10.0;
00509         if(occ>o_max) occ=o_max;
00510         if(occ<-o_max) occ = -o_max;
00511 
00512         double epsilon = ((e_min - e_max) / (2.0*o_max)) * (occ+o_max)+e_max;
00513 
00514         for(unsigned int i=0; i< points_.size(); i++)
00515         {
00516             Eigen::Vector3d tmp;
00517             tmp<<points_[i].x,points_[i].y,points_[i].z;
00518             mean_ = mean_ + epsilon * (tmp - mean_);
00519 
00520             cov_ = cov_+epsilon * ((tmp-mean_) * (tmp-mean_).transpose() - cov_);
00521             //occ += 1.0;
00522             //if(occ>o_max) occ=o_max;
00523                                                 //if(occ<-o_max) occ = -o_max;
00524         }
00525         hasGaussian_ = true;
00526         this->rescaleCovariance();
00527 
00530     }
00531     else if(mode == CELL_UPDATE_MODE_SAMPLE_VARIANCE_SURFACE_ESTIMATION)
00532     {
00535         Eigen::Vector3d meanSum_ = mean_ * N;
00536         Eigen::Matrix3d covSum_ = cov_ * (N-1);
00537 
00538         Eigen::Vector3d m2;
00539         m2<<0,0,0;
00540         for(unsigned int i=0; i< points_.size(); i++)
00541         {
00542             Eigen::Vector3d tmp;
00543             tmp<<points_[i].x,points_[i].y,points_[i].z;
00544             m2 += tmp;
00545         }
00546         Eigen::Vector3d T2 = m2;
00547 
00548         m2 /= (points_.size());
00549 
00550         pcl::PointXYZ orig;
00551         orig.x = origin[0];
00552         orig.y=origin[1];
00553         orig.z = origin[2];
00554 
00555         Eigen::Vector3d Xm;
00556         Eigen::Matrix3d c2=Eigen::Matrix3d::Zero();
00557 
00558 
00559 
00560         for(unsigned int i=0; i< points_.size(); i++)
00561         {
00562             Eigen::Vector3d X;
00563             X<<points_[i].x,points_[i].y,points_[i].z;
00564 
00565             computeMaximumLikelihoodAlongLine(orig, points_[i], Xm);
00566             double dist = (origin-X).norm();
00567             //double sigma_dist = 0.5 * ((dist*dist)/12.0); ///test for distance based sensor noise
00568             double sigma_dist = 0.5 * ((dist)/20.0); 
00569             double snoise = sigma_dist + sensor_noise;
00570             double model_trust_given_meas = 0.49 + 0.5*exp(-0.5 * ((Xm-X).norm()*(Xm-X).norm())/(snoise*snoise));
00571 
00572             //double loglik_m = log(model_trust_given_meas / (1-model_trust_given_meas));
00573             double oval = occ/10.0;
00574             if(oval > 5.0) oval = 5.0;
00575 
00576             double likweight = oval;
00577 
00578             double weight = (1.0 - 1.0/(1.0+exp(likweight)))*model_trust_given_meas;
00579             if(N<100) weight = 0;
00580             c2 = c2 + (1.0-weight) * (X-m2)*(X-m2).transpose() + weight * (Xm-mean_)*(Xm-mean_).transpose();
00581         }
00582 
00583 
00584         Eigen::Matrix3d c3;
00585 
00586         double w1 =  ((double) N / (double)(points_.size()*(N+points_.size())));
00587         double w2 = (double) (points_.size())/(double) N;
00588 
00589         c3 = covSum_ + c2 + w1 * (w2 * meanSum_ - (T2)) * ( w2 * meanSum_ - (T2)).transpose();
00590 
00591         meanSum_ = meanSum_ + T2;
00592         covSum_ = c3;
00593         N = N + points_.size();
00594 
00599         if(maxnumpoints > 0)
00600         {
00601             if(maxnumpoints < N)
00602             {
00603                 meanSum_ = meanSum_ * ((double)maxnumpoints / (double)N);
00604                 covSum_ = covSum_ * ((double)(maxnumpoints-1) / (double)(N-1));
00605                 N = maxnumpoints;
00606             }
00607         }
00608         mean_ = meanSum_ / (double) N;
00609         cov_ = covSum_ / (double) (N-1);
00610         this->rescaleCovariance();
00613     }
00614 
00615 
00616     updateColorInformation();
00617                 
00618                 points_.clear();
00619                 /*
00620     if( !(hasGaussian_ && occ < 0))
00621     {
00622         points_.clear();
00623     }*/
00624 
00625 
00626 }
00627 
00634 void NDTCell::updateColorInformation()
00635 {
00636 }
00637 
00638 //FIXME fix the template specialization here, is it still necessary?
00639 #if 0
00640 
00641 inline void NDTCell::updateColorInformation()
00642 {
00643     double r=0,g=0,b=0;
00644     for(unsigned int i=0; i< points_.size(); i++)
00645     {
00646         r+= ((double)points_[i].r)/255.0;
00647         g+= ((double)points_[i].g)/255.0;
00648         b+= ((double)points_[i].b)/255.0;
00649     }
00650     if(R == 0 && G == 0 && B == 0)
00651     {
00652         this->setRGB(r/(double)points_.size(), g/(double)points_.size(),b/(double)points_.size());
00653     }
00654     else
00655     {
00656         r /=  points_.size();
00657         g /=  points_.size();
00658         b /=  points_.size();
00659 
00660 
00661         R = 0.9*R + 0.1*r;
00662         G = 0.9*G + 0.1*g;
00663         B = 0.9*B + 0.1*b;
00664     }
00665 }
00667 inline void NDTCell<pcl::PointXYZI>::updateColorInformation()
00668 {
00669     double intensity=0;
00670     for(unsigned int i=0; i< points_.size(); i++)
00671     {
00672         intensity+= ((double)points_[i].intensity)/255.0;
00673     }
00674     this->setRGB(intensity/(double)points_.size(), intensity/(double)points_.size(),intensity/(double)points_.size());
00675 }
00676 #endif
00677 
00678 
00680 
00684 bool NDTCell::rescaleCovariance(Eigen::Matrix3d &cov, Eigen::Matrix3d &invCov)
00685 {
00686     Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> Sol (cov);
00687 
00688     Eigen::Matrix3d evecs;
00689     Eigen::Vector3d evals;
00690 
00691     evecs = Sol.eigenvectors().real();
00692     evals = Sol.eigenvalues().real();
00693 
00694     if(evals(0) <= 0 || evals(1) <= 0 || evals(2) <= 0)
00695     {
00696         //fprintf(stderr,"Negative Eigenvalues!\n");
00697         hasGaussian_ = false;
00698         return false;
00699     }
00700     else
00701     {
00702         bool recalc = false;
00703         //guard against near singular matrices::
00704         int idMax;
00705         //double minEval = evals.minCoeff(&idMin);
00706         double maxEval = evals.maxCoeff(&idMax);
00707         if(maxEval > evals(0)*EVAL_FACTOR)
00708         {
00709             evals(0) = evals(idMax)/EVAL_FACTOR;
00710             recalc = true;
00711         }
00712         if(maxEval > evals(1)*EVAL_FACTOR)
00713         {
00714             evals(1) = evals(idMax)/EVAL_FACTOR;
00715             recalc = true;
00716         }
00717         if(maxEval > evals(2)*EVAL_FACTOR)
00718         {
00719             evals(2) = evals(idMax)/EVAL_FACTOR;
00720             recalc = true;
00721         }
00722 
00723         if(recalc)
00724         {
00725             Eigen::Matrix3d Lam;
00726             Lam = evals.asDiagonal();
00727             cov = evecs*Lam*(evecs.transpose());
00728         }
00729 
00730         //compute inverse covariance
00731         Eigen::Matrix3d Lam;
00732         Lam = evals.asDiagonal();
00733         invCov = evecs*(Lam.inverse())*(evecs.transpose());
00734     }
00735     return true;
00736 }
00737 
00738 
00739 
00740 
00742 void NDTCell::rescaleCovariance()
00743 {
00744     Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> Sol (cov_);
00745 
00746     evecs_ = Sol.eigenvectors().real();
00747     evals_ = Sol.eigenvalues().real();
00748 
00749     //std::cout<<"evals = [ "<<evals_.transpose()<<"]';\n";
00750     if(evals_(0) <= 0 || evals_(1) <= 0|| evals_(2) <= 0)
00751     {
00752         //fprintf(stderr,"evals <=0\n");
00753         hasGaussian_ = false;
00754     }
00755     else
00756     {
00757         hasGaussian_ = true;
00758         
00759         bool recalc = false;
00760         //guard against near singular matrices::
00761         int idMax;
00762         //double minEval = evals.minCoeff(&idMin);
00763         double maxEval = evals_.maxCoeff(&idMax);
00764         if(maxEval > evals_(0)*EVAL_FACTOR)
00765         {
00766             evals_(0) = evals_(idMax)/EVAL_FACTOR;
00767             recalc = true;
00768         }
00769         if(maxEval > evals_(1)*EVAL_FACTOR)
00770         {
00771             evals_(1) = evals_(idMax)/EVAL_FACTOR;
00772             recalc = true;
00773         }
00774         if(maxEval > evals_(2)*EVAL_FACTOR)
00775         {
00776             evals_(2) = evals_(idMax)/EVAL_FACTOR;
00777             recalc = true;
00778         }
00779 
00780         if(recalc)
00781         {
00782             Eigen::Matrix3d Lam;
00783             Lam = evals_.asDiagonal();
00784             cov_ = evecs_*Lam*(evecs_.transpose());
00785         }
00786         classify();
00787         //compute inverse covariance
00788         Eigen::Matrix3d Lam;
00789         Lam = (evals_).asDiagonal();
00790         icov_ = evecs_*(Lam.inverse())*(evecs_.transpose());
00791     }
00792 }
00793 
00794 
00797 void NDTCell::writeJFFMatrix(FILE * jffout, Eigen::Matrix3d &mat)
00798 {
00799 
00800     double dtemp[6];
00801 
00802     dtemp[0] = mat.coeff(0,0);
00803     dtemp[1] = mat.coeff(1,0);
00804     dtemp[2] = mat.coeff(2,0);
00805     dtemp[3] = mat.coeff(1,1);
00806     dtemp[4] = mat.coeff(2,1);
00807     dtemp[5] = mat.coeff(2,2);
00808 
00809     fwrite(dtemp, sizeof(double), 6, jffout);
00810 
00811 }
00812 
00815 void NDTCell::writeJFFVector(FILE * jffout, Eigen::Vector3d &vec)
00816 {
00817 
00818     double dtemp[3];
00819 
00820     for(int i=0; i<3; i++)
00821     {
00822         dtemp[i] = vec.coeff(i);
00823     }
00824 
00825     fwrite(dtemp, sizeof(double), 3, jffout);
00826 
00827 }
00828 
00831 void NDTCell::writeJFFEventData(FILE * jffout, TEventData &evdata)
00832 {
00833 
00834     float    ftemp[4];
00835     uint8_t  ocval[1] = {evdata.occval};
00836     uint64_t evnts[1] = {evdata.events};
00837 
00838     ftemp[0] = evdata.a_exit_event;
00839     ftemp[1] = evdata.b_exit_event;
00840     ftemp[2] = evdata.a_entry_event;
00841     ftemp[3] = evdata.b_entry_event;
00842 
00843     fwrite(ocval, sizeof(uint8_t),  1, jffout);
00844     fwrite(ftemp, sizeof( float ),  4, jffout);
00845     fwrite(evnts, sizeof(uint64_t), 1, jffout);
00846 
00847 }
00848 
00851 int NDTCell::writeToJFF(FILE * jffout)
00852 {
00853 
00854     pcl::PointXYZ * center = &(this->center_);
00855     fwrite(center, sizeof(pcl::PointXYZ), 1, jffout);
00856     double cell_size[3] = {this->xsize_, this->ysize_, this->zsize_};
00857     fwrite(cell_size, sizeof(double), 3, jffout);
00858 
00859     writeJFFMatrix(jffout, cov_);
00860     //writeJFFMatrix(jffout, covSum_);
00861     writeJFFVector(jffout, mean_);
00862     //writeJFFVector(jffout, meanSum_);
00863 
00864     // Temporary arrays to write all cell data
00865     double dtemp[2] = {d1_, d2_};
00866     //int    itemp[2] = {N, emptyval};
00867     int    itemp[3] = {N, emptyval,(int) hasGaussian_};
00868     float  ftemp[5] = {R, G, B, occ};
00869 
00870     fwrite(dtemp, sizeof(double), 2, jffout);
00871     fwrite(itemp, sizeof( int ),  3, jffout);
00872     fwrite(ftemp, sizeof(float),  4, jffout);
00873 
00874     writeJFFEventData(jffout, edata);
00875 
00876     return 0;
00877 
00878 }
00879 
00882 int NDTCell::loadJFFMatrix(FILE * jffin, Eigen::Matrix3d &mat)
00883 {
00884 
00885     double dtemp[6];
00886 
00887     if(fread(&dtemp, sizeof(double), 6, jffin) <= 0)
00888         return -1;
00889 
00890     mat(0,0) = dtemp[0];
00891     mat(1,0) = dtemp[1];
00892     mat(2,0) = dtemp[2];
00893     mat(1,1) = dtemp[3];
00894     mat(2,1) = dtemp[4];
00895     mat(2,2) = dtemp[5];
00896     mat(0,1) = dtemp[1];
00897     mat(0,2) = dtemp[2];
00898     mat(1,2) = dtemp[4];
00899 
00900     return 0;
00901 
00902 }
00903 
00906 int NDTCell::loadJFFVector(FILE * jffin, Eigen::Vector3d &vec)
00907 {
00908 
00909     double dtemp[3];
00910 
00911     if(fread(&dtemp, sizeof(double), 3, jffin) <= 0)
00912         return -1;
00913 
00914     vec << dtemp[0], dtemp[1], dtemp[2];
00915 
00916     return 0;
00917 
00918 }
00919 
00922 int NDTCell::loadJFFEventData(FILE * jffin, TEventData &evdata)
00923 {
00924 
00925     float    ftemp[4];
00926     uint8_t  ocval;
00927     uint64_t evnts;
00928 
00929     if(fread(&ocval, sizeof(uint8_t),  1, jffin) <= 0)
00930         return -1;
00931     if(fread(&ftemp, sizeof( float ),  4, jffin) <= 0)
00932         return -1;
00933     if(fread(&evnts, sizeof(uint64_t), 1, jffin) <= 0)
00934         return -1;
00935 
00936     evdata.a_exit_event  = ftemp[0];
00937     evdata.b_exit_event  = ftemp[1];
00938     evdata.a_entry_event = ftemp[2];
00939     evdata.b_entry_event = ftemp[3];
00940     evdata.occval        = ocval;
00941     evdata.events        = evnts;
00942 
00943     return 0;
00944 }
00945 
00948 int NDTCell::loadFromJFF(FILE * jffin)
00949 {
00950 
00951     pcl::PointXYZ center;
00952     if(fread(&center, sizeof(pcl::PointXYZ), 1, jffin) <= 0)
00953         return -1;
00954     this->setCenter(center);
00955 
00956     double dimensions[3];
00957     if(fread(&dimensions, sizeof(double), 3, jffin) <= 0)
00958         return -1;
00959     this->setDimensions(dimensions[0], dimensions[1], dimensions[2]);
00960 
00961     Eigen::Matrix3d temp_matrix;
00962     Eigen::Vector3d temp_vector;
00963     if(loadJFFMatrix(jffin, temp_matrix) < 0)
00964         return -1;
00965     this->setCov(temp_matrix);
00966 
00967     if(loadJFFVector(jffin, temp_vector) < 0)
00968         return -1;
00969     this->setMean(temp_vector);
00970 
00971     // Temporary arrays to load all cell data to
00972     double dtemp[2];// = {d1_, d2_};
00973     int    itemp[3];// = {N, emptyval, hasGaussian_};
00974     float  ftemp[5];// = {R, G, B, occ, cellConfidence};
00975 
00976     if(fread(&dtemp, sizeof(double), 2, jffin) <= 0)
00977         return -1;
00978     if(fread(&itemp, sizeof( int ),  3, jffin) <= 0)
00979         return -1;
00980     if(fread(&ftemp, sizeof(float),  4, jffin) <= 0)
00981         return -1;
00982 
00983     this->d1_ = dtemp[0];
00984     this->d2_ = dtemp[1];
00985 
00986     this->setN(itemp[0]);
00987     this->setEmptyval(itemp[1]);
00988     this->hasGaussian_ = (bool) itemp[2];
00989 
00990     this->setRGB(ftemp[0], ftemp[1], ftemp[2]);
00991     this->setOccupancy(ftemp[3]);
00992 
00993     TEventData edata;
00994     loadJFFEventData(jffin, edata);
00995     this->setEventData(edata);
00996 
00997     return 0;
00998 
00999 }
01000 
01001 
01006 void NDTCell::classify()
01007 {
01008 
01009     cl_ = UNKNOWN;
01010 
01011     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> tr;
01012     tr = tr.rotate(evecs_);
01013 
01014     int index=-1;
01015     double minEval = evals_.minCoeff(&index);
01016     if(index<0 || index > 2) return;
01017 
01018     if(minEval > EVAL_ROUGH_THR )
01019     {
01020         cl_ = ROUGH;
01021     }
01022     //if 1 eval << other 2 -> planar distr
01023     else
01024     {
01025         //default case -> sloping surface
01026         cl_ = INCLINED;
01027 
01028         //check the orientation of the vanishing axis
01029         Eigen::Vector3d e3;
01030         e3<<0,0,1;
01031 
01032         Eigen::Vector3d minorAxis = evecs_.col(index); //tr*e3;
01033 
01034         //dot product with vertical axis gives us the angle
01035         double d = minorAxis.dot(e3);
01036         double l = minorAxis.norm();
01037         double ac = d/l;
01038         if(fabsf(ac) < EVEC_INCLINED_THR)
01039         {
01040             //angle is nearly perpendicular => vertical surface
01041             cl_ = VERTICAL;
01042         }
01043 
01044         if(fabsf(ac) > 1-EVEC_INCLINED_THR)
01045         {
01046             //angle is nearly 0 => horizontal surface
01047             cl_ = HORIZONTAL;
01048         }
01049     }
01050 }
01051 
01052 double NDTCell::getLikelihood(const pcl::PointXYZ &pt) const
01053 {
01054     //compute likelihood
01055     if(!hasGaussian_) return -1;
01056     Eigen::Vector3d vec (pt.x,pt.y,pt.z);
01057     vec = vec-mean_;
01058     double likelihood = vec.dot(icov_*vec);
01059     if(std::isnan(likelihood)) return -1;
01060 
01061     return exp(-likelihood/2);
01062     //return -d1*exp(-d2*likelihood/2);
01063 }
01064 
01065 
01068 void NDTCell::setCov(const Eigen::Matrix3d &_cov)
01069 {
01070     cov_ = _cov;
01071     this->rescaleCovariance();
01072 }
01083 double NDTCell::computeMaximumLikelihoodAlongLine(const pcl::PointXYZ &p1, const pcl::PointXYZ &p2, Eigen::Vector3d &out)
01084 {
01085     Eigen::Vector3d v1,v2;
01086     v1 << p1.x,p1.y,p1.z;
01087     v2 << p2.x,p2.y,p2.z;
01088 
01089     Eigen::Vector3d L = (v2-v1)/(v2-v1).norm();
01090     Eigen::Vector3d A = icov_ * L;
01091     Eigen::Vector3d B = (v2 - mean_);
01092 
01093     double sigma = A(0)*L(0)+A(1)*L(1)+A(2)*L(2);
01094     if(sigma == 0) return 1.0;
01095 
01096     double t = -(A(0)*B(0)+A(1)*B(1)+A(2)*B(2))/sigma;
01097 
01098     Eigen::Vector3d X = L*t+v2; 
01099 
01100     pcl::PointXYZ p;
01101     p.x = X(0);
01102     p.y = X(1);
01103     p.z = X(2);
01104     out = X;
01105     return getLikelihood(p);
01106 
01107 }
01108 
01109 
01110 
01111 
01112 }; // end namespace


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