15#include "auto_apms_behavior_tree_core/tree/tree_resource.hpp"
21#include "ament_index_cpp/get_resource.hpp"
22#include "auto_apms_behavior_tree_core/definitions.hpp"
23#include "auto_apms_behavior_tree_core/exceptions.hpp"
24#include "auto_apms_behavior_tree_core/tree/tree_document.hpp"
25#include "auto_apms_util/resource.hpp"
26#include "auto_apms_util/string.hpp"
34 std::vector<std::string> tokens =
37 if (tokens.size() == 2) {
40 }
else if (tokens.size() == 1) {
46 throw auto_apms_util::exceptions::ResourceIdentityFormatError(
47 "Behavior tree resource identity string '" + identity +
48 "' is invalid. Both <tree_file_stem> and <tree_name> must be provided.");
58 unique_identity_.behavior_alias, _AUTO_APMS_BEHAVIOR_TREE_CORE__RESOURCE_IDENTITY_ALIAS_SEP,
false);
60 if (tokens.size() != 2) {
61 throw auto_apms_util::exceptions::ResourceIdentityFormatError(
62 "Unique tree resource identity string '" + unique_identity_.str() +
63 "' is invalid. Behavior alias must be <tree_file_stem>" +
64 _AUTO_APMS_BEHAVIOR_TREE_CORE__RESOURCE_IDENTITY_ALIAS_SEP +
"<tree_name>.");
67 unique_identity_.file_stem = tokens[0];
68 unique_identity_.tree_name = tokens[1];
73 doc.
mergeFile(build_request_file_path_,
true);
74 }
catch (
const std::exception & e) {
75 throw auto_apms_util::exceptions::ResourceError(
76 "Failed to create TreeResource with identity '" + unique_identity_.str() +
"' because tree file " +
77 build_request_file_path_ +
" cannot be parsed: " + e.what());
81 if (!unique_identity_.tree_name.empty()) {
83 throw auto_apms_util::exceptions::ResourceError(
84 "Cannot create TreeResource with identity '" + unique_identity_.str() +
"' because '" +
85 unique_identity_.tree_name +
"' does not exist in tree file " + build_request_file_path_ +
".");
101 return !unique_identity_.tree_name.empty() || !doc_root_tree_name_.empty();
106 if (!unique_identity_.tree_name.empty())
return unique_identity_.tree_name;
109 if (!doc_root_tree_name_.empty())
return doc_root_tree_name_;
112 throw auto_apms_util::exceptions::ResourceError(
113 "Cannot get root tree name of tree resource '" + unique_identity_.str() +
114 "'. Since there is no XML attribute named '" + TreeDocument::ROOT_TREE_ATTRIBUTE_NAME +
115 "' and the resource identity doesn't specify <tree_name>, the root tree is unknown.");
122 i.
file_stem = unique_identity_.file_stem;
129 if (tree_name.empty()) {
130 throw auto_apms_util::exceptions::ResourceError(
"Cannot find tree resource: tree_name must not be empty.");
133 std::set<std::string> search_packages;
134 if (!package_name.empty()) {
135 search_packages.insert(package_name);
142 size_t matching_count = 0;
143 for (
const auto & p : search_packages) {
145 std::string base_path;
146 if (ament_index_cpp::get_resource(
147 _AUTO_APMS_BEHAVIOR_TREE_CORE__RESOURCE_TYPE_NAME__BEHAVIOR, p, content, &base_path)) {
148 for (
const auto & line :
151 line, _AUTO_APMS_BEHAVIOR_TREE_CORE__RESOURCE_MARKER_FILE_FIELD_PER_LINE_SEP,
false);
152 if (parts.size() != 6)
continue;
154 const std::string & found_category = parts[0];
155 const std::string & found_alias = parts[1];
158 if (found_category != _AUTO_APMS_BEHAVIOR_TREE_CORE__DEFAULT_BEHAVIOR_CATEGORY__TREE)
continue;
161 const std::vector<std::string> alias_tokens =
163 if (alias_tokens.size() != 2)
continue;
165 if (alias_tokens[1] == tree_name) {
177 if (matching_count == 0) {
178 throw auto_apms_util::exceptions::ResourceError(
179 "No tree resource with tree name '" + tree_name +
"' was found" +
180 (package_name.empty() ?
"." : (
" in package '" + package_name +
"'.")));
182 if (matching_count > 1) {
183 throw auto_apms_util::exceptions::ResourceError(
184 "Tree name '" + tree_name +
"' is ambiguous (" + std::to_string(matching_count) +
185 " matches). You must be more precise.");
193 if (file_stem.empty()) {
194 throw auto_apms_util::exceptions::ResourceError(
"Cannot find tree resource: file_stem must not be empty.");
197 std::set<std::string> search_packages;
198 if (!package_name.empty()) {
199 search_packages.insert(package_name);
206 size_t matching_count = 0;
207 for (
const auto & p : search_packages) {
209 std::string base_path;
210 if (ament_index_cpp::get_resource(
211 _AUTO_APMS_BEHAVIOR_TREE_CORE__RESOURCE_TYPE_NAME__BEHAVIOR, p, content, &base_path)) {
212 for (
const auto & line :
215 line, _AUTO_APMS_BEHAVIOR_TREE_CORE__RESOURCE_MARKER_FILE_FIELD_PER_LINE_SEP,
false);
216 if (parts.size() != 6)
continue;
218 const std::string & found_category = parts[0];
219 const std::string & found_alias = parts[1];
222 if (found_category != _AUTO_APMS_BEHAVIOR_TREE_CORE__DEFAULT_BEHAVIOR_CATEGORY__TREE)
continue;
225 const std::vector<std::string> alias_tokens =
227 if (alias_tokens.size() != 2)
continue;
229 if (alias_tokens[0] == file_stem) {
241 if (matching_count == 0) {
242 throw auto_apms_util::exceptions::ResourceError(
243 "No tree resource with file stem '" + file_stem +
"' was found" +
244 (package_name.empty() ?
"." : (
" in package '" + package_name +
"'.")));
246 if (matching_count > 1) {
247 throw auto_apms_util::exceptions::ResourceError(
248 "File stem '" + file_stem +
"' is ambiguous (" + std::to_string(matching_count) +
249 " matches). You must be more precise.");
BehaviorResourceTemplate(const Identity &search_identity)
std::string getRootTreeName() const
Get the name of this document's root tree.
TreeDocument & mergeFile(const std::string &path, bool adopt_root_tree=false)
Create a tree document from a file and merge it with this one.
std::vector< std::string > getAllTreeNames() const
Get the names of all behavior trees inside this document.
bool hasRootTreeName() const
Determine if this document specifies which of its trees is the root tree.
TreeResourceIdentity createIdentityForTree(const std::string &tree_name="") const
Create a valid identity string for a specific behavior tree of this resource.
std::string getRootTreeName() const
Get the name of the root tree of this behavior tree resource.
static TreeResource findByTreeName(const std::string &tree_name, const std::string &package_name="")
Find an installed behavior tree resource using a specific behavior tree name.
static TreeResource findByFileStem(const std::string &file_stem, const std::string &package_name="")
Find an installed behavior tree resource using an XML file stem.
TreeResource(const TreeResourceIdentity &search_identity)
Assemble a behavior tree resource using a TreeResourceIdentity.
bool hasRootTreeName() const
Determine if this behavior tree resource specifies a root tree.
bool contains(const ContainerT< ValueT, AllocatorT > &c, const ValueT &val)
Check whether a particular container structure contains a value.
std::vector< std::string > splitString(const std::string &str, const std::string &delimiter, bool remove_empty=true)
Split a string into multiple tokens using a specific delimiter string (Delimiter may consist of multi...
std::set< std::string > getPackagesWithResourceType(const std::string &resource_type, const std::set< std::string > &exclude_packages={})
Get a list of all package names that register a certain type of ament_index resources.
Core API for AutoAPMS's behavior tree implementation.
std::string category_name
Name of the category this behavior resource belongs to.
BehaviorResourceIdentity(const std::string &identity)
Constructor of a behavior resource identity object.
std::string behavior_alias
Alias for a single registered behavior.
std::string package_name
Name of the package that registers the behavior resource.
Struct that encapsulates the identity string for a registered behavior tree.
std::string tree_name
Name of a specific tree inside the resource's tree document.
std::string file_stem
Name of the file (without extension) that contains the resource's tree document.
TreeResourceIdentity()=default
Constructor of an empty behavior tree resource identity object.
TreeResourceIdentity(const std::string &identity)
Constructor of a tree resource identity object.