【行为树】05-使用子树进行行为组合

Composition of Behaviors with Subtree

使用子树进行行为组合

我们可以将大规模行为组合起来,通过将较小和可重复使用的行为组合成更大的行为。

换句话说,我们想要创建__层次__行为树。

这可以通过在XML中定义多个树结构来实现,包括一个嵌套在另一个中。

CrossDoor behavior

这个例子是受到一篇关于行为树的流行文章的启发article about behavior trees.

这也是第一个使用 DecoratorsFallback功能的实际示例。

<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>

为了提高可读性,我们的自定义节点使用一行代码进行注册:

CrossDoor::RegisterNodes(factory);

BT库提供的默认节点,如Fallback,已经被BehaviorTreeFactory注册。

可能会注意到,我们将树的一个相当复杂的分支封装在一个称为DoorClosed的独立树中,当门关闭时执行。

期望的行为是:

  • 如果门是打开的,就PassThroughDoor
  • 如果门是关闭的,尝试最多4次OpenDoor,然后PassThroughDoor
  • 如果无法打开关闭的门,就PassThroughWindow

Loggers

在C++的一侧,我们不需要做任何事情来构建可重用的子树。

因此我们借此机会介绍另一个新功能:BehaviorTree.CPP : Loggers.

一个记录器是一种用于显示、记录和/或发布树中任何状态变化的机制。

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值