行为树基础教程:创建你的第一个行为树

行为树基础教程:创建你的第一个行为树

如何创建你自己的动作节点(ActionNodes)

创建TreeNode的最常用(也是推荐)的方式是通过继承。

示例:自定义同步动作节点(无端口)
// 示例的自定义同步动作节点
class ApproachObject : public BT::SyncActionNode {
public:
    ApproachObject(const std::string& name) :
        BT::SyncActionNode(name, {})
    {}

    // 必须重写tick()虚拟函数
    BT::NodeStatus tick() override {
        std::cout << "ApproachObject: " << this->name() << std::endl;
        return BT::NodeStatus::SUCCESS;
    }
};
  • 任何TreeNode实例都有一个name。这个标识符旨在易于人类阅读,且不需要是唯一的。
  • tick()方法是实际动作发生的地方。它必须始终返回一个NodeStatus,即RUNNING、SUCCESS或FAILURE。

或者,我们可以使用依赖注入来创建TreeNode,给定一个函数指针(即“functor”)。

示例:使用函数指针创建TreeNode
using namespace BT;

// 简单函数返回NodeStatus
BT::NodeStatus CheckBattery() {
    std::cout << "[ Battery: OK ]" << std::endl;
    return BT::NodeStatus::SUCCESS;
}

// 将GripperInterface类的方法open()和close()封装成TreeNode
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; // 共享信息
};

我们可以从这些functors创建SimpleActionNode

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

使用XML动态创建树

考虑以下XML文件,名为my_tree.xml

<root BTCPP_format="4">
    <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>
  • 你必须首先在BehaviorTreeFactory中注册自定义的TreeNode,然后从文件或文本加载XML。
  • XML中使用的标识符必须与注册TreeNode时使用的一致。
  • 属性“name”表示实例的名称;它是可选的

代码实现

#include "behaviortree_cpp/bt_factory.h"

// 包含自定义节点定义的文件
#include "dummy_nodes.h"
using namespace DummyNodes;

int main() {
    // 使用BehaviorTreeFactory注册自定义节点
    BehaviorTreeFactory factory;

    // 通过继承创建节点的推荐方式
    factory.registerNodeType<ApproachObject>("ApproachObject");

    // 使用函数指针注册SimpleActionNode
    // 可以使用C++11 lambdas或std::bind
    factory.registerSimpleCondition("CheckBattery", [](BT::TreeNode&) { return CheckBattery(); });

    // 也可以使用类的方法创建SimpleActionNodes
    GripperInterface gripper;
    factory.registerSimpleAction("OpenGripper", [&gripper](BT::TreeNode&){ return gripper.open(); });
    factory.registerSimpleAction("CloseGripper", [&gripper](BT::TreeNode&){ return gripper.close(); });

    // 在部署时(即运行时,但只在开始时一次)创建树
    auto tree = factory.createTreeFromFile("./my_tree.xml");

    // 要“执行”树,你需要“触发”它
    // 触发将根据树的逻辑传播到子节点
    // 在这个例子中,因为Sequence的所有子节点都返回SUCCESS,所以执行了整个序列
    tree.tickWhileRunning();

    return 0;
}

/* 预期输出:
  [ Battery: OK ]
  GripperInterface::open
  ApproachObject: approach_object
  GripperInterface::close
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值