Apollo 11.0
自动驾驶开放平台
extract_ground_plane.h
浏览该文件的文档.
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
30namespace apollo {
31namespace localization {
32namespace 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 CalculateDegree(const Eigen::Vector3f &tmp0, const Eigen::Vector3f &tmp1)
void ExtractXYPlane(const PointCloudPtrT &cloud)
void Filter(PointCloudPtr output, bool searchable=false)
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37