diff --git a/include/kf_based_terrain_analysis.h b/include/kf_based_terrain_analysis.h index 6a1f953092d3262ecbe1ee1f9b54d5e89b34c891..4903f87092e6b98dc0dbcb950a32ead846c476d7 100644 --- a/include/kf_based_terrain_analysis.h +++ b/include/kf_based_terrain_analysis.h @@ -49,6 +49,11 @@ private: pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud, std::vector<std::vector<int>> &correspondence_indexes); + void fastGenerateElevationCloud(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); + void labelGroundPoints(const kf_based_terrain_analysis_lib::SensorConfiguration lidar_configuration, const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, const std::vector<std::vector<int> > &correspondence_indexes, const int reference_index, @@ -84,16 +89,14 @@ private: 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); + 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); + 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, diff --git a/include/structs_definitions.h b/include/structs_definitions.h index 00feb6e2fe1df3fc9c68e878aa3766dd1b8c626d..6c24cb040b60caa012904294f0a793434a3d9279 100644 --- a/include/structs_definitions.h +++ b/include/structs_definitions.h @@ -166,5 +166,13 @@ struct Edge int edge_class; }; +struct ElevationCloudCell +{ + pcl::PointXYZRGBNormal lowest_point_in_cell; + int index_of_lowest_point; + std::vector<int> indexes_of_points_in_cell; + std::vector<float> z_coordinates; +}; + } #endif /* INCLUDE_STRUCTS_DEFINITIONS_H_ */ diff --git a/src/kf_based_terrain_analysis.cpp b/src/kf_based_terrain_analysis.cpp index 66baf5323daf6d2bf5f0433fcee5be78abdb40e7..978c8635a5c520503d41a3e432305a2bb29b9417 100644 --- a/src/kf_based_terrain_analysis.cpp +++ b/src/kf_based_terrain_analysis.cpp @@ -314,9 +314,9 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( filtering_configuration.propagation_additive_noise, filtering_configuration.propagation_z_additive_noise); - //std::cout << "Reference_index = " << reference_index << std::endl; - //std::cout << "Using reference with ID = " - // << ground_reference_cloud_ptr->points[reference_index].data_n[GRND_REF_DATA_N_3_ORIGINAL_INDEX] << std::endl; +// std::cout << "Reference_index = " << reference_index << std::endl; +// std::cout << "Using reference with ID = " +// << ground_reference_cloud_ptr->points[reference_index].data_n[GRND_REF_DATA_N_3_ORIGINAL_INDEX] << std::endl; pcl::PointXYZRGBNormal reference_in_sensor_frame = ground_reference_cloud_ptr->points[reference_index]; pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr observations_for_tangent_plane_estimation( @@ -324,17 +324,17 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( // points in ROI come from elevation pointcloud, which is a reduction of the original // pointcloud (we have stored the indexes to be able to label the original pointcloud) - //std::cout << "Extracting observations for local tangent plane estimation..." << std::endl; +// std::cout << "Extracting observations for local tangent plane estimation..." << std::endl; for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator i = points_in_ROI->begin(); i != points_in_ROI->end(); ++i) { pcl::PointXYZRGBNormal point_in_sensor_frame = *i; float prediction_std_dev = -1.0; - //std::cout << "Computing mahalanobis distance..." << std::endl; +// std::cout << "Computing mahalanobis distance..." << std::endl; float mahalanobis_distance = mahalanobisDistance(reference_in_sensor_frame, point_in_sensor_frame, prediction_std_dev); - //std::cout << "Mahalanobis distance computed!" << std::endl; +// std::cout << "Mahalanobis distance computed!" << std::endl; if (std::isnan(mahalanobis_distance)) { std::cout << "prior pred sigma = " << prediction_std_dev << " uncertainty = " @@ -350,17 +350,17 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( // << " z = " << point_in_sensor_frame.z << std::endl << "mahalanobis_distance = " << mahalanobis_distance // << " mahalanobis_threshold = " << filtering_configuration.mahalanobis_threshold << std::endl; - //std::cout << "Inserting observation for plane estimation!" << std::endl; +// std::cout << "Inserting observation for plane estimation!" << std::endl; observations_for_tangent_plane_estimation->push_back(point_in_sensor_frame); // independently of exploration, any ground point is // used for plane estimation, to no discard useful // information! if ((int)std::floor(point_in_sensor_frame.data_c[DATA_C_1_ID_CLASS]) == CLASS_UNKNOWN) // we use unknown points to drive the exploration { - //std::cout << "Inserting observation to drive exploration! --> original index = " - // << point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX] << std::endl; +// std::cout << "Inserting observation to drive exploration! --> original index = " +// << point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX] << std::endl; - //std::cout << "elevation_cloud_ptr->points.size() = " << elevation_cloud_ptr->points.size() << std::endl; +// std::cout << "elevation_cloud_ptr->points.size() = " << elevation_cloud_ptr->points.size() << std::endl; new_references_creator.addGroundObservationInSensorFrame( reference_in_sensor_frame, @@ -375,7 +375,7 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( float index_of_labelling_ref = 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]; - //std::cout << "Updating elevation cloud point to represent ground data" << std::endl; +// std::cout << "Updating elevation cloud point to represent ground data" << std::endl; if ((int)std::floor(point_in_sensor_frame.data_c[DATA_C_1_ID_CLASS]) != CLASS_GROUND || std::floor((int)index_of_labelling_ref) == INDEX_UNKNOWN || index_of_labelling_ref - std::floor((int)index_of_labelling_ref) < score) // if the point was seen as obstacle from another POV @@ -387,7 +387,7 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( if ((int)std::floor(point_in_sensor_frame.data_c[DATA_C_1_ID_CLASS]) != CLASS_GROUND) { - //std::cout << "Storing z point as z ground" << std::endl; +// std::cout << "Storing z point as z ground" << std::endl; // as now the point is classified as ground, we store its own z value as z ground elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].data_n[DATA_N_1_Z_GROUND] = elevation_cloud_ptr->points[point_in_sensor_frame.data_c[DATA_C_3_ORIGINAL_INDEX]].z; @@ -405,9 +405,9 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( } else { - //std::cout << "Obstacle point found! x = " << point_in_sensor_frame.x << " y = " << point_in_sensor_frame.y - // << " z = " << point_in_sensor_frame.z << std::endl << "mahalanobis_distance = " << mahalanobis_distance - // << " mahalanobis_threshold = " << filtering_configuration.mahalanobis_threshold << std::endl; +// std::cout << "Obstacle point found! x = " << point_in_sensor_frame.x << " y = " << point_in_sensor_frame.y +// << " z = " << point_in_sensor_frame.z << std::endl << "mahalanobis_distance = " << mahalanobis_distance +// << " mahalanobis_threshold = " << filtering_configuration.mahalanobis_threshold << std::endl; if ((int)std::floor(point_in_sensor_frame.data_c[DATA_C_1_ID_CLASS]) != CLASS_GROUND) // we don't want to convert ground points to obstacles // because of the POV (one thing can be seem as obstacle or ground depending on the POV) @@ -443,7 +443,7 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( } } } - //std::cout << "Observations for local tangent plane estimation extracted!" << std::endl; +// std::cout << "Observations for local tangent plane estimation extracted!" << std::endl; //std::cout << "Reference Prior = " << std::endl; //std::cout << "x = " << ground_reference_cloud_ptr->points[reference_index].x << " y = " @@ -460,10 +460,10 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( // << sqrt(ground_reference_cloud_ptr->points[reference_index].data_n[GRND_REF_DATA_N_1_PITCH_VARIANCE]) * 180.0 // / M_PI << " )" << std::endl; - //std::cout << "Estimating tangent plane..." << std::endl; +// std::cout << "Estimating tangent plane..." << std::endl; estimateTangentPlane(observations_for_tangent_plane_estimation, (double)filtering_configuration.z_observation_std_dev, reference_in_sensor_frame); - //std::cout << "Posterior distribution obtained!" << std::endl; +// std::cout << "Posterior distribution obtained!" << std::endl; ground_reference_cloud_ptr->points[reference_index] = reference_in_sensor_frame; @@ -482,17 +482,17 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( // << sqrt(ground_reference_cloud_ptr->points[reference_index].data_n[GRND_REF_DATA_N_1_PITCH_VARIANCE]) * 180.0 // / M_PI << " )" << std::endl; - //std::cout << "Creating new references..." << std::endl; +// std::cout << "Creating new references..." << std::endl; new_references_creator.generateNewGroundReferences(reference_index, reference_in_sensor_frame, ground_reference_cloud_ptr, edges); - //std::cout << "New references created!" << std::endl; +// std::cout << "New references created!" << std::endl; - //std::cout << "Search for references in the ROI..." << std::endl; +// std::cout << "Search for references in the ROI..." << std::endl; extractPointsInROI(lidar_configuration, filtering_configuration, ground_reference_cloud_ptr->points[reference_index], ground_reference_cloud_ptr, references_in_ROI); - //std::cout << "Search concluded! Number of references in ROI = " << references_in_ROI->size() << std::endl; +// std::cout << "Search concluded! Number of references in ROI = " << references_in_ROI->size() << std::endl; - //std::cout << "Making edges to existing references in the ROI... " << std::endl; +// std::cout << "Making edges to existing references in the ROI... " << std::endl; int num_of_discarded_edges = 0; for (pcl::PointCloud<pcl::PointXYZRGBNormal>::iterator i = references_in_ROI->begin(); i != references_in_ROI->end(); ++i) @@ -531,7 +531,7 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( std::getchar(); } - //std::cout << "Checking connections..." << std::endl; +// std::cout << "Checking connections..." << std::endl; bool connect = true; int edge_class = CLASS_EDGE_ACCEPTED; @@ -571,11 +571,9 @@ void CKf_Based_Terrain_Analysis::labelLocalGroundPoints( // << reference_in_ROI.data_n[GRND_REF_DATA_N_3_ORIGINAL_INDEX] << std::endl; } } - //std::cout << "Total edges evaluated = " << references_in_ROI->points.size() << " discarded = " - // << num_of_discarded_edges << std::endl; +// std::cout << "Total edges evaluated = " << references_in_ROI->points.size() << " discarded = " +// << num_of_discarded_edges << std::endl; //getchar(); -// new_references_creator.generateNewGroundReferences(reference_index, reference_in_sensor_frame, -// ground_reference_cloud_ptr, edges); } void CKf_Based_Terrain_Analysis::labelGroundPoints( @@ -609,7 +607,7 @@ void CKf_Based_Terrain_Analysis::labelGroundPoints( labelLocalGroundPoints(lidar_configuration, filtering_configuration, correspondence_indexes, reference_index, points_in_ROI, references_in_ROI, ground_reference_cloud_ptr, elevation_cloud_ptr, cloud_ptr, edges, discarded_edges); - //std::cout << "Local ground points labeled!" << std::endl; +// std::cout << "Local ground points labeled!" << std::endl; // std::cout << "Number of edges after labeling = " << edges[reference_index].size() << std::endl; // getchar(); @@ -725,6 +723,108 @@ void CKf_Based_Terrain_Analysis::generateElevationCloud( } } +void CKf_Based_Terrain_Analysis::fastGenerateElevationCloud( + 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 number_of_rows_and_columns = std::ceil(2.0 * MAX_RANGE / filtering_configuration.elevation_grid_resolution); + //std::cout << "number_of_rows_and_columns = " << number_of_rows_and_columns << std::endl; + + kf_based_terrain_analysis_lib::ElevationCloudCell elevation_map[number_of_rows_and_columns][number_of_rows_and_columns]; + //std::cout << "elevation_map created! " << std::endl; + + int i = 0; + //std::cout << "Starting to fill the elevation_map! " << std::endl; + for (pcl::PointCloud<pcl::PointXYZRGBNormal>::const_iterator it = pcl_cloud_ptr->begin(); it != pcl_cloud_ptr->end(); + ++it) + { + int row = std::round((number_of_rows_and_columns / 2.0) + (it->x / filtering_configuration.elevation_grid_resolution)); + int col = std::round((number_of_rows_and_columns / 2.0) + (it->y / filtering_configuration.elevation_grid_resolution)); + + if(elevation_map[row][col].indexes_of_points_in_cell.empty()) + { + //std::cout << "Pointing to an empty cell, storing current point as lowest, and keeping its index! " << std::endl; + //std::cout << "Point number " << i << " row = " << row << " col = " << col << std::endl; + elevation_map[row][col].lowest_point_in_cell = *it; + elevation_map[row][col].index_of_lowest_point = i; + } + else + { + //std::cout << "Pointing to a NON-empty cell! checking z!" << std::endl; + if(it->z < elevation_map[row][col].lowest_point_in_cell.z) + { + //std::cout << "Current point is the lowest, storing it as it is!" << std::endl; + elevation_map[row][col].lowest_point_in_cell = *it; + elevation_map[row][col].index_of_lowest_point = i; + } + } + //std::cout << "Storing z coordinate and index in the indexes vector" << std::endl; + elevation_map[row][col].z_coordinates.push_back(it->z); + elevation_map[row][col].indexes_of_points_in_cell.push_back(i); + i++; + } + + //std::cout << "Now generating the elevation cloud from the elevation map!" << std::endl; + //DEBUG + //int total_number_of_points_stored = 0; + int index_respect_elevation_cloud = 0; + for(int row = 0; row < number_of_rows_and_columns; ++row) + { + for(int col = 0; col < number_of_rows_and_columns; ++col) + { + if(!elevation_map[row][col].indexes_of_points_in_cell.empty()) + { + pcl::PointXYZRGBNormal elevation_cloud_point = elevation_map[row][col].lowest_point_in_cell; + if (elevation_cloud_point.data_c[DATA_C_1_ID_CLASS] == OUTLIER) + { + elevation_cloud_point.r = R_CLASS_OUTLIER; + elevation_cloud_point.g = G_CLASS_OUTLIER; + elevation_cloud_point.b = B_CLASS_OUTLIER; + } + else + { + elevation_cloud_point.r = R_CLASS_UNKNOWN; + elevation_cloud_point.g = G_CLASS_UNKNOWN; + elevation_cloud_point.b = B_CLASS_UNKNOWN; + } + float sum = std::accumulate(elevation_map[row][col].z_coordinates.begin(), elevation_map[row][col].z_coordinates.end(), 0.0); + float z_mean = sum / (float)elevation_map[row][col].z_coordinates.size(); + float var = 0; + for (int n = 0; n < elevation_map[row][col].z_coordinates.size(); ++n) + var += ((elevation_map[row][col].z_coordinates[n] - z_mean) * (elevation_map[row][col].z_coordinates[n] - z_mean)); + + var /= (float)elevation_map[row][col].z_coordinates.size(); + + // Filling remaining fields + elevation_cloud_point.data_n[DATA_N_0_INTENSITY] = INTENSITY_UNKNOWN; + elevation_cloud_point.data_n[DATA_N_1_Z_GROUND] = Z_GROUND_UNKNOWN; + elevation_cloud_point.data_n[DATA_N_2_Z_MEAN] = z_mean; + elevation_cloud_point.data_n[DATA_N_3_Z_VARIANCE] = var; + + elevation_cloud_point.data_c[DATA_C_2_INDEX_OF_GROUND_REF_THAT_MADE_THE_LABEL] = INDEX_UNKNOWN; + elevation_cloud_point.data_c[DATA_C_3_ORIGINAL_INDEX] = index_respect_elevation_cloud++; //storing the index for later in labelling step + + //std::cout << "var z = " << it->data_n[DATA_N_3_Z_VARIANCE] << std::endl; + //std::cout << "z_coordinates.size() = " << z_coordinates.size() << std::endl; + + //DEBUG! + //total_number_of_points_stored += elevation_map[row][col].indexes_of_points_in_cell.size(); + + correspondence_indexes.push_back(elevation_map[row][col].indexes_of_points_in_cell); + //std::cout << "Storing point into elevation cloud!" << std::endl; + elevation_cloud->push_back(elevation_cloud_point); + } + } + } +// std::cout << "elevation_cloud generated!!" << std::endl; +// //std::cout << "total_number_of_points_stored = " << total_number_of_points_stored << std::endl; +// //std::cout << "original number of points = " << pcl_cloud_ptr->points.size() << std::endl; +} + void CKf_Based_Terrain_Analysis::generateRootVertex( const kf_based_terrain_analysis_lib::SensorConfiguration lidar_configuration, const kf_based_terrain_analysis_lib::FilteringConfiguration filtering_configuration, @@ -1448,11 +1548,17 @@ void CKf_Based_Terrain_Analysis::groundSegmentation( pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr elevation_cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGBNormal>); std::vector < std::vector<int> > correspondence_indexes; - generateElevationCloud(filtering_configuration, pcl_cloud_ptr, elevation_cloud_ptr, correspondence_indexes); + fastGenerateElevationCloud(filtering_configuration, pcl_cloud_ptr, elevation_cloud_ptr, correspondence_indexes); //std::cout << "Elevation cloud generated! Npoints = " << elevation_cloud_ptr->points.size() << std::endl; +// pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr fast_elevation_cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGBNormal>); +// std::vector < std::vector<int> > fast_correspondence_indexes; +// +// fastGenerateElevationCloud(filtering_configuration, pcl_cloud_ptr, fast_elevation_cloud_ptr, fast_correspondence_indexes); +// std::cout << "Fast Elevation cloud generated! Npoints = " << fast_elevation_cloud_ptr->points.size() << std::endl; + generateRootVertex(lidar_configuration, filtering_configuration, ground_reference_cloud_ptr); - //std::cout << "Root vertex generated! Num of points = " << ground_reference_cloud_ptr->points.size() << std::endl + //std::cout << "Root vertex generated! Num of points = " << ground_reference_cloud_ptr->points.size() << std::endl; // << "Number of edges = " << edges[0].size() << std::endl; //getchar();