Apollo 11.0
自动驾驶开放平台
hdmap_input.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 *****************************************************************************/
16
18
19#include <algorithm>
20#include <limits>
21
22#include "cyber/common/file.h"
23#include "cyber/common/log.h"
28
29namespace apollo {
30namespace perception {
31namespace map {
32
40
41using base::PointD;
45// HDMapInput
46
47HDMapInput::HDMapInput() {}
48
50 lib::MutexLock lock(&mutex_);
51 return InitInternal();
52}
53
54bool HDMapInput::InitInternal() {
55 if (inited_) {
56 return true;
57 }
58 if (!InitHDMap()) {
59 return false;
60 }
61 inited_ = true;
62 return true;
63}
64
66 lib::MutexLock lock(&mutex_);
67 inited_ = false;
68 return InitInternal();
69}
70
71bool HDMapInput::InitHDMap() {
72 hdmap_.reset(new apollo::hdmap::HDMap());
73
74 hdmap_sample_step_ = FLAGS_hdmap_sample_step;
75
76 // TO DO: Decide which map to use
77 // Option 1: Use global hdmap_ = apollo::hdmap::HDMapUtil::BaseMapPtr();
78 // hdmap_ = apollo::hdmap::HDMapUtil::BaseMapPtr();
79
80 // Option2: Load own map with different hdmap_sample_step_
81 // Load hdmap path from global_flagfile.txt
82 hdmap_file_ = absl::StrCat(FLAGS_map_dir, "/base_map.bin");
83 AINFO << "hdmap_file_: " << hdmap_file_;
84 if (!apollo::cyber::common::PathExists(hdmap_file_)) {
85 AERROR << "Failed to find hadmap file: " << hdmap_file_;
86 return false;
87 }
88 if (hdmap_->LoadMapFromFile(hdmap_file_) != 0) {
89 AERROR << "Failed to load hadmap file: " << hdmap_file_;
90 return false;
91 }
92
93 AINFO << "Load hdmap file: " << hdmap_file_;
94 return true;
95}
96
98 const base::PointD& pointd, const double distance,
99 std::shared_ptr<base::HdmapStruct> hdmap_struct_ptr) {
100 lib::MutexLock lock(&mutex_);
101 if (hdmap_.get() == nullptr) {
102 AERROR << "hdmap is not available";
103 return false;
104 }
105 // Get original road boundary and junction
106 std::vector<RoadRoiPtr> road_boundary_vec;
107 std::vector<JunctionInfoConstPtr> junctions_vec;
109 point.set_x(pointd.x);
110 point.set_y(pointd.y);
111 point.set_z(pointd.z);
112 if (hdmap_->GetRoadBoundaries(point, distance, &road_boundary_vec,
113 &junctions_vec) != 0) {
114 AERROR << "Failed to get road boundary, point: " << point.DebugString();
115 return false;
116 }
117 junctions_vec.clear();
118 if (hdmap_->GetJunctions(point, distance, &junctions_vec) != 0) {
119 AERROR << "Failed to get junctions, point: " << point.DebugString();
120 return false;
121 }
122 if (hdmap_struct_ptr == nullptr) {
123 return false;
124 }
125 hdmap_struct_ptr->hole_polygons.clear();
126 hdmap_struct_ptr->junction_polygons.clear();
127 hdmap_struct_ptr->road_boundary.clear();
128 hdmap_struct_ptr->road_polygons.clear();
129
130 // Merge boundary and junction
131 EigenVector<base::RoadBoundary> road_boundaries;
132 MergeBoundaryJunction(road_boundary_vec, junctions_vec, &road_boundaries,
133 &(hdmap_struct_ptr->road_polygons),
134 &(hdmap_struct_ptr->junction_polygons));
135 // Filter road boundary by junction
136 GetRoadBoundaryFilteredByJunctions(road_boundaries,
137 hdmap_struct_ptr->junction_polygons,
138 &(hdmap_struct_ptr->road_boundary));
139 return true;
140}
141
142void HDMapInput::MergeBoundaryJunction(
143 const std::vector<apollo::hdmap::RoadRoiPtr>& boundary,
144 const std::vector<apollo::hdmap::JunctionInfoConstPtr>& junctions,
145 EigenVector<base::RoadBoundary>* road_boundaries_ptr,
146 EigenVector<base::PointCloud<base::PointD>>* road_polygons_ptr,
147 EigenVector<base::PointCloud<base::PointD>>* junction_polygons_ptr) {
148 const int boundary_size = static_cast<int>(boundary.size());
149 const int junctions_size = static_cast<int>(junctions.size());
150 const int polygon_size = boundary_size;
151 road_boundaries_ptr->clear();
152 road_polygons_ptr->clear();
153 junction_polygons_ptr->clear();
154 road_polygons_ptr->resize(polygon_size);
155 junction_polygons_ptr->resize(junctions_size);
156 road_boundaries_ptr->resize(polygon_size);
157 int polygons_index = 0;
158 // Merge boundary
159 PointDCloudPtr temp_cloud = base::PointDCloudPool::Instance().Get();
160 for (int step = 0, i = 0; i < polygon_size; ++i) {
161 temp_cloud->clear();
162 const LineBoundary& left_boundary = boundary[i]->left_boundary;
163 const std::vector<apollo::common::PointENU>& left_line_points =
164 left_boundary.line_points;
165 ADEBUG << "Input left road_boundary size = " << left_line_points.size();
166 step = (left_line_points.size() > 2) ? hdmap_sample_step_ : 1;
167 for (unsigned int idx = 0; idx < left_line_points.size(); idx += step) {
168 PointD pointd;
169 pointd.x = left_line_points.at(idx).x();
170 pointd.y = left_line_points.at(idx).y();
171 pointd.z = left_line_points.at(idx).z();
172 temp_cloud->push_back(pointd);
173 }
174 DownsamplePoints(temp_cloud,
175 &(road_boundaries_ptr->at(polygons_index).left_boundary));
176 for (unsigned int index = 0;
177 index < road_boundaries_ptr->at(polygons_index).left_boundary.size();
178 ++index) {
179 road_polygons_ptr->at(polygons_index)
180 .push_back(
181 road_boundaries_ptr->at(polygons_index).left_boundary[index]);
182 }
183 ADEBUG << "Left road_boundary downsample size = "
184 << road_boundaries_ptr->at(polygons_index).left_boundary.size();
185 temp_cloud->clear();
186 const LineBoundary& right_boundary = boundary[i]->right_boundary;
187 const std::vector<apollo::common::PointENU>& right_line_points =
188 right_boundary.line_points;
189 ADEBUG << "Input right road_boundary size = " << right_line_points.size();
190 step = (right_line_points.size() > 2) ? hdmap_sample_step_ : 1;
191 for (unsigned int idx = 0; idx < right_line_points.size(); idx += step) {
192 PointD pointd;
193 pointd.x = right_line_points.at(idx).x();
194 pointd.y = right_line_points.at(idx).y();
195 pointd.z = right_line_points.at(idx).z();
196 temp_cloud->push_back(pointd);
197 }
198 DownsamplePoints(temp_cloud,
199 &(road_boundaries_ptr->at(polygons_index).right_boundary));
200 for (unsigned int index = 0;
201 index < road_boundaries_ptr->at(polygons_index).right_boundary.size();
202 ++index) {
203 road_polygons_ptr->at(polygons_index)
204 .push_back(road_boundaries_ptr->at(polygons_index)
205 .right_boundary[road_boundaries_ptr->at(polygons_index)
206 .right_boundary.size() -
207 1 - index]);
208 }
209 ADEBUG << "Right road_boundary downsample size = "
210 << road_boundaries_ptr->at(polygons_index).right_boundary.size();
211 ++polygons_index;
212 }
213
214 // Merge junctions
215 for (int idx = 0; idx < junctions_size; ++idx) {
216 const Polygon2d& polygon = junctions[idx]->polygon();
217 const std::vector<Vec2d>& points = polygon.points();
218 for (size_t idj = 0; idj < points.size(); ++idj) {
219 PointD pointd;
220 pointd.x = points[idj].x();
221 pointd.y = points[idj].y();
222 pointd.z = 0.0;
223 junction_polygons_ptr->at(idx).push_back(pointd);
224 }
225 }
226}
227
228bool HDMapInput::GetRoadBoundaryFilteredByJunctions(
229 const EigenVector<base::RoadBoundary>& road_boundaries,
230 const EigenVector<base::PointCloud<base::PointD>>& junctions,
231 EigenVector<base::RoadBoundary>* flt_road_boundaries_ptr) {
232 for (size_t n_rd = 0; n_rd < road_boundaries.size(); ++n_rd) {
233 const base::RoadBoundary& temp_road_boundary = road_boundaries[n_rd];
234 EigenVector<base::PointCloud<base::PointD>> temp_left_boundary_vec;
235 EigenVector<base::PointCloud<base::PointD>> temp_right_boundary_vec;
236 // Filter left boundary points
237 this->SplitBoundary(temp_road_boundary.left_boundary, junctions,
238 &temp_left_boundary_vec);
239 // Filter right boundary points
240 this->SplitBoundary(temp_road_boundary.right_boundary, junctions,
241 &temp_right_boundary_vec);
242 auto n_temp_road_boundary =
243 std::max(temp_left_boundary_vec.size(), temp_right_boundary_vec.size());
244 for (size_t i = 0; i < n_temp_road_boundary; ++i) {
245 base::RoadBoundary temp_road_boundary;
246 if (i < temp_left_boundary_vec.size()) {
247 temp_road_boundary.left_boundary = temp_left_boundary_vec[i];
248 }
249 if (i < temp_right_boundary_vec.size()) {
250 temp_road_boundary.right_boundary = temp_right_boundary_vec[i];
251 }
252 flt_road_boundaries_ptr->push_back(temp_road_boundary);
253 }
254 }
255
256 return true;
257}
258
259void HDMapInput::DownsamplePoints(const base::PointDCloudPtr& raw_cloud_ptr,
260 base::PointCloud<base::PointD>* polygon_ptr,
261 size_t min_points_num_for_sample) const {
262 constexpr double kDoubleEpsilon = std::numeric_limits<double>::epsilon();
263 const PointDCloud& raw_cloud = *raw_cloud_ptr;
264 unsigned int spt = 0;
265 double acos_theta = 0.0;
266 const double radian_to_degree = 57.29577951308232;
267 const size_t raw_cloud_size = raw_cloud.size();
268 if (raw_cloud_size <= min_points_num_for_sample) {
269 for (size_t i = 0; i < raw_cloud_size; ++i) {
270 polygon_ptr->push_back(raw_cloud[i]);
271 }
272 return;
273 }
274 // The first point
275 polygon_ptr->push_back(raw_cloud[0]);
276 for (size_t idx = 2; idx < raw_cloud_size; ++idx) {
277 const PointD& point_0 = raw_cloud[spt];
278 const PointD& point_1 = raw_cloud[idx - 1];
279 const PointD& point_2 = raw_cloud[idx];
280 Eigen::Vector2d v1(point_1.x - point_0.x, point_1.y - point_0.y);
281 Eigen::Vector2d v2(point_2.x - point_1.x, point_2.y - point_1.y);
282 double vector_dist =
283 sqrt(v1.cwiseProduct(v1).sum()) * sqrt(v2.cwiseProduct(v2).sum());
284 // Judge duplicate points
285 if (vector_dist < kDoubleEpsilon) {
286 continue;
287 }
288 double cos_theta = (v1.cwiseProduct(v2)).sum() / vector_dist;
289 if (cos_theta > 1.0) {
290 cos_theta = 1.0;
291 } else if (cos_theta < -1.0) {
292 cos_theta = -1.0;
293 }
294 double angle = (acos(cos_theta) * radian_to_degree);
295 acos_theta += angle;
296 if ((acos_theta - 1.0) > kDoubleEpsilon) {
297 polygon_ptr->push_back(point_1);
298 spt = static_cast<unsigned int>(idx - 1);
299 acos_theta = 0.0;
300 }
301 }
302 // The last point
303 polygon_ptr->push_back(raw_cloud[raw_cloud_size - 1]);
304 ADEBUG << "Downsample road boundary points from " << raw_cloud_size << " to "
305 << polygon_ptr->size();
306}
307
308void HDMapInput::SplitBoundary(
309 const base::PointCloud<base::PointD>& boundary_line,
310 const EigenVector<base::PointCloud<base::PointD>>& junctions,
311 EigenVector<base::PointCloud<base::PointD>>* boundary_line_vec_ptr) {
312 std::vector<bool> boundary_flag(boundary_line.size());
313 for (size_t npt = 0; npt < boundary_line.size(); ++npt) {
314 const PointD& pointd = boundary_line[npt];
315 boundary_flag[npt] = false;
316 for (size_t n_rj = 0; n_rj < junctions.size(); ++n_rj) {
317 if (algorithm::IsPointXYInPolygon2DXY(pointd, junctions[n_rj])) {
318 boundary_flag[npt] = true;
319 break;
320 }
321 }
322 }
323 std::vector<int> line_index;
324 base::PolygonDType temp_line;
325 for (size_t i = 1; i < boundary_flag.size(); ++i) {
326 if (!boundary_flag[i - 1] || !boundary_flag[i]) {
327 line_index.push_back(static_cast<int>(i - 1));
328 line_index.push_back(static_cast<int>(i));
329 } else if (line_index.size() > 1) {
330 auto pos = std::unique(line_index.begin(), line_index.end());
331 line_index.erase(pos, line_index.end());
332 for (size_t j = 0; j < line_index.size(); ++j) {
333 const PointD& pointd = boundary_line[line_index[j]];
334 temp_line.push_back(pointd);
335 }
336 boundary_line_vec_ptr->push_back(temp_line);
337 line_index.clear();
338 temp_line.clear();
339 }
340 }
341 // In case the last several unjunctioned points in the "boundary_line"
342 if (line_index.size() > 1) {
343 auto pos = std::unique(line_index.begin(), line_index.end());
344 line_index.erase(pos, line_index.end());
345 for (size_t j = 0; j < line_index.size(); ++j) {
346 const PointD& pointd = boundary_line[line_index[j]];
347 temp_line.push_back(pointd);
348 }
349 boundary_line_vec_ptr->push_back(temp_line);
350 }
351}
352
354 Eigen::Vector3d* lane_direction) {
355 // if (hdmap_ == nullptr) {
356 // return false;
357 // }
358 // apollo::common::PointENU point;
359 // point.set_x(pointd.x);
360 // point.set_y(pointd.y);
361 // point.set_z(pointd.z);
362 // apollo::hdmap::LaneInfoConstPtr nearest_lane;
363 // double nearest_s = 0.0;
364 // double nearest_l = 0.0;
365 // // get nearest lane of query point
366 // int status = hdmap_->GetNearestLane(point, &nearest_lane,
367 // &nearest_s, &nearest_l);
368 // if (status != 0) {
369 // AINFO << "Failed to get nearest lane for point " <<
370 // point.DebugString();
371 // return false;
372 // }
373 // // get lane heading of nearest s
374 // const adu::hdmap::Trajectory& nearest_lane_trajectory
375 // = nearest_lane->trajectory();
376 // double lane_heading
377 // = nearest_lane_trajectory.get_smooth_point(nearest_s).heading();
378 // *lane_direction = Eigen::Vector3d(cos(lane_heading), sin(lane_heading), 0);
379 return true;
380}
381
382bool HDMapInput::GetSignalsFromHDMap(
383 const Eigen::Vector3d& pointd, double forward_distance,
384 std::vector<apollo::hdmap::Signal>* signals) {
386 point.set_x(pointd(0));
387 point.set_y(pointd(1));
388 point.set_z(pointd(2));
389 std::vector<SignalInfoConstPtr> forward_signals;
390 if (hdmap_->GetForwardNearestSignalsOnLane(point, forward_distance,
391 &forward_signals) != 0) {
392 AERROR << "Failed to call HDMap::get_signal. point: "
393 << point.ShortDebugString();
394 return false;
395 }
396 signals->reserve(forward_signals.size());
397 for (auto& signal_info : forward_signals) {
398 signals->push_back(signal_info->signal());
399 ADEBUG << "Signal: " << signals->back().DebugString();
400 }
401 ADEBUG << "get_signal success. num_signals: " << signals->size()
402 << " point: " << point.ShortDebugString();
403 return true;
404}
405
406bool HDMapInput::GetBarrierGatesFromHDMap(
407 const Eigen::Vector3d& pointd, double forward_distance,
408 std::vector<apollo::hdmap::BarrierGate>* barrier_gates) {
410 point.set_x(pointd(0));
411 point.set_y(pointd(1));
412 point.set_z(pointd(2));
413 std::vector<BarrierGateInfoConstPtr> forward_barrier_gates;
414 if (hdmap_->GetForwardNearestBarriersOnLane(point, forward_distance,
415 &forward_barrier_gates) != 0) {
416 AERROR << "Failed to call HDMap::get barrier gates. point: "
417 << point.ShortDebugString();
418 return false;
419 }
420 barrier_gates->reserve(forward_barrier_gates.size());
421 for (auto& barrier_gate_info : forward_barrier_gates) {
422 barrier_gates->push_back(barrier_gate_info->barrier_gate());
423 ADEBUG << "Barrier gate: " << barrier_gates->back().DebugString();
424 }
425 ADEBUG << "get barrier gates success. num barrier gates: "
426 << barrier_gates->size() << " point: " << point.ShortDebugString();
427 return true;
428}
429
430bool HDMapInput::GetSignals(const Eigen::Vector3d& pointd,
431 double forward_distance,
432 std::vector<apollo::hdmap::Signal>* signals) {
433 lib::MutexLock lock(&mutex_);
434 if (hdmap_.get() == nullptr) {
435 AERROR << "hdmap is not available";
436 return false;
437 }
438 return GetSignalsFromHDMap(pointd, forward_distance, signals);
439}
440
442 const Eigen::Vector3d& pointd, double forward_distance,
443 std::vector<apollo::hdmap::BarrierGate>* barrier_gates) {
444 lib::MutexLock lock(&mutex_);
445 if (hdmap_.get() == nullptr) {
446 AERROR << "hdmap is not available";
447 return false;
448 }
449 return GetBarrierGatesFromHDMap(pointd, forward_distance, barrier_gates);
450}
451
452} // namespace map
453} // namespace perception
454} // namespace apollo
The class of polygon in 2-D.
Definition polygon2d.h:42
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
High-precision map loader interface.
Definition hdmap.h:54
virtual void push_back(const PointT &point)
bool GetBarrierGates(const Eigen::Vector3d &pointd, double forward_distance, std::vector< apollo::hdmap::BarrierGate > *barrier_gates)
apollo::common::EigenVector< EigenType > EigenVector
Definition hdmap_input.h:37
bool GetSignals(const Eigen::Vector3d &pointd, double forward_distance, std::vector< apollo::hdmap::Signal > *signals)
bool GetRoiHDMapStruct(const base::PointD &pointd, const double distance, std::shared_ptr< base::HdmapStruct > hdmap_struct_prt)
bool GetNearestLaneDirection(const base::PointD &pointd, Eigen::Vector3d *lane_direction)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
const double kDoubleEpsilon
bool PathExists(const std::string &path)
Check if the path exists.
Definition file.cc:195
std::shared_ptr< const JunctionInfo > JunctionInfoConstPtr
std::shared_ptr< const BarrierGateInfo > BarrierGateInfoConstPtr
std::shared_ptr< const SignalInfo > SignalInfoConstPtr
std::shared_ptr< RoadRoi > RoadRoiPtr
bool IsPointXYInPolygon2DXY(const PointT &point, const base::PointCloud< PointT > &polygon)
Definition common.h:35
std::shared_ptr< PointDCloud > PointDCloudPtr
AttributePointCloud< PointD > PointDCloud
PointCloud< PointD > PolygonDType
Point< double > PointD
Definition point.h:57
class register implement
Definition arena_queue.h:37
std::vector< apollo::common::PointENU > line_points