17#include <boost/archive/binary_iarchive.hpp>
18#include <boost/archive/binary_oarchive.hpp>
21#include <j2735_v2x_msgs/msg/lane_type_attributes.hpp>
59 const std::shared_ptr<lanelet::LaneletMap>& map, std::shared_ptr<const lanelet::routing::RoutingGraph> current_routing_graph)
61 std::unordered_map<uint8_t, std::unordered_set<uint16_t>> signal_group_to_exit_lanes;
62 std::unordered_map<uint8_t, std::unordered_set<uint16_t>> signal_group_to_entry_lanes;
66 throw std::invalid_argument(
"Map is not initialized yet as the georeference was not found...");
69 lanelet::projection::LocalFrameProjector local_projector(
target_frame_.c_str());
71 lanelet::GPSPoint gps_point;
72 gps_point.lat = intersection.ref_point.latitude;
73 gps_point.lon = intersection.ref_point.longitude;
74 gps_point.ele = intersection.ref_point.elevation;
76 auto ref_node = local_projector.forward(gps_point);
78 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Reference node in map frame x: " << ref_node.x() <<
", y: " << ref_node.y());
81 for (
auto lane : intersection.lane_list)
83 if (lane.lane_attributes.lane_type.choice != j2735_v2x_msgs::msg::LaneTypeAttributes::VEHICLE)
85 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Lane id: " << (
int)lane.lane_id <<
", is not a lane for vehicle. Only vehicle road is currently supported. Skipping..." );
88 std::vector<lanelet::Point3d> node_list;
90 double curr_x = ref_node.x();
91 double curr_y = ref_node.y();
97 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Applied reference point correction, delta_x: " <<
intersection_coord_correction_[intersection.id.id].first <<
101 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Processing Lane id: " << (
int)lane.lane_id);
103 size_t min_number_of_points = 2;
105 size_t size_of_available_points = lane.node_list.nodes.node_set_xy.size();
107 if (size_of_available_points < min_number_of_points)
109 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Not enough points are provided to match a lane. Skipping... ");
113 for (
size_t i = 0;
i < size_of_available_points;
i ++ )
115 curr_x = lane.node_list.nodes.node_set_xy[
i].delta.x + curr_x;
116 curr_y = lane.node_list.nodes.node_set_xy[
i].delta.y + curr_y;
117 lanelet::Point3d curr_node{map->pointLayer.uniqueId(), curr_x, curr_y, 0};
119 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Current node x: " << curr_x <<
", y: " << curr_y);
121 node_list.push_back(curr_node);
124 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Lane directions: " << (
int)lane.lane_attributes.directional_use.lane_direction);
129 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Reversed the node list!");
130 std::reverse(node_list.begin(), node_list.end());
133 for (
auto node : node_list)
135 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"), node.x() <<
", " << node.y());
139 for (
auto connection : lane.connect_to_list)
141 signal_group_to_exit_lanes[connection.signal_group].emplace(connection.connecting_lane.lane);
144 signal_group_to_entry_lanes[connection.signal_group].emplace(lane.lane_id);
150 if (affected_llts.empty())
154 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Given offset points are not inside the map for lane: " << (
int)lane.lane_id);
158 lanelet::Id corresponding_lanelet_id;
161 corresponding_lanelet_id = affected_llts.front().id();
162 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Default corresponding_lanelet_id: " << corresponding_lanelet_id <<
", in EGRESS");
167 corresponding_lanelet_id = affected_llts.back().id();
168 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Default corresponding_lanelet_id: " << corresponding_lanelet_id <<
", in INGRESS");
171 for (
auto llt : affected_llts)
173 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Checking if we can get entry/exit from lanelet " << llt.id());
175 if (llt.lanelet().get().hasAttribute(
"turn_direction") &&
176 (llt.lanelet().get().attribute(
"turn_direction").value().compare(
"left") == 0 ||
177 llt.lanelet().get().attribute(
"turn_direction").value().compare(
"right") == 0))
179 std::vector<lanelet::ConstLanelet> connecting_llts;
182 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"lanelet " << llt.id() <<
" is actually part of the intersecion. Trying to detect EGRESS...");
183 connecting_llts = current_routing_graph->following(llt.lanelet().get());
187 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"lanelet " << llt.id() <<
" is actually part of the intersecion. Trying to detect INGRESS...");
188 connecting_llts = current_routing_graph->previous(llt.lanelet().get());
191 if (!connecting_llts.empty())
193 corresponding_lanelet_id = connecting_llts[0].id();
197 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Interestingly, did not detect here");
205 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Found existing lanelet id: " << corresponding_lanelet_id);
209 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Detected INGRESS, " << (
int)lane.lane_id);
210 entry[lane.lane_id] = corresponding_lanelet_id;
214 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Detected EGRESS, " << (
int)lane.lane_id);
215 exit[lane.lane_id] = corresponding_lanelet_id;
221 for (
auto iter = signal_group_to_exit_lanes.begin(); iter != signal_group_to_exit_lanes.end(); iter++)
223 for (
auto exit_lane : iter->second)
225 if (exit.find(exit_lane) != exit.end())
227 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Adding exit_lane id: " << exit_lane);
234 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Unable to convert exit lane Id: " +
std::to_string((
int)exit_lane) +
", to lanelet id using the given MAP.msg!");
240 for (
auto iter = signal_group_to_entry_lanes.begin(); iter != signal_group_to_entry_lanes.end(); iter++)
242 for (
auto entry_lane : iter->second)
244 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Adding entry_lane id: " << entry_lane);
245 if (entry.find(entry_lane) != entry.end())
253 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Unable to convert entry lane Id: " +
std::to_string((
int)entry_lane) +
", to lanelet id using the given MAP.msg!");
261 lanelet::Id matching_id = lanelet::InvalId;
263 std::vector<lanelet::SignalizedIntersectionPtr> existing_si;
265 for (
auto llt : entry_llts)
267 auto intersections = llt.regulatoryElementsAs<lanelet::SignalizedIntersection>();
269 if (intersections.empty())
274 existing_si.insert(existing_si.end(), intersections.begin(),intersections.end());
277 for (
auto intersection : existing_si)
279 auto existing_entry_llts = intersection->getEntryLanelets();
280 auto existing_exit_llts = intersection->getExitLanelets();
282 if (existing_exit_llts.size() != exit_llts.size() || existing_entry_llts.size() != entry_llts.size())
285 bool is_different =
false;
287 for (
auto llt: existing_entry_llts)
289 if (std::find(entry_llts.begin(), entry_llts.end(), llt) == entry_llts.end())
297 for (
auto llt: existing_exit_llts)
299 if (std::find(exit_llts.begin(), exit_llts.end(), llt) == exit_llts.end())
310 matching_id = intersection->id();
322 std::vector<lanelet::LineString3d> stop_lines;
323 for (
auto llt : entry_lanelets)
325 std::vector<lanelet::Point3d> points;
326 points.push_back(lanelet::Point3d(lanelet::utils::getId(), llt.leftBound2d().back().x(), llt.leftBound2d().back().y(), 0));
327 points.push_back(lanelet::Point3d(lanelet::utils::getId(), llt.rightBound().back().x(), llt.rightBound().back().y(), 0));
329 lanelet::LineString3d stop_line(lanelet::utils::getId(), points);
330 stop_lines.push_back(stop_line);
333 lanelet::Id traffic_light_id = lanelet::utils::getId();
334 std::shared_ptr<lanelet::CarmaTrafficSignal> traffic_light(
new lanelet::CarmaTrafficSignal(lanelet::CarmaTrafficSignal::buildData(traffic_light_id, stop_lines, entry_lanelets, exit_lanelets)));
337 for (
auto llt : exit_lanelets)
341 for (
auto llt : entry_lanelets)
345 return traffic_light;
349 const std::shared_ptr<lanelet::LaneletMap>& map, std::shared_ptr<const lanelet::routing::RoutingGraph> routing_graph)
354 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Georeference is not loaded yet. Returning without processing this MAP msg.");
358 for (
auto const& intersection : map_msg.intersections)
360 std::unordered_map<uint8_t, lanelet::Id> entry;
361 std::unordered_map<uint8_t, lanelet::Id> exit;
365 std::vector<lanelet::Lanelet> entry_llts;
366 std::vector<lanelet::Lanelet> exit_llts;
368 for (
auto iter = entry.begin(); iter != entry.end(); iter++)
370 entry_llts.push_back(map->laneletLayer.get(iter->second));
372 for (
auto iter = exit.begin(); iter != exit.end(); iter++)
374 exit_llts.push_back(map->laneletLayer.get(iter->second));
379 if (intersection_id == lanelet::InvalId)
381 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"No existing intersection found. Creating a new one...");
382 intersection_id = lanelet::utils::getId();
386 std::shared_ptr<lanelet::SignalizedIntersection> sig_inter(
new lanelet::SignalizedIntersection
387 (lanelet::SignalizedIntersection::buildData(intersection_id, entry_llts, exit_llts, interior_llts)));
389 sig_intersections.push_back(sig_inter);
398 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::SignalizedIntersectionManager"),
"Creating signal for: " << (
int)sig_grp_pair.first);
406 std::vector<lanelet::Lanelet> exit_lanelets;
407 for (
auto iter = sig_grp_pair.second.begin(); iter != sig_grp_pair.second.end(); iter++)
409 exit_lanelets.push_back(map->laneletLayer.get(*iter));
411 std::vector<lanelet::Lanelet> entry_lanelets;
414 entry_lanelets.push_back(map->laneletLayer.get(*iter));
423 lanelet::BasicLineString2d polygon_corners;
425 if (entry_llts.size() < 2)
430 for (
auto llt : entry_llts)
432 lanelet::BasicPoint2d pt(llt.centerline2d().back().x(), llt.centerline2d().back().y());
433 polygon_corners.push_back(pt);
435 lanelet::BasicPolygon2d polygon(polygon_corners);
436 auto interior_llt_pairs = lanelet::geometry::findWithin2d(map->laneletLayer, polygon);
437 lanelet::Lanelets interior_llts;
439 for (
auto pair : interior_llt_pairs)
441 if (std::find(entry_llts.begin(),entry_llts.end(), pair.second) == entry_llts.end())
442 interior_llts.push_back(pair.second);
444 return interior_llts;
This class manages and keeps track of all signalized intersections in the map. All of the SPAT and MA...
lanelet::Lanelets identifyInteriorLanelets(const lanelet::Lanelets &entry_llts, const std::shared_ptr< lanelet::LaneletMap > &map)
Returns carma traffic signal and saves all id relevant id mappings (signal group to lanelet id) inter...
lanelet::Id matchSignalizedIntersection(const lanelet::Lanelets &entry_llts, const lanelet::Lanelets &exit_llts)
Returns existing signalized intersection with same entry and exit llts if exists.
std::unordered_map< uint16_t, std::pair< double, double > > intersection_coord_correction_
void setTargetFrame(const std::string &target_frame)
Saves the georeference string to be used for converting MAP.msg coordinates.
std::unordered_map< uint8_t, std::unordered_set< lanelet::Id > > signal_group_to_entry_lanelet_ids_
std::string target_frame_
std::unordered_map< uint16_t, lanelet::Id > intersection_id_to_regem_id_
std::shared_ptr< lanelet::CarmaTrafficSignal > createTrafficSignalUsingSGID(uint8_t signal_group_id, const lanelet::Lanelets &entry_lanelets, const lanelet::Lanelets &exit_lanelets)
Returns carma traffic signal and saves all id relevant id mappings (signal group to lanelet id) inter...
SignalizedIntersectionManager & operator=(SignalizedIntersectionManager other)
Assignment operator that copies everything except the traffic signal states. This is to keep the stat...
bool operator==(const SignalizedIntersectionManager &rhs)
Equality operator that checks if every mapping are same except the traffic signal states....
std::unordered_map< uint8_t, std::unordered_set< lanelet::Id > > signal_group_to_exit_lanelet_ids_
std::unordered_map< uint8_t, lanelet::Id > signal_group_to_traffic_light_id_
void convertLaneToLaneletId(std::unordered_map< uint8_t, lanelet::Id > &entry, std::unordered_map< uint8_t, lanelet::Id > &exit, const carma_v2x_msgs::msg::IntersectionGeometry &intersection, const std::shared_ptr< lanelet::LaneletMap > &map, std::shared_ptr< const lanelet::routing::RoutingGraph > current_routing_graph)
Returns mapping of MAP lane id to lanelet id for the given map and intersection.msg in the MAP....
void setMaxLaneWidth(double max_lane_width)
Sets the max lane width in meters. Map msg points are associated to a lanelet if they are within this...
void createIntersectionFromMapMsg(std::vector< lanelet::SignalizedIntersectionPtr > &intersections, std::vector< lanelet::CarmaTrafficSignalPtr > &traffic_signals, const carma_v2x_msgs::msg::MapData &map_msg, const std::shared_ptr< lanelet::LaneletMap > &map, std::shared_ptr< const lanelet::routing::RoutingGraph > routing_graph)
Create relevant signalized intersection and carma traffic signals based on the MAP....
SignalizedIntersectionManager()
auto to_string(const UtmZone &zone) -> std::string
lanelet::ConstLaneletOrAreas getAffectedLaneletOrAreas(const lanelet::Points3d &gf_pts, const lanelet::LaneletMapPtr &lanelet_map, std::shared_ptr< const lanelet::routing::RoutingGraph > routing_graph, double max_lane_width)
Gets the affected lanelet or areas based on the points in the given map's frame.
static const uint8_t INGRESS
static const uint8_t EGRESS