From e2e4bd5fff4a614bea5cada98b0a15fc7de52077 Mon Sep 17 00:00:00 2001 From: idelpino <telecosg@gmail.com> Date: Wed, 8 May 2024 18:39:10 +0200 Subject: [PATCH] Added mean filter for near range cells in low obstacle detection algorithm --- params/ONA2_iri_ground_segmentation.yaml | 6 +-- src/ground_segmentation_alg_node.cpp | 64 +++++++++++++++++++----- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/params/ONA2_iri_ground_segmentation.yaml b/params/ONA2_iri_ground_segmentation.yaml index 8bb4e7a..d4d5483 100644 --- a/params/ONA2_iri_ground_segmentation.yaml +++ b/params/ONA2_iri_ground_segmentation.yaml @@ -2,7 +2,7 @@ iri_ground_segmentation: { rate: 10.00, # Robot related geometric parameters - sensor_height: 0.3, ## Ground is expected to be at z = -1*sensor_height + sensor_height: 0.21, ## Ground is expected to be at z = -1*sensor_height robot_height: 1.5, ## All obstacle points above this value (w.r.t the z ground predicted by the algorithm) are treated as overhanging obstacles # Parameters affecting the exploration of the pointcloud @@ -21,7 +21,7 @@ iri_ground_segmentation: { # Kalman filter noise parameters ## initial uncertainties - z_initial_std_dev: 0.05, ## Uncertainty in z = -1*sensor_height + z_initial_std_dev: 0.02, ## Uncertainty in z = -1*sensor_height initial_angular_std_dev_deg: 1.5, ## Used to initialize x_slope and y_slope variances ## propagation additive noises @@ -53,7 +53,7 @@ iri_ground_segmentation: { # low obstacle detection parameters use_low_obstacle_detection: true, - low_obstacle_min_height: 0.07, + low_obstacle_min_height: 0.05, sensor_best_resolution_deg: 0.2, # Best resolution, either horizontal or vertical max_navigation_slope: 0.3, diff --git a/src/ground_segmentation_alg_node.cpp b/src/ground_segmentation_alg_node.cpp index 4c9f07b..d2052ca 100644 --- a/src/ground_segmentation_alg_node.cpp +++ b/src/ground_segmentation_alg_node.cpp @@ -608,7 +608,8 @@ void GroundSegmentationAlgNode::convertOutputsToSuitableFormats(void) this->PCLPointCloudToRosPointCloud(lidar_pcl_cloud_, lidar_points_ground_segmented_ros_cloud_); - this->PCLPointCloudToRosPointCloud(evaluated_segmentation_pointcloud_pcl_cloud_, evaluated_segmentation_pointcloud_ros_cloud_); + this->PCLPointCloudToRosPointCloud(evaluated_segmentation_pointcloud_pcl_cloud_, + evaluated_segmentation_pointcloud_ros_cloud_); this->PCLPointCloudToRosPointCloud(ground_dense_reconstruction_pcl_cloud_, ground_dense_reconstruction_ros_cloud_); @@ -683,11 +684,10 @@ void GroundSegmentationAlgNode::showPerformanceStatistics(void) evaluation_metrics_.rec = (float)evaluation_metrics_.tp / (float)(evaluation_metrics_.tp + evaluation_metrics_.fn); evaluation_metrics_.f1 = (2.0 * evaluation_metrics_.prec * evaluation_metrics_.rec) - / (evaluation_metrics_.prec + evaluation_metrics_.rec); + / (evaluation_metrics_.prec + evaluation_metrics_.rec); evaluation_metrics_.iou = (float)evaluation_metrics_.tp - / (float)(evaluation_metrics_.tp + evaluation_metrics_.fp - + evaluation_metrics_.fn); + / (float)(evaluation_metrics_.tp + evaluation_metrics_.fp + evaluation_metrics_.fn); evaluation_metrics_.acc = (float)(evaluation_metrics_.tp + evaluation_metrics_.tn) / (float)(evaluation_metrics_.tp + evaluation_metrics_.tn + evaluation_metrics_.fp + evaluation_metrics_.fn); @@ -703,7 +703,7 @@ void GroundSegmentationAlgNode::showPerformanceStatistics(void) std::cout << "FN = " << evaluation_metrics_.fn << std::endl; std::cout << "Precision = " << evaluation_metrics_.prec << std::endl; - std::cout << "Recall = " << evaluation_metrics_.rec << std::endl; + std::cout << "Recall = " << evaluation_metrics_.rec << std::endl; std::cout << "F1 = " << evaluation_metrics_.f1 << std::endl; std::cout << "Acc = " << evaluation_metrics_.acc << std::endl; @@ -714,12 +714,16 @@ void GroundSegmentationAlgNode::showPerformanceStatistics(void) struct Cell { - float z_min, z_max; + bool is_near = false; + float z_min, z_max = -1000.0; + std::vector<float> z_coordinates; int label = -1; // -1 uninitialized, 0 traversable, 1 obstacle }; void GroundSegmentationAlgNode::detectLowObstacles(float h, float res_deg, float alpha) { + float near_range_thres = 1.75; // TODO: Extract this parameter! + //std::cout << "Starting detectLowObstacles function!" << std::endl; float res = res_deg * M_PI / 180.0; float r_max = h / alpha; @@ -728,11 +732,11 @@ void GroundSegmentationAlgNode::detectLowObstacles(float h, float res_deg, float float cell_side = r_max / sqrt(8.0); // This comes from here: sqrt((r_max/2)^2 / 2) int num_of_cells = (d_max * 2.0 / cell_side); -// std::cout << "r_max = " << r_max << std::endl; -// std::cout << "K = " << K << std::endl; -// std::cout << "d_max = " << d_max << std::endl; -// std::cout << "cell_side = " << cell_side << std::endl; -// std::cout << "num_of_cells = " << num_of_cells << std::endl; + std::cout << "r_max = " << r_max << std::endl; + std::cout << "K = " << K << std::endl; + std::cout << "d_max = " << d_max << std::endl; + std::cout << "cell_side = " << cell_side << std::endl; + std::cout << "num_of_cells = " << num_of_cells << std::endl; std::vector < std::vector < Cell >> grid(num_of_cells, std::vector < Cell > (num_of_cells)); @@ -744,8 +748,13 @@ void GroundSegmentationAlgNode::detectLowObstacles(float h, float res_deg, float int x = i->x / cell_side + num_of_cells / 2.0; int y = i->y / cell_side + num_of_cells / 2.0; //std::cout << "x cell number = " << x << " y cell number = " << y << std::endl; + if (x >= 0 && x < num_of_cells && y >= 0 && y < num_of_cells) { + if (sqrt(i->x * i->x + i->y * i->y) < near_range_thres) + grid[x][y].is_near = true; + + grid[x][y].z_coordinates.push_back(i->z); if (grid[x][y].label == -1) { grid[x][y].z_min = grid[x][y].z_max = i->z; @@ -766,6 +775,13 @@ void GroundSegmentationAlgNode::detectLowObstacles(float h, float res_deg, float { if (grid[i][j].label != -1) { + float sum = std::accumulate(grid[i][j].z_coordinates.begin(), grid[i][j].z_coordinates.end(), 0.0); + float z_mean = sum / grid[i][j].z_coordinates.size(); + +// std::cout << "z_max - z_min = " << grid[i][j].z_max - grid[i][j].z_min +// << " z_mean = " << z_mean << " Total points = " +// << grid[i][j].z_coordinates.size() << std::endl; + for (int dx = -1; dx <= 1; ++dx) { for (int dy = -1; dy <= 1; ++dy) @@ -773,7 +789,28 @@ void GroundSegmentationAlgNode::detectLowObstacles(float h, float res_deg, float int nx = i + dx, ny = j + dy; if (nx >= 0 && nx < num_of_cells && ny >= 0 && ny < num_of_cells && grid[nx][ny].label != -1) { - if (abs(grid[i][j].z_min - grid[nx][ny].z_max) > h || abs(grid[i][j].z_max - grid[nx][ny].z_min) > h) + float sum_neighbour = std::accumulate(grid[nx][ny].z_coordinates.begin(), + grid[nx][ny].z_coordinates.end(), 0.0); + float z_mean_neighbour = sum_neighbour / grid[nx][ny].z_coordinates.size(); + + bool low_obstacle_detected = false; + bool use_mean = false; + if (grid[i][j].is_near) + use_mean = true; + + if (use_mean) + { + if (abs(z_mean - z_mean_neighbour) > h) + low_obstacle_detected = true; + } + else + { + if (abs(grid[i][j].z_min - grid[nx][ny].z_max) > h + || abs(grid[i][j].z_max - grid[nx][ny].z_min) > h) + low_obstacle_detected = true; + } + + if (low_obstacle_detected) { grid[i][j].label = 1; dx = dy = 2; // break the loop @@ -853,7 +890,8 @@ void GroundSegmentationAlgNode::evaluateSegmentation(void) else { if (detected_class == VEGETATION || detected_class == CLASS_UNKNOWN || detected_class == CLASS_OBSTACLE - || detected_class == CLASS_OVERHANGING_OBSTACLE || detected_class == TERRAIN || detected_class == CLASS_LOW_OBSTACLE) + || detected_class == CLASS_OVERHANGING_OBSTACLE || detected_class == TERRAIN + || detected_class == CLASS_LOW_OBSTACLE) detected_class = CLASS_OBSTACLE; else detected_class = CLASS_GROUND; -- GitLab