• How to create a BehaviorTree


    行为树类似于状态机,只是一种机制,在正确的条件下,正确的时间来唤醒回调函数。

    进一步,我们使用callback和tick来相互替换;

    这些回调函数里面具体执行什么取决于你;

    怎样创建你自己的ActionNodes

    默认的方法是采用继承的方式来实现一个TreeNode:

    //Example of custom SyncActionNode(synchronous action) without ports.
    class ApproachObject : public BT::SyncActionNode
    {
      public:
           ApproachObject(const std::string& name) :
            BT::SyncActionNode(name, {})
            {}
    
       //You must override the virtual function tick()
      BT::NodeStatus tick() override
      {
         std::out << "ApproachObject: " << this->name() <<std::endl;
        return BT::NodeStatus::SUCCESS;
      }
    };

    任何一个TreeNode的实例需要有一个名字,但不要求是唯一的;

    方法tick()是实际行为发生的地方。它必须总是返回一个节点状态,如RUNNING,SUCCESS或者FAILURE。

    另外,也可以用依赖注入的方式创建一个TreeNode,给定一个函数指针(如functor)

    对functor唯一的要求是具有如下之一的表示:

        BT::NodeStatus myFunction()
        BT::NodeStatus myFunction(BT::TreeNode& self) 
    

    例如:

    using namespace BT;
    
    // Simple function that return a NodeStatus
    BT::NodeStatus CheckBattery()
    {
        std::cout << "[ Battery: OK ]" << std::endl;
        return BT::NodeStatus::SUCCESS;
    }
    
    // We want to wrap into an ActionNode the methods open() and close()
    class GripperInterface
    {
    public:
        GripperInterface(): _open(true) {}
    
        NodeStatus open() {
            _open = true;
            std::cout << "GripperInterface::open" << std::endl;
            return NodeStatus::SUCCESS;
        }
    
        NodeStatus close() {
            std::cout << "GripperInterface::close" << std::endl;
            _open = false;
            return NodeStatus::SUCCESS;
        }
    
    private:
        bool _open; // shared information
    };
    

    我们可以构建一个SimpleActionNode从下面的functors中的任何一个:

    • CheckBattery()
    • GripperInterface::open()
    • GripperInterface::close()

    用一个XML来动态创建一棵树

    XML文件命名为my_tree.xml:

     <root main_tree_to_execute = "MainTree" >
         <BehaviorTree ID="MainTree">
            <Sequence name="root_sequence">
                <CheckBattery   name="check_battery"/>
                <OpenGripper    name="open_gripper"/>
                <ApproachObject name="approach_object"/>
                <CloseGripper   name="close_gripper"/>
            </Sequence>
         </BehaviorTree>
     </root>
    

    You can find more details about the XML schema here.

    首先比如注册我们自定义的TreeNodes到BehaviorTreeFactory中,然后从文件或者text中加载XML;

    在XML中使用的标志符必须与注册TreeNodes中使用的一致;

    属性name表示实例的名字,它是可选的;

    #include "behaviortree_cpp_v3/bt_factory.h"
    
    // file that contains the custom nodes definitions
    #include "dummy_nodes.h"
    
    int main()
    {
        // We use the BehaviorTreeFactory to register our custom nodes
        BehaviorTreeFactory factory;
    
        // Note: the name used to register should be the same used in the XML.
        using namespace DummyNodes;
    
        // The recommended way to create a Node is through inheritance.
        factory.registerNodeType<ApproachObject>("ApproachObject");
    
        // Registering a SimpleActionNode using a function pointer.
        // you may also use C++11 lambdas instead of std::bind
        factory.registerSimpleCondition("CheckBattery", std::bind(CheckBattery));
    
        //You can also create SimpleActionNodes using methods of a class
        GripperInterface gripper;
        factory.registerSimpleAction("OpenGripper", 
                                     std::bind(&GripperInterface::open, &gripper));
        factory.registerSimpleAction("CloseGripper", 
                                     std::bind(&GripperInterface::close, &gripper));
    
        // Trees are created at deployment-time (i.e. at run-time, but only 
        // once at the beginning). 
    
        // IMPORTANT: when the object "tree" goes out of scope, all the 
        // TreeNodes are destroyed
        auto tree = factory.createTreeFromFile("./my_tree.xml");
    
        // To "execute" a Tree you need to "tick" it.
        // The tick is propagated to the children based on the logic of the tree.
        // In this case, the entire sequence is executed, because all the children
        // of the Sequence return SUCCESS.
        tree.tickRoot();
    
        return 0;
    }
    
    /* Expected output:
    *
           [ Battery: OK ]
           GripperInterface::open
           ApproachObject: approach_object
           GripperInterface::close
    */
  • 相关阅读:
    使用ServiceLoader辅助责任链模式
    聊聊ThreadLocal
    Log4J
    Scalable IO in Java
    MySQL的索引
    Git的操作与理解
    阿里校招内推总结
    Executor框架的简要分析
    Java 8 中的ConcurrentHashMap源码分析
    从C#到Swift,Swift学习笔记
  • 原文地址:https://www.cnblogs.com/gary-guo/p/14694207.html
Copyright © 2020-2023  润新知