Apollo 10.0
自动驾驶开放平台
sub_topo_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 <cmath>
21#include <utility>
22
24
25namespace apollo {
26namespace routing {
27
28namespace {
29
30const double MIN_DIFF_LENGTH = 0.1e-6; // in meters
31const double MIN_INTERNAL_FOR_NODE = 0.01; // in meters
32const double MIN_POTENTIAL_LANE_CHANGE_LEN = 3.0; // in meters
33
34bool IsCloseEnough(double s1, double s2) {
35 return std::fabs(s1 - s2) < MIN_DIFF_LENGTH;
36}
37
38void MergeBlockRange(const TopoNode* topo_node,
39 const std::vector<NodeSRange>& origin_range,
40 std::vector<NodeSRange>* block_range) {
41 std::vector<NodeSRange> sorted_origin_range;
42 sorted_origin_range.insert(sorted_origin_range.end(), origin_range.begin(),
43 origin_range.end());
44 sort(sorted_origin_range.begin(), sorted_origin_range.end());
45 int cur_index = 0;
46 int total_size = static_cast<int>(sorted_origin_range.size());
47 while (cur_index < total_size) {
48 NodeSRange range(sorted_origin_range[cur_index]);
49 ++cur_index;
50 while (cur_index < total_size &&
51 range.MergeRangeOverlap(sorted_origin_range[cur_index])) {
52 ++cur_index;
53 }
54 if (range.EndS() < topo_node->StartS() ||
55 range.StartS() > topo_node->EndS()) {
56 continue;
57 }
58 range.SetStartS(std::max(topo_node->StartS(), range.StartS()));
59 range.SetEndS(std::min(topo_node->EndS(), range.EndS()));
60 block_range->push_back(std::move(range));
61 }
62}
63
64void GetSortedValidRange(const TopoNode* topo_node,
65 const std::vector<NodeSRange>& origin_range,
66 std::vector<NodeSRange>* valid_range) {
67 std::vector<NodeSRange> block_range;
68 MergeBlockRange(topo_node, origin_range, &block_range);
69 double start_s = topo_node->StartS();
70 double end_s = topo_node->EndS();
71 std::vector<double> all_value;
72 all_value.push_back(start_s);
73 for (const auto& range : block_range) {
74 all_value.push_back(range.StartS());
75 all_value.push_back(range.EndS());
76 }
77 all_value.push_back(end_s);
78 for (size_t i = 0; i < all_value.size(); i += 2) {
79 NodeSRange new_range(all_value[i], all_value[i + 1]);
80 valid_range->push_back(std::move(new_range));
81 }
82}
83
84bool IsReachable(const TopoNode* from_node, const TopoNode* to_node) {
85 double start_s = to_node->StartS() / to_node->Length() * from_node->Length();
86 start_s = std::max(start_s, from_node->StartS());
87 double end_s = to_node->EndS() / to_node->Length() * from_node->Length();
88 end_s = std::min(end_s, from_node->EndS());
89 return (end_s - start_s > MIN_POTENTIAL_LANE_CHANGE_LEN);
90}
91
92} // namespace
93
95 const std::unordered_map<const TopoNode*, std::vector<NodeSRange>>&
96 black_map) {
97 std::vector<NodeSRange> valid_range;
98 for (const auto& map_iter : black_map) {
99 valid_range.clear();
100 GetSortedValidRange(map_iter.first, map_iter.second, &valid_range);
101 InitSubNodeByValidRange(map_iter.first, valid_range);
102 }
103
104 for (const auto& map_iter : black_map) {
105 InitSubEdge(map_iter.first);
106 }
107
108 for (const auto& map_iter : black_map) {
109 AddPotentialEdge(map_iter.first);
110 }
111}
112
114
116 const TopoEdge* edge,
117 std::unordered_set<const TopoEdge*>* const sub_edges) const {
118 const auto* from_node = edge->FromNode();
119 const auto* to_node = edge->ToNode();
120 std::unordered_set<TopoNode*> sub_nodes;
121 if (from_node->IsSubNode() || to_node->IsSubNode() ||
122 !GetSubNodes(to_node, &sub_nodes)) {
123 sub_edges->insert(edge);
124 return;
125 }
126 for (const auto* sub_node : sub_nodes) {
127 for (const auto* in_edge : sub_node->InFromAllEdge()) {
128 if (in_edge->FromNode() == from_node) {
129 sub_edges->insert(in_edge);
130 }
131 }
132 }
133}
134
136 const TopoEdge* edge,
137 std::unordered_set<const TopoEdge*>* const sub_edges) const {
138 const auto* from_node = edge->FromNode();
139 const auto* to_node = edge->ToNode();
140 std::unordered_set<TopoNode*> sub_nodes;
141 if (from_node->IsSubNode() || to_node->IsSubNode() ||
142 !GetSubNodes(from_node, &sub_nodes)) {
143 sub_edges->insert(edge);
144 return;
145 }
146 for (const auto* sub_node : sub_nodes) {
147 for (const auto* out_edge : sub_node->OutToAllEdge()) {
148 if (out_edge->ToNode() == to_node) {
149 sub_edges->insert(out_edge);
150 }
151 }
152 }
153}
154
156 double s) const {
157 const auto& map_iter = sub_node_range_sorted_map_.find(topo_node);
158 if (map_iter == sub_node_range_sorted_map_.end()) {
159 return topo_node;
160 }
161 const auto& sorted_vec = map_iter->second;
162 // sorted vec can't be empty!
163 int index = BinarySearchForStartS(sorted_vec, s);
164 if (index < 0) {
165 return nullptr;
166 }
167 return sorted_vec[index].GetTopoNode();
168}
169
170void SubTopoGraph::InitSubNodeByValidRange(
171 const TopoNode* topo_node, const std::vector<NodeSRange>& valid_range) {
172 // Attention: no matter topo node has valid_range or not,
173 // create map value first;
174 auto& sub_node_vec = sub_node_range_sorted_map_[topo_node];
175 auto& sub_node_set = sub_node_map_[topo_node];
176
177 std::vector<TopoNode*> sub_node_sorted_vec;
178 for (const auto& range : valid_range) {
179 if (range.Length() < MIN_INTERNAL_FOR_NODE) {
180 continue;
181 }
182 std::shared_ptr<TopoNode> sub_topo_node_ptr;
183 sub_topo_node_ptr.reset(new TopoNode(topo_node, range));
184 sub_node_vec.emplace_back(sub_topo_node_ptr.get(), range);
185 sub_node_set.insert(sub_topo_node_ptr.get());
186 sub_node_sorted_vec.push_back(sub_topo_node_ptr.get());
187 topo_nodes_.push_back(std::move(sub_topo_node_ptr));
188 }
189
190 for (size_t i = 1; i < sub_node_sorted_vec.size(); ++i) {
191 auto* pre_node = sub_node_sorted_vec[i - 1];
192 auto* next_node = sub_node_sorted_vec[i];
193 if (IsCloseEnough(pre_node->EndS(), next_node->StartS())) {
194 Edge edge;
195 edge.set_from_lane_id(topo_node->LaneId());
196 edge.set_to_lane_id(topo_node->LaneId());
197 edge.set_direction_type(Edge::FORWARD);
198 edge.set_cost(0.0);
199 std::shared_ptr<TopoEdge> topo_edge_ptr;
200 topo_edge_ptr.reset(new TopoEdge(edge, pre_node, next_node));
201 pre_node->AddOutEdge(topo_edge_ptr.get());
202 next_node->AddInEdge(topo_edge_ptr.get());
203 topo_edges_.push_back(std::move(topo_edge_ptr));
204 }
205 }
206}
207
208void SubTopoGraph::InitSubEdge(const TopoNode* topo_node) {
209 std::unordered_set<TopoNode*> sub_nodes;
210 if (!GetSubNodes(topo_node, &sub_nodes)) {
211 return;
212 }
213
214 for (auto* sub_node : sub_nodes) {
215 InitInSubNodeSubEdge(sub_node, topo_node->InFromAllEdge());
216 InitOutSubNodeSubEdge(sub_node, topo_node->OutToAllEdge());
217 }
218}
219
220void SubTopoGraph::InitInSubNodeSubEdge(
221 TopoNode* const sub_node,
222 const std::unordered_set<const TopoEdge*> origin_edge) {
223 std::unordered_set<TopoNode*> other_sub_nodes;
224 for (const auto* in_edge : origin_edge) {
225 if (GetSubNodes(in_edge->FromNode(), &other_sub_nodes)) {
226 for (auto* sub_from_node : other_sub_nodes) {
227 if (!sub_from_node->IsOverlapEnough(sub_node, in_edge)) {
228 continue;
229 }
230 std::shared_ptr<TopoEdge> topo_edge_ptr;
231 topo_edge_ptr.reset(
232 new TopoEdge(in_edge->PbEdge(), sub_from_node, sub_node));
233 sub_node->AddInEdge(topo_edge_ptr.get());
234 sub_from_node->AddOutEdge(topo_edge_ptr.get());
235 topo_edges_.push_back(std::move(topo_edge_ptr));
236 }
237 } else if (in_edge->FromNode()->IsOverlapEnough(sub_node, in_edge)) {
238 std::shared_ptr<TopoEdge> topo_edge_ptr;
239 topo_edge_ptr.reset(
240 new TopoEdge(in_edge->PbEdge(), in_edge->FromNode(), sub_node));
241 sub_node->AddInEdge(topo_edge_ptr.get());
242 topo_edges_.push_back(std::move(topo_edge_ptr));
243 }
244 }
245}
246
247void SubTopoGraph::InitOutSubNodeSubEdge(
248 TopoNode* const sub_node,
249 const std::unordered_set<const TopoEdge*> origin_edge) {
250 std::unordered_set<TopoNode*> other_sub_nodes;
251 for (const auto* out_edge : origin_edge) {
252 if (GetSubNodes(out_edge->ToNode(), &other_sub_nodes)) {
253 for (auto* sub_to_node : other_sub_nodes) {
254 if (!sub_node->IsOverlapEnough(sub_to_node, out_edge)) {
255 continue;
256 }
257 std::shared_ptr<TopoEdge> topo_edge_ptr;
258 topo_edge_ptr.reset(
259 new TopoEdge(out_edge->PbEdge(), sub_node, sub_to_node));
260 sub_node->AddOutEdge(topo_edge_ptr.get());
261 sub_to_node->AddInEdge(topo_edge_ptr.get());
262 topo_edges_.push_back(std::move(topo_edge_ptr));
263 }
264 } else if (sub_node->IsOverlapEnough(out_edge->ToNode(), out_edge)) {
265 std::shared_ptr<TopoEdge> topo_edge_ptr;
266 topo_edge_ptr.reset(
267 new TopoEdge(out_edge->PbEdge(), sub_node, out_edge->ToNode()));
268 sub_node->AddOutEdge(topo_edge_ptr.get());
269 topo_edges_.push_back(std::move(topo_edge_ptr));
270 }
271 }
272}
273
274bool SubTopoGraph::GetSubNodes(
275 const TopoNode* node,
276 std::unordered_set<TopoNode*>* const sub_nodes) const {
277 const auto& iter = sub_node_map_.find(node);
278 if (iter == sub_node_map_.end()) {
279 return false;
280 }
281 sub_nodes->clear();
282 sub_nodes->insert(iter->second.begin(), iter->second.end());
283 return true;
284}
285
286void SubTopoGraph::AddPotentialEdge(const TopoNode* topo_node) {
287 std::unordered_set<TopoNode*> sub_nodes;
288 if (!GetSubNodes(topo_node, &sub_nodes)) {
289 return;
290 }
291 for (auto* sub_node : sub_nodes) {
292 AddPotentialInEdge(sub_node, topo_node->InFromLeftOrRightEdge());
293 AddPotentialOutEdge(sub_node, topo_node->OutToLeftOrRightEdge());
294 }
295}
296
297void SubTopoGraph::AddPotentialInEdge(
298 TopoNode* const sub_node,
299 const std::unordered_set<const TopoEdge*> origin_edge) {
300 std::unordered_set<TopoNode*> other_sub_nodes;
301 for (const auto* in_edge : origin_edge) {
302 if (GetSubNodes(in_edge->FromNode(), &other_sub_nodes)) {
303 for (auto* sub_from_node : other_sub_nodes) {
304 if (sub_node->GetInEdgeFrom(sub_from_node) != nullptr) {
305 continue;
306 }
307 if (!IsReachable(sub_from_node, sub_node)) {
308 continue;
309 }
310 std::shared_ptr<TopoEdge> topo_edge_ptr;
311 topo_edge_ptr.reset(
312 new TopoEdge(in_edge->PbEdge(), sub_from_node, sub_node));
313 sub_node->AddInEdge(topo_edge_ptr.get());
314 sub_from_node->AddOutEdge(topo_edge_ptr.get());
315 topo_edges_.push_back(std::move(topo_edge_ptr));
316 }
317 } else {
318 if (sub_node->GetInEdgeFrom(in_edge->FromNode()) != nullptr) {
319 continue;
320 }
321 std::shared_ptr<TopoEdge> topo_edge_ptr;
322 topo_edge_ptr.reset(
323 new TopoEdge(in_edge->PbEdge(), in_edge->FromNode(), sub_node));
324 sub_node->AddInEdge(topo_edge_ptr.get());
325 topo_edges_.push_back(std::move(topo_edge_ptr));
326 }
327 }
328}
329
330void SubTopoGraph::AddPotentialOutEdge(
331 TopoNode* const sub_node,
332 const std::unordered_set<const TopoEdge*> origin_edge) {
333 std::unordered_set<TopoNode*> other_sub_nodes;
334 for (const auto* out_edge : origin_edge) {
335 if (GetSubNodes(out_edge->ToNode(), &other_sub_nodes)) {
336 for (auto* sub_to_node : other_sub_nodes) {
337 if (sub_node->GetOutEdgeTo(sub_to_node) != nullptr) {
338 continue;
339 }
340 if (!IsReachable(sub_node, sub_to_node)) {
341 continue;
342 }
343 std::shared_ptr<TopoEdge> topo_edge_ptr;
344 topo_edge_ptr.reset(
345 new TopoEdge(out_edge->PbEdge(), sub_node, sub_to_node));
346 sub_node->AddOutEdge(topo_edge_ptr.get());
347 sub_to_node->AddInEdge(topo_edge_ptr.get());
348 topo_edges_.push_back(std::move(topo_edge_ptr));
349 }
350 } else {
351 if (sub_node->GetOutEdgeTo(out_edge->ToNode()) != nullptr) {
352 continue;
353 }
354 std::shared_ptr<TopoEdge> topo_edge_ptr;
355 topo_edge_ptr.reset(
356 new TopoEdge(out_edge->PbEdge(), sub_node, out_edge->ToNode()));
357 sub_node->AddOutEdge(topo_edge_ptr.get());
358 topo_edges_.push_back(std::move(topo_edge_ptr));
359 }
360 }
361}
362
363} // namespace routing
364} // namespace apollo
const TopoNode * topo_node
void GetSubInEdgesIntoSubGraph(const TopoEdge *edge, std::unordered_set< const TopoEdge * > *const sub_edges) const
const TopoNode * GetSubNodeWithS(const TopoNode *topo_node, double s) const
SubTopoGraph(const std::unordered_map< const TopoNode *, std::vector< NodeSRange > > &black_map)
void GetSubOutEdgesIntoSubGraph(const TopoEdge *edge, std::unordered_set< const TopoEdge * > *const sub_edges) const
const TopoNode * ToNode() const
Definition topo_node.cc:324
const TopoNode * FromNode() const
Definition topo_node.cc:322
bool IsCloseEnough(double value_1, double value_2)
int BinarySearchForStartS(const std::vector< T > &sorted_vec, double value_s)
Definition range_utils.h:91
class register implement
Definition arena_queue.h:37