Apollo 11.0
自动驾驶开放平台
road_graph.cc
浏览该文件的文档.
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
18
19#include <algorithm>
20#include <set>
21#include <utility>
22
26
27namespace apollo {
28namespace prediction {
29namespace {
30
35
36// Custom helper functions for sorting purpose.
37bool HeadingIsAtLeft(const std::vector<double>& heading1,
38 const std::vector<double>& heading2, const size_t idx) {
39 if (idx >= heading1.size() || idx >= heading2.size()) {
40 return true;
41 }
42 const double angle =
43 apollo::common::math::NormalizeAngle(heading1[idx] - heading2[idx]);
44 if (angle > 0.0) {
45 return true;
46 } else if (angle < 0.0) {
47 return false;
48 }
49 return HeadingIsAtLeft(heading1, heading2, idx + 1);
50}
51
52int ConvertTurnTypeToDegree(const Lane& lane) {
53 // Sanity checks.
54 if (!lane.has_turn()) {
55 return 0;
56 }
57
58 // Assign a number to measure how much it is bent to the left.
59 switch (lane.turn()) {
60 case Lane::NO_TURN:
61 return 0;
62 case Lane::LEFT_TURN:
63 return 1;
64 case Lane::U_TURN:
65 return 2;
66 default:
67 break;
68 }
69
70 return -1;
71}
72
73bool IsAtLeft(std::shared_ptr<const LaneInfo> lane1,
74 std::shared_ptr<const LaneInfo> lane2) {
75 if (lane1->lane().has_turn() && lane2->lane().has_turn() &&
76 lane1->lane().turn() != lane2->lane().turn()) {
77 int degree_to_left_1 = ConvertTurnTypeToDegree(lane1->lane());
78 int degree_to_left_2 = ConvertTurnTypeToDegree(lane2->lane());
79 return degree_to_left_1 > degree_to_left_2;
80 }
81 return HeadingIsAtLeft(lane1->headings(), lane2->headings(), 0);
82}
83
84} // namespace
85
86RoadGraph::RoadGraph(const double start_s, const double length,
87 const bool consider_divide,
88 std::shared_ptr<const LaneInfo> lane_info_ptr)
89 : start_s_(start_s),
90 length_(length),
91 consider_divide_(consider_divide),
92 lane_info_ptr_(lane_info_ptr) {}
93
94Status RoadGraph::BuildLaneGraph(LaneGraph* const lane_graph_ptr) {
95 // Sanity checks.
96 if (length_ < 0.0 || lane_info_ptr_ == nullptr) {
97 const auto error_msg = absl::StrCat(
98 "Invalid road graph settings. Road graph length = ", length_);
99 AERROR << error_msg;
100 return Status(ErrorCode::PREDICTION_ERROR, error_msg);
101 }
102 if (lane_graph_ptr == nullptr) {
103 const auto error_msg = "Invalid input lane graph.";
104 AERROR << error_msg;
105 return Status(ErrorCode::PREDICTION_ERROR, error_msg);
106 }
107
108 // Run the recursive function to perform DFS.
109 std::list<LaneSegment> lane_segments;
110 double accumulated_s = 0.0;
111 ConstructLaneSequence(accumulated_s, start_s_, lane_info_ptr_,
112 FLAGS_road_graph_max_search_horizon, consider_divide_,
113 &lane_segments, lane_graph_ptr);
114
115 return Status::OK();
116}
117
118Status RoadGraph::BuildLaneGraphBidirection(LaneGraph* const lane_graph_ptr) {
119 // Sanity checks.
120 if (length_ < 0.0 || lane_info_ptr_ == nullptr) {
121 const auto error_msg = absl::StrCat(
122 "Invalid road graph settings. Road graph length = ", length_);
123 AERROR << error_msg;
124 return Status(ErrorCode::PREDICTION_ERROR, error_msg);
125 }
126 if (lane_graph_ptr == nullptr) {
127 const auto error_msg = "Invalid input lane graph.";
128 AERROR << error_msg;
129 return Status(ErrorCode::PREDICTION_ERROR, error_msg);
130 }
131
132 // Run the recursive function to perform DFS.
133 std::list<LaneSegment> lane_segments;
134 LaneGraph lane_graph_successor;
135 ConstructLaneSequence(true, 0.0, start_s_, lane_info_ptr_,
136 FLAGS_road_graph_max_search_horizon, consider_divide_,
137 &lane_segments, &lane_graph_successor);
138 lane_segments.clear();
139 LaneGraph lane_graph_predecessor;
140 length_ = length_ / 2.0;
141 ConstructLaneSequence(false, 0.0, start_s_, lane_info_ptr_,
142 FLAGS_road_graph_max_search_horizon, consider_divide_,
143 &lane_segments, &lane_graph_predecessor);
144 *lane_graph_ptr =
145 CombineLaneGraphs(lane_graph_predecessor, lane_graph_successor);
146
147 return Status::OK();
148}
149
150LaneGraph RoadGraph::CombineLaneGraphs(const LaneGraph& lane_graph_predecessor,
151 const LaneGraph& lane_graph_successor) {
152 LaneGraph final_lane_graph;
153 for (const auto& lane_sequence_pre : lane_graph_predecessor.lane_sequence()) {
154 const auto& ending_lane_segment = lane_sequence_pre.lane_segment(
155 lane_sequence_pre.lane_segment_size() - 1);
156 for (const auto& lane_sequence_suc : lane_graph_successor.lane_sequence()) {
157 if (lane_sequence_suc.lane_segment(0).lane_id() ==
158 ending_lane_segment.lane_id()) {
159 LaneSequence* lane_sequence = final_lane_graph.add_lane_sequence();
160 for (const auto& it : lane_sequence_pre.lane_segment()) {
161 *(lane_sequence->add_lane_segment()) = it;
162 }
163 lane_sequence
164 ->mutable_lane_segment(lane_sequence->lane_segment_size() - 1)
165 ->set_end_s(lane_sequence_suc.lane_segment(0).end_s());
166 lane_sequence
167 ->mutable_lane_segment(lane_sequence->lane_segment_size() - 1)
168 ->set_adc_s(lane_sequence_suc.lane_segment(0).start_s());
169 lane_sequence->set_adc_lane_segment_idx(
170 lane_sequence->lane_segment_size() - 1);
171 for (int i = 1; i < lane_sequence_suc.lane_segment_size(); ++i) {
172 *(lane_sequence->add_lane_segment()) =
173 lane_sequence_suc.lane_segment(i);
174 }
175 }
176 }
177 }
178
179 return final_lane_graph;
180}
181
182bool RoadGraph::IsOnLaneGraph(std::shared_ptr<const LaneInfo> lane_info_ptr,
183 const LaneGraph& lane_graph) {
184 if (!lane_graph.IsInitialized()) {
185 return false;
186 }
187
188 for (const auto& lane_sequence : lane_graph.lane_sequence()) {
189 for (const auto& lane_segment : lane_sequence.lane_segment()) {
190 if (lane_segment.has_lane_id() &&
191 lane_segment.lane_id() == lane_info_ptr->id().id()) {
192 return true;
193 }
194 }
195 }
196 return false;
197}
198
199void RoadGraph::ConstructLaneSequence(
200 const double accumulated_s, const double curr_lane_seg_s,
201 std::shared_ptr<const LaneInfo> lane_info_ptr,
202 const int graph_search_horizon, const bool consider_lane_split,
203 std::list<LaneSegment>* const lane_segments,
204 LaneGraph* const lane_graph_ptr) const {
205 ConstructLaneSequence(true, accumulated_s, curr_lane_seg_s, lane_info_ptr,
206 graph_search_horizon, consider_lane_split,
207 lane_segments, lane_graph_ptr);
208}
209
210void RoadGraph::ConstructLaneSequence(
211 const bool search_forward_direction, const double accumulated_s,
212 const double curr_lane_seg_s, std::shared_ptr<const LaneInfo> lane_info_ptr,
213 const int graph_search_horizon, const bool consider_lane_split,
214 std::list<LaneSegment>* const lane_segments,
215 LaneGraph* const lane_graph_ptr) const {
216 // Sanity checks.
217 if (lane_info_ptr == nullptr) {
218 AERROR << "Invalid lane.";
219 return;
220 }
221 if (graph_search_horizon < 0) {
222 AERROR << "The lane search has already reached the limits";
223 AERROR << "Possible map error found!";
224 return;
225 }
226
227 // Create a new lane_segment based on the current lane_info_ptr.
228 double curr_s =
229 curr_lane_seg_s >= 0.0 ? curr_lane_seg_s : lane_info_ptr->total_length();
230 LaneSegment lane_segment;
231 lane_segment.set_adc_s(curr_s);
232 lane_segment.set_lane_id(lane_info_ptr->id().id());
233 lane_segment.set_lane_turn_type(
234 PredictionMap::LaneTurnType(lane_info_ptr->id().id()));
235 lane_segment.set_total_length(lane_info_ptr->total_length());
236 if (search_forward_direction) {
237 lane_segment.set_start_s(curr_s);
238 lane_segment.set_end_s(std::fmin(curr_s + length_ - accumulated_s,
239 lane_info_ptr->total_length()));
240 } else {
241 lane_segment.set_start_s(
242 std::fmax(0.0, curr_s - (length_ - accumulated_s)));
243 lane_segment.set_end_s(curr_s);
244 }
245 if (search_forward_direction) {
246 lane_segments->push_back(std::move(lane_segment));
247 } else {
248 lane_segments->push_front(std::move(lane_segment));
249 }
250
251 // End condition: if search reached the maximum search distance,
252 // or if there is no more successor lane_segment.
253 if (search_forward_direction) {
254 if (lane_segments->back().end_s() < lane_info_ptr->total_length() ||
255 lane_info_ptr->lane().successor_id().empty()) {
256 LaneSequence* sequence = lane_graph_ptr->add_lane_sequence();
257 for (const auto& it : *lane_segments) {
258 *(sequence->add_lane_segment()) = it;
259 }
260 lane_segments->pop_back();
261 return;
262 }
263 } else {
264 if (lane_segments->front().start_s() > 0.0 ||
265 lane_info_ptr->lane().predecessor_id().empty()) {
266 LaneSequence* sequence = lane_graph_ptr->add_lane_sequence();
267 for (const auto& it : *lane_segments) {
268 *(sequence->add_lane_segment()) = it;
269 }
270 lane_segments->pop_front();
271 return;
272 }
273 }
274
275 // Otherwise, continue searching for subsequent lane_segments.
276 double new_accumulated_s = 0.0;
277 double new_lane_seg_s = 0.0;
278 std::vector<std::shared_ptr<const hdmap::LaneInfo>> candidate_lanes;
279 std::set<std::string> set_lane_ids;
280 if (search_forward_direction) {
281 new_accumulated_s = accumulated_s + lane_info_ptr->total_length() - curr_s;
282 // Reundancy removal.
283 for (const auto& successor_lane_id : lane_info_ptr->lane().successor_id()) {
284 set_lane_ids.insert(successor_lane_id.id());
285 }
286 for (const auto& unique_id : set_lane_ids) {
287 candidate_lanes.push_back(PredictionMap::LaneById(unique_id));
288 }
289 // Sort the successor lane_segments from left to right.
290 std::sort(candidate_lanes.begin(), candidate_lanes.end(), IsAtLeft);
291 // Based on other conditions, select what successor lanes should be used.
292 if (!consider_lane_split) {
293 candidate_lanes = {
295 }
296 } else {
297 new_accumulated_s = accumulated_s + curr_s;
298 new_lane_seg_s = -0.1;
299 // Redundancy removal.
300 for (const auto& predecessor_lane_id :
301 lane_info_ptr->lane().predecessor_id()) {
302 set_lane_ids.insert(predecessor_lane_id.id());
303 }
304 for (const auto& unique_id : set_lane_ids) {
305 candidate_lanes.push_back(PredictionMap::LaneById(unique_id));
306 }
307 }
308 bool consider_further_lane_split =
309 !search_forward_direction ||
310 (FLAGS_prediction_offline_mode ==
312 (FLAGS_prediction_offline_mode ==
314 (consider_lane_split && candidate_lanes.size() == 1);
315 // Recursively expand lane-sequence.
316 for (const auto& candidate_lane : candidate_lanes) {
317 ConstructLaneSequence(search_forward_direction, new_accumulated_s,
318 new_lane_seg_s, candidate_lane,
319 graph_search_horizon - 1, consider_further_lane_split,
320 lane_segments, lane_graph_ptr);
321 }
322 if (search_forward_direction) {
323 lane_segments->pop_back();
324 } else {
325 lane_segments->pop_front();
326 }
327}
328
329} // namespace prediction
330} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static int LaneTurnType(const std::string &lane_id)
Get lane turn type.
static std::shared_ptr< const hdmap::LaneInfo > LaneWithSmallestAverageCurvature(const std::vector< std::shared_ptr< const hdmap::LaneInfo > > &lane_infos)
Get the pointer to the lane with the smallest average curvature
static std::shared_ptr< const hdmap::LaneInfo > LaneById(const std::string &id)
Get a shared pointer to a lane by lane ID.
bool IsOnLaneGraph(std::shared_ptr< const hdmap::LaneInfo > lane_info_ptr, const LaneGraph &lane_graph)
Check if a lane with an s is on the lane graph
common::Status BuildLaneGraph(LaneGraph *const lane_graph)
Build the lane graph.
Definition road_graph.cc:94
common::Status BuildLaneGraphBidirection(LaneGraph *const lane_graph_ptr)
RoadGraph(const double start_s, const double length, const bool consider_divide, std::shared_ptr< const hdmap::LaneInfo > lane_info_ptr)
Constructor
Definition road_graph.cc:86
#define AERROR
Definition log.h:44
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
class register implement
Definition arena_queue.h:37
Holds all global constants for the prediction module.
repeated LaneSequence lane_sequence
repeated LaneSegment lane_segment