25 #include <pcl/features/integral_image_normal.h> 26 #include <pcl/features/normal_3d.h> 27 #include <pcl/ModelCoefficients.h> 28 #include <pcl/segmentation/organized_multi_plane_segmentation.h> 29 #include <pcl/segmentation/organized_connected_component_segmentation.h> 30 #include <pcl/filters/extract_indices.h> 31 #include <pcl/filters/voxel_grid.h> 32 #include <pcl/common/transforms.h> 33 #include <pcl/common/time.h> 42 #define WATCH_BINARY 0 46 using namespace Eigen;
54 assert(hist1.size() == hist2.size());
56 double BhattachDist_aux = 0.0;
57 for(
unsigned i=0; i < hist1.size(); i++)
58 BhattachDist_aux += sqrt(hist1[i]*hist2[i]);
60 BhattachDist = sqrt(1 - BhattachDist_aux);
146 PbMapMaker::PbMapMaker(
const string &config_file) :
147 cloudViewer(
"Cloud Viewer"),
148 mpPbMapLocaliser(NULL),
149 m_pbmaker_must_stop(false),
150 m_pbmaker_finished(false)
180 float distThres2 = distThreshold * distThreshold;
289 for(
size_t i = 0; i < observedPlane.
prog_Nrgb.size(); i++)
295 double rel_areas = observedPlane.area / observedPlane.
prog_area[i];
296 if( rel_areas < area_THRESHOLD_inv || rel_areas >
configPbMap.area_THRESHOLD )
306 if( rel_ratios < elongation_THRESHOLD_inv || rel_ratios >
configPbMap.elongation_THRESHOLD )
357 if(i == observedPlane.
id)
366 double rel_areas = observedPlane.area / prevPlane.area;
367 if( rel_areas < area_THRESHOLD_inv || rel_areas >
configPbMap.area_THRESHOLD )
376 if( rel_ratios < elongation_THRESHOLD_inv || rel_ratios >
configPbMap.elongation_THRESHOLD )
431 observedPlane.
prog_area.push_back(observedPlane.area);
447 cout <<
" ...Watching finished\n";
452 cout <<
"PbMapMaker::saveInfoFiles(...)\n";
466 results_file =
"results/areaRestriction.txt";
467 file.open(results_file.c_str(), ios::app);
471 results_file =
"results/elongRestriction.txt";
472 file.open(results_file.c_str(), ios::app);
478 results_file =
"results/c1c2c3Restriction.txt";
479 file.open(results_file.c_str(), ios::app);
483 results_file =
"results/NrgbRestriction.txt";
484 file.open(results_file.c_str(), ios::app);
488 results_file =
"results/IntensityRestriction.txt";
489 file.open(results_file.c_str(), ios::app);
493 results_file =
"results/ColorRestriction.txt";
494 file.open(results_file.c_str(), ios::app);
498 results_file =
"results/HueRestriction.txt";
499 file.open(results_file.c_str(), ios::app);
506 Eigen::Matrix4f &poseKF,
507 double distThreshold,
double angleThreshold,
double minInliersF)
511 unsigned minInliers = minInliersF * pointCloudPtr_arg->size();
514 cout <<
"detectPlanes in a cloud with " << pointCloudPtr_arg->size() <<
" points " << minInliers <<
" minInliers\n";
517 pcl::PointCloud<PointT>::Ptr pointCloudPtr_arg2(
new pcl::PointCloud<PointT>);
518 pcl::copyPointCloud(*pointCloudPtr_arg,*pointCloudPtr_arg2);
520 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr alignedCloudPtr(
new pcl::PointCloud<pcl::PointXYZRGBA>);
521 pcl::transformPointCloud(*pointCloudPtr_arg,*alignedCloudPtr,poseKF);
526 static pcl::VoxelGrid<pcl::PointXYZRGBA> grid;
527 grid.setLeafSize(0.02,0.02,0.02);
528 pcl::PointCloud<pcl::PointXYZRGBA> globalMap;
530 grid.filter (globalMap);
535 pcl::IntegralImageNormalEstimation<PointT, pcl::Normal> ne;
536 ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
537 ne.setMaxDepthChangeFactor (0.02f);
538 ne.setNormalSmoothingSize (10.0f);
539 ne.setDepthDependentSmoothing (
true);
541 pcl::OrganizedMultiPlaneSegmentation<PointT, pcl::Normal, pcl::Label> mps;
542 mps.setMinInliers (minInliers); cout <<
"Params " << minInliers <<
" " << angleThreshold <<
" " << distThreshold << endl;
543 mps.setAngularThreshold (angleThreshold);
544 mps.setDistanceThreshold (distThreshold);
546 pcl::PointCloud<pcl::Normal>::Ptr normal_cloud (
new pcl::PointCloud<pcl::Normal>);
547 ne.setInputCloud (pointCloudPtr_arg2);
548 ne.compute (*normal_cloud);
551 double plane_extract_start = pcl::getTime ();
553 mps.setInputNormals (normal_cloud);
554 mps.setInputCloud (pointCloudPtr_arg2);
557 std::vector<pcl::ModelCoefficients> model_coefficients;
558 std::vector<pcl::PointIndices> inlier_indices;
559 pcl::PointCloud<pcl::Label>::Ptr labels (
new pcl::PointCloud<pcl::Label>);
560 std::vector<pcl::PointIndices> label_indices;
561 std::vector<pcl::PointIndices> boundary_indices;
562 mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
565 double plane_extract_end = pcl::getTime();
566 std::cout <<
"Plane extraction took " << double (plane_extract_end - plane_extract_start) << std::endl;
568 cout << regions.size() <<
" planes detected\n";
573 vector<Plane> detectedPlanes;
574 for (
size_t i = 0; i < regions.size (); i++)
578 Vector3f centroid = regions[i].getCentroid ();
580 plane.
v3normal = poseKF.block(0,0,3,3) * Vector3f(model_coefficients[i].
values[0], model_coefficients[i].
values[1], model_coefficients[i].
values[2]);
587 pcl::ExtractIndices<pcl::PointXYZRGBA> extract;
588 extract.setInputCloud (pointCloudPtr_arg2);
589 extract.setIndices ( boost::make_shared<const pcl::PointIndices> (inlier_indices[i]) );
590 extract.setNegative (
false);
593 static pcl::VoxelGrid<pcl::PointXYZRGBA> plane_grid;
594 plane_grid.setLeafSize(0.05,0.05,0.05);
595 pcl::PointCloud<pcl::PointXYZRGBA> planeCloud;
597 plane_grid.filter (planeCloud);
601 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr contourPtr(
new pcl::PointCloud<pcl::PointXYZRGBA>);
602 contourPtr->points = regions[i].getContour();
603 plane_grid.setLeafSize(0.1,0.1,0.1);
604 plane_grid.setInputCloud (contourPtr);
618 bool isSamePlane =
false;
619 for (
size_t j = 0; j < detectedPlanes.size(); j++)
627 cout <<
"\tTwo regions support the same plane in the same KeyFrame\n";
633 detectedPlanes.push_back(plane);
637 cout << detectedPlanes.size () <<
" Planes detected\n";
645 for (
size_t i = 0; i < detectedPlanes.size (); i++)
648 bool isSamePlane =
false;
651 for(
size_t j = 0; j < numPrevPlanes; j++, itPlane++)
730 cout <<
"Same plane\n";
734 for(
size_t k = j+1; k < numPrevPlanes; k++, itPlane++)
748 for(
size_t h = k+1; h < numPrevPlanes; h++)
751 for(
size_t h = 0; h < numPrevPlanes; h++)
775 cout <<
"MERGE TWO PREVIOUS PLANES WHEREBY THE INCORPORATION OF A NEW REGION \n";
785 detectedPlanes[i].numObservations = 1;
786 detectedPlanes[i].bFullExtent =
false;
787 detectedPlanes[i].nFramesAreaIsStable = 0;
796 cout <<
"New plane " << detectedPlanes[i].id <<
" area " << detectedPlanes[i].areaVoxels<<
" of polygon " << detectedPlanes[i].areaHull << endl;
805 detectedPlanes[i].neighborPlanes[*it] = 1;
806 mPbMap.
vPlanes[*it].neighborPlanes[detectedPlanes[i].id] = 1;
820 cout <<
"\n\tobservedPlanes: ";
840 cout <<
"Plane " << observedPlane.
id <<
" color\n" << observedPlane.
v3colorNrgb << endl;
859 cout <<
"Verify that the observed planes centers are above the floor\n";
894 cout <<
"DetectedPlanesCloud finished\n";
904 if ( (event.getKeySym () ==
"r" ||
event.getKeySym () ==
"R") && event.keyDown ())
924 float thres_max_dist = max(distThreshold, distThreshold*2*(plane2.
v3center - plane1.
v3center).norm());
925 if(fabs(dist_normal) > thres_max_dist )
949 static pcl::VoxelGrid<pcl::PointXYZRGBA> merge_grid;
950 merge_grid.setLeafSize(0.05,0.05,0.05);
951 pcl::PointCloud<pcl::PointXYZRGBA> mergeCloud;
953 merge_grid.filter (mergeCloud);
976 unsigned char red [10] = {255, 0, 0, 255, 255, 0, 255, 204, 0, 255};
977 unsigned char grn [10] = { 0, 255, 0, 255, 0, 255, 160, 51, 128, 222};
978 unsigned char blu [10] = { 0, 0, 255, 0, 255, 255, 0 , 204, 0, 173};
980 double ared [10] = {1.0, 0, 0, 1.0, 1.0, 0, 1.0, 0.8, 0, 1.0};
981 double agrn [10] = { 0, 1.0, 0, 1.0, 0, 1.0, 0.6, 0.2, 0.5, 0.9};
982 double ablu [10] = { 0, 0, 1.0, 0, 1.0, 1.0, 0, 0.8, 0, 0.7};
996 viz.removeAllShapes();
997 viz.removeAllPointClouds();
1065 viz.addText(
name, 10, 20);
1077 sprintf (
name,
"normal_%u", static_cast<unsigned>(i));
1078 pcl::PointXYZ pt1, pt2;
1109 sprintf (
name,
"plane_%02u", static_cast<unsigned>(i));
1135 viz.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10,
name);
1176 viz.addText3D (it->first, it->second, 0.3, 0.9, 0.9, 0.9, it->first);
1188 size_t numPrevKFs = 0;
1189 size_t minGrowPlanes = 5;
1207 cout <<
"PARTITION SIZE " << size_partition << endl;
1208 assert(size_partition < 2);
1229 updateLock.unlock();
1237 cout <<
"Waiting for PbMapMaker thread to die.." << endl;
1247 cout <<
"\n\n\nPbMapMaker destructor called -> Save color information to file\n";
1255 cout <<
" .. PbMapMaker has died." << endl;
This class provides simple critical sections functionality.
A class acquiring a CCriticalSection at its constructor, and releasing it at destructor.
Eigen::Vector3f diffPoints(const POINT &P1, const POINT &P2)
PlaneInferredInfo * mpPlaneInferInfo
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
std::vector< double > prog_area
std::vector< Eigen::Vector3f > prog_Nrgb
std::map< std::string, pcl::PointXYZ > foundPlaces
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr polygonContourPtr
std::set< unsigned > observedPlanes
GLboolean GLenum GLenum GLvoid * values
A class used to store a planar feature (Plane for short).
mrpt::synch::CCriticalSection CS_visualize
PbMapLocaliser * mpPbMapLocaliser
bool areSamePlane(Plane &plane1, Plane &plane2, const float &cosAngleThreshold, const float &distThreshold, const float &proxThreshold)
This class allows loading and storing values and vectors of different types from ".ini" files easily.
void checkProximity(Plane &plane, float proximity)
void serializePbMap(std::string path)
void keyboardEventOccurred(const pcl::visualization::KeyboardEvent &event, void *viewer_void)
boost::mutex mtx_pbmap_busy
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
void viz_cb(pcl::visualization::PCLVisualizer &viz)
Eigen::Vector3f v3colorNrgb
! Radiometric description
float intensity_threshold
void watchProperties(std::set< unsigned > &observedPlanes, Plane &observedPlane)
struct config_pbmap configPbMap
void calcElongationAndPpalDir()
A class used to infer some semantic meaning to the planes of a PbMap.
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
std::string path_save_registered_cloud
std::map< unsigned, std::vector< unsigned > > groups
mrpt::system::TThreadHandle pbmaker_hd
std::vector< Eigen::Vector3f > prog_C1C2C3
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr alignedModelPtr
std::vector< float > prog_intensity
Eigen::Matrix< dataType, 3, 1 > compose(Eigen::Matrix< dataType, 4, 4 > &pose, Eigen::Matrix< dataType, 3, 1 > &point)
void mergePlanes(Plane &updatePlane, Plane &discardPlane)
void BASE_IMPEXP sleep(int time_ms) MRPT_NO_THROWS
An OS-independent method for sending the current thread to "sleep" for a given period of time...
void isFullExtent(Plane &plane, double newArea)
! Check if the area of input plane is stable and bounded (e.g < 1 m2) along the last keyframes that o...
std::string path_save_pbmap
std::set< unsigned > nearbyPlanes
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr planePointCloudPtr
bool searchTheFloor(Eigen::Matrix4f &poseSensor, Plane &plane)
! Check if the input plane correpond to the floor.
void forcePtsLayOnPlane()
std::vector< double > prog_elongation
SemanticClustering * clusterize
void clear()
Mark the handle as invalid.
float proximity_threshold
GLsizei const GLchar ** string
std::vector< unsigned > vQueueObservedPlanes
pcl::PointCloud< PointT >::Ptr globalMapPtr
void BASE_IMPEXP joinThread(TThreadHandle &threadHandle)
Waits until the given thread ends.
bool arePlanesNearby(Plane &plane1, Plane &plane2, const float distThreshold)
TThreadHandle createThreadFromObjectMethod(CLASS *obj, void(CLASS::*func)(PARAM), PARAM param)
Creates a new thread running a non-static method (so it will have access to "this") from another meth...
float proximity_neighbor_planes
bool save_registered_cloud
float compute2DPolygonalArea()
Compute the area of a 2D planar polygon patch - using a given normal.
float PBMAP_IMPEXP dist3D_Segment_to_Segment2(Segment S1, Segment S2)
std::vector< std::vector< float > > prog_hist_H
void detectPlanesCloud(pcl::PointCloud< PointT >::Ptr &pointCloudPtr_arg, Eigen::Matrix4f &poseKF, double distThreshold, double angleThreshold, double minInliersF)
int evalPartition(std::set< unsigned > &observedPlanes)
unsigned id
! Parameters to allow the plane-based representation of the map by a graph
bool PBMAP_IMPEXP isInHull(PointT &point3D, pcl::PointCloud< PointT >::Ptr hull3D)
void computeMassCenterAndArea()
Compute the patch's convex-hull area and mass center.
std::vector< float > hist_H
GLuint const GLchar * name
std::vector< frameRGBDandPose > frameQueue
#define ASSERT_FILE_EXISTS_(FIL)
int BASE_IMPEXP sprintf(char *buf, size_t bufSize, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
Eigen::Vector3f v3center
! Geometric description
void readConfigFile(const string &config_file_name)
void savePbMap(std::string filePath)
std::vector< Plane > vPlanes
float max_dist_center_plane
unsigned currentSemanticGroup
Eigen::Vector3f v3colorC1C2C3
void calcConvexHull(pcl::PointCloud< pcl::PointXYZRGBA >::Ptr &pointCloud, std::vector< size_t > &indices=DEFAULT_VECTOR)
! Calculate the plane's convex hull with the monotone chain algorithm.
CONTAINER::Scalar norm(const CONTAINER &v)
pcl::visualization::CloudViewer cloudViewer
Eigen::Vector3f getVector3fromPointXYZ(pointPCL &pt)
double BhattacharyyaDist(std::vector< float > &hist1, std::vector< float > &hist2)