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;
00180 unsigned int maxIter = 10;
00181
00182
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
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
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
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
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
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
00284 updateOccupancy(logoddlikoccu, occupancy_limit);
00285
00286 #endif
00287 }
00288
00289
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
00522
00523
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
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
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
00621
00622
00623
00624
00625
00626 }
00627
00634 void NDTCell::updateColorInformation()
00635 {
00636 }
00637
00638
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
00697 hasGaussian_ = false;
00698 return false;
00699 }
00700 else
00701 {
00702 bool recalc = false;
00703
00704 int idMax;
00705
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
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
00750 if(evals_(0) <= 0 || evals_(1) <= 0|| evals_(2) <= 0)
00751 {
00752
00753 hasGaussian_ = false;
00754 }
00755 else
00756 {
00757 hasGaussian_ = true;
00758
00759 bool recalc = false;
00760
00761 int idMax;
00762
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
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
00861 writeJFFVector(jffout, mean_);
00862
00863
00864
00865 double dtemp[2] = {d1_, d2_};
00866
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(¢er, 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
00972 double dtemp[2];
00973 int itemp[3];
00974 float ftemp[5];
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
01023 else
01024 {
01025
01026 cl_ = INCLINED;
01027
01028
01029 Eigen::Vector3d e3;
01030 e3<<0,0,1;
01031
01032 Eigen::Vector3d minorAxis = evecs_.col(index);
01033
01034
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
01041 cl_ = VERTICAL;
01042 }
01043
01044 if(fabsf(ac) > 1-EVEC_INCLINED_THR)
01045 {
01046
01047 cl_ = HORIZONTAL;
01048 }
01049 }
01050 }
01051
01052 double NDTCell::getLikelihood(const pcl::PointXYZ &pt) const
01053 {
01054
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
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 };