/* * veloscan implementation * * Copyright (C) Andreas Nuechter, Li Wei, Li Ming * * Released under the GPL version 3. * */ /** * @file * @brief Implementation of a 3D scan and of 3D scan matching in all variants * @author Li Wei, Wuhan University, China * @author Li Ming, Wuhan University, China * @author Andreas Nuechter. Jacobs University Bremen, Germany */ #ifdef _MSC_VER #ifdef OPENMP #define _OPENMP #endif #endif #include using std::ifstream; using std::ofstream; #include using std::cout; using std::cerr; using std::endl; #include using std::stringstream; #include "veloslam/veloscan.h" #ifdef _OPENMP #include #endif #ifdef _MSC_VER #include #else #include #endif #ifdef _MSC_VER #define strcasecmp _stricmp #define strncasecmp _strnicmp #else #include #endif #include using std::flush; #include "slam6d/Boctree.h" #include "veloslam/veloscan.h" #include "veloslam/pcddump.h" #include "veloslam/trackermanager.h" #include "veloslam/clusterboundingbox.h" #ifdef _OPENMP #include #endif #ifdef _MSC_VER #include #else #include #endif #ifdef _MSC_VER #define strcasecmp _stricmp #define strncasecmp _strnicmp #else #include #endif #include using std::flush; #include #include #ifdef _MSC_VER #include #else #include #endif #include "veloslam/velodefs.h" #include "veloslam/color_util.h" int scanCount =0; TrackerManager trackMgr; float absf(float a) { return a>0?a:-a; } Trajectory::Trajectory() { } /** * default Constructor */ VeloScan::VeloScan() : Scan() { isTrackerHandled =false; } /** * Desctuctor */ VeloScan::~VeloScan() { FreeAllCellAndCluterMemory(); } int VeloScan::DeletePoints() { FreeAllCellAndCluterMemory(); return 0; } /** * Copy constructor */ VeloScan::VeloScan(const VeloScan& s) : Scan(s) { } int VeloScan::TransferToCellArray(int maxDist, int minDist) { #define DefaultColumnSize 360 Point P; DataXYZ xyz(get("xyz")); int size= xyz.size(); int columnSize= 360; //cfg.cfgPlaneDetect.ColumnSize; int CellSize= 50; //cfg.cfgPlaneDetect.CellSize; int MinRad=minDist; //cfg.cfgPlaneDetect.MinRad; int MaxRad=maxDist; //cfg.cfgPlaneDetect.MaxRad if((MaxRad-MinRad)%CellSize!=0) CellSize=10; int i,j,count=0; int CellNumber=(MaxRad-MinRad)/CellSize; float flag; int offset; if(columnSize==0) return -1; if(columnSize%360!=0) columnSize=DefaultColumnSize; int sectionSize=columnSize/8; scanCellArray.resize(columnSize); for(i=0; i tanv; vector::iterator result; for(i=0; i=MaxRad) continue; // some point losted which on the vline or hline if(pt.x >=0 && pt.z>=0 ) { if(pt.x > pt.z) { flag= pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize-1; } else { offset=result-tanv.begin(); } } else { flag=1/pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize; } else { diff=result-tanv.begin(); offset=sectionSize*2-1-(diff); } } } else if(pt.x <= 0 && pt.z >=0) { if(-pt.x>pt.z) { flag=-pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize*3; } else { offset=sectionSize*4-1-(result-tanv.begin()); } } else { flag=1/-pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize*3-1; } else { offset=sectionSize*2+(result-tanv.begin()); } } } else if(pt.x<=0 && pt.z<=0) { if(-pt.x>-pt.z) { flag=pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize*5-1; } else { offset=sectionSize*4+(result-tanv.begin()); } } else { flag=1/pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize*5; } else { offset=sectionSize*6-1-(result-tanv.begin()); } } } else if(pt.x>=0&&pt.z<=0) { if(pt.x>-pt.z) { flag=-pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize*7; } else { offset=sectionSize*8-1-(result-tanv.begin()); } } else { flag=1/-pt.tan_theta; result=upper_bound(tanv.begin(),tanv.end(),flag); if(result==tanv.end()) { offset=sectionSize*7-1; } else { offset=sectionSize*6+(result-tanv.begin()); } } } else { continue; } int k= (int)((pt.rad-MinRad)/(CellSize*1.0)); scanCellArray[offset][k].push_back(&pt); } return 0; } int VeloScan::CalcCellFeature(cell& cellobj, cellFeature& f) { int outlier; float lastMaxY; f.size=cellobj.size(); f.cellType=0; if(f.size==0) { f.cellType|=CELL_TYPE_INVALID; return 0; } f.ave_x= f.ave_y = f.ave_z=0.0; f.delta_y=0; int i=0; for(i=0; ix; f.ave_z+=cellobj[i]->z; f.ave_y+=cellobj[i]->y; // if(cellobj[i]->type & POINT_TYPE_BELOW_R) // f.cellType |=CELL_TYPE_BELOW_R; if(i==0) { outlier=0; f.min_x=f.max_x=cellobj[i]->x; f.min_z=f.max_z=cellobj[i]->z; lastMaxY=f.min_y=f.max_y=cellobj[i]->y; } else { if(f.max_xx) f.max_x=cellobj[i]->x; if(f.min_x>cellobj[i]->x) f.min_x=cellobj[i]->x; if(f.max_zz) f.max_z=cellobj[i]->z; if(f.min_z>cellobj[i]->z) f.min_z=cellobj[i]->z; if(f.max_yy) { lastMaxY=f.max_y; f.max_y=cellobj[i]->y; outlier=i; } if(f.min_y>cellobj[i]->y) f.min_y=cellobj[i]->y; } } if(f.size>1) { int y=f.ave_y-cellobj[outlier]->y; y/=(f.size-1)*1.0; if(cellobj[outlier]->y-y<50) { outlier=-1; f.ave_y/=f.size*1.0; } else { f.max_y=lastMaxY; f.ave_y=y; } } else { outlier=-1; f.ave_y/=f.size*1.0; } f.ave_x/=f.size*1.0; f.ave_z/=f.size*1.0; for(i=0; iy - f.ave_y); } float threshold; threshold=f.delta_y; float GridThresholdGroundDetect =120; if( threshold > GridThresholdGroundDetect) f.cellType =CELL_TYPE_STATIC; else f.cellType =CELL_TYPE_GROUND; return 0; } int VeloScan::CalcScanCellFeature() { int i,j; if( scanCellArray.size()==0) return -1; int columnSize=scanCellArray.size(); int cellNumber=scanCellArray[0].size(); if( scanCellFeatureArray.size()==0) { scanCellFeatureArray.resize(columnSize); for(i=0; i 120) // { // scanCellFeatureArray[j][i].cellType |= CELL_TYPE_STATIC; // for(int k=0;k type |= POINT_TYPE_ABOVE_DELTA_Y; // // } } } return 0; } int VeloScan::SearchNeigh(cluster& clu,charvv& flagvv,int i,int j) { int columnSize=scanCellArray.size(); int cellNumber=scanCellArray[0].size(); if(i==-1) i= columnSize-1; if(i==columnSize) i= 0; if(i<0||i>=columnSize||j<0||j>=cellNumber) return 0; if(flagvv[i][j]==1) return 0; if(scanCellFeatureArray[i][j].size==0) { flagvv[i][j]=1; return 0; } if(scanCellFeatureArray[i][j].cellType & CELL_TYPE_STATIC) { flagvv[i][j]=1; clu.push_back(&scanCellFeatureArray[i][j]); SearchNeigh(clu,flagvv,i-1,j-1); SearchNeigh(clu,flagvv,i-1,j); SearchNeigh(clu,flagvv,i-1,j+1); SearchNeigh(clu,flagvv,i,j-1); SearchNeigh(clu,flagvv,i,j+1); SearchNeigh(clu,flagvv,i+1,j-1); SearchNeigh(clu,flagvv,i+1,j); SearchNeigh(clu,flagvv,i+1,j+1); SearchNeigh(clu,flagvv,i,j+2); SearchNeigh(clu,flagvv,i,j-2); SearchNeigh(clu,flagvv,i+2,j); SearchNeigh(clu,flagvv,i-2,j); //SearchNeigh(clu,flagvv,i,j+3); //SearchNeigh(clu,flagvv,i,j-3); //SearchNeigh(clu,flagvv,i+3,j); //SearchNeigh(clu,flagvv,i-3,j); } return 0; } int VeloScan::CalcClusterFeature(cluster& clu, clusterFeature& f) { f.size=clu.size(); if(f.size==0) { return 0; } f.clusterType=0; f.pointNumber=0; f.avg_x =0; f.avg_y=0; f.avg_z=0; int i=0; for(i=0; iave_x; f.avg_y += clu[i]->ave_y; f.avg_z += clu[i]->ave_z; if(i==0) { f.min_x=f.max_x=clu[i]->min_x; f.min_z=f.max_z=clu[i]->min_z; f.min_y=f.max_y=clu[i]->min_y; } else { if(f.max_xmax_x) f.max_x=clu[i]->max_x; if(f.min_x>clu[i]->min_x) f.min_x=clu[i]->min_x; if(f.max_zmax_z) f.max_z=clu[i]->max_z; if(f.min_z>clu[i]->min_z) f.min_z=clu[i]->min_z; if(f.max_ymax_y) f.max_y=clu[i]->max_y; if(f.min_y>clu[i]->min_y) f.min_y=clu[i]->min_y; } f.pointNumber+=clu[i]->size; f.theta += clu[i]->size*clu[i]->columnID; f.radius += clu[i]->size*clu[i]->cellID; } f.size_x=f.max_x-f.min_x; f.size_z=f.max_z-f.min_z; f.size_y=f.max_y-f.min_y; f.avg_x /= f.size; f.avg_y /= f.size; f.avg_z /= f.size; f.theta=f.theta / (f.pointNumber*1.0); f.radius=f.radius / (f.pointNumber*1.0); return 0; } int VeloScan::FindAndCalcScanClusterFeature() { int i,j; if( scanCellArray.size()==0) return -1; int columnSize=scanCellArray.size(); int cellNumber=scanCellArray[0].size(); charvv searchedFlag; searchedFlag.resize(columnSize); for(i=0; i *oct = new BOctTree(PointerArray(xyz_t).get(), xyz_t.size(), reduction_voxelSize, reduction_pointtype); vector center; center.clear(); if (reduction_nrpts > 0) { if (reduction_nrpts == 1) { oct->GetOctTreeRandom(center); } else { oct->GetOctTreeRandom(center, reduction_nrpts); } } else { oct->GetOctTreeCenter(center); } // storing it as reduced scan unsigned int size = center.size(); DataXYZ xyz_r(create("xyz reduced", sizeof(double)*3*size)); for(unsigned int i = 0; i < size; ++i) { for(unsigned int j = 0; j < 3; ++j) { xyz_r[i][j] = center[i][j]; } } delete oct; } bool findBusCluster(clusterFeature &glu, cluster &gluData) { /* double labelSVM; for(int i=0;i<360;i++) { nod[i].index=i+1; nod[i].value=intersectionFeature[i].slashLength/slashMaxLength; } nod[360].index=-1; labelSVM= svm_predict(m,nod); ofstream output; output.open("intersection.txt"); output<<"labelSVM:"<0.5) cout<<"intersection"< 800 || glu.size_z > 800 ) { return false; } return true; // no filter //char filename[256]; //string file; //sprintf(filename,"c:\\filename%d.txt", objcount); //file =filename; //DumpPointtoFile(gluData, file); //DumpFeaturetoFile(glu, "c:\\feature"); //objcount++; } //long objcount =0; // In one scans find which the more like moving object such as pedestrian, car, bus. bool FindMovingObjcets(clusterFeature &glu, cluster &gluData) { // for debug moving object detections. if( glu.size_y > 200 && ((glu.size_x>glu.size_y?glu.size_x:glu.size_y))<360) { return false; } else if((glu.size_y>350 && glu.size_x<140)|| (glu.size_x>350 && glu.size_y<140)) { return false; } else if(glu.size_y > 250 ) { return false; } else if((glu.size_x>glu.size_y?glu.size_x:glu.size_y)>420 && glu.size_z<130) { return false; } else if((glu.size_x>glu.size_y?glu.size_x:glu.size_y)>3.5 && ((glu.size_x>glu.size_y?glu.size_x:glu.size_y)/(glu.size_x4)) { return false; } else if(glu.size_x<700 && glu.size_z<700 && glu.size_y > 100 ) { return true; } if(glu.size_x>1500 || glu.size_z>1500 || glu.size_x*glu.size_z >600*600 ) { return false; } if (glu.size_x*glu.size_z > 500*500 && glu.size_x/glu.size_z < 1.5) { return false; } if(glu.size_y < 100) { return false; } if((glu.size_x + glu.size_y + glu.size_z)<1.5) { return false; } if(glu.size_z>700) { return false; } if(glu.size_x>700) { return false; } if(( glu.size_x + glu.size_z) <4) { return false; } if( glu.size_x/glu.size_z> 3.0) { return false; } return true; } // bi classification for distigushed the moving or static void VeloScan::ClassifiAllObject() { int i,j; int clustersize=scanClusterArray.size(); //Find moving Ojbects for(i=0; isize(); cell &gCell =*( gcellFreature.pCell); for( k=0; k< gcellFreature.pCell->size();++k) { // find Point in scan raw points by point_id; Point p = *(gCell[k]); if(gcellFreature.cellType & CELL_TYPE_STATIC) Pt[p.point_id] = POINT_TYPE_STATIC_OBJECT; if(gcellFreature.cellType & CELL_TYPE_MOVING) Pt[p.point_id] = POINT_TYPE_MOVING_OBJECT; if(gcellFreature.cellType & CELL_TYPE_GROUND) Pt[p.point_id] = POINT_TYPE_GROUND; } } } } void VeloScan::FindingAllofObject(int maxDist, int minDist) { TransferToCellArray(maxDist, minDist); CalcScanCellFeature(); FindAndCalcScanClusterFeature(); return; } void VeloScan::TrackingAllofObject(int trackingAlgo) { trackMgr.HandleScan(*this,trackingAlgo); } void VeloScan::ClassifiAllofObject() { ClassifiAllObject(); } void VeloScan::ExchangePointCloud() { MarkStaticorMovingPointCloud(); return; }