Introduction to BTs
翻译自:https://www.behaviortree.dev
Introduction to BTs [BT 简介]
Unlike a Finite State Machine, a Behaviour Tree is a tree of hierarchical nodes that controls the flow of execution of “tasks”. [与有限状态机不同,行为树是控制“任务”执行流程的__分层节点树__。]
Basic Concepts [基本概念]
-
A signal called “tick” is sent to the root of the tree and propagates through the tree until it reaches a leaf node. [一个称为“tick”的信号被发送到树的根部并在树中传播,直到它到达叶节点。]
-
A TreeNode that receives a tick signal executes it’s callback. This callback must return either [接收到__tick__信号的 TreeNode 会执行它的回调。此回调必须返回]
- SUCCESS, [成功]
- FAILURE or [失败]
- RUNNING, if the action is asynchronous and it needs more time to complete. [正在运行]
-
If a TreeNode has one or more children, it is in charge for ticking them, based on its state, external parameters or the result of the previous sibling. [如果 TreeNode 有一个或多个子节点,它负责根据其状态、外部参数或前一个兄弟节点的结果对它们进行标记。]
-
The LeafNodes, those TreeNodes which don’t have any children, are the actual commands, i.e. the place where the behavior tree interacts with the rest of the system. Actions nodes are the most common type of LeafNodes. [LeafNodes,那些没有任何子节点的 TreeNodes,是实际的命令,即行为树与系统其余部分交互的地方。__动作__节点是最常见的叶节点类型。]
Note
The word tick will be often used as a verb (to tick / to be ticked) and it means [Tick 这个词经常被用作动词(tick/被tick),它的意思是]
“To invoke the callbacktick()
of aTreeNode
”. [“调用 TreeNode 的回调 tick()”。]
In a service-oriented architecture, the leaves would contain the “client” code that communicates with the “server”, that performs the actual operation. [在面向服务的体系结构中,叶子将包含与“服务器”通信的“客户端”代码,执行实际操作。]
How tick works [tick的工作原理]
To mentally visualize how ticking the tree works, consider the example below. [要在脑海中想象树的工作原理,请考虑下面的示例。]
A Sequence is the simplest ControlNode: it execute its children one after the other and, if they all Succeed, it returns SUCCESS (green) too. [Sequence 是最简单的 ControlNode:它一个接一个地执行它的子节点,如果它们都成功,它也返回 SUCCESS(绿色)。]
- The first tick set the Sequence node to RUNNING (orange). [第一个刻度将 Sequence 节点设置为 RUNNING(橙色)。]
- Sequence tick the first child, “DetectObject”, that eventually returns SUCCESS. [序列tick第一个孩子,“DetectObject”,最终返回成功。]
- As a result, the second child “GraspObject” is ticked and the entire Sequence switch from RUNNING to SUCCESS. [结果,第二个孩子“GraspObject”被tick,整个序列从RUNNING切换到SUCCESS。]
Types of nodes [节点类型]
Type of TreeNode | Children Count | Notes |
---|---|---|
ControlNode | 1…N | Usually, ticks a child based on the result of its siblings or/and its own state. [通常,根据其兄弟姐妹的结果或/和它自己的状态来标记一个孩子。] |
DecoratorNode | 1 | Among other things, it may alter the result of the children or tick it multiple times. [除其他外,它可能会改变孩子的结果或多次tick。] |
ConditionNode | 0 | Should not alter the system. Shall not return RUNNING. [不应该改变系统。不应返回 RUNNING。] |
ActionNode | 0 | It can alter the system. [它可以改变系统。] |
In the context of ActionNodes, we may further distinguish between synchronous and asynchronous nodes. [在 ActionNodes 的上下文中,我们可能会进一步区分同步和异步节点。]
The former are executed atomically and block the tree until a SUCCESS or FAILURE is returned. [前者以原子方式执行并阻塞树,直到返回 SUCCESS 或 FAILURE。]
Asynchronous actions, instead, may return RUNNING to communicate that the action is still being executed. [相反,异步操作可能会返回 RUNNING 以表明该操作仍在执行中。]
We need to tick them again, until SUCCESS or FAILURE is eventually returned. [我们需要再次tick它们,直到最终返回 SUCCESS 或 FAILURE。]
Examples [示例]
To better understand how BehaviorTrees work, let’s focus on some practical examples. For the sake of simplicity we will not take into account what happens when an action returns RUNNING. [为了更好地理解 BehaviorTrees 的工作原理,让我们关注一些实际示例。为了简单起见,我们不会考虑当一个动作返回 RUNNING 时会发生什么。]
We will assume that each Action is executed atomically and synchronously. [我们将假设每个 Action 都是原子同步执行的。]
First ControlNode: Sequence [第一个控制节点:序列]
Let’s illustrate how a BT works using the most basic and frequently used ControlNode: the SequenceNode. [让我们用最基本和最常用的 ControlNode 来说明 BT 是如何工作的:SequenceNode。]
The children of a ControlNode are always ordered; in the graphical representation, the order of execution is from left to right. [ControlNode 的子节点总是有序的;在图形表示中,执行顺序是从左到右。]
In short: [简而言之:]
- If a child returns SUCCESS, tick the next one. [如果孩子返回成功,请tick下一个。]
- If a child returns FAILURE, then no more children are ticked and the Sequence returns FAILURE. [如果一个孩子返回 FAILURE,则没有更多的孩子被tick并且序列返回 FAILURE。]
- If all the children return SUCCESS, then the Sequence returns SUCCESS too. [如果所有的孩子都返回成功,那么序列也返回成功。]
warning “Have you spotted the bug?” [你发现错误了吗?]
If the action GrabBeer fails, the door of the fridge would remain open, since the last action CloseFridge is skipped. [如果动作 GrabBeer 失败,冰箱门将保持打开状态,因为最后一个动作 CloseFridge 被跳过。]
Decorators [装饰器]
Depending on the type of DecoratorNode, the goal of this node could be either: [根据 DecoratorNode 的类型,该节点的目标可能是:]
- to transform the result it received from the child. [转换它从孩子那里收到的结果。]
- to halt the execution of the child. [停止对孩子的处决。]
- to repeat ticking the child, depending on the type of Decorator. [根据 Decorator 的类型重复tick子项。]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OblQDhBZ-1656247266593)(images/DecoratorEnterRoom.svg)]
The node Inverter is a Decorator that inverts the result returned by its child; An Inverter followed by the node called isDoorOpen is therefore equivalent to [节点 Inverter 是一个装饰器,它反转其子节点返回的结果;因此,一个 Inverter 后跟名为 isDoorOpen 的节点等价于]
"Is the door closed?". [门关闭了吗?]
The node Retry will repeat ticking the child up to num_attempts times (5 in this case) if the child returns FAILURE. [如果子节点返回 FAILURE,节点 Retry 将重复对子节点进行 num_attempts 次(在本例中为 5 次)。]
Apparently, the branch on the right side means: [显然,右侧的分支意味着:]
If the door is closed, then try to open it.
Try up to 5 times, otherwise give up and return FAILURE.
But…
warning “Have you spotted the bug?”
If isDoorOpen returns FAILURE, we have the desired behaviour. But if it returns SUCCESS, the left branch fails and the entire Sequence is interrupted. [如果 isDoorOpen 返回 FAILURE,我们就有了想要的行为。但是如果返回SUCCESS,则左分支失败,整个Sequence中断。]
We will see later how we can improve this tree. [稍后我们将看到如何改进这棵树。]
Second ControlNode: Fallback [第二个 ControlNode:后备]
FallbackNodes, known also as “Selectors”, are nodes that can express, as the name suggests, fallback strategies, i.e. what to do next if a child returns FAILURE. [FallbackNodes,也称为“选择器”,顾名思义,是可以表达后备策略的节点,即如果孩子返回 FAILURE,下一步该做什么。]
It ticks the children in order and: [它按顺序标记孩子,并且:]
- If a child returns FAILURE, tick the next one. [如果孩子返回失败,请tick下一个。]
- If a child returns SUCCESS, then no more children are ticked and the Fallback returns SUCCESS. [如果一个孩子返回 SUCCESS,则没有更多的孩子被tick,Fallback 返回 SUCCESS。]
- If all the children return FAILURE, then the Fallback returns FAILURE too. [如果所有的孩子都返回 FAILURE,那么 Fallback 也返回 FAILURE。]
In the next example, you can see how Sequences and Fallbacks can be combined: [在下一个示例中,您可以看到如何组合 Sequences 和 Fallbacks:]
Is the door open? [门开着吗?]
If not, try to open the door. [如果没有,请尝试打开门。]
Otherwise, if you have a key, unlock and open the door. [否则,如果有钥匙,解锁开门。]
Otherwise, smash the door. [否则,砸门。]
If any of these actions succeeded, then enter the room. [如果任何一个操作成功,则进入房间。]
“Fetch me a beer” revisited [“给我来杯啤酒” 重温]
We can now improve the “Fetch Me a Beer” example, which left the door open if the beer was not inside the fridge. [我们现在可以改进“给我拿啤酒”的例子,如果啤酒不在冰箱里,它就会把门打开。]
We use the color “green” to represent nodes which return SUCCESS and “red” for those which return FAILURE. Black nodes haven’t been executed. [我们使用颜色“绿色”表示返回 SUCCESS 的节点,使用“红色”表示返回 FAILURE 的节点。黑色节点尚未执行。]
Let’s create an alternative tree that closes the door even when GrabBeer returns FAILURE. [让我们创建一个替代树,即使 GrabBeer 返回 FAILURE 也会关门。]
Both these trees will close the door of the fridge, eventually, but: [这两棵树最终都会关上冰箱的门,但是:]
-
the tree on the left side will always return SUCCESS, no matter if we have actually grabbed the beer. [无论我们是否真的抓住了啤酒,左侧的树总是会返回 SUCCESS。]
-
the tree on the right side will return SUCCESS if the beer was there, FAILURE otherwise. [如果啤酒在那里,右侧的树将返回 SUCCESS,否则返回 FAILURE。]
Everything works as expected if GrabBeer returns SUCCESS. [如果 GrabBeer 返回 SUCCESS,一切都会按预期进行。]