Apollo  6.0
Open source self driving car software
extract_ground_plane.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2017 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 #pragma once
18 
19 #include <map>
20 #include <vector>
21 
22 #include "pcl/sample_consensus/impl/ransac.hpp"
23 #include "pcl/sample_consensus/impl/sac_model_plane.hpp"
24 #include "pcl/sample_consensus/ransac.h"
25 #include "pcl/sample_consensus/sac_model_plane.h"
26 
27 #include "cyber/common/log.h"
29 
30 namespace apollo {
31 namespace localization {
32 namespace msf {
34  public:
35  typedef pcl::PointXYZI PointT;
36  typedef pcl::PointCloud<PointT> PointCloudT;
37  typedef PointCloudT::Ptr PointCloudPtrT;
38 
39  public:
41  min_grid_size_ = 0.5;
42  max_grid_size_ = 4.00;
43  plane_inlier_distance_ = 0.05;
44  min_planepoints_number_ = 60;
45  plane_type_degree_ = 80.0;
46  below_lidar_height_ = 1.0;
47  xy_plane_cloud_ = PointCloudPtrT(new PointCloudT);
48  non_xy_plane_cloud_ = PointCloudPtrT(new PointCloudT);
49  }
50 
51  void SetMinGridSize(double d) { min_grid_size_ = d; }
52 
53  void SetMaxGridSize(double d) { max_grid_size_ = d; }
54 
55  void SetPlaneInlierDistance(double d) { plane_inlier_distance_ = d; }
56 
57  void SetMinPlanepointsNumber(double d) {
58  min_planepoints_number_ = static_cast<int>(d);
59  }
60 
61  void SetPlaneTypeDegree(double d) { plane_type_degree_ = d; }
62 
63  void SetBelowLidarHeight(double d) { below_lidar_height_ = d; }
64 
65  float CalculateDegree(const Eigen::Vector3f& tmp0,
66  const Eigen::Vector3f& tmp1) {
67  float cos_theta = tmp0.dot(tmp1) / (tmp0.norm() * tmp1.norm());
68  return static_cast<float>(std::acos(cos_theta) * 180.0 / M_PI);
69  }
70 
71  PointCloudPtrT& GetXYPlaneCloud() { return xy_plane_cloud_; }
72 
73  PointCloudPtrT& GetNonXYPlaneCloud() { return non_xy_plane_cloud_; }
74 
75  void ExtractXYPlane(const PointCloudPtrT& cloud) {
76  xy_plane_cloud_.reset(new PointCloudT);
77  PointCloudPtrT pointcloud_ptr(new PointCloudT);
78  pcl::copyPointCloud<PointT>(*cloud, *pointcloud_ptr);
79  int iter_num = static_cast<int>(log2(max_grid_size_ / min_grid_size_));
80  if (iter_num == 0) {
81  iter_num = 1;
82  }
83  std::clock_t plane_time;
84  plane_time = std::clock();
85  int total_plane_num = 0;
86  double power2 = 0.5; // 2^-1
87  for (int iter = 0; iter <= iter_num; ++iter) {
88  power2 *= 2;
89  float grid_size = static_cast<float>(max_grid_size_ / power2);
91  vgc.setInputCloud(pointcloud_ptr);
92  vgc.SetMinPointPerVoxel(min_planepoints_number_);
93  vgc.setLeafSize(grid_size, grid_size, grid_size);
94  vgc.Filter(false);
95 
96  PointCloudT cloud_tmp;
97  int plane_num = 0;
98  typename std::map<size_t, VoxelGridCovariance<PointT>::Leaf>::iterator it;
99  for (it = vgc.GetLeaves().begin(); it != vgc.GetLeaves().end(); it++) {
100  if (it->second.GetPointCount() < min_planepoints_number_) {
101  cloud_tmp += it->second.cloud_;
102  continue;
103  }
104  PointCloudT cloud_outlier;
105  if (GetPlaneFeaturePoint(it->second.cloud_, &cloud_outlier)) {
106  cloud_tmp += cloud_outlier;
107  plane_num++;
108  } else {
109  cloud_tmp += it->second.cloud_;
110  }
111  }
112  AINFO << "the " << iter << " interation: plane_num = " << plane_num;
113  total_plane_num += plane_num;
114  pointcloud_ptr.reset(new PointCloudT);
115  *pointcloud_ptr = cloud_tmp;
116  }
117 
118  *non_xy_plane_cloud_ = *pointcloud_ptr;
119  plane_time = std::clock() - plane_time;
120  AINFO << "plane_patch takes:"
121  << static_cast<double>(plane_time) / CLOCKS_PER_SEC << "sec.";
122  AINFO << "total_plane_num = " << total_plane_num;
123  AINFO << "total_points_num = " << xy_plane_cloud_->points.size();
124  return;
125  }
126 
127  private:
128  bool GetPlaneFeaturePoint(const PointCloudT& cloud,
129  PointCloudT* cloud_outlier) {
130  // ransac plane
131  std::vector<int> inliers;
132  PointCloudPtrT cloud_new(new PointCloudT);
133  *cloud_new = cloud;
134  pcl::SampleConsensusModelPlane<PointT>::Ptr model_plane(
135  new pcl::SampleConsensusModelPlane<PointT>(cloud_new));
136  pcl::RandomSampleConsensus<PointT> ransac(model_plane);
137  ransac.setDistanceThreshold(plane_inlier_distance_);
138  ransac.computeModel();
139  ransac.getInliers(inliers);
140  if (static_cast<int>(inliers.size()) < min_planepoints_number_) {
141  return false;
142  }
143  PointCloudPtrT cloud_inlier(new PointCloudT);
144  pcl::copyPointCloud<PointT>(*cloud_new, inliers, *cloud_inlier);
145  std::vector<int> outliers;
146  unsigned int inlier_idx = 0;
147  for (unsigned int i = 0; i < cloud_new->points.size(); ++i) {
148  if (inlier_idx >= inliers.size() ||
149  static_cast<int>(i) < inliers[inlier_idx]) {
150  outliers.push_back(i);
151  } else {
152  inlier_idx++;
153  }
154  }
155  pcl::copyPointCloud<PointT>(*cloud_new, outliers, *cloud_outlier);
156 
157  Eigen::Vector4f centroid;
158  pcl::compute3DCentroid(*cloud_inlier, centroid);
159 
160  if (centroid(2) > -below_lidar_height_) {
161  return true;
162  }
163 
164  // get plane's normal (which is normalized)
165  Eigen::VectorXf coeff;
166  ransac.getModelCoefficients(coeff);
167  // determine the plane type
168  double tan_theta = 0;
169  double tan_refer_theta = std::tan(plane_type_degree_ / 180.0 * M_PI);
170  if ((std::abs(coeff(2)) > std::abs(coeff(0))) &&
171  (std::abs(coeff(2)) > std::abs(coeff(1)))) {
172  tan_theta = std::abs(coeff(2)) /
173  std::sqrt(coeff(0) * coeff(0) + coeff(1) * coeff(1));
174  if (tan_theta > tan_refer_theta) {
175  *xy_plane_cloud_ += *cloud_inlier;
176  } else {
177  // cloud_outlier += *cloud_inlier;
178  }
179  }
180  return true;
181  }
182 
183  private:
184  // parameters
185  double min_grid_size_;
186  double max_grid_size_;
187  double plane_inlier_distance_;
188  int min_planepoints_number_;
189  double plane_type_degree_;
190  double below_lidar_height_;
191 
192  PointCloudPtrT xy_plane_cloud_;
193  PointCloudPtrT non_xy_plane_cloud_;
194 };
195 
196 } // namespace msf
197 } // namespace localization
198 } // namespace apollo
float tan(Angle16 a)
PointCloudT::Ptr PointCloudPtrT
Definition: extract_ground_plane.h:37
void SetPlaneInlierDistance(double d)
Definition: extract_ground_plane.h:55
Eigen::Vector3f Vector3f
Definition: base_map_fwd.h:29
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
void SetMinGridSize(double d)
Definition: extract_ground_plane.h:51
void SetMinPointPerVoxel(int min_points_per_voxel)
Definition: voxel_grid_covariance_hdmap.h:182
T abs(const T &x)
Definition: misc.h:48
void SetMinPlanepointsNumber(double d)
Definition: extract_ground_plane.h:57
void SetBelowLidarHeight(double d)
Definition: extract_ground_plane.h:63
void ExtractXYPlane(const PointCloudPtrT &cloud)
Definition: extract_ground_plane.h:75
std::map< size_t, Leaf > & GetLeaves()
Definition: voxel_grid_covariance_hdmap.h:281
float CalculateDegree(const Eigen::Vector3f &tmp0, const Eigen::Vector3f &tmp1)
Definition: extract_ground_plane.h:65
pcl::PointCloud< PointT > PointCloudT
Definition: extract_ground_plane.h:36
PointCloudPtrT & GetXYPlaneCloud()
Definition: extract_ground_plane.h:71
Definition: extract_ground_plane.h:33
void Filter(PointCloudPtr output, bool searchable=false)
Definition: voxel_grid_covariance_hdmap.h:205
PointCloudPtrT & GetNonXYPlaneCloud()
Definition: extract_ground_plane.h:73
void SetPlaneTypeDegree(double d)
Definition: extract_ground_plane.h:61
pcl::PointXYZI PointT
Definition: extract_ground_plane.h:35
FeatureXYPlane()
Definition: extract_ground_plane.h:40
#define AINFO
Definition: log.h:42
Definition: voxel_grid_covariance_hdmap.h:73
void SetMaxGridSize(double d)
Definition: extract_ground_plane.h:53