34 std::unordered_map<std::string, NodeBuilder>
builders;
35 std::unordered_map<std::string, TreeNodeManifest>
manifests;
45 _p->parser = std::make_shared<XMLParser>(*
this);
46 registerNodeType<FallbackNode>(
"Fallback");
47 registerNodeType<FallbackNode>(
"AsyncFallback",
true);
48 registerNodeType<SequenceNode>(
"Sequence");
49 registerNodeType<SequenceNode>(
"AsyncSequence",
true);
50 registerNodeType<SequenceWithMemory>(
"SequenceWithMemory");
52 #ifdef USE_BTCPP3_OLD_NAMES
53 registerNodeType<SequenceWithMemory>(
"SequenceStar");
56 registerNodeType<ParallelNode>(
"Parallel");
57 registerNodeType<ParallelAllNode>(
"ParallelAll");
58 registerNodeType<ReactiveSequence>(
"ReactiveSequence");
59 registerNodeType<ReactiveFallback>(
"ReactiveFallback");
60 registerNodeType<IfThenElseNode>(
"IfThenElse");
61 registerNodeType<WhileDoElseNode>(
"WhileDoElse");
63 registerNodeType<InverterNode>(
"Inverter");
65 registerNodeType<RetryNode>(
"RetryUntilSuccessful");
66 registerNodeType<KeepRunningUntilFailureNode>(
"KeepRunningUntilFailure");
67 registerNodeType<RepeatNode>(
"Repeat");
68 registerNodeType<TimeoutNode>(
"Timeout");
69 registerNodeType<DelayNode>(
"Delay");
70 registerNodeType<RunOnceNode>(
"RunOnce");
72 registerNodeType<ForceSuccessNode>(
"ForceSuccess");
73 registerNodeType<ForceFailureNode>(
"ForceFailure");
75 registerNodeType<AlwaysSuccessNode>(
"AlwaysSuccess");
76 registerNodeType<AlwaysFailureNode>(
"AlwaysFailure");
77 registerNodeType<ScriptNode>(
"Script");
78 registerNodeType<ScriptCondition>(
"ScriptCondition");
79 registerNodeType<SetBlackboardNode>(
"SetBlackboard");
80 registerNodeType<SleepNode>(
"Sleep");
81 registerNodeType<UnsetBlackboardNode>(
"UnsetBlackboard");
83 registerNodeType<SubTreeNode>(
"SubTree");
85 registerNodeType<PreconditionNode>(
"Precondition");
87 registerNodeType<SwitchNode<2>>(
"Switch2");
88 registerNodeType<SwitchNode<3>>(
"Switch3");
89 registerNodeType<SwitchNode<4>>(
"Switch4");
90 registerNodeType<SwitchNode<5>>(
"Switch5");
91 registerNodeType<SwitchNode<6>>(
"Switch6");
93 registerNodeType<LoopNode<int>>(
"LoopInt");
94 registerNodeType<LoopNode<bool>>(
"LoopBool");
95 registerNodeType<LoopNode<double>>(
"LoopDouble");
96 registerNodeType<LoopNode<std::string>>(
"LoopString");
98 registerNodeType<EntryUpdatedAction>(
"WasEntryUpdated");
102 for(
const auto& it :
_p->builders)
104 _p->builtin_IDs.insert(it.first);
107 _p->scripting_enums = std::make_shared<std::unordered_map<std::string, int>>();
112 this->_p = std::move(other._p);
117 this->_p = std::move(other._p);
128 throw LogicError(
"You can not remove the builtin registration ID [", ID,
"]");
130 auto it =
_p->builders.find(ID);
131 if(it ==
_p->builders.end())
135 _p->builders.erase(ID);
136 _p->manifests.erase(ID);
143 auto it =
_p->builders.find(
manifest.registration_ID);
144 if(it !=
_p->builders.end())
149 _p->builders.insert({
manifest.registration_ID, builder });
157 NodeBuilder builder = [tick_functor, ID](
const std::string& name,
159 return std::make_unique<SimpleConditionNode>(name, tick_functor, config);
170 NodeBuilder builder = [tick_functor, ID](
const std::string& name,
172 return std::make_unique<SimpleActionNode>(name, tick_functor, config);
183 NodeBuilder builder = [tick_functor, ID](
const std::string& name,
185 return std::make_unique<SimpleDecoratorNode>(name, tick_functor, config);
195 loader.
load(file_path);
205 std::cout <<
"ERROR loading library [" << file_path <<
"]: can't find symbol ["
213 const char os_pathsep(
';');
215 const char os_pathsep(
':');
221 std::vector<std::string> getCatkinLibraryPaths()
223 std::vector<std::string> lib_paths;
224 const char* env = std::getenv(
"CMAKE_PREFIX_PATH");
227 const std::string env_catkin_prefix_paths(env);
228 std::vector<BT::StringView> catkin_prefix_paths =
232 std::filesystem::path path(
static_cast<std::string
>(catkin_prefix_path));
233 std::filesystem::path lib(
"lib");
234 lib_paths.push_back((path / lib).
string());
242 std::vector<std::string> plugins;
244 std::vector<std::string> catkin_lib_paths = getCatkinLibraryPaths();
246 for(
const auto& plugin : plugins)
249 for(
const auto& lib_path : catkin_lib_paths)
251 const auto full_path = std::filesystem::path(lib_path) / filename;
252 if(std::filesystem::exists(full_path))
254 std::cout <<
"Registering ROS plugins from " << full_path.string() << std::endl;
265 throw RuntimeError(
"Using attribute [ros_pkg] in <include>, but this library was "
266 "compiled without ROS support. Recompile the BehaviorTree.CPP "
272 const std::filesystem::path& filename)
274 _p->parser->loadFromFile(filename);
284 return _p->parser->registeredBehaviorTrees();
289 _p->parser->clearInternalState();
293 const std::string& name,
const std::string& ID,
const NodeConfig& config)
const
295 auto idNotFound = [
this, ID] {
296 std::cerr << ID <<
" not included in this list:" << std::endl;
297 for(
const auto& builder_it :
_p->builders)
299 std::cerr << builder_it.first << std::endl;
301 throw RuntimeError(
"BehaviorTreeFactory: ID [", ID,
"] not registered");
304 auto it_manifest =
_p->manifests.find(ID);
305 if(it_manifest ==
_p->manifests.end())
310 std::unique_ptr<TreeNode> node;
312 bool substituted =
false;
313 for(
const auto& [filter, rule] :
_p->substitution_rules)
319 if(
const auto substituted_ID = std::get_if<std::string>(&rule))
321 auto it_builder =
_p->builders.find(*substituted_ID);
322 if(it_builder !=
_p->builders.end())
324 auto& builder = it_builder->second;
325 node = builder(name, config);
329 throw RuntimeError(
"Substituted Node ID [", *substituted_ID,
"] not found");
334 else if(
const auto test_config = std::get_if<TestNodeConfig>(&rule))
337 auto test_node =
new TestNode(name, config, *test_config);
338 node.reset(test_node);
348 auto it_builder =
_p->builders.find(ID);
349 if(it_builder ==
_p->builders.end())
353 auto& builder = it_builder->second;
354 node = builder(name, config);
357 node->setRegistrationID(ID);
358 node->config().enums =
_p->scripting_enums;
360 auto AssignConditions = [](
auto& conditions,
auto& executors) {
361 for(
const auto& [cond_id, script] : conditions)
365 executors[size_t(cond_id)] = executor.value();
369 throw LogicError(
"Error in the script \"", script,
"\"\n", executor.error());
373 AssignConditions(config.
pre_conditions, node->preConditionsScripts());
374 AssignConditions(config.
post_conditions, node->postConditionsScripts());
384 const std::unordered_map<std::string, TreeNodeManifest>&
387 return _p->manifests;
392 return _p->builtin_IDs;
398 if(!
_p->parser->registeredBehaviorTrees().empty())
400 std::cout <<
"WARNING: You executed BehaviorTreeFactory::createTreeFromText "
401 "after registerBehaviorTreeFrom[File/Text].\n"
402 "This is NOT, probably, what you want to do.\n"
403 "You should probably use BehaviorTreeFactory::createTree, instead"
416 if(!
_p->parser->registeredBehaviorTrees().empty())
418 std::cout <<
"WARNING: You executed BehaviorTreeFactory::createTreeFromFile "
419 "after registerBehaviorTreeFrom[File/Text].\n"
420 "This is NOT, probably, what you want to do.\n"
421 "You should probably use BehaviorTreeFactory::createTree, instead"
435 auto tree =
_p->parser->instantiateTree(blackboard, tree_name);
443 auto it =
_p->manifests.find(node_id);
444 if(it ==
_p->manifests.end())
446 throw std::runtime_error(
"addMetadataToManifest: wrong ID");
448 it->second.metadata = metadata;
453 const auto str = std::string(name);
454 auto it =
_p->scripting_enums->find(str);
455 if(it ==
_p->scripting_enums->end())
457 _p->scripting_enums->insert({ str, value });
461 if(it->second != value)
464 StrCat(
"Registering the enum [", name,
"] twice with different values, first ",
472 _p->substitution_rules.clear();
477 _p->substitution_rules[std::string(filter)] = rule;
484 std::unordered_map<std::string, TestNodeConfig> configs;
486 auto test_configs =
json.
at(
"TestNodeConfigs");
487 for(
auto const& [name, test_config] : test_configs.items())
489 auto& config = configs[name];
491 auto return_status = test_config.
at(
"return_status").
get<std::string>();
493 if(test_config.contains(
"async_delay"))
496 std::chrono::milliseconds(test_config[
"async_delay"].get<int>());
498 if(test_config.contains(
"post_script"))
500 config.post_script = test_config[
"post_script"].get<std::string>();
502 if(test_config.contains(
"success_script"))
504 config.success_script = test_config[
"success_script"].get<std::string>();
506 if(test_config.contains(
"failure_script"))
508 config.failure_script = test_config[
"failure_script"].get<std::string>();
512 auto substitutions =
json.
at(
"SubstitutionRules");
513 for(
auto const& [node_name, test] : substitutions.items())
515 auto test_name = test.
get<std::string>();
516 auto it = configs.find(test_name);
517 if(it == configs.end())
528 const std::unordered_map<std::string, BehaviorTreeFactory::SubstitutionRule>&
531 return _p->substitution_rules;
536 subtrees = std::move(other.subtrees);
547 (*this) = std::move(other);
552 wake_up_ = std::make_shared<WakeUpSignal>();
555 for(
auto& node : subtree->nodes)
573 auto visitor = [](
BT::TreeNode* node) { node->haltNode(); };
585 auto& subtree_nodes =
subtrees.front()->nodes;
586 return subtree_nodes.empty() ? nullptr : subtree_nodes.front().get();
592 std::chrono::duration_cast<std::chrono::milliseconds>(timeout));
619 return subtrees.front()->blackboard;
662 wake_up_->waitFor(std::chrono::milliseconds(0)))
673 sleep(std::chrono::milliseconds(sleep_time));
682 assert(backup.size() == tree.
subtrees.size());
683 for(
size_t i = 0; i < tree.
subtrees.size(); i++)
685 backup[i]->cloneInto(*(tree.
subtrees[i]->blackboard));
691 std::vector<Blackboard::Ptr> bb;
693 for(
const auto& sub : tree.
subtrees)
696 sub->blackboard->cloneInto(*bb.back());
704 for(
const auto& subtree : tree.
subtrees)
707 auto sub_name = subtree->instance_name;
710 sub_name = subtree->tree_ID;
721 throw std::runtime_error(
"Number of blackboards don't match:");
725 for(
auto& [key, array] :
json.items())
727 auto& subtree = tree.
subtrees.at(index++);