Apollo 11.0
自动驾驶开放平台
lidar_object_util.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 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 *****************************************************************************/
17
18#include <algorithm>
19#include <limits>
20
23
24namespace apollo {
25namespace perception {
26namespace lidar {
27
28using base::Object;
29using base::PointCloud;
30using base::PointD;
31using base::PointF;
32
33static const float kEpsilon = 1e-6;
34
35void GetBoundingBox2d(const std::shared_ptr<Object>& object,
36 PointCloud<PointD>* box, double expand) {
37 box->clear();
38 box->resize(4);
39
40 Eigen::Vector3d direction = object->direction.cast<double>();
41 Eigen::Vector3d odirection(-direction(1), direction(0), 0.0);
42 double half_length = object->size(0) * 0.5 + expand;
43 double half_width = object->size(1) * 0.5 + expand;
44
45 box->at(0).x = half_length * direction(0) + half_width * odirection(0) +
46 object->center(0);
47 box->at(0).y = half_length * direction(1) + half_width * odirection(1) +
48 object->center(1);
49 box->at(1).x = -half_length * direction(0) + half_width * odirection(0) +
50 object->center(0);
51 box->at(1).y = -half_length * direction(1) + half_width * odirection(1) +
52 object->center(1);
53 box->at(2).x = -half_length * direction(0) - half_width * odirection(0) +
54 object->center(0);
55 box->at(2).y = -half_length * direction(1) - half_width * odirection(1) +
56 object->center(1);
57 box->at(3).x = half_length * direction(0) - half_width * odirection(0) +
58 object->center(0);
59 box->at(3).y = half_length * direction(1) - half_width * odirection(1) +
60 object->center(1);
61}
62
63void ComputeObjectShapeFromPolygon(std::shared_ptr<Object> object,
64 bool use_world_cloud) {
65 const PointCloud<PointD>& polygon = object->polygon;
66 const PointCloud<PointF>& cloud = object->lidar_supplement.cloud;
67 const PointCloud<PointD>& world_cloud = object->lidar_supplement.cloud_world;
68
69 if (polygon.empty() || cloud.empty()) {
70 AINFO << "Failed to compute box, polygon size: " << polygon.size()
71 << " cloud size: " << cloud.size();
72 return;
73 }
74
75 // note here we assume direction is not changed
76 Eigen::Vector2d polygon_xy;
77 Eigen::Vector2d projected_polygon_xy;
78 Eigen::Vector3d raw_direction = object->direction.cast<double>();
79 Eigen::Vector2d direction = raw_direction.head<2>();
80 Eigen::Vector2d odirection(-direction(1), direction(0));
81
82 constexpr double kDoubleMax = std::numeric_limits<double>::max();
83 Eigen::Vector2d min_polygon_xy(kDoubleMax, kDoubleMax);
84 Eigen::Vector2d max_polygon_xy(-kDoubleMax, -kDoubleMax);
85
86 // note we keep this offset to avoid numeric precision issues in world frame
87 Eigen::Vector2d offset(object->polygon[0].x, object->polygon[0].y);
88
89 for (const auto& point : object->polygon.points()) {
90 polygon_xy << point.x, point.y;
91 polygon_xy -= offset;
92 projected_polygon_xy(0) = direction.dot(polygon_xy);
93 projected_polygon_xy(1) = odirection.dot(polygon_xy);
94 min_polygon_xy(0) = std::min(min_polygon_xy(0), projected_polygon_xy(0));
95 min_polygon_xy(1) = std::min(min_polygon_xy(1), projected_polygon_xy(1));
96 max_polygon_xy(0) = std::max(max_polygon_xy(0), projected_polygon_xy(0));
97 max_polygon_xy(1) = std::max(max_polygon_xy(1), projected_polygon_xy(1));
98 }
99
100 double min_z = 0.0;
101 double max_z = 0.0;
102 if (use_world_cloud) {
103 min_z = world_cloud[0].z;
104 max_z = world_cloud[0].z;
105 for (const auto& point : world_cloud.points()) {
106 min_z = std::min(min_z, point.z);
107 max_z = std::max(max_z, point.z);
108 }
109 } else {
110 min_z = cloud[0].z;
111 max_z = cloud[0].z;
112 for (const auto& point : cloud.points()) {
113 min_z = std::min(min_z, static_cast<double>(point.z));
114 max_z = std::max(max_z, static_cast<double>(point.z));
115 }
116 }
117
118 // update size
119 object->size << static_cast<float>(max_polygon_xy(0) - min_polygon_xy(0)),
120 static_cast<float>(max_polygon_xy(1) - min_polygon_xy(1)),
121 static_cast<float>(max_z - min_z);
122 // for safety issues, set a default minmium value
123 object->size(0) = std::max(object->size(0), 0.01f);
124 object->size(1) = std::max(object->size(1), 0.01f);
125 object->size(2) = std::max(object->size(2), 0.01f);
126 // update center
127 projected_polygon_xy << (min_polygon_xy(0) + max_polygon_xy(0)) * 0.5,
128 (min_polygon_xy(1) + max_polygon_xy(1)) * 0.5;
129 polygon_xy = projected_polygon_xy(0) * direction +
130 projected_polygon_xy(1) * odirection;
131 object->center << polygon_xy(0) + offset(0), polygon_xy(1) + offset(1), min_z;
132}
133
135 const Eigen::Vector3d& ref_center,
136 const base::ObjectPtr& object,
137 Eigen::Vector3f* direction) {
138 if (object->polygon.size() == 0 ||
139 object->lidar_supplement.cloud.size() < 4u) {
140 return;
141 }
142 size_t max_point_index = 0;
143 size_t min_point_index = 0;
145 object, ref_center, &max_point_index, &min_point_index);
146 Eigen::Vector3d max_point(
147 object->polygon[max_point_index].x,
148 object->polygon[max_point_index].y,
149 object->polygon[max_point_index].z);
150 Eigen::Vector3d min_point(
151 object->polygon[min_point_index].x,
152 object->polygon[min_point_index].y,
153 object->polygon[min_point_index].z);
154 Eigen::Vector3d line = max_point - min_point;
155 double max_dis = 0;
156 bool vertices_in_vision = false;
157 size_t visible_max_start_point_index = 0;
158 size_t visible_max_end_point_index = 0;
159 for (size_t i = min_point_index, count = 0; count < object->polygon.size();
160 i = (i + 1) % object->polygon.size(), ++count) {
161 size_t j = (i + 1) % object->polygon.size();
162 Eigen::Vector3d p_i;
163 p_i[0] = object->polygon[i].x;
164 p_i[1] = object->polygon[i].y;
165 p_i[2] = object->polygon[i].z;
166 Eigen::Vector3d p_j;
167 p_j[0] = object->polygon[j].x;
168 p_j[1] = object->polygon[j].y;
169 p_j[2] = object->polygon[j].z;
170 Eigen::Vector3d ray;
171 if ((i == min_point_index && j == max_point_index) ||
172 (i == max_point_index && j == min_point_index)) {
173 continue;
174 } else {
175 if (j != min_point_index && j != max_point_index) {
176 ray = p_j - min_point;
177 } else { // j == min_point_index || j == max_point_index
178 ray = p_i - min_point;
179 }
180 if (line[0] * ray[1] - ray[0] * line[1] < kEpsilon) {
181 double dist = sqrt((p_j[0] - p_i[0]) * (p_j[0] - p_i[0]) +
182 (p_j[1] - p_i[1]) * (p_j[1] - p_i[1]));
183 if (dist > max_dis) {
184 max_dis = dist;
185 visible_max_start_point_index = i;
186 visible_max_end_point_index = j;
187 }
188 vertices_in_vision = true;
189 }
190 }
191 }
192 size_t start_point_index = 0;
193 size_t end_point_index = 0;
194 if (vertices_in_vision) {
195 start_point_index = visible_max_start_point_index;
196 end_point_index = visible_max_end_point_index;
197 } else {
198 start_point_index = min_point_index;
199 end_point_index = max_point_index;
200 }
201 Eigen::Vector3d start_point(
202 object->polygon[start_point_index].x,
203 object->polygon[start_point_index].y,
204 object->polygon[start_point_index].z);
205 Eigen::Vector3d end_point(
206 object->polygon[end_point_index].x,
207 object->polygon[end_point_index].y,
208 object->polygon[end_point_index].z);
209 Eigen::Vector3d dir = end_point - start_point;
210 *direction << static_cast<float>(dir[0]),
211 static_cast<float>(dir[1]),
212 static_cast<float>(dir[2]);
213 direction->normalize();
214}
215
217 const base::ObjectPtr& object,
218 const Eigen::Vector3d& ref_center,
219 size_t* max_point_index,
220 size_t* min_point_index) {
221 Eigen::Vector3d p_0;
222 p_0[0] = object->polygon[0].x;
223 p_0[1] = object->polygon[0].y;
224 p_0[2] = object->polygon[0].z;
225 Eigen::Vector3d max_point = p_0 - ref_center;
226 Eigen::Vector3d min_point = p_0 - ref_center;
227 for (size_t i = 1; i < object->polygon.size(); ++i) {
228 Eigen::Vector3d p;
229 p[0] = object->polygon[i].x;
230 p[1] = object->polygon[i].y;
231 p[2] = object->polygon[i].z;
232 Eigen::Vector3d ray = p - ref_center;
233 // clock direction
234 if (max_point[0] * ray[1] - ray[0] * max_point[1] < kEpsilon) {
235 max_point = ray;
236 *max_point_index = i;
237 }
238 // unclock direction
239 if (min_point[0] * ray[1] - ray[0] * min_point[1] > kEpsilon) {
240 min_point = ray;
241 *min_point_index = i;
242 }
243 }
244}
245
246} // namespace lidar
247} // namespace perception
248} // namespace apollo
const PointT * at(size_t col, size_t row) const
Definition point_cloud.h:63
virtual void resize(size_t size)
Definition point_cloud.h:88
const std::vector< PointT > & points() const
#define AINFO
Definition log.h:42
Point< float > PointF
Definition point.h:56
std::shared_ptr< Object > ObjectPtr
Definition object.h:127
Point< double > PointD
Definition point.h:57
void GetBoundingBox2d(const std::shared_ptr< Object > &object, PointCloud< PointD > *box, double expand)
void ComputeObjectShapeFromPolygon(std::shared_ptr< Object > object, bool use_world_cloud)
void ComputeMinMaxDirectionPoint(const base::ObjectPtr &object, const Eigen::Vector3d &ref_center, size_t *max_point_index, size_t *min_point_index)
Compute min max direction
void ComputePolygonDirection(const Eigen::Vector3d &ref_center, const base::ObjectPtr &object, Eigen::Vector3f *direction)
Compute polygon direction
class register implement
Definition arena_queue.h:37