utilities.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. * Copyright 2015-2019 Autoware Foundation. 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. * Authors: Kenji Miyake, Ryohsuke Mitsudome
  17. *
  18. */
  19. #include <lanelet2_core/geometry/LineString.h>
  20. #include <lanelet2_core/primitives/BasicRegulatoryElements.h>
  21. #include <lanelet2_traffic_rules/TrafficRules.h>
  22. #include <lanelet2_traffic_rules/TrafficRulesFactory.h>
  23. #include <lanelet2_extension/utility/utilities.h>
  24. #include <ros/ros.h>
  25. #include <algorithm>
  26. #include <map>
  27. #include <utility>
  28. #include <vector>
  29. namespace lanelet
  30. {
  31. namespace utils
  32. {
  33. namespace
  34. {
  35. bool exists(const std::vector<int>& array, const int element)
  36. {
  37. return std::find(array.begin(), array.end(), element) != array.end();
  38. }
  39. /**
  40. * [removeImpossibleCandidates eliminates the impossible lanelet id candidates
  41. * according to lanelet routing graph information ]
  42. * @method removeImpossibleCandidates
  43. * @param waypoints [list of waypoints]
  44. * @param wp_candidate_lanelets list of lanelet id candidates for each
  45. * waypoint
  46. */
  47. void removeImpossibleCandidates(const lanelet::LaneletMapPtr lanelet_map,
  48. const lanelet::routing::RoutingGraphPtr routing_graph,
  49. const std::vector<autoware_msgs::Waypoint>& waypoints,
  50. std::map<int, std::vector<int> >* wp_candidate_lanelets, const bool reverse)
  51. {
  52. if (!lanelet_map)
  53. {
  54. ROS_ERROR_STREAM("No lanelet map is set!");
  55. return;
  56. }
  57. int prev_wp_gid;
  58. bool first_wp = true;
  59. for (const auto& wp : waypoints)
  60. {
  61. if (first_wp)
  62. {
  63. prev_wp_gid = wp.gid;
  64. first_wp = false;
  65. continue;
  66. }
  67. auto candidate_ids_ptr = &wp_candidate_lanelets->at(wp.gid);
  68. const auto prev_wp_candidate_ids_ptr = &wp_candidate_lanelets->at(prev_wp_gid);
  69. // do not eliminate if previous waypoint do not have any candidate
  70. if (prev_wp_candidate_ids_ptr->empty())
  71. continue;
  72. std::vector<int> removing_ids;
  73. for (const auto candidate_id : *candidate_ids_ptr)
  74. {
  75. // do not eliminate if the belonging lane exists in candidates of previous
  76. // waypoint
  77. if (exists(*prev_wp_candidate_ids_ptr, candidate_id))
  78. continue;
  79. auto lanelet = lanelet_map->laneletLayer.get(candidate_id);
  80. // get available previous lanelet from routing graph
  81. lanelet::ConstLanelets previous_lanelets;
  82. if (reverse)
  83. {
  84. previous_lanelets = routing_graph->following(lanelet);
  85. }
  86. else
  87. {
  88. previous_lanelets = routing_graph->previous(lanelet);
  89. }
  90. // connection is impossible if none of predecessor lanelets match with
  91. // lanelet candidates from previous waypoint
  92. bool connection_possible = false;
  93. for (const auto& previous_lanelet : previous_lanelets)
  94. {
  95. if (exists(*prev_wp_candidate_ids_ptr, previous_lanelet.id()))
  96. {
  97. connection_possible = true;
  98. break;
  99. }
  100. }
  101. if (!connection_possible)
  102. {
  103. removing_ids.push_back(candidate_id);
  104. }
  105. }
  106. // declare function for remove_if separately, because roslint is not supporting lambda functions very well.
  107. auto remove_existing_func = [removing_ids](int id) { return exists(removing_ids, id); };
  108. auto result = std::remove_if(candidate_ids_ptr->begin(), candidate_ids_ptr->end(), remove_existing_func);
  109. candidate_ids_ptr->erase(result, candidate_ids_ptr->end());
  110. prev_wp_gid = wp.gid;
  111. }
  112. }
  113. /**
  114. * [getContactingLanelets retrieves id of lanelets which has distance 0m to
  115. * search_point]
  116. * @param lanelet_map [pointer to lanelet]
  117. * @param trafficRules [traffic rules to ignore lanelets that are not
  118. * traversible]
  119. * @param search_point [2D point used for searching]
  120. * @param search_n [initial guess used for findNearest function (default
  121. * 5)]
  122. * @param contacting_lanelet_ids [array of lanelet ids that is contacting with
  123. * search_point]
  124. */
  125. void getContactingLanelets(const lanelet::LaneletMapPtr lanelet_map,
  126. const lanelet::traffic_rules::TrafficRulesPtr traffic_rules,
  127. const lanelet::BasicPoint2d search_point, const int search_n,
  128. std::vector<int>* contacting_lanelet_ids)
  129. {
  130. if (!lanelet_map)
  131. {
  132. ROS_ERROR_STREAM("No lanelet map is set!");
  133. return;
  134. }
  135. if (contacting_lanelet_ids == nullptr)
  136. {
  137. ROS_ERROR_STREAM(__FUNCTION__ << " contacting_lanelet_ids is null pointer!");
  138. return;
  139. }
  140. int n = search_n;
  141. double max_distance = 0.0;
  142. const int increment = 3;
  143. const double epsilon = 1e-6;
  144. std::vector<std::pair<double, lanelet::Lanelet> > actuallyNearestLanelets;
  145. // keep searching nearest lanelet as long as all retrieved lanelet has
  146. // distance == 0m.
  147. while (max_distance < epsilon)
  148. {
  149. actuallyNearestLanelets = lanelet::geometry::findNearest(lanelet_map->laneletLayer, search_point, n);
  150. max_distance = 0.0;
  151. for (auto const& item : actuallyNearestLanelets)
  152. {
  153. if (item.first > max_distance)
  154. {
  155. max_distance = item.first;
  156. }
  157. }
  158. // exit loop if all lanelets in the map intersects with the waypoint,
  159. // e.g. when there is only one lanelet in the map.
  160. if (actuallyNearestLanelets.size() < n)
  161. {
  162. break;
  163. }
  164. n += increment;
  165. }
  166. contacting_lanelet_ids->reserve(n - increment);
  167. for (auto const& item : actuallyNearestLanelets)
  168. {
  169. if (item.first < epsilon && traffic_rules->canPass(item.second))
  170. {
  171. contacting_lanelet_ids->push_back(item.second.id());
  172. }
  173. }
  174. }
  175. std::vector<double> calculateSegmentDistances(const lanelet::ConstLineString3d& line_string)
  176. {
  177. std::vector<double> segment_distances;
  178. segment_distances.reserve(line_string.size() - 1);
  179. for (size_t i = 1; i < line_string.size(); ++i)
  180. {
  181. const auto distance = lanelet::geometry::distance2d(line_string[i], line_string[i - 1]);
  182. segment_distances.push_back(distance);
  183. }
  184. return segment_distances;
  185. }
  186. std::vector<double> calculateAccumulatedLengths(const lanelet::ConstLineString3d& line_string)
  187. {
  188. const auto segment_distances = calculateSegmentDistances(line_string);
  189. std::vector<double> accumulated_lengths{ 0 };
  190. accumulated_lengths.reserve(segment_distances.size() + 1);
  191. std::partial_sum(std::begin(segment_distances), std::end(segment_distances), std::back_inserter(accumulated_lengths));
  192. return accumulated_lengths;
  193. }
  194. std::pair<size_t, size_t> findNearestIndexPair(const std::vector<double>& accumulated_lengths,
  195. const double target_length)
  196. {
  197. // List size
  198. const auto N = accumulated_lengths.size();
  199. // Front
  200. if (target_length < accumulated_lengths.at(1))
  201. {
  202. return std::make_pair(0, 1);
  203. }
  204. // Back
  205. if (target_length > accumulated_lengths.at(N - 2))
  206. {
  207. return std::make_pair(N - 2, N - 1);
  208. }
  209. // Middle
  210. for (auto i = 1; i < N; ++i)
  211. {
  212. if (accumulated_lengths.at(i - 1) <= target_length && target_length <= accumulated_lengths.at(i))
  213. {
  214. return std::make_pair(i - 1, i);
  215. }
  216. }
  217. // Throw an exception because this never happens
  218. throw std::runtime_error("No nearest point found.");
  219. }
  220. std::vector<lanelet::BasicPoint3d> resamplePoints(const lanelet::ConstLineString3d& line_string, const int num_segments)
  221. {
  222. // Calculate length
  223. const auto line_length = lanelet::geometry::length(line_string);
  224. // Calculate accumulated lengths
  225. const auto accumulated_lengths = calculateAccumulatedLengths(line_string);
  226. // Create each segment
  227. std::vector<lanelet::BasicPoint3d> resampled_points;
  228. for (auto i = 0; i <= num_segments; ++i)
  229. {
  230. // Find two nearest points
  231. const auto target_length = (static_cast<double>(i) / num_segments) * line_length;
  232. const auto index_pair = findNearestIndexPair(accumulated_lengths, target_length);
  233. // Apply linear interpolation
  234. const lanelet::BasicPoint3d back_point = line_string[index_pair.first];
  235. const lanelet::BasicPoint3d front_point = line_string[index_pair.second];
  236. const auto direction_vector = (front_point - back_point);
  237. const auto back_length = accumulated_lengths.at(index_pair.first);
  238. const auto front_length = accumulated_lengths.at(index_pair.second);
  239. const auto segment_length = front_length - back_length;
  240. const auto target_point = back_point + (direction_vector * (target_length - back_length) / segment_length);
  241. // Add to list
  242. resampled_points.push_back(target_point);
  243. }
  244. return resampled_points;
  245. }
  246. lanelet::LineString3d generateFineCenterline(const lanelet::ConstLanelet& lanelet_obj)
  247. {
  248. // Parameter
  249. constexpr double point_interval = 1.0; // [m]
  250. // Get length of longer border
  251. const double left_length = lanelet::geometry::length(lanelet_obj.leftBound());
  252. const double right_length = lanelet::geometry::length(lanelet_obj.rightBound());
  253. const double longer_distance = (left_length > right_length) ? left_length : right_length;
  254. const int num_segments = std::max(static_cast<int>(ceil(longer_distance / point_interval)), 1);
  255. // Resample points
  256. const auto left_points = resamplePoints(lanelet_obj.leftBound(), num_segments);
  257. const auto right_points = resamplePoints(lanelet_obj.rightBound(), num_segments);
  258. // Create centerline
  259. lanelet::LineString3d centerline(lanelet::utils::getId());
  260. for (int i = 0; i < num_segments + 1; i++)
  261. {
  262. // Add ID for the average point of left and right
  263. const auto center_basic_point = (right_points.at(i) + left_points.at(i)) / 2;
  264. const lanelet::Point3d center_point(lanelet::utils::getId(), center_basic_point.x(), center_basic_point.y(),
  265. center_basic_point.z());
  266. centerline.push_back(center_point);
  267. }
  268. return centerline;
  269. }
  270. } // namespace
  271. void matchWaypointAndLanelet(const lanelet::LaneletMapPtr lanelet_map,
  272. const lanelet::routing::RoutingGraphPtr routing_graph,
  273. const autoware_msgs::LaneArray& lane_array,
  274. std::map<int, lanelet::Id>* waypointid2laneletid)
  275. {
  276. if (!lanelet_map)
  277. {
  278. ROS_ERROR_STREAM("No lanelet map is set!");
  279. return;
  280. }
  281. if (waypointid2laneletid == nullptr)
  282. {
  283. ROS_ERROR_STREAM(__FUNCTION__ << ": waypointid2laneletid null pointer!");
  284. return;
  285. }
  286. // map of waypoint_id to lanelet_id
  287. // first item = gid of waypoint
  288. // second item = lanelet_ids
  289. std::map<int, std::vector<int> > wp_candidate_lanelet_ids;
  290. lanelet::traffic_rules::TrafficRulesPtr traffic_rules =
  291. lanelet::traffic_rules::TrafficRulesFactory::create(lanelet::Locations::Germany, lanelet::Participants::Vehicle);
  292. // get possible candidates of lanelets for each waypoint
  293. // "candidate lanelets" means lanelets that have 0 distance with waypoint.
  294. // multiple candidates could appear at intersections.
  295. for (auto& lane : lane_array.lanes)
  296. {
  297. for (auto& wp : lane.waypoints)
  298. {
  299. std::vector<int> contacting_lanelet_ids;
  300. lanelet::BasicPoint2d search_point(wp.pose.pose.position.x, wp.pose.pose.position.y);
  301. getContactingLanelets(lanelet_map, traffic_rules, search_point, 5, &contacting_lanelet_ids);
  302. wp_candidate_lanelet_ids[wp.gid] = contacting_lanelet_ids;
  303. }
  304. }
  305. // eliminate impossible candidates using routing graph. (forward direction)
  306. for (const auto& lane : lane_array.lanes)
  307. {
  308. removeImpossibleCandidates(lanelet_map, routing_graph, lane.waypoints, &wp_candidate_lanelet_ids, false);
  309. }
  310. // eliminate impossible candidates using routing graph. (reverse direction)
  311. for (const auto& lane : lane_array.lanes)
  312. {
  313. auto reverse_waypoints = lane.waypoints;
  314. std::reverse(reverse_waypoints.begin(), reverse_waypoints.end());
  315. removeImpossibleCandidates(lanelet_map, routing_graph, reverse_waypoints, &wp_candidate_lanelet_ids, true);
  316. }
  317. for (auto candidate : wp_candidate_lanelet_ids)
  318. {
  319. if (candidate.second.empty())
  320. {
  321. ROS_WARN_STREAM("No lanelet was matched for waypoint with gid: " << candidate.first);
  322. continue;
  323. }
  324. if (candidate.second.size() >= 2)
  325. {
  326. ROS_WARN("ambiguous waypoint. Randomly choosing from candidates");
  327. }
  328. (*waypointid2laneletid)[candidate.first] = candidate.second.front();
  329. }
  330. }
  331. void overwriteLaneletsCenterline(lanelet::LaneletMapPtr lanelet_map, const bool force_overwrite)
  332. {
  333. for (auto& lanelet_obj : lanelet_map->laneletLayer)
  334. {
  335. if (force_overwrite || !lanelet_obj.hasCustomCenterline())
  336. {
  337. const auto fine_center_line = generateFineCenterline(lanelet_obj);
  338. lanelet_obj.setCenterline(fine_center_line);
  339. }
  340. }
  341. }
  342. } // namespace utils
  343. } // namespace lanelet