22 : tf2_buffer_(tf2_buffer) {}
41 const std::vector<lanelet::BasicPoint2d>& via,
42 const lanelet::BasicPoint2d end,
43 const lanelet::LaneletMapConstPtr map_pointer,
47 auto start_lanelet_vector = lanelet::geometry::findNearest(map_pointer->laneletLayer, start, 1);
49 if(start_lanelet_vector.empty())
51 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Found no lanelets in the map. Routing cannot be done.");
52 return lanelet::Optional<lanelet::routing::Route>();
55 auto start_lanelet = lanelet::ConstLanelet(start_lanelet_vector[0].second.constData());
57 auto end_lanelet_vector = lanelet::geometry::findNearest(map_pointer->laneletLayer, end, 1);
59 auto end_lanelet = lanelet::ConstLanelet(end_lanelet_vector[0].second.constData());
61 lanelet::ConstLanelets via_lanelets_vector;
62 for(lanelet::BasicPoint2d
point : via)
64 auto via_lanelet_vector = lanelet::geometry::findNearest(map_pointer->laneletLayer,
point, 1);
65 via_lanelets_vector.emplace_back(lanelet::ConstLanelet(via_lanelet_vector[0].second.constData()));
68 return graph_pointer->getRouteVia(start_lanelet, via_lanelets_vector, end_lanelet);
77 const std::shared_ptr<carma_planning_msgs::srv::GetAvailableRoutes::Request>,
78 std::shared_ptr<carma_planning_msgs::srv::GetAvailableRoutes::Response> resp)
81 if(!boost::filesystem::exists(boost::filesystem::path(this->
route_file_path_)))
88 boost::filesystem::directory_iterator end_point;
89 for(boost::filesystem::directory_iterator itr(boost::filesystem::path(this->
route_file_path_)); itr != end_point; ++itr)
92 if(boost::filesystem::is_directory(itr->status()))
97 auto full_file_name = itr->path().filename().generic_string();
98 carma_planning_msgs::msg::Route route_msg;
101 if(full_file_name.find(
".csv") == std::string::npos)
107 route_msg.route_id = full_file_name.substr(0, full_file_name.find(
".csv"));
108 std::ifstream fin(itr->path().generic_string());
109 std::string dest_name;
115 std::getline(fin, temp);
116 if(temp !=
"") dest_name = temp;
122 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"File open failed...");
124 auto last_comma = dest_name.find_last_of(
',');
125 if(!std::isdigit(dest_name.substr(last_comma + 1).at(0)))
127 route_msg.route_name = dest_name.substr(last_comma + 1);
128 resp->available_routes.push_back(move(route_msg));
151 const std::shared_ptr<carma_planning_msgs::srv::SetActiveRoute::Request> req,
152 std::shared_ptr<carma_planning_msgs::srv::SetActiveRoute::Response> resp)
157 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"System is already following a route.");
158 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ALREADY_FOLLOWING_ROUTE;
163 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"Valid state proceeding with selection");
170 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"No vehicle position. Routing cannot be completed.");
171 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTING_FAILURE;
179 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Could not generate route as there was no map projection available");
180 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTING_FAILURE;
187 std::vector<lanelet::BasicPoint3d> destination_points;
188 if(req->choice == carma_planning_msgs::srv::SetActiveRoute::Request::ROUTE_ID)
190 RCLCPP_INFO_STREAM(
logger_->get_logger(),
"set_active_route_cb: Selected Route ID: " << req->route_id);
194 else if(req->choice == carma_planning_msgs::srv::SetActiveRoute::Request::DESTINATION_POINTS_ARRAY)
196 RCLCPP_INFO_STREAM(
logger_->get_logger(),
"set_active_route_cb: Destination Points array of size " << req->destination_points.size());
201 if(destination_points.size() < 1)
203 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Provided route contains no destination points. Routing cannot be completed.");
204 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTE_FILE_ERROR;
211 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"World model has not been initialized.");
212 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTING_FAILURE;
225 destination_points_in_map_with_vehicle.insert(destination_points_in_map_with_vehicle.begin(), vehicle_position);
229 for (
auto pt : destination_points_in_map_with_vehicle)
231 if ((
world_model_->getLaneletsFromPoint(pt, 1)).empty())
233 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Route Generator: " << idx
234 <<
"th destination point is not in the map, x: " << pt.x() <<
" y: " << pt.y());
235 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTE_FILE_ERROR;
246 auto route =
routing(destination_points_in_map_with_vehicle.front(),
247 std::vector<lanelet::BasicPoint2d>(destination_points_in_map_with_vehicle.begin() + 1, destination_points_in_map_with_vehicle.end() - 1),
248 destination_points_in_map_with_vehicle.back(),
253 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Cannot find a route passing all destinations.");
254 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTING_FAILURE;
262 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"At least one duplicate Lanelet ID occurs in the shortest path. Routing cannot be completed.");
263 resp->error_status = carma_planning_msgs::srv::SetActiveRoute::Response::ROUTING_FAILURE;
270 lanelet::Point3d end_point{lanelet::utils::getId(), destination_points_in_map_with_vehicle.back().x(), destination_points_in_map_with_vehicle.back().y(), 0};
272 route->setEndPoint(end_point);
277 for(
auto id :
route_msg_.route_path_lanelet_ids)
299 std::vector<lanelet::Id> shortest_path_lanelet_ids;
302 for(
const auto& ll :
route.shortestPath())
304 shortest_path_lanelet_ids.push_back(ll.id());
308 std::sort(shortest_path_lanelet_ids.begin(), shortest_path_lanelet_ids.end());
310 if (std::adjacent_find(shortest_path_lanelet_ids.begin(), shortest_path_lanelet_ids.end()) != shortest_path_lanelet_ids.end())
323 throw std::invalid_argument(
"loadRouteDestinationsInMapFrame (using destination points array) before map projection was set");
326 lanelet::projection::LocalFrameProjector projector(
map_proj_.get().c_str());
329 std::vector<lanelet::BasicPoint3d> destination_points;
330 for (
const auto& destination : destinations)
332 lanelet::GPSPoint coordinate;
333 coordinate.lon = destination.longitude;
334 coordinate.lat = destination.latitude;
336 if(destination.elevation_exists)
338 coordinate.ele = destination.elevation;
342 coordinate.ele = 0.0;
345 destination_points.emplace_back(projector.forward(coordinate));
348 return destination_points;
355 std::ifstream fs(route_file_name);
359 std::vector<carma_v2x_msgs::msg::Position3D> destination_points;
360 while(std::getline(fs, line))
362 carma_v2x_msgs::msg::Position3D gps_point;
365 auto comma = line.find(
",");
367 gps_point.longitude = std::stof(line.substr(0, comma));
368 line.erase(0, comma + 1);
369 comma = line.find(
",");
371 gps_point.latitude = std::stof(line.substr(0, comma));
373 line.erase(0, comma + 1);
374 comma = line.find(
",");
375 gps_point.elevation = std::stof(line.substr(0, comma));
376 gps_point.elevation_exists =
true;
378 destination_points.push_back(gps_point);
381 return destination_points;
386 std::vector<lanelet::ConstPoint3d> points;
387 auto end_point_3d =
route.get().getEndPoint();
388 auto last_ll =
route.get().shortestPath().back();
392 auto points_until_end_point = int (last_ll.centerline().size() * (end_point_downtrack / lanelet_downtrack));
394 for(
const auto& ll :
route.get().shortestPath())
396 if (ll.id() == last_ll.id())
398 for (
int i = 0;
i < points_until_end_point;
i++)
400 points.push_back(ll.centerline()[
i]);
404 for(
const auto& pt : ll.centerline())
406 points.push_back(pt);
413 visualization_msgs::msg::Marker marker;
414 marker.header.frame_id =
"map";
415 marker.header.stamp = rclcpp::Time();
416 marker.type = visualization_msgs::msg::Marker::SPHERE_LIST;
417 marker.action = visualization_msgs::msg::Marker::ADD;
418 marker.ns =
"route_visualizer";
420 marker.scale.x = 0.65;
421 marker.scale.y = 0.65;
422 marker.scale.z = 0.65;
423 marker.frame_locked =
true;
426 marker.color.r = 1.0F;
427 marker.color.g = 1.0F;
428 marker.color.b = 1.0F;
429 marker.color.a = 1.0F;
433 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"No central line points! Returning");
437 for (
int i = 0;
i < points.size();
i=
i+5)
439 geometry_msgs::msg::Point temp_point;
440 temp_point.x = points[
i].x();
441 temp_point.y = points[
i].y();
444 marker.points.push_back(temp_point);
452 carma_planning_msgs::msg::Route msg;
454 for(
const auto& ll :
route.get().shortestPath())
456 msg.shortest_path_lanelet_ids.push_back(ll.id());
459 for(
const auto& ll :
route.get().laneletSubmap()->laneletLayer)
461 msg.route_path_lanelet_ids.push_back(ll.id());
463 msg.end_point.x =
route->getEndPoint().x();
464 msg.end_point.y =
route->getEndPoint().y();
465 msg.end_point.z =
route->getEndPoint().z();
471 const std::shared_ptr<carma_planning_msgs::srv::AbortActiveRoute::Request>,
472 std::shared_ptr<carma_planning_msgs::srv::AbortActiveRoute::Response> resp)
478 resp->error_status = carma_planning_msgs::srv::AbortActiveRoute::Response::NO_ERROR;
480 route_msg_ = carma_planning_msgs::msg::Route{};
483 resp->error_status = carma_planning_msgs::srv::AbortActiveRoute::Response::NO_ACTIVE_ROUTE;
498 tf_ =
tf2_buffer_.lookupTransform(
"map",
"vehicle_front", rclcpp::Time(0,0), rclcpp::Duration(1.0*1e9));
501 catch (
const tf2::TransformException &ex)
503 RCLCPP_WARN_STREAM(
logger_->get_logger(), ex.what());
506 geometry_msgs::msg::PoseStamped updated_vehicle_pose;
519 }
catch (std::invalid_argument ex) {
520 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Routing has finished but carma_wm has not receive it!");
526 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Current active route name is " <<
route_msg_.route_name <<
", WorldModel is using " << this->world_model_->getRouteName());
532 ll_id_ = current_lanelet.id();
538 lanelet::Optional<carma_wm::TrafficRulesConstPtr> traffic_rules =
world_model_->getTrafficRules();
543 if (laneletIterator !=
world_model_->getMap()->laneletLayer.end()) {
544 speed_limit_ = (*traffic_rules)->speedLimit(*laneletIterator).speedLimit.value();
548 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Failed to set the current speed limit. The lanelet_id: "
549 <<
ll_id_ <<
" could not be matched with a lanelet in the map. The previous speed limit of "
556 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Failed to set the current speed limit. Valid traffic rules object could not be built.");
558 std::shared_ptr<geometry_msgs::msg::PoseStamped> pose_ptr(
new geometry_msgs::msg::PoseStamped(*
vehicle_pose_));
568 double route_length_2d =
world_model_->getRouteEndTrackPos().downtrack;
588 const carma_ros2_utils::PubPtr<carma_planning_msgs::msg::RouteState>& route_state_pub,
589 const carma_ros2_utils::PubPtr<carma_planning_msgs::msg::Route>& route_pub,
590 const carma_ros2_utils::PubPtr<visualization_msgs::msg::Marker>& route_marker_pub)
610 std::vector<lanelet::BasicPoint2d> destination_points_in_map_temp;
612 for(
const auto &
i:destination_points_in_map)
614 double destination_down_track=
world_model_->routeTrackPos(
i).downtrack;
618 destination_points_in_map_temp.push_back(
i);
620 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"destination_down_track:" << destination_down_track);
643 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"Rerouting required");
651 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"Cannot find a route passing all destinations.");
658 RCLCPP_ERROR_STREAM(
logger_->get_logger(),
"At least one duplicate Lanelet ID occurs in the shortest path. Routing cannot be completed.");
668 std::string original_route_name =
route_msg_.route_name;
690 carma_planning_msgs::msg::RouteState state_msg;
691 state_msg.header.stamp =
clock_->now();
697 state_msg.lanelet_id =
ll_id_;
705 RCLCPP_INFO_STREAM(
logger_->get_logger(),
"Publishing a route event!");
714 lanelet::BasicPoint2d position;
716 position.x()= msg->pose.position.x;
717 position.y()= msg->pose.position.y;
719 if(boost::geometry::within(position, current.polygon2d()))
725 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"LLt Polygon Dimensions1: " << current.polygon2d().front().x()<<
", "<< current.polygon2d().front().y());
726 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"LLt Polygon Dimensions2: " << current.polygon2d().back().x()<<
", "<< current.polygon2d().back().y());
727 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"Distance1: " << boost::geometry::distance(position, current.polygon2d()) <<
" Max allowed Crosstrack: " <<
cross_track_dist_ );
729 if (boost::geometry::distance(position, current.polygon2d()) >
cross_track_dist_)
753 double min = std::numeric_limits<double>::infinity();
754 lanelet::ConstLanelet min_llt;
757 double dist = boost::geometry::distance(position,
i.polygon2d());
Position in a track based coordinate system where the axis are downtrack and crosstrack....
tf2::Stamped< tf2::Transform > frontbumper_transform_
static constexpr double epsilon_
bool setActiveRouteCb(const std::shared_ptr< rmw_request_id_t >, const std::shared_ptr< carma_planning_msgs::srv::SetActiveRoute::Request > req, std::shared_ptr< carma_planning_msgs::srv::SetActiveRoute::Response > resp)
Set_active_route service callback. User can select a route to start following by calling this service...
void setCrosstrackErrorDistance(double cte_dist)
set the maximum crosstrack error distance
bool getAvailableRouteCb(const std::shared_ptr< rmw_request_id_t >, const std::shared_ptr< carma_planning_msgs::srv::GetAvailableRoutes::Request >, std::shared_ptr< carma_planning_msgs::srv::GetAvailableRoutes::Response > resp)
Get_available_route service callback. Calls to this service will respond with a list of route names f...
bool new_route_msg_generated_
void addLanelet(lanelet::ConstLanelet llt)
double current_downtrack_distance_
RouteStateWorker rs_worker_
void setLoggerInterface(rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger)
Dependency injection for logger interface.
void setWorldModelPtr(carma_wm::WorldModelConstPtr wm)
Dependency injection for world model pointer.
double ll_crosstrack_distance_
bool new_route_marker_generated_
std::vector< lanelet::BasicPoint2d > destination_points_in_map_
void setRouteFilePath(const std::string &path)
Set method for configurable parameter.
void initializeBumperTransformLookup()
Initialize transform lookup from front bumper to map.
tf2_ros::Buffer & tf2_buffer_
void setClock(rclcpp::Clock::SharedPtr clock)
Dependency injection for clock object.
void bumperPoseCb()
Callback for the front bumper pose transform.
void setReroutingChecker(const std::function< bool()> inputFunction)
setReroutingChecker function to set the rerouting flag
lanelet::Optional< lanelet::routing::Route > rerouteAfterRouteInvalidation(const std::vector< lanelet::BasicPoint2d > &destination_points_in_map)
After route is invalidated, this function returns a new route based on the destinations points.
void setCrosstrackErrorCountMax(int cte_max)
set the crosstrack error counter maximum limit
void setDowntrackDestinationRange(double dt_dest_range)
Set method for configurable parameter.
lanelet::ConstLanelet getClosestLaneletFromRouteLanelets(lanelet::BasicPoint2d position) const
"Get the closest lanelet on the route relative to the vehicle's current position. If the input list d...
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger_
boost::optional< std::string > map_proj_
visualization_msgs::msg::Marker composeRouteMarkerMsg(const lanelet::Optional< lanelet::routing::Route > &route)
composeRouteMarkerMsg is a function to generate route rviz markers
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::Route > route_pub_
visualization_msgs::msg::Marker route_marker_msg_
bool spinCallback()
Spin callback which will be called frequently based on spin rate.
lanelet::BasicPoint2d current_loc_
std::string route_file_path_
double down_track_target_range_
geometry_msgs::msg::TransformStamped tf_
void twistCb(geometry_msgs::msg::TwistStamped::UniquePtr msg)
Callback for the twist subscriber, which will store latest twist locally.
RouteGeneratorWorker(tf2_ros::Buffer &tf2_buffer)
Constructor for RouteGeneratorWorker class taking in dependencies via dependency injection.
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::RouteEvent > route_event_pub_
std::vector< lanelet::BasicPoint3d > loadRouteDestinationsInMapFrame(const std::vector< carma_v2x_msgs::msg::Position3D > &destinations) const
Function to take route destination points from a vector of 3D points and convert them from lat/lon va...
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::RouteState > route_state_pub_
std::function< bool()> reroutingChecker
reroutingChecker function to set the rerouting flag locally
carma_wm::WorldModelConstPtr world_model_
carma_planning_msgs::msg::RouteEvent route_event_msg_
lanelet::Optional< lanelet::routing::Route > routing(const lanelet::BasicPoint2d start, const std::vector< lanelet::BasicPoint2d > &via, const lanelet::BasicPoint2d end, const lanelet::LaneletMapConstPtr map_pointer, const carma_wm::LaneletRoutingGraphConstPtr graph_pointer) const
Generate Lanelet2 route based on input destinations.
carma_planning_msgs::msg::Route route_msg_
std::vector< carma_v2x_msgs::msg::Position3D > loadRouteDestinationGpsPointsFromRouteId(const std::string &route_id) const
Function to load route destination points from a route file and store them in a vector of 3D points.
carma_planning_msgs::msg::Route composeRouteMsg(const lanelet::Optional< lanelet::routing::Route > &route) const
Helper function to generate a CARMA route message based on planned lanelet route.
void setPublishers(const carma_ros2_utils::PubPtr< carma_planning_msgs::msg::RouteEvent > &route_event_pub, const carma_ros2_utils::PubPtr< carma_planning_msgs::msg::RouteState > &route_state_pub, const carma_ros2_utils::PubPtr< carma_planning_msgs::msg::Route > &route_pub, const carma_ros2_utils::PubPtr< visualization_msgs::msg::Marker > &route_marker_pub)
Method to pass publishers into worker class.
rclcpp::Clock::SharedPtr clock_
lanelet::ConstLanelets route_llts
std::unique_ptr< tf2_ros::TransformListener > tf2_listener_
bool crosstrackErrorCheck(const std::shared_ptr< geometry_msgs::msg::PoseStamped > &msg, lanelet::ConstLanelet current_llt)
crosstrackErrorCheck is a function that determines when the vehicle has left the route and reports wh...
void georeferenceCb(std_msgs::msg::String::UniquePtr msg)
Callback for the georeference subscriber used to set the map projection.
carma_ros2_utils::PubPtr< visualization_msgs::msg::Marker > route_marker_pub_
bool abortActiveRouteCb(const std::shared_ptr< rmw_request_id_t >, const std::shared_ptr< carma_planning_msgs::srv::AbortActiveRoute::Request >, std::shared_ptr< carma_planning_msgs::srv::AbortActiveRoute::Response > resp)
Abort_active_route service callback. User can call this service to abort a current following route an...
bool checkForDuplicateLaneletsInShortestPath(const lanelet::routing::Route &route) const
Helper function to check whether a route's shortest path contains any duplicate Lanelet IDs....
boost::optional< geometry_msgs::msg::PoseStamped > vehicle_pose_
std::queue< uint8_t > route_event_queue
void publishRouteEvent(uint8_t event_type)
double ll_downtrack_distance_
double current_crosstrack_distance_
RouteState getRouteState() const
Get current route state machine state.
void setLoggerInterface(rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger)
void onRouteEvent(RouteEvent event)
Process route event based on designed state machine diagram.
TrackPos trackPos(const lanelet::ConstLanelet &lanelet, const lanelet::BasicPoint2d &point)
Returns the TrackPos, computed in 2d, of the provided point relative to the centerline of the provide...
std::shared_ptr< const WorldModel > WorldModelConstPtr
std::shared_ptr< const lanelet::routing::RoutingGraph > LaneletRoutingGraphConstPtr