From 51a4257e9f08809ca47af22307790df914f28d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20del=20Pino?= <idelpino@iri.upc.edu> Date: Tue, 12 Jul 2022 19:04:07 +0200 Subject: [PATCH] added fast labelling mode, to enable it just set the number_of_reference_used_for_labelling to zero --- include/kf_based_terrain_analysis.h | 8 + include/structs_definitions.h | 4 +- src/kf_based_terrain_analysis.cpp | 400 ++++++++++++++++++++++++++-- 3 files changed, 395 insertions(+), 17 deletions(-) diff --git a/include/kf_based_terrain_analysis.h b/include/kf_based_terrain_analysis.h index 6136571..6a1f953 100644 --- a/include/kf_based_terrain_analysis.h +++ b/include/kf_based_terrain_analysis.h @@ -87,6 +87,14 @@ private: const std::vector<std::vector<int>> &edges, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_cloud_ptr); + void fastLabelPointcloudUsingGroundModel( + const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, + const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud_ptr, + const std::vector<std::vector<int> > &correspondence_indexes, + const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr ground_reference_cloud_ptr, + const std::vector<std::vector<int>> &edges, + pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_cloud_ptr); + void ensureThatConnectionsAreReflectedInBothEnds( const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr ground_reference_cloud_ptr, std::vector<std::vector<int>> edges); diff --git a/include/structs_definitions.h b/include/structs_definitions.h index 0d59f13..00feb6e 100644 --- a/include/structs_definitions.h +++ b/include/structs_definitions.h @@ -20,9 +20,11 @@ const int DATA_N_3_Z_VARIANCE = 3; const int DATA_C_0_RGB_CAST_INTO_FLOAT = 0; const int DATA_C_1_ID_CLASS = 1; -const int DATA_C_2_CAR_PROB = 2; +const int DATA_C_2_INDEX_OF_GROUND_REF_THAT_MADE_THE_LABEL = 2; const int DATA_C_3_ORIGINAL_INDEX = 3; +const int DATA_C_2_CAR_PROB = 2; // TODO: remove this + const int GRND_REF_DATA_C_0_RGB_CAST_INTO_FLOAT = 0; const int GRND_REF_DATA_C_1_ROLL = 1; const int GRND_REF_DATA_C_2_PITCH = 2; diff --git a/src/kf_based_terrain_analysis.cpp b/src/kf_based_terrain_analysis.cpp index a9f266a..dd3c622 100644 --- a/src/kf_based_terrain_analysis.cpp +++ b/src/kf_based_terrain_analysis.cpp @@ -24,8 +24,8 @@ void CKf_Based_Terrain_Analysis::extractPointsInROI( // if (filtering_configuration.measure_performance) // CFunctionMonitor performance_monitor("extractPointsInROI", performance_supervisor_ptr_); - //std::cout << "Extracting points in ROI: reference.x = " << reference.x << " reference.y = " << reference.y - // << " reference.z = " << reference.z << std::endl; +//std::cout << "Extracting points in ROI: reference.x = " << reference.x << " reference.y = " << reference.y +// << " reference.z = " << reference.z << std::endl; float x_min, x_max, y_min, y_max, x_search_range, y_search_range; @@ -387,6 +387,10 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].r = R_CLASS_GROUND; elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].g = G_CLASS_GROUND; elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].b = B_CLASS_GROUND; + + // and store the reference for the later full pointcloud labelling step + elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].data_c[DATA_C_2_INDEX_OF_GROUND_REF_THAT_MADE_THE_LABEL] = + reference_index; } } else @@ -413,6 +417,9 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].g = G_CLASS_OBSTACLE; elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].b = B_CLASS_OBSTACLE; } + // and store the reference for the later full pointcloud labelling step + elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].data_c[DATA_C_2_INDEX_OF_GROUND_REF_THAT_MADE_THE_LABEL] = + reference_index; } } //std::cout << "Observations for local tangent plane estimation extracted!" << std::endl; @@ -560,7 +567,7 @@ void CKf_Based_Terrain_Analysis::labelGroundPoints( std::vector<std::vector<kf_based_terrain_analysis_lib::Edge>> &discarded_edges) { //if (filtering_configuration.measure_performance) - CFunctionMonitor performance_monitor("labelGroundPoints", performance_supervisor_ptr_); + //CFunctionMonitor performance_monitor("labelGroundPoints", performance_supervisor_ptr_); pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr points_in_ROI(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr references_in_ROI(new pcl::PointCloud<pcl::PointXYZRGBNormal>); @@ -587,13 +594,143 @@ void CKf_Based_Terrain_Analysis::labelGroundPoints( // getchar(); } +// Just a try to optimize this function, it turned out to be slower :( +//void CKf_Based_Terrain_Analysis::generateElevationCloud( +// const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, +// pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_cloud_ptr, +// pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud, std::vector<std::vector<int>> &correspondence_indexes) +//{ +// //if (filtering_configuration.measure_performance) +// CFunctionMonitor performance_monitor("generateElevationCloud", performance_supervisor_ptr_); +// +// int i = 0; +// for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator it = pcl_cloud_ptr->begin(); it != pcl_cloud_ptr->end(); +// ++it) +// it->data_c[DATA_C_3_ORIGINAL_INDEX] = i++; +// +// // We want to find the x and y values, but not interested in z +// //std::cout << "Elevation grid resolution = " << filtering_configuration.elevation_grid_resolution << std::endl; +// pcl::VoxelGrid < pcl::PointXYZRGBNormal > voxel_grid; +// voxel_grid.setInputCloud(pcl_cloud_ptr); +// voxel_grid.setLeafSize(filtering_configuration.elevation_grid_resolution, +// filtering_configuration.elevation_grid_resolution, OUT_OF_RANGE); +// voxel_grid.filter(*elevation_cloud); +// //std::cout << "Number of points after voxelization = " << elevation_cloud->points.size() << std::endl; +// +// pcl::PassThrough < pcl::PointXYZRGBNormal > pass; +// pass.setInputCloud(pcl_cloud_ptr); +// +// i = 0; +// for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator it = elevation_cloud->begin(); it != elevation_cloud->end(); +// ++it) +// { +// float x_min, x_max, y_min, y_max, x_search_range, y_search_range; +// +// x_search_range = filtering_configuration.elevation_grid_resolution; +// y_search_range = filtering_configuration.elevation_grid_resolution; +// +// x_min = it->x - x_search_range; +// y_min = it->y - y_search_range; +// x_max = it->x + x_search_range; +// y_max = it->y + y_search_range; +// +// pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr points_in_cell(new pcl::PointCloud<pcl::PointXYZRGBNormal>); +// +// // Extracting lidar points +// pass.setFilterFieldName("x"); +// pass.setFilterLimits(x_min, x_max); +// pass.filter(*points_in_cell); +// pass.setInputCloud(points_in_cell); +// pass.setFilterFieldName("y"); +// pass.setFilterLimits(y_min, y_max); +// pass.filter(*points_in_cell); +// +// std::vector<int> pointIdxRadiusSearch; +// for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator cell_point_iterator = points_in_cell->begin(); +// cell_point_iterator != points_in_cell->end(); ++cell_point_iterator) +// { +// //std::cout << "id = " << cell_point_iterator->data_c[DATA_C_3_ORIGINAL_INDEX] << std::endl; +// pointIdxRadiusSearch.push_back(cell_point_iterator->data_c[DATA_C_3_ORIGINAL_INDEX]); +// } +// //std::cout << "Total number of points in cell = " << pointIdxRadiusSearch.size() << std::endl; +// +// std::vector<float> z_coordinates; +// std::vector<float> x_coordinates; +// std::vector<float> y_coordinates; +// +// bool outlier_detected = false; +// for (std::vector<int>::const_iterator iterator = pointIdxRadiusSearch.begin(); +// iterator != pointIdxRadiusSearch.end(); ++iterator) +// { +// //std::cout << "storing coordinates of point in cell with id = " << *iterator << std::endl; +// z_coordinates.push_back(pcl_cloud_ptr->points[*iterator].z); +// x_coordinates.push_back(pcl_cloud_ptr->points[*iterator].x); +// y_coordinates.push_back(pcl_cloud_ptr->points[*iterator].y); +// +// if (pcl_cloud_ptr->points[*iterator].data_c[DATA_C_1_ID_CLASS] == OUTLIER) +// outlier_detected = true; +// } +// +// if (outlier_detected) +// { +// //std::cout << "Outlier detected!" << std::endl; +// it->data_c[DATA_C_1_ID_CLASS] = OUTLIER; +// it->r = R_CLASS_OUTLIER; +// it->g = G_CLASS_OUTLIER; +// it->b = B_CLASS_OUTLIER; +// } +// else +// { +// //std::cout << "Not outlier, setting points to unknown class" << std::endl; +// it->data_c[DATA_C_1_ID_CLASS] = CLASS_UNKNOWN; +// it->r = R_CLASS_UNKNOWN; +// it->g = G_CLASS_UNKNOWN; +// it->b = B_CLASS_UNKNOWN; +// } +// +// //std::cout << "Computing cell statistics!" << std::endl; +// float sum = std::accumulate(z_coordinates.begin(), z_coordinates.end(), 0.0); +// float z_mean = sum / (float)z_coordinates.size(); +// float var = 0; +// for (int n = 0; n < z_coordinates.size(); ++n) +// var += ((z_coordinates[n] - z_mean) * (z_coordinates[n] - z_mean)); +// +// var /= (float)z_coordinates.size(); +// +// //std::cout << "Retrieving the position of the lowest point in cell..." << std::endl; +// std::vector<float>::iterator lowest_point_in_cell = std::min_element(z_coordinates.begin(), z_coordinates.end()); +// int position_in_vector = std::distance(z_coordinates.begin(), lowest_point_in_cell); +// +// it->z = z_coordinates[position_in_vector]; +// it->x = x_coordinates[position_in_vector]; +// it->y = y_coordinates[position_in_vector]; +// +// //std::cout << "Filling remaining fields" << std::endl; +// it->data_n[DATA_N_0_INTENSITY] = INTENSITY_UNKNOWN; +// it->data_n[DATA_N_1_Z_GROUND] = Z_GROUND_UNKNOWN; +// it->data_n[DATA_N_2_Z_MEAN] = z_mean; +// it->data_n[DATA_N_3_Z_VARIANCE] = var; +// +// it->data_c[DATA_C_2_CAR_PROB] = PROB_UNKNOWN; +// +// //std::cout << "storing the index for later in labelling step" << std::endl; +// it->data_c[DATA_C_3_ORIGINAL_INDEX] = i++; +// +// //std::cout << "var z = " << it->data_n[DATA_N_3_Z_VARIANCE] << std::endl; +// //std::cout << "z_coordinates.size() = " << z_coordinates.size() << std::endl; +// +// //std::cout << "storing the vector of indexes" << std::endl; +// correspondence_indexes.push_back(pointIdxRadiusSearch); +// } +//} + void CKf_Based_Terrain_Analysis::generateElevationCloud( const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_cloud_ptr, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud, std::vector<std::vector<int>> &correspondence_indexes) { //if (filtering_configuration.measure_performance) - CFunctionMonitor performance_monitor("generateElevationCloud", performance_supervisor_ptr_); + //CFunctionMonitor performance_monitor("generateElevationCloud", performance_supervisor_ptr_); pcl::PointCloud<pcl::PointXY>::Ptr pcl_pointcloud_2D_ptr(new pcl::PointCloud<pcl::PointXY>); pcl::PointXY point; @@ -605,19 +742,19 @@ void CKf_Based_Terrain_Analysis::generateElevationCloud( pcl_pointcloud_2D_ptr->points.push_back(point); } -//std::cout << "Number of points in pcl_pointcloud_2D_ptr = " << pcl_pointcloud_2D_ptr->points.size() << std::endl; + //std::cout << "Number of points in pcl_pointcloud_2D_ptr = " << pcl_pointcloud_2D_ptr->points.size() << std::endl; pcl::KdTreeFLANN < pcl::PointXY > kdtree_2D; kdtree_2D.setInputCloud(pcl_pointcloud_2D_ptr); -// We want to find the x and y values, but not interested in z -//std::cout << "Elevation grid resolution = " << filtering_configuration.elevation_grid_resolution << std::endl; + // We want to find the x and y values, but not interested in z + //std::cout << "Elevation grid resolution = " << filtering_configuration.elevation_grid_resolution << std::endl; pcl::VoxelGrid < pcl::PointXYZRGBNormal > voxel_grid; voxel_grid.setInputCloud(pcl_cloud_ptr); voxel_grid.setLeafSize(filtering_configuration.elevation_grid_resolution, filtering_configuration.elevation_grid_resolution, OUT_OF_RANGE); voxel_grid.filter(*elevation_cloud); -//std::cout << "Number of points after voxelization = " << elevation_cloud->points.size() << std::endl; + //std::cout << "Number of points after voxelization = " << elevation_cloud->points.size() << std::endl; const float DISTANCE_FROM_CELL_CENTER_TO_CELL_CORNER = 0.7071067812 * filtering_configuration.elevation_grid_resolution; //sqrt(2)/2.0 @@ -687,7 +824,7 @@ void CKf_Based_Terrain_Analysis::generateElevationCloud( it->data_n[DATA_N_2_Z_MEAN] = z_mean; it->data_n[DATA_N_3_Z_VARIANCE] = var; - it->data_c[DATA_C_2_CAR_PROB] = PROB_UNKNOWN; + it->data_c[DATA_C_2_INDEX_OF_GROUND_REF_THAT_MADE_THE_LABEL] = INDEX_UNKNOWN; it->data_c[DATA_C_3_ORIGINAL_INDEX] = i++; //storing the index for later in labelling step //std::cout << "var z = " << it->data_n[DATA_N_3_Z_VARIANCE] << std::endl; @@ -739,7 +876,7 @@ void CKf_Based_Terrain_Analysis::createDenseGroundCloud( pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_dense_cloud_ptr) { //if (filtering_configuration.measure_performance) - CFunctionMonitor performance_monitor("createDenseGroundCloud", performance_supervisor_ptr_); + CFunctionMonitor performance_monitor("createDenseGroundCloud", performance_supervisor_ptr_); //std::cout << "setting input cloud" << std::endl; pcl::KdTreeFLANN < pcl::PointXYZRGBNormal > kdtree; @@ -831,6 +968,229 @@ void CKf_Based_Terrain_Analysis::createDenseGroundCloud( //std::cout << "Finished dense cloud creation!!" << std::endl; } +void CKf_Based_Terrain_Analysis::fastLabelPointcloudUsingGroundModel( + const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, + const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud_ptr, + const std::vector<std::vector<int> > &correspondence_indexes, + const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr ground_reference_cloud_ptr, + const std::vector<std::vector<int>> &edges, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_cloud_ptr) +{ + //if (filtering_configuration.measure_performance) + //CFunctionMonitor performance_monitor("labelPointcloudUsingGroundModel", performance_supervisor_ptr_); + //std::cout << "Labeling points in the original pointcloud using the posterior and the ROI indexes vectors..." + // << std::endl; + for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator i = elevation_cloud_ptr->begin(); + i != elevation_cloud_ptr->end(); ++i) + { + pcl::PointXYZRGBNormal point_in_sensor_frame = *i; + + bool elevation_cloud_point_is_ground = false; + if ((int)std::floor(point_in_sensor_frame.data_c[DATA_C_1_ID_CLASS]) == CLASS_GROUND) + elevation_cloud_point_is_ground = true; + + bool elevation_cloud_point_is_not_predictable_using_the_model = false; + int reference_index = (int)std::floor( + point_in_sensor_frame.data_c[DATA_C_2_INDEX_OF_GROUND_REF_THAT_MADE_THE_LABEL]); + if (reference_index == INDEX_UNKNOWN) + elevation_cloud_point_is_not_predictable_using_the_model = true; + + if (!elevation_cloud_point_is_not_predictable_using_the_model) + { + pcl::PointXYZRGBNormal reference_in_sensor_frame = ground_reference_cloud_ptr->points[reference_index]; + if (elevation_cloud_point_is_ground) //&& sqrt(reference_in_sensor_frame.data_c[GRND_REF_DATA_C_3_Z_VARIANCE]) < 0.06) //TODO!!! + { + // If the lowest point is ground we need to check one by one the rest of points in the cell + // In case we find not-overhanging obstacles in its cell, we will classify the lowest point in cell also as obstacle + bool flag_not_overhanging_obstacle_found = false; + + // 1) We point to the vector of indices related to the elevation_cloud point under evaluation + std::vector<std::vector<int>>::const_iterator index_iterator = correspondence_indexes.begin() + + point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]; + + // and iterate over this vector + for (std::vector<int>::const_iterator point_iterator = index_iterator->begin(); + point_iterator != index_iterator->end(); ++point_iterator) + { + bool observation_z_is_below_prediction = false; + float prediction_std_dev = -1.0; + float mahalanobis_distance = mahalanobisDistance(reference_in_sensor_frame, + pcl_cloud_ptr->points[*point_iterator], prediction_std_dev, + observation_z_is_below_prediction); + if (std::isnan(mahalanobis_distance)) + { + std::cout << "posterior pred sigma = " << prediction_std_dev << " uncertainty = " + << prediction_std_dev * filtering_configuration.mahalanobis_threshold << " mahalanobis distance = " + << mahalanobis_distance << std::endl; + + std::getchar(); + } + + if (mahalanobis_distance < filtering_configuration.mahalanobis_threshold) + { + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_1_Z_GROUND] = pcl_cloud_ptr->points[*point_iterator].z; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_2_Z_MEAN] = + point_in_sensor_frame.data_n[DATA_N_2_Z_MEAN]; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_3_Z_VARIANCE] = + point_in_sensor_frame.data_n[DATA_N_3_Z_VARIANCE]; + + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_GROUND; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_GROUND; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_GROUND; + + float score = 0.99 - (mahalanobis_distance / filtering_configuration.mahalanobis_threshold); + if (score < 0.0) + score = 0.0; + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_GROUND + score; + // data_c[2] is reserved for Car probability, as we do not estimate it in this algorithm we leave this value untouched + // so if there are others segmentators working out there, we do not erase their job! + + // data_c[3] is reserved to store the original index, so we do not want to change it! + } + else + { + //std::cout << "obstacle z distance from ground = " << pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z << std::endl; + + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_1_Z_GROUND] = point_in_sensor_frame.z; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_2_Z_MEAN] = + point_in_sensor_frame.data_n[DATA_N_2_Z_MEAN]; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_3_Z_VARIANCE] = + point_in_sensor_frame.data_n[DATA_N_3_Z_VARIANCE]; + + //std::cout << "obstacle z distance from ground = " << pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z << std::endl; + if ((pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z) + < filtering_configuration.robot_height) + { + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_OBSTACLE; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_OBSTACLE; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_OBSTACLE; + + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_OBSTACLE + 0.99; + + flag_not_overhanging_obstacle_found = true; + } + else + { + //std::cout << "Overhanging obstacle detected!" << std::endl; + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_OVERHANGING_OBSTACLE; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_OVERHANGING_OBSTACLE; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_OVERHANGING_OBSTACLE; + + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_OVERHANGING_OBSTACLE + + 0.99; + // data_c[2] is reserved for Car probability, as we do not estimate it in this algorithm we leave this value untouched + // so if there are others segmentators working out there, we do not erase their job! + + // data_c[3] is reserved to store the original index, so we do not want to change it! + } + } + } + } + else // If the lowest point in cell is already an obstacle, the remaining points are also obstacles + { + //std::cout << "Labeling all points in cell as obstacle!" << std::endl; + // 1) We point to the vector of indices related to the elevation_cloud point under evaluation + std::vector<std::vector<int>>::const_iterator index_iterator = correspondence_indexes.begin() + + point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]; + + for (std::vector<int>::const_iterator point_iterator = index_iterator->begin(); + point_iterator != index_iterator->end(); ++point_iterator) + { + // Intensity is already in the pointcloud so we do not copy data_n[0] (in fact this value is not present in elevation cloud) + float z_ground = i->z; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_1_Z_GROUND] = z_ground; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_2_Z_MEAN] = + point_in_sensor_frame.data_n[DATA_N_2_Z_MEAN]; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_3_Z_VARIANCE] = + point_in_sensor_frame.data_n[DATA_N_3_Z_VARIANCE]; + + //std::cout << "obstacle z distance from ground = " << pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z << std::endl; + if ((pcl_cloud_ptr->points[*point_iterator].z - z_ground) < filtering_configuration.robot_height) + { + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_OBSTACLE; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_OBSTACLE; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_OBSTACLE; + + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_OBSTACLE + 0.99; + } + else + { + //std::cout << "Overhanging obstacle detected!" << std::endl; + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_OVERHANGING_OBSTACLE; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_OVERHANGING_OBSTACLE; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_OVERHANGING_OBSTACLE; + + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_OVERHANGING_OBSTACLE + 0.99; + // data_c[2] is reserved for Car probability, as we do not estimate it in this algorithm we leave this value untouched + // so if there are others segmentators working out there, we do not erase their job! + + // data_c[3] is reserved to store the original index, so we do not want to change it! + } + } + } + } + else // if we don't have enough information to try to predict the ground level at this point + { + std::vector<std::vector<int>>::const_iterator index_iterator = correspondence_indexes.begin() + + point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]; + + if (filtering_configuration.classify_not_labeled_points_as_obstacles) + { + for (std::vector<int>::const_iterator point_iterator = index_iterator->begin(); + point_iterator != index_iterator->end(); ++point_iterator) + { + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_1_Z_GROUND] = point_in_sensor_frame.z; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_2_Z_MEAN] = + point_in_sensor_frame.data_n[DATA_N_2_Z_MEAN]; + pcl_cloud_ptr->points[*point_iterator].data_n[DATA_N_3_Z_VARIANCE] = + point_in_sensor_frame.data_n[DATA_N_3_Z_VARIANCE]; + + //std::cout << "obstacle z distance from ground = " << pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z << std::endl; + if ((pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z) + < filtering_configuration.ground_threshold_in_not_analyzed_areas) + { + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_GROUND; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_GROUND; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_GROUND; + + float score = 0.01; // we don't have too much confidence in these points, because they are not analyzed + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_GROUND + score; + } + else if ((pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z) + < filtering_configuration.robot_height) + { + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_OBSTACLE; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_OBSTACLE; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_OBSTACLE; + + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_OBSTACLE + 0.99; + } + else + { + //std::cout << "Overhanging obstacle detected!" << std::endl; + // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it + pcl_cloud_ptr->points[*point_iterator].r = R_CLASS_OVERHANGING_OBSTACLE; // We use instead the r g b channels directly + pcl_cloud_ptr->points[*point_iterator].g = G_CLASS_OVERHANGING_OBSTACLE; + pcl_cloud_ptr->points[*point_iterator].b = B_CLASS_OVERHANGING_OBSTACLE; + + pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_OVERHANGING_OBSTACLE + 0.99; + // data_c[2] is reserved for Car probability, as we do not estimate it in this algorithm we leave this value untouched + // so if there are others segmentators working out there, we do not erase their job! + + // data_c[3] is reserved to store the original index, so we do not want to change it! + } + } + } + } + } + //std::cout << "Labeling concluded!" << std::endl; +} + void CKf_Based_Terrain_Analysis::labelPointcloudUsingGroundModel( const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud_ptr, @@ -839,7 +1199,7 @@ void CKf_Based_Terrain_Analysis::labelPointcloudUsingGroundModel( const std::vector<std::vector<int>> &edges, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pcl_cloud_ptr) { //if (filtering_configuration.measure_performance) - CFunctionMonitor performance_monitor("labelPointcloudUsingGroundModel", performance_supervisor_ptr_); + //CFunctionMonitor performance_monitor("labelPointcloudUsingGroundModel", performance_supervisor_ptr_); //std::cout << "Labeling points in the original pointcloud using the posterior and the ROI indexes vectors..." // << std::endl; for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator i = elevation_cloud_ptr->begin(); @@ -925,7 +1285,7 @@ void CKf_Based_Terrain_Analysis::labelPointcloudUsingGroundModel( { pcl::PointXYZRGBNormal reference_in_sensor_frame = ground_reference_cloud_ptr->points[pointIdxKNNSearch[best_reference_index]]; - if (elevation_cloud_point_is_ground)//&& sqrt(reference_in_sensor_frame.data_c[GRND_REF_DATA_C_3_Z_VARIANCE]) < 0.06) //TODO!!! + if (elevation_cloud_point_is_ground) //&& sqrt(reference_in_sensor_frame.data_c[GRND_REF_DATA_C_3_Z_VARIANCE]) < 0.06) //TODO!!! { //std::cout << "std_dev_z = " << sqrt(reference_in_sensor_frame.data_c[GRND_REF_DATA_C_3_Z_VARIANCE]) << std::endl; // We classify the elevation cloud point as ground @@ -1126,7 +1486,7 @@ void CKf_Based_Terrain_Analysis::labelPointcloudUsingGroundModel( float score = 0.01; // we don't have too much confidence in these points, because they are not analyzed pcl_cloud_ptr->points[*point_iterator].data_c[DATA_C_1_ID_CLASS] = (float)CLASS_GROUND + score; } - else if((pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z) + else if ((pcl_cloud_ptr->points[*point_iterator].z - point_in_sensor_frame.z) < filtering_configuration.robot_height) { // data_c[0] is reserved to cast the RGB values into a float (PCL convention) so we do not use it @@ -1236,9 +1596,17 @@ void CKf_Based_Terrain_Analysis::groundSegmentation( // to be sure that connections are reflected in both ends ensureThatConnectionsAreReflectedInBothEnds(ground_reference_cloud_ptr, edges); - labelPointcloudUsingGroundModel(filtering_configuration, elevation_cloud_ptr, correspondence_indexes, - ground_reference_cloud_ptr, edges, pcl_cloud_ptr); - + if (filtering_configuration.number_of_references_used_for_labelling > 0) + { + labelPointcloudUsingGroundModel(filtering_configuration, elevation_cloud_ptr, correspondence_indexes, + ground_reference_cloud_ptr, edges, pcl_cloud_ptr); + } + else + { + //std::cout << "Using fast labelling function!" << std::endl; + fastLabelPointcloudUsingGroundModel(filtering_configuration, elevation_cloud_ptr, correspondence_indexes, + ground_reference_cloud_ptr, edges, pcl_cloud_ptr); + } // Dense reconstruction aims to serve as debugging or visualizing tool, it generates an XY regular grid with predicted // Z values using the closest reference point -- GitLab