00001 #ifndef NDT_MCL_3D_HPP_
00002 #define NDT_MCL_3D_HPP_
00003 #include <mrpt/utils/CTicTac.h>
00004 #include <pcl/ros/conversions.h>
00005 #include <pcl/point_cloud.h>
00006 #include <pcl/io/pcd_io.h>
00007 #include <pcl/point_types.h>
00008 #include <cstdio>
00009 #include <Eigen/Eigen>
00010 #include <Eigen/Geometry>
00011 #include <fstream>
00012 #include <ndt_map/ndt_map.h>
00013 #include <ndt_map/ndt_cell.h>
00014 #include <pointcloud_vrml/pointcloud_utils.h>
00015 #include "ndt_mcl/ParticleFilter3D.h"
00016
00020 template <typename PointT>
00021 class NDTMCL3D{
00022 public:
00023 lslgeneric::NDTMap<PointT> map;
00024 ParticleFilter3D pf;
00025 double resolution;
00026 double resolution_sensor;
00027 int counter;
00028 double zfilt_min;
00029 bool forceSIR;
00033 NDTMCL3D(double map_resolution, lslgeneric::NDTMap<PointT> &nd_map, double zfilter):
00034 map(new lslgeneric::LazyGrid<PointT>(map_resolution))
00035 {
00036 isInit = false;
00037 forceSIR = false;
00038 resolution=map_resolution;
00039 resolution_sensor = resolution;
00040 counter = 0;
00041 zfilt_min = zfilter;
00042 sinceSIR = 0;
00045 double cx,cy,cz;
00046 if(!nd_map.getCentroid(cx, cy, cz)){
00047 fprintf(stderr,"Centroid NOT Given-abort!\n");
00048 exit(1);
00049 }else{
00050 fprintf(stderr,"Centroid(%lf,%lf,%lf)\n",cx,cy,cz);
00051 }
00052
00053 double wx,wy,wz;
00054
00055 if(!nd_map.getGridSizeInMeters(wx, wy, wz)){
00056 fprintf(stderr,"Grid size NOT Given-abort!\n");
00057 exit(1);
00058 }else{
00059 fprintf(stderr,"GridSize(%lf,%lf,%lf)\n",wx,wy,wz);
00060 }
00061
00062 map.initialize(cx,cy,cz,wx,wy,wz);
00063
00064 std::vector<lslgeneric::NDTCell<PointT>*> ndts;
00065 ndts = nd_map.getAllCells();
00066 fprintf(stderr,"NDT MAP with %d components",ndts.size());
00067 for(unsigned int i=0;i<ndts.size();i++){
00068 Eigen::Vector3d m = ndts[i]->getMean();
00069 if(m[2]>zfilter){
00070 Eigen::Matrix3d cov = ndts[i]->getCov();
00071 unsigned int nump = ndts[i]->getN();
00072
00073 map.addDistributionToCell(cov, m,nump);
00074 }
00075 }
00076 }
00077
00082 void initializeFilter(double x, double y, double z, double roll, double pitch, double yaw,
00083 double x_e, double y_e, double z_e, double roll_e, double pitch_e, double yaw_e,
00084 unsigned int numParticles)
00085 {
00086 pf.initializeNormalRandom(numParticles, x,y,z,roll,pitch, yaw, x_e,y_e,z_e,roll_e,pitch_e,yaw_e);
00087 }
00094
00095 void updateAndPredict(Eigen::Affine3d Tmotion, pcl::PointCloud<PointT> &cloud){
00096 Eigen::Vector3d tr = Tmotion.translation();
00097 Eigen::Vector3d rot = Tmotion.rotation().eulerAngles(0,1,2);
00098
00099 mrpt::utils::CTicTac tictac;
00100 tictac.Tic();
00101
00102 pf.predict(Tmotion, tr[0]*0.1, tr[1]*0.1, tr[2]*0.1, rot[0]*0.1, rot[1]*0.1, rot[2]*0.1);
00103 double t_pred = tictac.Tac();
00104
00105
00106
00107
00108 lslgeneric::NDTMap<PointT> local_map(new lslgeneric::LazyGrid<PointT>(resolution_sensor));
00109
00110 local_map.addPointCloudSimple(cloud);
00111 local_map.computeNDTCells();
00112
00113 int Nn = 0;
00114
00115 double t_pseudo = 0;
00116
00117 for(int i=0;i<pf.size();i++){
00118 Eigen::Affine3d T = pf.pcloud[i].T;
00119
00120 std::vector<lslgeneric::NDTCell<PointT>*> ndts;
00121 tictac.Tic();
00122 ndts = local_map.pseudoTransformNDT(T);
00123 t_pseudo += tictac.Tac();
00124 double score=1;
00125
00126 if(ndts.size()==0) fprintf(stderr,"ERROR no gaussians in measurement!!!\n");
00127 Nn = ndts.size();
00128
00129 for(int n=0;n<ndts.size();n++){
00130 Eigen::Vector3d m = ndts[n]->getMean();
00131 if(m[2]<zfilt_min) continue;
00132
00133 lslgeneric::NDTCell<PointT> *cell;
00134 PointT p;
00135 p.x = m[0];p.y=m[1];p.z=m[2];
00136
00137 if(map.getCellAtPoint(p,cell)){
00138
00139 if(cell == NULL) continue;
00140 if(cell->hasGaussian_){
00141 Eigen::Matrix3d covCombined = cell->getCov() + ndts[n]->getCov();
00142 Eigen::Matrix3d icov;
00143 bool exists;
00144 double det = 0;
00145 covCombined.computeInverseAndDetWithCheck(icov,det,exists);
00146 if(!exists) continue;
00147 double l = (cell->getMean() - m).dot(icov*(cell->getMean() - m));
00148 if(l*0 != 0) continue;
00149 score += 0.1 + 0.9 * exp(-0.05*l/2.0);
00150 }else{
00151 }
00152 }
00153 }
00154
00155 pf.pcloud[i].lik = score;
00156 for(unsigned int j=0;j<ndts.size();j++){
00157 delete ndts[j];
00158 }
00159
00160 }
00161
00162 pf.normalize();
00163
00164
00165 if(forceSIR){
00166 fprintf(stderr, "forceSIR(%d) ",forceSIR);
00167 pf.SIRUpdate();
00168 }else{
00169
00170 double varP=0;
00171 for(int i = 0; i<pf.size();i++){
00172 varP += (pf.pcloud[i].p - 1.0/pf.size())*(pf.pcloud[i].p - 1.0/pf.size());
00173 }
00174 varP /= pf.size();
00175 varP = sqrt(varP);
00176 fprintf(stderr,"Var P=%lf (Npf=%d, Nm=%d) (t_pred = %.3lf t_pseudo=%.3lf)",varP,pf.size(), Nn, t_pred,t_pseudo);
00177 if(varP > 0.006 || sinceSIR >25){
00178 fprintf(stderr,"-SIR- ");
00179 sinceSIR = 0;
00180 pf.SIRUpdate();
00181 }else{
00182 sinceSIR++;
00183 }
00184
00185 }
00186 }
00187
00194
00195 void updateAndPredictEff(Eigen::Affine3d Tmotion, pcl::PointCloud<PointT> &cloud){
00196 Eigen::Vector3d tr = Tmotion.translation();
00197 Eigen::Vector3d rot = Tmotion.rotation().eulerAngles(0,1,2);
00198
00199 mrpt::utils::CTicTac tictac;
00200 tictac.Tic();
00201
00202
00203 if(rot[2]<(0.5 * M_PI/180.0) && tr[0]>=0){
00204 pf.predict(Tmotion, tr[0]*0.2 + 0.005, tr[1]*0.1+ 0.005, tr[2]*0.1+0.005 ,rot[0]*0.2+0.001,rot[1]*0.2+0.001, rot[2]*0.2+0.001);
00205 }else if(tr[0]>=0){
00206 pf.predict(Tmotion,tr[0]*0.5 + 0.005, tr[1]*0.1+ 0.005, tr[2]*0.1+0.005 ,rot[0]*0.2+0.001,rot[1]*0.2+0.001, rot[2]*0.4+0.001);
00207 }else{
00208 pf.predict(Tmotion, tr[0]*0.2 + 0.005, tr[1]*0.1+ 0.005, tr[2]*0.1+0.005 ,rot[0]*0.2+0.001,rot[1]*0.2+0.001, rot[2]*0.2+0.001);
00209 }
00210
00211
00212 double t_pred = tictac.Tac();
00213
00214 lslgeneric::NDTMap<PointT> local_map(new lslgeneric::LazyGrid<PointT>(resolution_sensor));
00215 local_map.addPointCloudSimple(cloud);
00216
00217 local_map.computeNDTCellsSimple();
00218
00219 std::vector<lslgeneric::NDTCell<PointT>*> ndts = local_map.getAllCells();
00220
00221
00222
00223 int Nn = 0;
00224
00225 double t_pseudo = 0;
00226 #pragma omp parallel num_threads(4)
00227 {
00228 #pragma omp for
00229 for(int i=0;i<pf.size();i++){
00230 Eigen::Affine3d T = pf.pcloud[i].T;
00231
00232
00233
00234
00235
00236 double score=1;
00237
00238 if(ndts.size()==0) fprintf(stderr,"ERROR no gaussians in measurement!!!\n");
00239 Nn = ndts.size();
00240
00241 for(int n=0;n<ndts.size();n++){
00242 Eigen::Vector3d m = T*ndts[n]->getMean();
00243
00244 if(m[2]<zfilt_min) continue;
00245
00246 lslgeneric::NDTCell<PointT> *cell;
00247 PointT p;
00248 p.x = m[0];p.y=m[1];p.z=m[2];
00249
00250 if(map.getCellAtPoint(p,cell)){
00251
00252 if(cell == NULL) continue;
00253 if(cell->hasGaussian_){
00254 Eigen::Matrix3d covCombined = cell->getCov() + T.rotation()*ndts[n]->getCov() *T.rotation().transpose();
00255 Eigen::Matrix3d icov;
00256 bool exists;
00257 double det = 0;
00258 covCombined.computeInverseAndDetWithCheck(icov,det,exists);
00259 if(!exists) continue;
00260 double l = (cell->getMean() - m).dot(icov*(cell->getMean() - m));
00261 if(l*0 != 0) continue;
00262 score += 0.1 + 0.9 * exp(-0.05*l/2.0);
00263 }else{
00264 }
00265 }
00266 }
00267
00268 pf.pcloud[i].lik = score;
00269
00270
00271 }
00272 }
00273 for(unsigned int j=0;j<ndts.size();j++){
00274 delete ndts[j];
00275 }
00276
00277
00278 pf.normalize();
00279
00280
00281 if(forceSIR){
00282 fprintf(stderr, "forceSIR(%d) ",forceSIR);
00283 pf.SIRUpdate();
00284 }else{
00285
00286 double varP=0;
00287 for(int i = 0; i<pf.size();i++){
00288 varP += (pf.pcloud[i].p - 1.0/pf.size())*(pf.pcloud[i].p - 1.0/pf.size());
00289 }
00290 varP /= pf.size();
00291 varP = sqrt(varP);
00292 fprintf(stderr,"Var P=%lf (Npf=%d, Nm=%d) (t_pred = %.3lf t_pseudo=%.3lf)",varP,pf.size(), Nn, t_pred,t_pseudo);
00293 if(varP > 0.006 || sinceSIR >25){
00294 fprintf(stderr,"-SIR- ");
00295 sinceSIR = 0;
00296 pf.SIRUpdate();
00297 }else{
00298 sinceSIR++;
00299 }
00300
00301 }
00302 }
00303
00310 Eigen::Vector3d getMeanVector(){
00311 return (pf.getMean().translation());
00312
00313
00314
00315 }
00316 Eigen::Affine3d getMean(){
00317 return (pf.getMean());
00318
00319
00320
00321 }
00322
00323
00324 private:
00325 bool isInit;
00326 int sinceSIR;
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 };
00339
00340 #endif
00341