Apollo 10.0
自动驾驶开放平台
graph_creator.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 <vector>
20
21#include "absl/strings/match.h"
22#include "cyber/common/file.h"
29
30namespace apollo {
31namespace routing {
32
40using ::google::protobuf::RepeatedPtrField;
41
42namespace {
43
44bool IsAllowedToCross(const LaneBoundary& boundary) {
45 for (const auto& boundary_type : boundary.boundary_type()) {
46 if (boundary_type.types(0) != LaneBoundaryType::DOTTED_YELLOW &&
47 boundary_type.types(0) != LaneBoundaryType::DOTTED_WHITE) {
48 return false;
49 }
50 }
51 return true;
52}
53
54} // namespace
55
56GraphCreator::GraphCreator(const std::string& base_map_file_path,
57 const std::string& dump_topo_file_path,
58 const RoutingConfig& routing_conf)
59 : base_map_file_path_(base_map_file_path),
60 dump_topo_file_path_(dump_topo_file_path),
61 routing_conf_(routing_conf) {}
62
64 if (absl::EndsWith(base_map_file_path_, ".xml")) {
65 if (!hdmap::adapter::OpendriveAdapter::LoadData(base_map_file_path_,
66 &pbmap_)) {
67 AERROR << "Failed to load base map file from " << base_map_file_path_;
68 return false;
69 }
70 } else {
71 if (!cyber::common::GetProtoFromFile(base_map_file_path_, &pbmap_)) {
72 AERROR << "Failed to load base map file from " << base_map_file_path_;
73 return false;
74 }
75 }
76
77 AINFO << "Number of lanes: " << pbmap_.lane_size();
78
79 graph_.set_hdmap_version(pbmap_.header().version());
80 graph_.set_hdmap_district(pbmap_.header().district());
81
82 node_index_map_.clear();
83 road_id_map_.clear();
84 showed_edge_id_set_.clear();
85
86 for (const auto& road : pbmap_.road()) {
87 for (const auto& section : road.section()) {
88 for (const auto& lane_id : section.lane_id()) {
89 road_id_map_[lane_id.id()] = road.id().id();
90 }
91 }
92 }
93
94 InitForbiddenLanes();
95 const double min_turn_radius =
97
98 for (const auto& lane : pbmap_.lane()) {
99 const auto& lane_id = lane.id().id();
100 if (forbidden_lane_id_set_.find(lane_id) != forbidden_lane_id_set_.end()) {
101 ADEBUG << "Ignored lane id: " << lane_id
102 << " because its type is NOT CITY_DRIVING.";
103 continue;
104 }
105 if (lane.turn() == hdmap::Lane::U_TURN &&
106 !IsValidUTurn(lane, min_turn_radius)) {
107 ADEBUG << "The u-turn lane radius is too small for the vehicle to turn";
108 continue;
109 }
110 AINFO << "Current lane id: " << lane_id;
111 node_index_map_[lane_id] = graph_.node_size();
112 const auto iter = road_id_map_.find(lane_id);
113 if (iter != road_id_map_.end()) {
114 node_creator::GetPbNode(lane, iter->second, routing_conf_,
115 graph_.add_node());
116 } else {
117 AWARN << "Failed to find road id of lane " << lane_id;
118 node_creator::GetPbNode(lane, "", routing_conf_, graph_.add_node());
119 }
120 }
121
122 for (const auto& lane : pbmap_.lane()) {
123 const auto& lane_id = lane.id().id();
124 if (forbidden_lane_id_set_.find(lane_id) != forbidden_lane_id_set_.end()) {
125 ADEBUG << "Ignored lane id: " << lane_id
126 << " because its type is NOT CITY_DRIVING.";
127 continue;
128 }
129 const auto& from_node = graph_.node(node_index_map_[lane_id]);
130
131 AddEdge(from_node, lane.successor_id(), Edge::FORWARD);
132 if (lane.length() < FLAGS_min_length_for_lane_change) {
133 continue;
134 }
135 if (lane.has_left_boundary() && IsAllowedToCross(lane.left_boundary())) {
136 AddEdge(from_node, lane.left_neighbor_forward_lane_id(), Edge::LEFT);
137 }
138
139 if (lane.has_right_boundary() && IsAllowedToCross(lane.right_boundary())) {
140 AddEdge(from_node, lane.right_neighbor_forward_lane_id(), Edge::RIGHT);
141 }
142 }
143
144 if (!absl::EndsWith(dump_topo_file_path_, ".bin") &&
145 !absl::EndsWith(dump_topo_file_path_, ".txt")) {
146 AERROR << "Failed to dump topo data into file, incorrect file type "
147 << dump_topo_file_path_;
148 return false;
149 }
150 auto type_pos = dump_topo_file_path_.find_last_of(".") + 1;
151 std::string bin_file = dump_topo_file_path_.replace(type_pos, 3, "bin");
152 std::string txt_file = dump_topo_file_path_.replace(type_pos, 3, "txt");
153 if (!cyber::common::SetProtoToASCIIFile(graph_, txt_file)) {
154 AERROR << "Failed to dump topo data into file " << txt_file;
155 return false;
156 }
157 AINFO << "Txt file is dumped successfully. Path: " << txt_file;
158 if (!cyber::common::SetProtoToBinaryFile(graph_, bin_file)) {
159 AERROR << "Failed to dump topo data into file " << bin_file;
160 return false;
161 }
162 AINFO << "Bin file is dumped successfully. Path: " << bin_file;
163 return true;
164}
165
166std::string GraphCreator::GetEdgeID(const std::string& from_id,
167 const std::string& to_id) {
168 return from_id + "->" + to_id;
169}
170
171void GraphCreator::AddEdge(const Node& from_node,
172 const RepeatedPtrField<Id>& to_node_vec,
173 const Edge::DirectionType& type) {
174 for (const auto& to_id : to_node_vec) {
175 if (forbidden_lane_id_set_.find(to_id.id()) !=
176 forbidden_lane_id_set_.end()) {
177 ADEBUG << "Ignored lane [id = " << to_id.id();
178 continue;
179 }
180 const std::string edge_id = GetEdgeID(from_node.lane_id(), to_id.id());
181 if (showed_edge_id_set_.count(edge_id) != 0) {
182 continue;
183 }
184 showed_edge_id_set_.insert(edge_id);
185 const auto& iter = node_index_map_.find(to_id.id());
186 if (iter == node_index_map_.end()) {
187 continue;
188 }
189 const auto& to_node = graph_.node(iter->second);
190 edge_creator::GetPbEdge(from_node, to_node, type, routing_conf_,
191 graph_.add_edge());
192 }
193}
194
195bool GraphCreator::IsValidUTurn(const hdmap::Lane& lane, const double radius) {
196 if (lane.turn() != hdmap::Lane::U_TURN) { // not a u-turn
197 return false;
198 }
199 // approximate the radius from start point, middle point and end point.
200 if (lane.central_curve().segment().empty() ||
201 !lane.central_curve().segment(0).has_line_segment()) {
202 return false;
203 }
204 std::vector<PointENU> points;
205 for (const auto& segment : lane.central_curve().segment()) {
206 points.insert(points.end(), segment.line_segment().point().begin(),
207 segment.line_segment().point().end());
208 }
209 if (points.empty()) {
210 return false;
211 }
212 Vec2d p1{points.front().x(), points.front().y()};
213 const auto& mid = points[points.size() / 2];
214 Vec2d p2{mid.x(), mid.y()};
215 Vec2d p3{points.back().x(), points.back().y()};
216 Vec2d q1 = ((p1 + p2) / 2); // middle of p1---p2
217 Vec2d q2 = (p2 - p1).rotate(M_PI / 2) + q1; // perpendicular to p1-p2
218 Vec2d q3 = ((p2 + p3) / 2); // middle of p2 -- p3
219 Vec2d q4 = (p3 - p2).rotate(M_PI / 2) + q3; // perpendicular to p2-p3
220 const double s1 = CrossProd(q3, q1, q2);
221 if (std::fabs(s1) < kMathEpsilon) { // q3 is the circle center
222 return q3.DistanceTo(p1) >= radius;
223 }
224 const double s2 = CrossProd(q4, q1, q2);
225 if (std::fabs(s2) < kMathEpsilon) { // q4 is the circle center
226 return q4.DistanceTo(p1) >= radius;
227 }
228 if (std::fabs(s1 - s2) < kMathEpsilon) { // parallel case, a wide u-turn
229 return true;
230 }
231 Vec2d center = q3 + (q4 - q3) * s1 / (s1 - s2);
232 return p1.DistanceTo(center) >= radius;
233}
234
235void GraphCreator::InitForbiddenLanes() {
236 for (const auto& lane : pbmap_.lane()) {
237 if (lane.type() != hdmap::Lane::CITY_DRIVING) {
238 forbidden_lane_id_set_.insert(lane.id().id());
239 }
240 }
241}
242
243} // namespace routing
244} // namespace apollo
Definition node.h:31
@Brief This is a helper class that can load vehicle configurations.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
static bool LoadData(const std::string &filename, apollo::hdmap::Map *pb_map)
GraphCreator(const std::string &base_map_file_path, const std::string &dump_topo_file_path, const RoutingConfig &routing_conf)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
Math-related util functions.
constexpr double kMathEpsilon
Definition vec2d.h:35
double CrossProd(const Vec2d &start_point, const Vec2d &end_point_1, const Vec2d &end_point_2)
Cross product between two 2-D vectors from the common start point, and end at two other points.
Definition math_utils.cc:28
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
bool SetProtoToBinaryFile(const google::protobuf::Message &message, const std::string &file_name)
Sets the content of the file specified by the file_name to be the binary representation of the input ...
Definition file.cc:111
bool SetProtoToASCIIFile(const google::protobuf::Message &message, int file_descriptor)
Definition file.cc:43
void GetPbEdge(const Node &node_from, const Node &node_to, const Edge::DirectionType &type, const RoutingConfig &routing_config, Edge *edge)
void GetPbNode(const hdmap::Lane &lane, const std::string &road_id, const RoutingConfig &routingconfig, Node *const node)
class register implement
Definition arena_queue.h:37
optional VehicleParam vehicle_param
optional bytes version
Definition map.proto:30
optional bytes district
Definition map.proto:33
optional Header header
Definition map.proto:45
repeated Lane lane
Definition map.proto:49
repeated Road road
Definition map.proto:56