AutoAPMS
Resilient Robot Mission Management
Loading...
Searching...
No Matches
tree_resource.cpp
Go to the documentation of this file.
1// Copyright 2024 Robin Müller
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// https://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
16
17#include <tinyxml2.h>
18
19#include <filesystem>
20
21#include "ament_index_cpp/get_resource.hpp"
25
27{
28
29std::vector<TreeResource> TreeResource::collectFromPackage(const std::string& package_name)
30{
31 std::string content;
32 std::string base_path;
33 std::vector<TreeResource> resources;
34 if (ament_index_cpp::get_resource(_AUTO_APMS_BEHAVIOR_TREE__RESOURCE_TYPE_NAME__TREE, package_name, content,
35 &base_path))
36 {
37 std::vector<std::string> lines = auto_apms_core::util::splitString(content, "\n", false);
38 auto make_absolute_path = [base_path](const std::string& s) { return base_path + "/" + s; };
39 for (const auto& line : lines)
40 {
41 std::vector<std::string> parts = auto_apms_core::util::splitString(line, "|");
42 if (parts.size() != 4)
43 {
44 throw std::runtime_error("Invalid behavior tree resource file (Package: '" + package_name + "').");
45 }
47 r.tree_file_stem = parts[0];
48 r.tree_file_path = make_absolute_path(parts[1]);
50 r.node_manifest_file_path = make_absolute_path(parts[2]);
51 std::vector<std::string> tree_ids_vec = auto_apms_core::util::splitString(parts[3], ";");
52 r.tree_names = { tree_ids_vec.begin(), tree_ids_vec.end() };
53 resources.push_back(r);
54 }
55 }
56 return resources;
57}
58
59TreeResource TreeResource::selectByTreeName(const std::string& tree_name, const std::string& package_name)
60{
61 std::set<std::string> search_packages;
62 if (!package_name.empty())
63 {
64 search_packages.insert(package_name);
65 }
66 else
67 {
68 search_packages = auto_apms_core::getAllPackagesWithResource(_AUTO_APMS_BEHAVIOR_TREE__RESOURCE_TYPE_NAME__TREE);
69 }
70
71 std::vector<TreeResource> matching_resources;
72 for (const auto& package_name : search_packages)
73 {
74 for (const auto& r : collectFromPackage(package_name))
75 {
76 if (r.tree_names.find(tree_name) != r.tree_names.end())
77 {
78 matching_resources.push_back(r);
79 }
80 }
81 }
82
83 if (matching_resources.empty())
84 {
85 throw auto_apms_core::exceptions::ResourceNotFoundError{ "No behavior tree with name '" + tree_name +
86 "' was registered." };
87 }
88 if (matching_resources.size() > 1)
89 {
90 throw auto_apms_core::exceptions::ResourceNotFoundError{ "The behavior tree name '" + tree_name +
91 "' exists multiple times. Use the 'package_name' argument "
92 "to narrow down the search." };
93 }
94
95 return matching_resources[0];
96}
97
98TreeResource TreeResource::selectByFileName(const std::string& file_name, const std::string& package_name)
99{
100 const std::string file_stem = std::filesystem::path{ file_name }.stem().string();
101 std::set<std::string> search_packages;
102 if (!package_name.empty())
103 {
104 search_packages.insert(package_name);
105 }
106 else
107 {
108 search_packages = auto_apms_core::getAllPackagesWithResource(_AUTO_APMS_BEHAVIOR_TREE__RESOURCE_TYPE_NAME__TREE);
109 }
110
111 std::vector<TreeResource> matching_resources;
112 for (const auto& package_name : search_packages)
113 {
114 for (const auto& r : collectFromPackage(package_name))
115 {
116 if (r.tree_file_stem == file_stem)
117 {
118 matching_resources.push_back(r);
119 }
120 }
121 }
122
123 if (matching_resources.empty())
124 {
125 throw auto_apms_core::exceptions::ResourceNotFoundError{ "No behavior tree file with name '" + file_stem +
126 ".xml' was registered." };
127 }
128 if (matching_resources.size() > 1)
129 {
130 throw auto_apms_core::exceptions::ResourceNotFoundError{ "Multiple behavior tree files with name '" + file_stem +
131 ".xml' are registered. Use the 'package_name' argument to "
132 "narrow down the search." };
133 }
134
135 return matching_resources[0];
136}
137
138TreeResource TreeResource::fromString(const std::string& identity)
139{
140 const auto tokens = auto_apms_core::util::splitString(identity, "::");
141 if (tokens.size() != 3)
142 {
143 throw exceptions::ResourceIdentityFormatError("Identity string '" + identity +
144 "' has wrong format. Number of string tokens separated by '::' must "
145 "be 3.");
146 }
147 const std::string& tree_file_stem = tokens[0];
148 const std::string& tree_name = tokens[1];
149 const std::string& package_name = tokens[2];
150 if (tree_name.empty())
152 if (tree_file_stem.empty())
153 return selectByTreeName(tree_name, package_name);
154
155 // Full signature: Verify that <tree_name> can be found in file with stem <tree_file_stem>
157 if (resource.tree_names.find(tree_name) == resource.tree_names.end())
158 {
160 "Found behavior tree file '" + tree_file_stem + ".xml' in package '" + resource.package_name +
161 "' but no tree with name '" + tree_name + "' exists in that file.");
162 }
163 return resource;
164}
165
167{
168 tinyxml2::XMLDocument doc;
169 if (doc.LoadFile(tree_file_path.c_str()) != tinyxml2::XMLError::XML_SUCCESS)
170 {
171 throw exceptions::TreeXMLFormatError("Invalid tree xml in resource file " + tree_file_path + ": " + doc.ErrorStr());
172 }
173 tinyxml2::XMLPrinter printer;
174 doc.Print(&printer);
175 return printer.CStr();
176}
177
178} // namespace auto_apms_behavior_tree
std::vector< std::string > splitString(const std::string &str, const std::string &delimiter, bool preserve_empty=true)
Split a string into multiple tokens using a specific delimiter string (Delimiter may consist of multi...
Definition string.cpp:24
std::set< std::string > getAllPackagesWithResource(const std::string &resource_type)
Collect all package names that register a certain type of ament_index resources.
Definition resources.cpp:25
Struct containing behavior tree resource data.
static TreeResource fromString(const std::string &identity)
Find a behavior tree resource using an identity string.
static TreeResource selectByFileName(const std::string &file_name, const std::string &package_name="")
static std::vector< TreeResource > collectFromPackage(const std::string &package_name)
Collect all behavior tree resources registered by a certain package.
static TreeResource selectByTreeName(const std::string &tree_name, const std::string &package_name="")