17#include <autoware_lanelet2_ros2_interface/utility/message_conversion.hpp>
18#include <lanelet2_extension/regulatory_elements/DirectionOfTravel.h>
19#include <lanelet2_extension/regulatory_elements/StopRule.h>
20#include <lanelet2_extension/regulatory_elements/CarmaTrafficSignal.h>
21#include <lanelet2_extension/regulatory_elements/SignalizedIntersection.h>
22#include <lanelet2_routing/internal/Graph.h>
52 return std::static_pointer_cast<const WorldModel>(
world_model_);
60 lanelet::LaneletMapPtr new_map(
new lanelet::LaneletMap);
67 bool more_updates_to_apply =
true;
74 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"There were unapplied updates in carma_wm when a new map was received.");
80 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Done applying updates for new map. However, more updates are waiting for a future map.");
81 more_updates_to_apply =
false;
96 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Dropping delayed route message which was never applied as updated map was not recieved");
99 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"There is a delayed route message still waiting to be applied in carma_wm");
124 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
125 "inter id: " << intersection_id <<
", regem id: " << regulatory_element_id);
129 for (
const auto & entry_llt_id : entry_llt_ids)
131 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"signal id: " << (
int)signal_id <<
", entry llt id: " << entry_llt_id);
136 for (
const auto & exit_llt_id : exit_llt_ids)
138 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"signal id: " << (
int)signal_id <<
", exit llt id: " << exit_llt_id);
143 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"signal id: " << (
int)signal_id <<
", regem id: " << regem_id);
149 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Map Update Being Evaluated. SeqNum: " << geofence_msg->seq_id);
152 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Currently new route is being processed. Queueing this update. Received seq: " << geofence_msg->seq_id <<
" prev seq: " <<
most_recent_update_msg_seq_);
157 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Dropping map update which has already been processed. Received seq: " << geofence_msg->seq_id <<
" prev seq: " <<
most_recent_update_msg_seq_);
159 }
else if(!
world_model_->getMap() || current_map_version_ < geofence_msg->map_version) {
160 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Update received for newer map version than available. Queueing update until map is available.");
164 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Dropping old map update as newer map is already available.");
167 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Queuing map update as we are waiting on an earlier update to be applied. most_recent_update_msg_seq_: " <<
most_recent_update_msg_seq_ <<
"geofence_msg->seq_id: " << geofence_msg->seq_id);
173 if(geofence_msg->invalidates_route==
true &&
world_model_->getRoute())
178 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Received notice that route has been invalidated in mapUpdateCallback");
182 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Route is not yet available. Therefore queueing the update");
195 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Processing Map Update with Geofence Id:" << gf_ptr->id_);
197 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Geofence id" << gf_ptr->id_ <<
" requests addition of lanelets size: " << gf_ptr->lanelet_additions_.size());
198 for (
auto llt : gf_ptr->lanelet_additions_)
201 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Adding new lanelet with id: " << llt.id());
202 auto left = llt.leftBound3d();
206 for (
size_t i = 0;
i < left.size();
i ++)
208 if (
world_model_->getMutableMap()->pointLayer.exists(left[
i].id()))
210 llt.leftBound3d()[
i] =
world_model_->getMutableMap()->pointLayer.get(left[
i].
id());
213 auto right = llt.rightBound3d();
214 for (
size_t i = 0;
i < right.size();
i ++)
216 if (
world_model_->getMutableMap()->pointLayer.exists(right[
i].id()))
218 llt.rightBound3d()[
i] =
world_model_->getMutableMap()->pointLayer.get(right[
i].
id());
225 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Geofence id" << gf_ptr->id_ <<
" sends record of traffic_lights_id size: " << gf_ptr->traffic_light_id_lookup_.size());
226 for (
auto const &[traffic_light_id, lanelet_id] : gf_ptr->traffic_light_id_lookup_)
228 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Adding new pair for traffic light ids: " << traffic_light_id <<
", and lanelet::Id: " << lanelet_id);
229 world_model_->setTrafficLightIds(traffic_light_id, lanelet_id);
232 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Geofence id" << gf_ptr->id_ <<
" sends record of intersections size: " << gf_ptr->sim_.intersection_id_to_regem_id_.size());
233 if (gf_ptr->sim_.intersection_id_to_regem_id_.size() > 0)
239 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Geofence id" << gf_ptr->id_ <<
" requests removal of size: " << gf_ptr->remove_list_.size());
240 for (
auto const &[lanelet_id, lanelet_to_remove] : gf_ptr->remove_list_)
242 auto parent_llt =
world_model_->getMutableMap()->laneletLayer.get(lanelet_id);
245 auto regems_copy_to_check = parent_llt.regulatoryElements();
246 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Regems found in lanelet: " << regems_copy_to_check.size());
247 for (
auto regem: regems_copy_to_check)
250 if (lanelet_to_remove->id() == regem->id())
world_model_->getMutableMap()->remove(parent_llt, regem);
252 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Regems left in lanelet after removal: " << parent_llt.regulatoryElements().size());
256 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Geofence id" << gf_ptr->id_ <<
" requests update of size: " << gf_ptr->update_list_.size());
259 for (
auto const &[lanelet_id, lanelet_to_update]: gf_ptr->update_list_)
262 auto parent_llt =
world_model_->getMutableMap()->laneletLayer.get(lanelet_id);
264 auto regemptr_it =
world_model_->getMutableMap()->regulatoryElementLayer.find(lanelet_to_update->id());
268 if (regemptr_it !=
world_model_->getMutableMap()->regulatoryElementLayer.end())
271 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Reapplying previously existing element for lanelet id:" << parent_llt.id() <<
", and regem id: " << regemptr_it->get()->id());
273 world_model_->getMutableMap()->update(parent_llt, *regemptr_it);
277 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"New regulatory element at lanelet: " << parent_llt.id() <<
", and id: " << lanelet_to_update->id());
287 if (geofence_msg->has_routing_graph) {
292 throw std::invalid_argument(
"Map updated provided routing graph which could not be applied to the current map.");
304 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Finished Applying the Map Update with Geofence Id:" << gf_ptr->id_);
309 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Calling user defined map update callback");
324 auto factory_regem = lanelet::RegulatoryElementFactory::create(regem->attribute(lanelet::AttributeName::Subtype).value(),
325 std::const_pointer_cast<lanelet::RegulatoryElementData>(regem->constData()));
332 lanelet::PassingControlLinePtr control_line = std::dynamic_pointer_cast<lanelet::PassingControlLine>(factory_regem);
335 world_model_->getMutableMap()->update(parent_llt, control_line);
339 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid control line");
346 lanelet::DigitalSpeedLimitPtr speed = std::dynamic_pointer_cast<lanelet::DigitalSpeedLimit>(factory_regem);
349 world_model_->getMutableMap()->update(parent_llt, speed);
353 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid speed limit");
360 lanelet::RegionAccessRulePtr rar = std::dynamic_pointer_cast<lanelet::RegionAccessRule>(factory_regem);
367 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid region access rule");
375 lanelet::DigitalMinimumGapPtr min_gap = std::dynamic_pointer_cast<lanelet::DigitalMinimumGap>(factory_regem);
378 world_model_->getMutableMap()->update(parent_llt, min_gap);
382 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid minimum gap rule");
390 lanelet::DirectionOfTravelPtr dot = std::dynamic_pointer_cast<lanelet::DirectionOfTravel>(factory_regem);
397 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid direction of travel");
405 lanelet::StopRulePtr sr = std::dynamic_pointer_cast<lanelet::StopRule>(factory_regem);
412 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid stop rule");
418 lanelet::CarmaTrafficSignalPtr ctl = std::dynamic_pointer_cast<lanelet::CarmaTrafficSignal>(factory_regem);
425 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid carma traffic signal");
431 lanelet::SignalizedIntersectionPtr si = std::dynamic_pointer_cast<lanelet::SignalizedIntersection>(factory_regem);
438 std::invalid_argument(
"Dynamic Pointer cast failed on getting valid signalized intersection");
444 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"World Model instance received an unsupported geofence type in its map update callback!");
453 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Received routing graph does not have matching vehicle type for world model. WM Type: "
455 <<
" graph type: " << msg.participant_type
463 lanelet::ConstLanelets passable_lanelets;
464 lanelet::ConstAreas passable_areas;
466 passable_lanelets.reserve(msg.lanelet_vertices.size());
467 passable_areas.reserve(msg.area_vertices.size());
472 for (
auto vertex : msg.lanelet_vertices) {
473 passable_lanelets.emplace_back(map->laneletLayer.get(vertex.lanelet_or_area));
476 for (
auto vertex : msg.area_vertices) {
477 passable_areas.emplace_back(map->areaLayer.get(vertex.lanelet_or_area));
480 }
catch(
const lanelet::NoSuchPrimitiveError& e) {
482 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Received routing graph specifies lanelets which do not match the current map version. Actual exception: " << e.what());
491 auto passable_map = lanelet::utils::createConstSubmap(passable_lanelets, passable_areas);
494 auto graph = std::make_unique<lanelet::routing::internal::RoutingGraphGraph>(msg.num_unique_routing_cost_ids);
497 for (
auto ll : passable_lanelets) {
498 graph->addVertex(lanelet::routing::internal::VertexInfo{ll});
501 for (
auto area : passable_areas) {
502 graph->addVertex(lanelet::routing::internal::VertexInfo{area});
506 for (
size_t i = 0;
i < msg.lanelet_vertices.size(); ++
i) {
508 auto vertex = msg.lanelet_vertices[
i];
509 auto lanelet = passable_lanelets[
i];
511 for (
size_t j = 0; j < vertex.lanelet_or_area_ids.size(); ++j) {
513 lanelet::routing::RelationType relation;
516 switch (vertex.edge_relations[j])
518 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_SUCCESSOR:
519 relation = lanelet::routing::RelationType::Successor;
break;
521 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_LEFT:
524 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_RIGHT:
527 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_ADJACENT_LEFT:
528 relation = lanelet::routing::RelationType::AdjacentLeft;
break;
530 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_ADJACENT_RIGHT:
531 relation = lanelet::routing::RelationType::AdjacentRight;
break;
533 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_CONFLICTING:
534 relation = lanelet::routing::RelationType::Conflicting;
break;
536 case autoware_lanelet2_msgs::msg::RoutingGraphVertexAndEdges::RELATION_AREA:
537 relation = lanelet::routing::RelationType::Area;
break;
540 relation = lanelet::routing::RelationType::None;
break;
548 map->laneletLayer.get(vertex.lanelet_or_area_ids[j]),
549 lanelet::routing::internal::EdgeInfo{vertex.edge_routing_costs[j], vertex.edge_routing_cost_source_ids[j], relation}
552 }
catch(
const lanelet::NoSuchPrimitiveError& e) {
554 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Received routing graph specifies lanelets which do not match the current map version. Not found lanelet or area: "
555 << vertex.lanelet_or_area_ids[j] <<
" Actual exception: " << e.what());
564 return std::make_shared<lanelet::routing::RoutingGraph>(std::move(graph), std::move(passable_map));
576 world_model_->setRoadwayObjects(msg->roadway_obstacles);
581 world_model_->setRos1Clock(rclcpp::Time(clock_msg->clock));
586 world_model_->setSimulationClock(rclcpp::Time(clock_msg->clock));
592 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Route message rejected as it is for an older map");
598 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Route message received for future map. Delaying application until map is recieved");
603 bool route_invalidated_by_queued_map_update =
false;
611 bool more_updates_to_apply =
true;
618 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Apply from reroute: There were unapplied updates in carma_wm when a new map was recieved.");
622 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Applying queued update after route was recieved. ");
624 if (update->invalidates_route ==
true) {
625 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Applied queued map update has invalidated the route.");
626 route_invalidated_by_queued_map_update =
true;
629 update->invalidates_route=
false;
633 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Apply from reroute: Done applying updates for new map. However, more updates are waiting for a future map.");
634 more_updates_to_apply =
false;
642 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"WMListener received a route before a map was available. Dropping route message.");
648 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"At least one applied queued map update has invalidated the route. Routing graph will be recomputed.");
650 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Finished recomputing the routing graph for the applied queued map update(s)");
659 auto path = lanelet::ConstLanelets();
660 for(
auto id : route_msg->shortest_path_lanelet_ids)
666 auto route_opt = path.size() == 1 ?
world_model_->getMapRoutingGraph()->getRoute(path.front(), path.back())
667 :
world_model_->getMapRoutingGraph()->getRouteVia(path.front(), lanelet::ConstLanelets(path.begin() + 1, path.end() - 1), path.back());
668 if(route_opt.is_initialized()) {
669 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMListenerWorker"),
"Setting route in world model");
670 auto ptr = std::make_shared<lanelet::routing::Route>(std::move(route_opt.get()));
674 world_model_->setRouteEndPoint({route_msg->end_point.x,route_msg->end_point.y,route_msg->end_point.z});
Class which implements the WorldModel interface. In addition this class provides write access to the ...
This class manages and keeps track of all signalized intersections in the map. All of the SPAT and MA...
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_
boost::optional< carma_planning_msgs::msg::Route > delayed_route_msg_
void setConfigSpeedLimit(double config_lim)
Allows user to set a callback to be triggered when a map update is received.
std::function< void()> map_callback_
void isSpatWallTime(bool is_spat_wall_time)
set true if incoming spat is based on wall clock
void mapUpdateCallback(autoware_lanelet2_msgs::msg::MapBin::SharedPtr geofence_msg)
Callback for new map update messages (geofence). Updates the underlying map.
double getConfigSpeedLimit() const
Returns the current configured speed limit value.
void enableUpdatesWithoutRoute()
Enable updates without route and set route_node_flag_ as true.
std::shared_ptr< CARMAWorldModel > world_model_
void setRouteCallback(std::function< void()> callback)
Allows user to set a callback to be triggered when a route update is received.
void newRegemUpdateHelper(lanelet::Lanelet parent_llt, lanelet::RegulatoryElement *regem) const
This is a helper function updates the parent_llt with specified regem. This function is needed as we ...
LaneletRoutingGraphPtr routingGraphFromMsg(const autoware_lanelet2_msgs::msg::RoutingGraph &msg, lanelet::LaneletMapPtr map) const
Helper function to convert a routing graph message into a actual RoutingGraph object.
void routeCallback(const carma_planning_msgs::msg::Route::SharedPtr route_msg)
Callback for route message.
void setMapCallback(std::function< void()> callback)
Allows user to set a callback to be triggered when a map update is received.
bool checkIfReRoutingNeeded() const
Check if re-routing is needed and returns re-routing flag.
void incomingSpatCallback(const carma_v2x_msgs::msg::SPAT::SharedPtr spat_msg)
incoming spat message
void roadwayObjectListCallback(const carma_perception_msgs::msg::RoadwayObstacleList::SharedPtr msg)
Callback for roadway objects msg.
double config_speed_limit_
std::function< void()> route_callback_
void mapCallback(const autoware_lanelet2_msgs::msg::MapBin::SharedPtr map_msg)
Callback for new map messages. Updates the underlying map.
void simClockCallback(const rosgraph_msgs::msg::Clock::SharedPtr clock_msg)
Callback for Simulation clock message (used in Simulation runs)
size_t current_map_version_
void isUsingSimTime(bool use_sim_time)
set true if simulation_mode is on
std::string getVehicleParticipationType() const
Returns the Vehicle Participation Type value.
bool recompute_route_flag_
WorldModelConstPtr getWorldModel() const
Constructor.
void ros1ClockCallback(const rosgraph_msgs::msg::Clock::SharedPtr clock_msg)
Callback for ROS1 clock message (used in Simulation runs)
std::queue< autoware_lanelet2_msgs::msg::MapBin::SharedPtr > map_update_queue_
WMListenerWorker()
Constructor.
long most_recent_update_msg_seq_
void setVehicleParticipationType(std::string participant)
Allows user to set a callback to be triggered when a map update is received.
bool callback(cav_srvs::PlanTrajectory::Request &req, cav_srvs::PlanTrajectory::Response &res)
std::shared_ptr< lanelet::routing::RoutingGraph > LaneletRoutingGraphPtr
std::shared_ptr< const WorldModel > WorldModelConstPtr
void fromBinMsg(const autoware_lanelet2_msgs::msg::MapBin &msg, std::shared_ptr< carma_wm::TrafficControl > gf_ptr, lanelet::LaneletMapPtr lanelet_map=nullptr)
GeofenceType resolveGeofenceType(const std::string &rule_name)
void logSignalizedIntersectionManager(const carma_wm::SignalizedIntersectionManager &sim)
@ SIGNALIZED_INTERSECTION