Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
carma_wm::SignalizedIntersectionManager Class Reference

This class manages and keeps track of all signalized intersections in the map. All of the SPAT and MAP standard's lane ids to lanelet id mapping is recorded here. NOTE: This class functions do not update the map given. More...

#include <SignalizedIntersectionManager.hpp>

Collaboration diagram for carma_wm::SignalizedIntersectionManager:
Collaboration graph

Public Member Functions

 SignalizedIntersectionManager ()
 
 SignalizedIntersectionManager (const SignalizedIntersectionManager &other)
 Copy constructor that copies everything except the traffic signal states. This is to keep the states although the map is updated or a similar event happened NOTE: The function does not update the map with new elements. More...
 
SignalizedIntersectionManageroperator= (SignalizedIntersectionManager other)
 Assignment operator that copies everything except the traffic signal states. This is to keep the states although the map is updated or a similar event happened NOTE: The function does not update the map with new elements. More...
 
bool operator== (const SignalizedIntersectionManager &rhs)
 Equality operator that checks if every mapping are same except the traffic signal states. This is to keep the states although the map is updated or a similar event happened NOTE: The function does not update the map with new elements. More...
 
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.msg and the lanelet_map NOTE: The function does not update the map with new elements. More...
 
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.msg. This function also records signal_group_id_to its own lanelet id, and also signal group to entry and exit lanelets id mappings. More...
 
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 distance to a lanelet as map msg points are guaranteed to apply to a single lane. More...
 
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. More...
 
void setTargetFrame (const std::string &target_frame)
 Saves the georeference string to be used for converting MAP.msg coordinates. More...
 
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) internally. More...
 
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) internally. More...
 

Public Attributes

std::unordered_map< uint16_t, std::pair< double, double > > intersection_coord_correction_
 
std::unordered_map< uint16_t, lanelet::Id > intersection_id_to_regem_id_
 
std::unordered_map< uint8_t, lanelet::Id > signal_group_to_traffic_light_id_
 
std::unordered_map< uint8_t, std::unordered_set< lanelet::Id > > signal_group_to_exit_lanelet_ids_
 
std::unordered_map< uint8_t, std::unordered_set< lanelet::Id > > signal_group_to_entry_lanelet_ids_
 
std::unordered_map< uint16_t, std::unordered_map< uint8_t, std::vector< std::pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState > > > > traffic_signal_states_
 
std::unordered_map< uint16_t, std::unordered_map< uint8_t, std::vector< boost::posix_time::ptime > > > traffic_signal_start_times_
 
std::unordered_map< uint16_t, std::unordered_map< uint8_t, std::pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState > > > last_seen_state_
 
std::unordered_map< uint16_t, std::unordered_map< uint8_t, int > > signal_state_counter_
 

Private Attributes

std::string target_frame_ = ""
 
double max_lane_width_ = 4
 

Detailed Description

This class manages and keeps track of all signalized intersections in the map. All of the SPAT and MAP standard's lane ids to lanelet id mapping is recorded here. NOTE: This class functions do not update the map given.

Definition at line 52 of file SignalizedIntersectionManager.hpp.

Constructor & Destructor Documentation

◆ SignalizedIntersectionManager() [1/2]

carma_wm::SignalizedIntersectionManager::SignalizedIntersectionManager ( )
inline

Definition at line 56 of file SignalizedIntersectionManager.hpp.

56{}

◆ SignalizedIntersectionManager() [2/2]

carma_wm::SignalizedIntersectionManager::SignalizedIntersectionManager ( const SignalizedIntersectionManager other)

Copy constructor that copies everything except the traffic signal states. This is to keep the states although the map is updated or a similar event happened NOTE: The function does not update the map with new elements.

Parameters
[out]othermanager

Definition at line 458 of file SignalizedIntersectionManager.cpp.

459 {
460 this->signal_group_to_entry_lanelet_ids_ = other.signal_group_to_entry_lanelet_ids_;
461 this->signal_group_to_exit_lanelet_ids_ = other.signal_group_to_exit_lanelet_ids_;
462 this->intersection_id_to_regem_id_ = other.intersection_id_to_regem_id_;
463 this->signal_group_to_traffic_light_id_ = other.signal_group_to_traffic_light_id_;
464 this->intersection_coord_correction_ = other.intersection_coord_correction_;
465 }
std::unordered_map< uint16_t, std::pair< double, double > > intersection_coord_correction_
std::unordered_map< uint8_t, std::unordered_set< lanelet::Id > > signal_group_to_entry_lanelet_ids_
std::unordered_map< uint16_t, lanelet::Id > intersection_id_to_regem_id_
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_

References intersection_coord_correction_, intersection_id_to_regem_id_, signal_group_to_entry_lanelet_ids_, signal_group_to_exit_lanelet_ids_, and signal_group_to_traffic_light_id_.

Member Function Documentation

◆ convertLaneToLaneletId()

void carma_wm::SignalizedIntersectionManager::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.msg. This function also records signal_group_id_to its own lanelet id, and also signal group to entry and exit lanelets id mappings.

Parameters
[out]entrylane id to lanelet id mappings to return
[out]exitlane id to lanelet id mappings to return
intersectionMAP.msg that consists all static data portion of the intersection
maplanelet_map to check
routing_graphof the lanelet map to accurately detect lanes
Exceptions
invalid_argumentif given coordinates in the msg doesn't exist in the map TODO: Need to think about error buffer in the future. Map msgs are made from google maps or open streets maps normally so this function might run into some errors from that.

Definition at line 58 of file SignalizedIntersectionManager.cpp.

60 {
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;
63
64 if (target_frame_ == "")
65 {
66 throw std::invalid_argument("Map is not initialized yet as the georeference was not found...");
67 }
68
69 lanelet::projection::LocalFrameProjector local_projector(target_frame_.c_str());
70
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;
75
76 auto ref_node = local_projector.forward(gps_point);
77
78 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Reference node in map frame x: " << ref_node.x() << ", y: " << ref_node.y());
79
80
81 for (auto lane : intersection.lane_list)
82 {
83 if (lane.lane_attributes.lane_type.choice != j2735_v2x_msgs::msg::LaneTypeAttributes::VEHICLE)
84 {
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..." );
86 continue;
87 }
88 std::vector<lanelet::Point3d> node_list;
89
90 double curr_x = ref_node.x();
91 double curr_y = ref_node.y();
92
93 if (intersection_coord_correction_.find(intersection.id.id) != intersection_coord_correction_.end())
94 {
95 curr_x += intersection_coord_correction_[intersection.id.id].first;
96 curr_y += intersection_coord_correction_[intersection.id.id].second;
97 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Applied reference point correction, delta_x: " << intersection_coord_correction_[intersection.id.id].first <<
98 ", delta_y: " << intersection_coord_correction_[intersection.id.id].second << ", to intersection id: " << (int)lane.lane_id);
99 }
100
101 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Processing Lane id: " << (int)lane.lane_id);
102
103 size_t min_number_of_points = 2; // two points minimum are required
104
105 size_t size_of_available_points = lane.node_list.nodes.node_set_xy.size();
106
107 if (size_of_available_points < min_number_of_points)
108 {
109 RCLCPP_WARN_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Not enough points are provided to match a lane. Skipping... ");
110 continue;
111 }
112
113 for (size_t i = 0; i < size_of_available_points; i ++ )
114 {
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};
118
119 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Current node x: " << curr_x << ", y: " << curr_y);
120
121 node_list.push_back(curr_node);
122 }
123
124 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Lane directions: " << (int)lane.lane_attributes.directional_use.lane_direction);
125
126 if (lane.lane_attributes.directional_use.lane_direction == LANE_DIRECTION::INGRESS)
127 {
128 // flip direction if ingress to pick up correct lanelets
129 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Reversed the node list!");
130 std::reverse(node_list.begin(), node_list.end());
131 }
132
133 for (auto node : node_list)
134 {
135 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), node.x() << ", " << node.y());
136 }
137
138 // save which signal group connect to which exit lanes
139 for (auto connection : lane.connect_to_list)
140 {
141 signal_group_to_exit_lanes[connection.signal_group].emplace(connection.connecting_lane.lane);
142
143 if (lane.lane_attributes.directional_use.lane_direction == LANE_DIRECTION::INGRESS)
144 signal_group_to_entry_lanes[connection.signal_group].emplace(lane.lane_id);
145 }
146
147 // query corresponding lanelet lane from local map
148 auto affected_llts = carma_wm::query::getAffectedLaneletOrAreas(node_list, map, current_routing_graph, max_lane_width_);
149
150 if (affected_llts.empty())
151 {
152 // https://github.com/usdot-fhwa-stol/carma-platform/issues/1593
153 // Open issue TODO on how this error is handled
154 RCLCPP_WARN_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Given offset points are not inside the map for lane: " << (int)lane.lane_id);
155 continue;
156 }
157
158 lanelet::Id corresponding_lanelet_id;
159 if (lane.lane_attributes.directional_use.lane_direction == LANE_DIRECTION::EGRESS)
160 {
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");
163
164 }
165 else //ingress
166 {
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");
169 }
170
171 for (auto llt : affected_llts) // filter out intersection lanelets
172 {
173 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Checking if we can get entry/exit from lanelet " << llt.id());
174 //TODO direction of affected_llts may play role, but it should be good
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))
178 {
179 std::vector<lanelet::ConstLanelet> connecting_llts;
180 if (lane.lane_attributes.directional_use.lane_direction == LANE_DIRECTION::EGRESS)
181 {
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());
184 }
185 else
186 {
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());
189 }
190
191 if (!connecting_llts.empty())
192 {
193 corresponding_lanelet_id = connecting_llts[0].id();
194 }
195 else
196 {
197 RCLCPP_WARN_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Interestingly, did not detect here");
198 continue;
199 }
200
201 break;
202 }
203 }
204
205 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Found existing lanelet id: " << corresponding_lanelet_id);
206
207 if (lane.lane_attributes.directional_use.lane_direction == LANE_DIRECTION::INGRESS)
208 {
209 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Detected INGRESS, " << (int)lane.lane_id);
210 entry[lane.lane_id] = corresponding_lanelet_id;
211 }
212 else if (lane.lane_attributes.directional_use.lane_direction == LANE_DIRECTION::EGRESS)
213 {
214 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Detected EGRESS, " << (int)lane.lane_id);
215 exit[lane.lane_id] = corresponding_lanelet_id;
216 }
217 // ignoring types that are neither ingress nor egress
218 }
219
220 // convert and save exit lane ids into lanelet ids with their corresponding signal group ids
221 for (auto iter = signal_group_to_exit_lanes.begin(); iter != signal_group_to_exit_lanes.end(); iter++)
222 {
223 for (auto exit_lane : iter->second)
224 {
225 if (exit.find(exit_lane) != exit.end())
226 {
227 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Adding exit_lane id: " << exit_lane);
228 signal_group_to_exit_lanelet_ids_[iter->first].insert(exit[exit_lane]);
229 }
230 else
231 {
232 // https://github.com/usdot-fhwa-stol/carma-platform/issues/1593
233 // Open issue TODO on how this error is handled
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!");
235 }
236 }
237 }
238
239 // convert and save entry lane ids into lanelet ids with their corresponding signal group ids
240 for (auto iter = signal_group_to_entry_lanes.begin(); iter != signal_group_to_entry_lanes.end(); iter++)
241 {
242 for (auto entry_lane : iter->second)
243 {
244 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Adding entry_lane id: " << entry_lane);
245 if (entry.find(entry_lane) != entry.end())
246 {
247 signal_group_to_entry_lanelet_ids_[iter->first].insert(entry[entry_lane]);
248 }
249 else
250 {
251 // https://github.com/usdot-fhwa-stol/carma-platform/issues/1593
252 // Open issue TODO on how this error is handled
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!");
254 }
255 }
256 }
257 }
auto to_string(const UtmZone &zone) -> std::string
Definition: utm_zone.cpp:21
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.

References carma_wm::LANE_DIRECTION::EGRESS, carma_wm::query::getAffectedLaneletOrAreas(), process_bag::i, carma_wm::LANE_DIRECTION::INGRESS, intersection_coord_correction_, max_lane_width_, signal_group_to_entry_lanelet_ids_, signal_group_to_exit_lanelet_ids_, target_frame_, and carma_cooperative_perception::to_string().

Referenced by createIntersectionFromMapMsg().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ createIntersectionFromMapMsg()

void carma_wm::SignalizedIntersectionManager::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.msg and the lanelet_map NOTE: The function does not update the map with new elements.

Parameters
[out]intersectionsto return
[out]traffic_signalsto return
map_msgMAP.msg that consists all static data portion of the intersection
maplanelet_map to check
routing_graphof the lanelet map to accurately detect lanes

Definition at line 348 of file SignalizedIntersectionManager.cpp.

350 {
351
352 if (target_frame_ == "")
353 {
354 RCLCPP_WARN_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Georeference is not loaded yet. Returning without processing this MAP msg.");
355 return;
356 }
357
358 for (auto const& intersection : map_msg.intersections)
359 {
360 std::unordered_map<uint8_t, lanelet::Id> entry;
361 std::unordered_map<uint8_t, lanelet::Id> exit;
362
363 convertLaneToLaneletId(entry, exit, intersection, map, routing_graph);
364
365 std::vector<lanelet::Lanelet> entry_llts;
366 std::vector<lanelet::Lanelet> exit_llts;
367
368 for (auto iter = entry.begin(); iter != entry.end(); iter++)
369 {
370 entry_llts.push_back(map->laneletLayer.get(iter->second));
371 }
372 for (auto iter = exit.begin(); iter != exit.end(); iter++)
373 {
374 exit_llts.push_back(map->laneletLayer.get(iter->second));
375 }
376
377 lanelet::Id intersection_id = matchSignalizedIntersection(entry_llts, exit_llts);
378
379 if (intersection_id == lanelet::InvalId)
380 {
381 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "No existing intersection found. Creating a new one...");
382 intersection_id = lanelet::utils::getId();
383
384 std::vector<lanelet::Lanelet> interior_llts = identifyInteriorLanelets(entry_llts, map);
385
386 std::shared_ptr<lanelet::SignalizedIntersection> sig_inter(new lanelet::SignalizedIntersection
387 (lanelet::SignalizedIntersection::buildData(intersection_id, entry_llts, exit_llts, interior_llts)));
388 intersection_id_to_regem_id_[intersection.id.id] = intersection_id;
389 sig_intersections.push_back(sig_inter);
390 }
391 }
392
393
394 // create signal group for each from the message
395 // check if it already exists
396 for (auto sig_grp_pair : signal_group_to_exit_lanelet_ids_)
397 {
398 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm::SignalizedIntersectionManager"), "Creating signal for: " << (int)sig_grp_pair.first);
399 // ignore the traffic signals already inside
400 if (signal_group_to_traffic_light_id_.find(sig_grp_pair.first) != signal_group_to_traffic_light_id_.end() &&
401 map->regulatoryElementLayer.exists(signal_group_to_traffic_light_id_[sig_grp_pair.first]))
402 {
403 continue;
404 }
405
406 std::vector<lanelet::Lanelet> exit_lanelets;
407 for (auto iter = sig_grp_pair.second.begin(); iter != sig_grp_pair.second.end(); iter++)
408 {
409 exit_lanelets.push_back(map->laneletLayer.get(*iter));
410 }
411 std::vector<lanelet::Lanelet> entry_lanelets;
412 for (auto iter = signal_group_to_entry_lanelet_ids_[sig_grp_pair.first].begin(); iter != signal_group_to_entry_lanelet_ids_[sig_grp_pair.first].end(); iter++)
413 {
414 entry_lanelets.push_back(map->laneletLayer.get(*iter));
415 }
416
417 traffic_signals.push_back(createTrafficSignalUsingSGID(sig_grp_pair.first, entry_lanelets, exit_lanelets));
418 }
419 }
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::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...
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....

References convertLaneToLaneletId(), createTrafficSignalUsingSGID(), identifyInteriorLanelets(), intersection_id_to_regem_id_, matchSignalizedIntersection(), signal_group_to_entry_lanelet_ids_, signal_group_to_exit_lanelet_ids_, signal_group_to_traffic_light_id_, and target_frame_.

Here is the call graph for this function:

◆ createTrafficSignalUsingSGID()

std::shared_ptr< lanelet::CarmaTrafficSignal > carma_wm::SignalizedIntersectionManager::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) internally.

Parameters
signal_group_idof the traffic signal
exit_lltsof the signal_group
entry_lltsof the signal_group
Returns
traffic signal corresponding to the signal group

Definition at line 320 of file SignalizedIntersectionManager.cpp.

321 {
322 std::vector<lanelet::LineString3d> stop_lines;
323 for (auto llt : entry_lanelets)
324 {
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));
328
329 lanelet::LineString3d stop_line(lanelet::utils::getId(), points);
330 stop_lines.push_back(stop_line);
331 }
332
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)));
335 signal_group_to_traffic_light_id_[signal_group_id] = traffic_light_id;
336
337 for (auto llt : exit_lanelets)
338 {
339 signal_group_to_exit_lanelet_ids_[signal_group_id].insert(llt.id());
340 }
341 for (auto llt : entry_lanelets)
342 {
343 signal_group_to_entry_lanelet_ids_[signal_group_id].insert(llt.id());
344 }
345 return traffic_light;
346 }

References signal_group_to_entry_lanelet_ids_, signal_group_to_exit_lanelet_ids_, and signal_group_to_traffic_light_id_.

Referenced by createIntersectionFromMapMsg().

Here is the caller graph for this function:

◆ identifyInteriorLanelets()

lanelet::Lanelets carma_wm::SignalizedIntersectionManager::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) internally.

Parameters
signal_group_idof the traffic signal
exit_lltsof the signal_group
entry_lltsof the signal_group
Returns
traffic signal corresponding to the signal group

Definition at line 421 of file SignalizedIntersectionManager.cpp.

422 {
423 lanelet::BasicLineString2d polygon_corners;
424
425 if (entry_llts.size() < 2) //at least two lanes (1 ingress and 1 egress) needed to form intersection
426 {
427 return {};
428 }
429
430 for (auto llt : entry_llts)
431 {
432 lanelet::BasicPoint2d pt(llt.centerline2d().back().x(), llt.centerline2d().back().y());
433 polygon_corners.push_back(pt);
434 }
435 lanelet::BasicPolygon2d polygon(polygon_corners);
436 auto interior_llt_pairs = lanelet::geometry::findWithin2d(map->laneletLayer, polygon);
437 lanelet::Lanelets interior_llts;
438
439 for (auto pair : interior_llt_pairs)
440 {
441 if (std::find(entry_llts.begin(),entry_llts.end(), pair.second) == entry_llts.end())
442 interior_llts.push_back(pair.second);
443 }
444 return interior_llts;
445 }

Referenced by createIntersectionFromMapMsg().

Here is the caller graph for this function:

◆ matchSignalizedIntersection()

lanelet::Id carma_wm::SignalizedIntersectionManager::matchSignalizedIntersection ( const lanelet::Lanelets &  entry_llts,
const lanelet::Lanelets &  exit_llts 
)

Returns existing signalized intersection with same entry and exit llts if exists.

Parameters
entry_lltsof the intersection
exit_lltsof the intersection
Returns
id of the matching intersection in the map, or lanelet::InvalId if none exists

Definition at line 259 of file SignalizedIntersectionManager.cpp.

260 {
261 lanelet::Id matching_id = lanelet::InvalId;
262
263 std::vector<lanelet::SignalizedIntersectionPtr> existing_si;
264
265 for (auto llt : entry_llts)
266 {
267 auto intersections = llt.regulatoryElementsAs<lanelet::SignalizedIntersection>();
268
269 if (intersections.empty())
270 {
271 // no match if any of the entry lanelet is not part of any intersection.
272 break;
273 }
274 existing_si.insert(existing_si.end(), intersections.begin(),intersections.end());
275 }
276
277 for (auto intersection : existing_si)
278 {
279 auto existing_entry_llts = intersection->getEntryLanelets();
280 auto existing_exit_llts = intersection->getExitLanelets();
281
282 if (existing_exit_llts.size() != exit_llts.size() || existing_entry_llts.size() != entry_llts.size())
283 continue;
284
285 bool is_different = false;
286
287 for (auto llt: existing_entry_llts)
288 {
289 if (std::find(entry_llts.begin(), entry_llts.end(), llt) == entry_llts.end())
290 {
291 is_different = true;
292
293 break;
294 }
295 }
296
297 for (auto llt: existing_exit_llts)
298 {
299 if (std::find(exit_llts.begin(), exit_llts.end(), llt) == exit_llts.end())
300 {
301 is_different = true;
302
303 break;
304 }
305 }
306
307 if (!is_different)
308 {
309 // found a match
310 matching_id = intersection->id();
311
312 break;
313 }
314
315 }
316
317 return matching_id;
318 }

Referenced by createIntersectionFromMapMsg().

Here is the caller graph for this function:

◆ operator=()

SignalizedIntersectionManager & carma_wm::SignalizedIntersectionManager::operator= ( SignalizedIntersectionManager  other)

Assignment operator that copies everything except the traffic signal states. This is to keep the states although the map is updated or a similar event happened NOTE: The function does not update the map with new elements.

Parameters
[out]othermanager

Definition at line 447 of file SignalizedIntersectionManager.cpp.

448 {
449 this->signal_group_to_entry_lanelet_ids_ = other.signal_group_to_entry_lanelet_ids_;
450 this->signal_group_to_exit_lanelet_ids_ = other.signal_group_to_exit_lanelet_ids_;
451 this->intersection_id_to_regem_id_ = other.intersection_id_to_regem_id_;
452 this->signal_group_to_traffic_light_id_ = other.signal_group_to_traffic_light_id_;
453 this->intersection_coord_correction_ = other.intersection_coord_correction_;
454
455 return *this;
456 }

References intersection_coord_correction_, intersection_id_to_regem_id_, signal_group_to_entry_lanelet_ids_, signal_group_to_exit_lanelet_ids_, and signal_group_to_traffic_light_id_.

◆ operator==()

bool carma_wm::SignalizedIntersectionManager::operator== ( const SignalizedIntersectionManager rhs)

Equality operator that checks if every mapping are same except the traffic signal states. This is to keep the states although the map is updated or a similar event happened NOTE: The function does not update the map with new elements.

Parameters
[out]rhsmanager

Definition at line 35 of file SignalizedIntersectionManager.cpp.

36 {
37 bool is_same = true;
38 if (rhs.intersection_id_to_regem_id_ != this->intersection_id_to_regem_id_)
39 {
40 is_same = false;
41 }
42 if (rhs.signal_group_to_entry_lanelet_ids_ != this->signal_group_to_entry_lanelet_ids_)
43 {
44 is_same = false;
45 }
46 if (rhs.signal_group_to_exit_lanelet_ids_ != this->signal_group_to_exit_lanelet_ids_)
47 {
48 is_same = false;
49 }
50 if (rhs.signal_group_to_traffic_light_id_ != this->signal_group_to_traffic_light_id_)
51 {
52 is_same = false;
53 }
54
55 return is_same;
56 }

References intersection_id_to_regem_id_, signal_group_to_entry_lanelet_ids_, signal_group_to_exit_lanelet_ids_, and signal_group_to_traffic_light_id_.

◆ setMaxLaneWidth()

void carma_wm::SignalizedIntersectionManager::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 distance to a lanelet as map msg points are guaranteed to apply to a single lane.

Definition at line 30 of file SignalizedIntersectionManager.cpp.

31 {
32 max_lane_width_ = max_lane_width;
33 }

References max_lane_width_.

◆ setTargetFrame()

void carma_wm::SignalizedIntersectionManager::setTargetFrame ( const std::string &  target_frame)

Saves the georeference string to be used for converting MAP.msg coordinates.

Parameters
target_framePROJ string of the map

Definition at line 25 of file SignalizedIntersectionManager.cpp.

26 {
27 target_frame_ = target_frame;
28 }

References target_frame_.

Member Data Documentation

◆ intersection_coord_correction_

std::unordered_map<uint16_t, std::pair<double, double> > carma_wm::SignalizedIntersectionManager::intersection_coord_correction_

◆ intersection_id_to_regem_id_

◆ last_seen_state_

std::unordered_map<uint16_t, std::unordered_map<uint8_t,std::pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState> > > carma_wm::SignalizedIntersectionManager::last_seen_state_

Definition at line 169 of file SignalizedIntersectionManager.hpp.

◆ max_lane_width_

double carma_wm::SignalizedIntersectionManager::max_lane_width_ = 4
private

Definition at line 179 of file SignalizedIntersectionManager.hpp.

Referenced by convertLaneToLaneletId(), and setMaxLaneWidth().

◆ signal_group_to_entry_lanelet_ids_

std::unordered_map<uint8_t, std::unordered_set<lanelet::Id> > carma_wm::SignalizedIntersectionManager::signal_group_to_entry_lanelet_ids_

◆ signal_group_to_exit_lanelet_ids_

std::unordered_map<uint8_t, std::unordered_set<lanelet::Id> > carma_wm::SignalizedIntersectionManager::signal_group_to_exit_lanelet_ids_

◆ signal_group_to_traffic_light_id_

◆ signal_state_counter_

std::unordered_map<uint16_t, std::unordered_map<uint8_t,int> > carma_wm::SignalizedIntersectionManager::signal_state_counter_

Definition at line 172 of file SignalizedIntersectionManager.hpp.

◆ target_frame_

std::string carma_wm::SignalizedIntersectionManager::target_frame_ = ""
private

◆ traffic_signal_start_times_

std::unordered_map<uint16_t, std::unordered_map<uint8_t,std::vector<boost::posix_time::ptime> > > carma_wm::SignalizedIntersectionManager::traffic_signal_start_times_

◆ traffic_signal_states_

std::unordered_map<uint16_t, std::unordered_map<uint8_t,std::vector<std::pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState> > > > carma_wm::SignalizedIntersectionManager::traffic_signal_states_

The documentation for this class was generated from the following files: