行为树(BT)笔记(二):行为树简介

行为树简介

与有限状态机不同,行为树是一个分层节点树,它控制决策流和“任务”的执行,或者我们将进一步称之为“ 动作 ”。

树的叶子是实际命令,即我们的协调组件与系统其余部分交互的位置。

例如,在面向服务的体系结构中,叶子将包含与执行操作的“服务器”通信的“客户端”代码。

在下面的示例中,我们可以看到在序列中执行的两个Actions, DetectObject以及GraspObject。

å¶å°ç»ä»¶éä¿¡

树的其他节点,即不是叶子的节点,控制“执行流程”。

为了更好地理解这种控制流是如何发生的,设想一个叫做“ tick ” 的信号; 它在树的根部执行,并通过分支传播,直到它到达一个或多个叶子。

单词tick经常用作动词(勾选/被勾选),这意味着“调用一个tick()名为TreeNode的回调“。

当一个TreeNode被选中,它会返回一个NodeStatus

  • SUCCESS
  • FAILURE
  • RUNNING
  • IDLE

前两个正如它们的名字一样,通知它们父母的行动是成功还是失败。

异步节点在执行未完成时返回RUNNING,并且需要更多时间来返回有效结果。

此C ++库还提供IDLE状态; 这意味着节点已准备好启动。

节点的结果将传播回其父节点,该节点将决定下一个应该选中哪个子节点,或者将结果返回给它自己的父节点。

 

节点的类型

ControlNodes是可以有1到N 个子节点的节点。一旦收到tick,该tick可以传播给一个或多个子节点。

DecoratorNodes类似于ControlNode,但它只能有一个子节点。

ActionNodes是叶子,没有子节点。用户应该实现自己的ActionNodes来执行实际任务。

ConditionNodes等效于ActionNodes,但它们始终是原子的,即它们不能返回RUNNING。它们不应该改变系统的状态。

UMLå±æ¬¡ç»æ

 

例子

为了更好地理解BehaviorTrees如何工作,让我们关注一些实际的例子。为简单起见,我们不会考虑操作返回RUNNING时会发生什么。

我们假设每个Action都是原子地和同步地执行的。

第一个ControlNode:序列

让我们来说明BT如何使用最基本和最常用的ControlNode:SequenceNode

ControlNode的子节点总是有序的 ; 是由ControlNode来考虑这个顺序。

在图形表示中,执行顺序是从左到右

ç®åçåºåï¼å°ç®±

简而言之:

  • 如果子节点返回SUCCESS,请勾选子节点。
  • 如果子节点返回FAILURE,则不再勾选子节点并且向Sequence返回FAILURE。
  • 如果所有子节点返回SUCCESS,则Sequence也返回SUCCESS。
存在的bug
如果操作GrabBeer失败,冰箱的门将保持打开状态,因为跳过了最后一个动作CloseFridge。

装饰器

DecoratorNode的目标是转接从子节点接收的结果,终止子节点,或重复tick子节点,具体取决于Decorator的类型。

您可以创建自己的装饰器。

ç®åçè£é¥°èï¼è¿å¥æ¿é´

节点Inverter是一个装饰器,它反转其子节点返回的结果; 因此,Inverter后跟着一个称为DoorOpen的节点 相当于

“门关上了吗?”

如果子节点返回FAILURE ,节点Retry将重复给子节点tick N次(在该例子中为3次)。

显而易见的,右侧的分支意味着:

如果门关闭,请尝试打开它。
尝试最多3次,否则放弃并返回FAILURE。

但是...

如果DoorOpen返回FAILURE,我们会有所行动。但是如果它返回SUCCESS,则左分支失败并且整个序列被中断。

稍后我们将看到如何改进这棵树。

第二个ControlNode:反馈

FallbackNodes,也称为“选择器”,是一个节点,顾名思义,它可以表达反馈策略,即如果子节点退出失败,下一步该怎么做。

简而言之,它按顺序给子节点打勾,并且:

  • 如果子节点退回FAILURE,请勾选下一个子节点。
  • 如果子节点返回SUCCESS,则不再勾选子项,并且Fallback返回SUCCESS。
  • 如果所有子节点都返回FAILURE,那么Fallback也会返回FAILURE。

在下一个示例中,您可以看到序列和反馈如何组合:

FallbackNodes

门开了吗?

如果没有,请尝试打开门。

门没开,如果您有钥匙,请解锁并打开门。

否则,砸门。

如果这些操作中的任何一个成功,则进入房间。

重写“给我拿一杯啤酒”

我们现在可以改进“给我拿一杯啤酒”的例子,如果啤酒不在冰箱内保持开门的状态。

我们使用绿色表示返回SUCCESS的节点,使用红色表示返回FAILURE的节点,黑色节点则表示永远不会执行。

FetchBeer失败

让我们创建一个替代树,即使GrabBeer 返回FAILURE 也会关闭门。

FetchBeer失败

这两棵树最终将关闭冰箱的门,但是:

  • 如果我们设法打开和关闭冰箱,左侧的树将始终返回SUCCESS。

  • 如果啤酒在那里,右侧的树将返回SUCCESS,否则将失败。

如果GrabBeer返回SUCCESS,一切都按预期工作。

FetchBeeræå
 

猜你喜欢

转载自blog.csdn.net/Travis_X/article/details/87687914