Tutorial 5: Subtrees and Loggers

翻译自:https://www.behaviortree.dev

Composition of Behaviors with Subtree

We can build large scale behavior composing together smaller and reusable behaviors into larger ones. [我们可以构建大规模行为,将更小且可重用的行为组合成更大的行为。]

In other words, we want to create hierarchical behavior trees. [换句话说,我们想要创建分层行为树。]

This can be achieved easily defining multiple trees in the XML including one into the other. [这可以很容易地在 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>
            <RetryUntilSuccessful num_attempts="4">
                <OpenDoor/>
            </RetryUntilSuccessful>
            <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>

For readability, our custom nodes are registered with the one-liner: [为了便于阅读,我们的自定义节点使用单线注册:]

CrossDoor::RegisterNodes(factory);

Default nodes provided by the BT library such as Fallback are already registered by the BehaviorTreeFactory. [BT 库提供的默认节点(例如 Fallback)已经由 BehaviorTreeFactory 注册。]

It may be noticed that we incapsulated a quite complex branch of the tree, the one to execute when the door is closed, into a separate tree called DoorClosed. [可能会注意到,我们将树的一个非常复杂的分支(门关闭时执行的分支)封装到一个名为 DoorClosed 的单独树中。]

The desired behavior is: [期望的行为是:]

  • If the door is open, PassThroughDoor. [如果门打开,PassThroughDoor。]
  • If the door is closed, try up to 4 times to OpenDoor and, then, PassThroughDoor. [如果门已关闭,请最多尝试 4 次 OpenDoor,然后再尝试 PassThroughDoor。]
  • If it was not possible to open the closed door, PassThroughWindow. [如果无法打开关闭的门,PassThroughWindow。]

Loggers

On the C++ side we don’t need to do anything to build reusable subtrees. [在 C++ 方面,我们不需要做任何事情来构建可重用的子树。]

Therefore we take this opportunity to introduce another neat feature of BehaviorTree.CPP : Loggers. [因此,我们借此机会介绍 BehaviorTree.CPP 的另一个简洁功能:记录器。]

A Logger is a mechanism to display, record and/or publish any state change in the tree. [记录器是一种显示、记录和/或发布树中任何状态变化的机制。]


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();
            // IMPORTANT: you must always add some sleep if you call tickRoot()
            // in a loop, to avoid using 100% of your CPU (busy loop).
            // The method Tree::sleep() is recommended, because it can be
            // interrupted by an internal event inside the tree.
            tree.sleep( milliseconds(10) );
        }
        if( LOOP )
        {
            std::this_thread::sleep_for( milliseconds(1000) );
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值