注册节点
#include "behaviortree_cpp_v3/bt_factory.h"
using namespace BT;
BehaviorTreeFactory factory;
// 下面的funciton指的是:
// BT::NodeStatus FunctionName() {}
// 1.registerNodeType<ClassName>("nodeName"); 这里的类需要继承BT::SyncActionNode
factory.registerNodeType<SaySomething>("SaySomething");
// 2.registerSimpleCondition("nodeName", function)
factory.registerSimpleCondition("CheckBattery", std::bind(CheckBattery));
// 3.普通类
GripperInterface gripper;
factory.registerSimpleAction("OpenGripper", std::bind(&GripperInterface::open, &gripper));
// 4.registerSimpleAction("nodeName", function, portsList);
PortsList say_something_ports = { InputPort<std::string>("message") };
factory.registerSimpleAction("SaySomething2", SaySomethingSimple,
say_something_ports );
// 5.registerBuilder
NodeBuilder builder_A = [](const std::string& name, const NodeConfiguration& config) {
return std::make_unique<Action_A>(name, config, 42, 3.14, "hello world");
};
factory.registerBuilder<Action_A>("Action_A", builder_A);
创建行为树
BehaviorTreeFactory factory;
// 1.from file,第二个参数可以传入黑板
auto tree = factory.createTreeFromFile("source/turtle2.xml");
// 2.from text,第二个参数可以传入黑板
std::string text;
auto tree = factory.createTreeFromText(text);
//3.第二个参数可以传入黑板
auto tree = factory.createTree("name", blackboard)
注册行为树
// 方法一 有效
static const char* xml_text_main = R"(
<root main_tree_to_execute="MainTree">
<BehaviorTree ID="MainTree">
<Sequence>
<SaySomething message="starting MainTree" />
<SubTree ID="SubA"/>
<SubTree ID="SubB"/>
</Sequence>
</BehaviorTree>
</root> )";
factory.registerBehaviorTreeFromText(xml_text_main);
// 方法二 写demo测试有问题
factory.registerBehaviorTreeFromFile("main_tree.xml");
节点的参数传递与对应的注册方法
// 方法一
class Action_A : public SyncActionNode
{
public:
// additional arguments passed to the constructor
Action_A(const std::string& name, const NodeConfiguration& config, int arg1,
double arg2, std::string arg3) :
SyncActionNode(name, config), _arg1(arg1), _arg2(arg2), _arg3(arg3)
{}
static PortsList providedPorts()
{
return {};
}
...
}
// 方法二
class Action_B : public SyncActionNode
{
public:
Action_B(const std::string& name, const NodeConfiguration& config) :
SyncActionNode(name, config)
{}
// we want this method to be called ONCE and BEFORE the first tick()
void init(int arg1, double arg2, std::string arg3)
{
_arg1 = (arg1);
_arg2 = (arg2);
_arg3 = (arg3);
}
static PortsList providedPorts()
{
return {};
}
...
}
// 对应的注册方式也不一样
BehaviorTreeFactory factory;
NodeBuilder builder_A = [](const std::string& name, const NodeConfiguration& config) {
return std::make_unique<Action_A>(name, config, 42, 3.14, "hello world");
};
factory.registerBuilder<Action_A>("Action_A", builder_A);
factory.registerNodeType<Action_B>("Action_B");
auto tree = factory.createTreeFromText(xml_text);
for (auto& node : tree.nodes)
{
if (auto action_B_node = dynamic_cast<Action_B*>(node.get()))
{
action_B_node->init(69, 9.99, "interesting_value");
}
}
Type of ControlNode | Child returns RUNNING |
---|---|
Fallback | Tick again |
ReactiveFallback | Restart |
- “重新开始”意味着整个回退将从列表的第一个子节点重新开始。
- “再次触发”意味着下次触发回退时,同一子节点将再次被触发。已经返回失败的前一个兄弟节点不会再次被触发。
Type of ControlNode | Child returns FAILURE | Child returns RUNNING |
---|---|---|
Sequence | Restart | Tick again |
ReactiveSequence | Restart | Restart |
SequenceStar | Tick again | Tick again |
数据流、端口和黑板
-
一个黑板是树的所有节点共享的键/值存储
-
端口是节点之间交换信息的机制。
-
端口用黑板的相同键进行连接
-
节点的数量、名称和类型端口必须在编译时(C++)知道;端口之间的连接在部署时(XML)完成
Types of nodes
Type of TreeNode | Children Count | Notes |
---|---|---|
ControlNode | 1…N | 通常,根据其兄弟节点的状态和/或自身状态来确定一个子节点是否执行 |
DecoratorNode | 1 | 可能会改变子节点的结果或多次tick它 |
ConditionNode | 0 | 不应该改变系统,不应该返回RUNNING |
ActionNode | 0 | 它可以改变系统 |