Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
graph_loader.cpp
1 // Copyright (c) 2025, Open Navigation LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <memory>
16 
17 #include "nav2_route/graph_loader.hpp"
18 #include "ament_index_cpp/get_package_share_directory.hpp"
19 
20 namespace nav2_route
21 {
22 
24  nav2_util::LifecycleNode::SharedPtr node,
25  std::shared_ptr<tf2_ros::Buffer> tf,
26  const std::string frame)
27 : plugin_loader_("nav2_route", "nav2_route::GraphFileLoader"),
28  default_plugin_id_("GeoJsonGraphFileLoader")
29 {
30  logger_ = node->get_logger();
31  tf_ = tf;
32  route_frame_ = frame;
33 
34  nav2_util::declare_parameter_if_not_declared(
35  node, "graph_filepath", rclcpp::ParameterValue(std::string("")));
36  graph_filepath_ = node->get_parameter("graph_filepath").as_string();
37 
38  // Default Graph Parser
39  nav2_util::declare_parameter_if_not_declared(
40  node, "graph_file_loader", rclcpp::ParameterValue(default_plugin_id_));
41  auto graph_file_loader_id = node->get_parameter("graph_file_loader").as_string();
42  if (graph_file_loader_id == default_plugin_id_) {
43  nav2_util::declare_parameter_if_not_declared(
44  node, default_plugin_id_ + ".plugin",
45  rclcpp::ParameterValue("nav2_route::GeoJsonGraphFileLoader"));
46  }
47 
48  // Create graph file loader plugin
49  try {
50  plugin_type_ = nav2_util::get_plugin_type_param(node, graph_file_loader_id);
51  graph_file_loader_ = plugin_loader_.createSharedInstance((plugin_type_));
52  RCLCPP_INFO(
53  logger_, "Created GraphFileLoader %s of type %s",
54  graph_file_loader_id.c_str(), plugin_type_.c_str());
55  graph_file_loader_->configure(node);
56  } catch (pluginlib::PluginlibException & ex) {
57  RCLCPP_FATAL(
58  logger_,
59  "Failed to create GraphFileLoader. Exception: %s", ex.what());
60  throw ex;
61  }
62 }
63 
65  Graph & graph,
66  GraphToIDMap & graph_to_id_map,
67  const std::string & filepath)
68 {
69  if (filepath.empty()) {
70  RCLCPP_ERROR(
71  logger_, "The graph filepath was not provided.");
72  return false;
73  }
74 
75  RCLCPP_INFO(
76  logger_,
77  "Loading graph file from %s, by parser %s", filepath.c_str(), plugin_type_.c_str());
78 
79  if (!graph_file_loader_->loadGraphFromFile(graph, graph_to_id_map, filepath)) {
80  return false;
81  }
82 
83  if (!transformGraph(graph)) {
84  RCLCPP_WARN(
85  logger_,
86  "Failed to transform nodes graph file (%s) to %s!", filepath.c_str(), route_frame_.c_str());
87  return false;
88  }
89 
90  return true;
91 }
92 
94  Graph & graph,
95  GraphToIDMap & graph_to_id_map)
96 {
97  if (graph_filepath_.empty()) {
98  RCLCPP_INFO(logger_, "No graph file provided to load yet.");
99  return true;
100  }
101 
102  RCLCPP_INFO(
103  logger_,
104  "Loading graph file from %s, by parser %s", graph_filepath_.c_str(), plugin_type_.c_str());
105 
106  if (!graph_file_loader_->loadGraphFromFile(graph, graph_to_id_map, graph_filepath_)) {
107  return false;
108  }
109 
110  if (!transformGraph(graph)) {
111  RCLCPP_WARN(
112  logger_,
113  "Failed to transform nodes graph file (%s) to %s!",
114  graph_filepath_.c_str(), route_frame_.c_str());
115  return false;
116  }
117 
118  return true;
119 }
120 
121 bool GraphLoader::transformGraph(Graph & graph)
122 {
123  std::unordered_map<std::string, tf2::Transform> cached_transforms;
124  for (auto & node : graph) {
125  std::string node_frame = node.coords.frame_id;
126  if (node_frame.empty() || node_frame == route_frame_) {
127  continue;
128  }
129 
130  if (cached_transforms.find(node_frame) == cached_transforms.end()) {
131  tf2::Transform tf_transform;
132  bool got_transform = nav2_util::getTransform(
133  node_frame, route_frame_, tf2::durationFromSec(0.1), tf_, tf_transform);
134 
135  if (!got_transform) {
136  return false;
137  }
138 
139  cached_transforms.insert({node_frame, tf_transform});
140  }
141 
142  tf2::Vector3 graph_coord(
143  node.coords.x,
144  node.coords.y,
145  0.0);
146 
147  tf2::Vector3 new_coord = cached_transforms[node_frame] * graph_coord;
148 
149  node.coords.x = static_cast<float>(new_coord.x());
150  node.coords.y = static_cast<float>(new_coord.y());
151  node.coords.frame_id = route_frame_;
152  }
153 
154  return true;
155 }
156 
157 } // namespace nav2_route
bool transformGraph(Graph &graph)
Transform the coordinates in the graph to the route frame.
bool loadGraphFromFile(Graph &graph, GraphToIDMap &idx_map, const std::string &filepath)
Loads a graph object with file information from a filepath.
bool loadGraphFromParameter(Graph &graph, GraphToIDMap &idx_map)
Loads a graph object with file information from ROS parameter, if provided.
GraphLoader(nav2_util::LifecycleNode::SharedPtr node, std::shared_ptr< tf2_ros::Buffer > tf, const std::string frame)
A constructor for nav2_route::GraphLoader.