20 #include "nav2_route/plugins/graph_file_loaders/geojson_graph_file_loader.hpp"
26 const rclcpp_lifecycle::LifecycleNode::SharedPtr node)
28 RCLCPP_INFO(node->get_logger(),
"Configuring geojson graph file loader");
29 logger_ = node->get_logger();
33 Graph & graph, GraphToIDMap & graph_to_id_map, std::string filepath)
36 RCLCPP_ERROR(logger_,
"The filepath %s does not exist", filepath.c_str());
40 std::ifstream graph_file(filepath);
44 json_graph = Json::parse(graph_file);
45 }
catch (Json::parse_error & ex) {
46 RCLCPP_ERROR(logger_,
"Failed to parse %s: %s", filepath.c_str(), ex.what());
50 auto features = json_graph[
"features"];
51 std::vector<Json> nodes, edges;
54 if (nodes.empty() || edges.empty()) {
56 logger_,
"The graph is malformed. Is does not contain nodes or edges. Please check %s",
61 graph.resize(nodes.size());
69 return std::filesystem::exists(filepath);
73 const Json & features, std::vector<Json> & nodes, std::vector<Json> & edges)
75 for (
const auto & feature : features) {
76 if (feature[
"geometry"][
"type"] ==
"Point") {
77 nodes.emplace_back(feature);
79 feature[
"geometry"][
"type"] ==
"MultiLineString" ||
80 feature[
"geometry"][
"type"] ==
"LineString")
82 edges.emplace_back(feature);
88 Graph & graph, GraphToIDMap & graph_to_id_map, std::vector<Json> & nodes)
91 for (
const auto & node : nodes) {
92 const auto properties = node[
"properties"];
93 graph[idx].nodeid = properties[
"id"];
94 graph_to_id_map[graph[idx].nodeid] = idx;
103 Graph & graph, GraphToIDMap & graph_to_id_map, std::vector<Json> & edges)
105 for (
const auto & edge : edges) {
107 const auto properties = edge[
"properties"];
108 unsigned int id = properties[
"id"];
109 unsigned int start_id = properties[
"startid"];
110 unsigned int end_id = properties[
"endid"];
112 if (graph_to_id_map.find(start_id) == graph_to_id_map.end()) {
113 RCLCPP_ERROR(logger_,
"Start id %u does not exist for edge id %u", start_id,
id);
117 if (graph_to_id_map.find(end_id) == graph_to_id_map.end()) {
118 RCLCPP_ERROR(logger_,
"End id of %u does not exist for edge id %u", end_id,
id);
126 graph[graph_to_id_map[start_id]].addEdge(
127 edge_cost, &graph[graph_to_id_map[end_id]],
id,
128 metadata, operations);
135 const auto & properties = node[
"properties"];
136 if (properties.contains(
"frame")) {
137 coords.frame_id = properties[
"frame"];
140 const auto & coordinates = node[
"geometry"][
"coordinates"];
141 coords.x = coordinates[0];
142 coords.y = coordinates[1];
148 const Json & properties,
149 const std::string & key)
152 if (!properties.contains(key)) {
return metadata;}
154 for (
const auto & data : properties[key].items()) {
155 if (data.value().is_object() ) {
157 metadata.setValue(data.key(), new_metadata);
161 const auto setPrimitiveType = [&](
const auto & value) -> std::any
163 if (value.is_number()) {
164 if (value.is_number_unsigned()) {
165 return static_cast<unsigned int>(value);
166 }
else if (value.is_number_integer()) {
167 return static_cast<int>(value);
169 return static_cast<float>(value);
173 if (value.is_boolean()) {
174 return static_cast<bool>(value);
177 if (value.is_string()) {
178 return static_cast<std::string
>(value);
181 logger_,
"Failed to convert the key: %s to a value", data.key().c_str());
182 throw std::runtime_error(
"Failed to convert");
185 if (data.value().is_array()) {
186 std::vector<std::any> array;
187 for (
const auto & el : data.value()) {
188 auto value = setPrimitiveType(el);
189 array.push_back(value);
191 metadata.setValue(data.key(), array);
195 auto value = setPrimitiveType(data.value());
196 metadata.setValue(data.key(), value);
205 json_operation.at(
"type").get_to(operation.type);
206 Json trigger = json_operation.at(
"trigger");
207 operation.trigger = trigger.get<OperationTrigger>();
209 operation.metadata = metadata;
216 Operations operations;
217 if (properties.contains(
"operations")) {
218 for (
const auto & json_operation : properties[
"operations"]) {
228 if (properties.contains(
"cost")) {
229 edge_cost.cost = properties[
"cost"];
232 if (properties.contains(
"overridable")) {
233 edge_cost.overridable = properties[
"overridable"];
240 #include "pluginlib/class_list_macros.hpp"
A GraphFileLoader plugin to load a geojson graph representation.
Coordinates convertCoordinatesFromJson(const Json &node)
Converts the coordinates from the json object into the Coordinates type.
bool doesFileExist(const std::string &filepath)
Checks if a file even exists on the filesystem.
Operation convertOperationFromJson(const Json &json_operation)
Converts the operation from the json object into the operation type.
Operations convertOperationsFromJson(const Json &properties)
Converts the operations data from the json object into the operations type if present.
void addNodesToGraph(Graph &graph, GraphToIDMap &graph_to_id_map, std::vector< Json > &nodes)
Add nodes into the graph.
Metadata convertMetaDataFromJson(const Json &properties, const std::string &key="metadata")
Converts the metadata from the json object into the metadata type.
void configure(const rclcpp_lifecycle::LifecycleNode::SharedPtr node) override
Configure, but do not store the node.
void addEdgesToGraph(Graph &graph, GraphToIDMap &graph_to_id_map, std::vector< Json > &edges)
Add edges into the graph.
EdgeCost convertEdgeCostFromJson(const Json &properties)
Converts the edge cost data from the json object into the edge cost type.
bool loadGraphFromFile(Graph &graph, GraphToIDMap &graph_to_id_map, std::string filepath) override
Loads the geojson file into the graph.
void getGraphElements(const Json &features, std::vector< Json > &nodes, std::vector< Json > &edges)
Get the nodes and edges from features.
A plugin interface to parse a file into the graph.
An object to store Node coordinates in different frames.
An object to store edge cost or cost metadata for scoring.
An object to store operations to perform on events with types and metadata.