可以构建将多个更小的可重复使用的行为到一个更大的树中;
换句话说,想构建分层的行为树;
通过在XML中定义多个树来实现;
CrossDoor behavior
This example is inspired by a popular article about behavior trees.
It is also the first practical example that uses Decorators
and Fallback
.
<root main_tree_to_execute = "MainTree"> <BehaviorTree ID="DoorClosed"> <Sequence name="door_closed_sequence"> <Inverter> <IsDoorOpen/> </Inverter> <RetryUntilSuccesful num_attempts="4"> <OpenDoor/> </RetryUntilSuccesful> <PassThroughDoor/> </Sequence> </BehaviorTree> <BehaviorTree ID="MainTree"> <Fallback name="root_Fallback"> <Sequence name="door_open_sequence"> <IsDoorOpen/> <PassThroughDoor/> </Sequence> <SubTree ID="DoorClosed"/> <PassThroughWindow/> </Fallback> </BehaviorTree> </root>
The desired behavior is:
- If the door is open,
PassThroughDoor
. - If the door is closed, try up to 4 times to
OpenDoor
and, then,PassThroughDoor
. - If it was not possible to open the closed door,
PassThroughWindow
.
Loggers
一个Logger是一种用于显示,记录,或者发布在树中任何状态的改变的机制:
int main() { using namespace BT; BehaviorTreeFactory factory; // register all the actions into the factory // We don't show how these actions are implemented, since most of the // times they just print a message on screen and return SUCCESS. // See the code on Github for more details. factory.registerSimpleCondition("IsDoorOpen", std::bind(IsDoorOpen)); factory.registerSimpleAction("PassThroughDoor", std::bind(PassThroughDoor)); factory.registerSimpleAction("PassThroughWindow", std::bind(PassThroughWindow)); factory.registerSimpleAction("OpenDoor", std::bind(OpenDoor)); factory.registerSimpleAction("CloseDoor", std::bind(CloseDoor)); factory.registerSimpleCondition("IsDoorLocked", std::bind(IsDoorLocked)); factory.registerSimpleAction("UnlockDoor", std::bind(UnlockDoor)); // Load from text or file... auto tree = factory.createTreeFromText(xml_text); // This logger prints state changes on console StdCoutLogger logger_cout(tree); // This logger saves state changes on file FileLogger logger_file(tree, "bt_trace.fbl"); // This logger stores the execution time of each node MinitraceLogger logger_minitrace(tree, "bt_trace.json"); #ifdef ZMQ_FOUND // This logger publish status changes using ZeroMQ. Used by Groot PublisherZMQ publisher_zmq(tree); #endif printTreeRecursively(tree.rootNode()); //while (1) { NodeStatus status = NodeStatus::RUNNING; // Keep on ticking until you get either a SUCCESS or FAILURE state while( status == NodeStatus::RUNNING) { status = tree.tickRoot(); CrossDoor::SleepMS(1); // optional sleep to avoid "busy loops" } CrossDoor::SleepMS(2000); } return 0; }