behaviortree和Groot
Behavior Tree
官方文档:https://www.behaviortree.dev/docs/Intro
BehaviorTree.CPP
https://github.com/BehaviorTree/BehaviorTree.CPP
BehaviorTree官方文档:
https://www.behaviortree.dev/bt_basics/
Behavior Tree 原理
分四种节点
行为树(Behavior Tree)具有如下的特性:
它只有4大类型的Node:
* Composite Node 组合节点
* Decorator Node 修饰节点
* Condition Node 条件节点(叶节点)
* Action Node 动作节点(叶节点)
任何Node被执行后,必须向其Parent Node报告执行结果:成功 / 失败。
这简单的成功 / 失败汇报原则被很巧妙地用于控制整棵树的决策方向。
一、组合节点 Composite Node
先看Composite Node,其实它按复合性质还可以细分为3种:
1. Selector Node
(选择节点,顺序执行,满足任意子节点true)
当执行本类型Node时,它将从begin到end迭代执行自己的Child Node:
如遇到一个Child Node执行后返回True,那停止迭代,
本Node向自己的Parent Node也返回True;否则所有Child Node都返回False,
那本Node向自己的Parent Node返回False。
2. Sequence Node
(顺序执行节点,全部子节点都必须true,否则false)
当执行本类型Node时,它将从begin到end迭代执行自己的Child Node:
如遇到一个Child Node执行后返回False,那停止迭代,
本Node向自己的Parent Node也返回False;否则所有Child Node都返回True,
那本Node向自己的Parent Node返回True。
3. Parallel Node
(并发执行节点)
并发执行它的所有Child Node。
而向Parent Node返回的值和Parallel Node所采取的具体策略相关:
Parallel Selector Node: 一False则返回False,全True才返回True。
Parallel Sequence Node: 一True则返回True,全False才返回False。
Parallel Hybird Node: 指定数量的Child Node返回True或False后才决定结果。
Parallel Node提供了并发,提高性能。
不需要像Selector/Sequence那样预判哪个Child Node应摆前,哪个应摆后,
常见情况是:
(1)用于并行多棵Action子树。
(2)在Parallel Node下挂一棵子树,并挂上多个Condition Node,
以提供实时性和性能。
Parallel Node增加性能和方便性的同时,也增加实现和维护复杂度。
PS:上面的Selector/Sequence准确来说是Liner Selector/Liner Sequence。
AI术语中称为strictly-order:按既定先后顺序迭代。
Selector和Sequence可以进一步提供非线性迭代的加权随机变种。
Weight Random Selector提供每次执行不同的First True Child Node的可能。
Weight Random Sequence则提供每次不同的迭代顺序。
AI术语中称为partial-order,能使AI避免总出现可预期的结果。
二、修饰节点 Decorator Node
再看Decorator Node,它的功能正如它的字面意思:它将它的Child Node执行
后返回的结果值做额外处理后,再返回给它的Parent Node。
比如
Decorator Not
Decorator FailUtil
Decorator Counter
Decorator Time
Decorator Log
Decorator Ani
Decorator Nothing
…
三、条件节点(叶节点) Condition Node
Condition Node,它仅当满足Condition时返回True。
四、动作节点(叶节点)Action Node
Action Node,它完成具体的一次(或一个step)的行为,视需求返回值。
而当行为需要分step/Node间进行时,可引入Blackboard进行简单数据交互。
小结
整棵行为树中,只有Condition Node和Action Node才能成为Leaf Node,而也
只有Leaf Node才是需要特别定制的Node;Composite Node和Decorator Node均
用于控制行为树中的决策走向。
每个节点都应该有以下三种状态:
Running,
Success,
Failed
Running状态用于表明该节点的结果不能立刻获知,比如游戏中的角色进行“向目标移动”
这个动作,很显然这个动作不能在这一帧中立刻完成,当行为树运行到此节点时,并不能
获知是success或者failed,于是返回running,表示该节点正在运行中,并记录此节点
的位置,下一帧运行到此节点的父节点时,则从此节点继续运行,跳过之前的节点。
==================================================================================
行为树架构图
行为树 结构图如下,一棵倒置的树
行为树采用节点描述行为逻辑,主要节点类型有:
组合节点:选择节点、顺序节点、随机选择节点、随机顺序节点、随机权重节点、并行节点、并行执行所有节点、if 判断并行节点、if 判断顺序节点
修饰节点:修饰节点取反、修饰节点重复、修饰节点_返回 Fail、修饰节点_返回 Success、修饰节点_直到 Fail、修饰节点_直到 Success
行为树入门:https://zhuanlan.zhihu.com/p/463182588
https://robohub.org/introduction-to-behavior-trees/
组合节点与叶节点区分
一棵行为树表示一个AI逻辑。执行这个 AI 逻辑,需要从根节点开始深度优先遍历执行节点,执行过程中,节点根据自身的类型确定执行逻辑或调用子节点,节点将执行结果反馈给父节点。
从结构上节点可分为:组合节点、叶节点 。
组合节点就是拥有子节点的节点。
叶节点 就是不能添加子节点的节点。
其中叶节点 :条件节点、行为节点。其他为组合节点
如下图一个行为树示例图:
行为树节点顺序如下,
节点1 为根节点, 节点2、节点5为中间节点,节点3、4、6、7,为子节点
节点 1、2、5为组合节点,节点3、4、6、7为叶节点
节点执行结果
执行结果可分为三种:Fail、Success、Running。
Fail : 节点执行失败(如:条件节点判定为 false、执行节点失败、没有符合执行的节点等)
Success:节点执行成功(如:条件节点判定为 true、执行节点成功等)
Running:节点执行中(如:正在跑向目标、正在吃饭、动画播放中等)
叶节点
叶节点类型分为两种:条件节点和行为节点
条件叶节点
条件节点(Condition)即是条件判定,例如:“是否饿了?”、“是否有饭?”、“是否有作业”等。
如果条件测试结果为真,向父节点返回 Success,否则返回 Fail。
条件节点为叶子节点
行为叶节点
行为节点(Action)用来执行实际的工作,如:做饭、吃饭、打球、写作业等。
行为节点有些可能一帧就可以执行完成,有些可能需要多帧才能完成。
行为节点执行过程中失败,向父节点返回 Fail,
执行完毕(成功)向父节点返回 Success,
正在执行中向父节点返回 Running。
组合节点
组合节点用来控制树的遍历方式,每种组合节点的遍历方式都不相同。下面是各个组合节点的执行逻辑
1.选择节点
选择节点:依次从头顺次遍历执行所有子节点
当前执行节点返回 Success,退出停止,向父节点
返回 Success
当前执行节点返回 Fail,退出当前节点
继续执行下一个节点
当前执行节点返回 Running, 记录当前节点,向父节
点返回 Running,下次执行直接从该节点开始
如果所有节点都返回Fail,执行完所有节点后
向父节点返回 Fail
2.顺序节点
顺序节点:依次执行子节点
当前执行节点返回 Success,就继续执行后续节点
当前执行节点返回 Fail,退出停止,向父节点
返回 Fail,下次执行直接从第一个节点开始
当前执行节点返回 Running, 记录当前节点,向父节
点返回 Running,下次执行直接从该节点开始
如果所有节点都返回 Success,向父节点返回 Success
3.随机选择节点
随机选择节点:(参考选择节点)
每次随机一个未执行的节点,总随机次数为子节点个数
当前执行节点返回 Success,退出停止
向父节点返回 Success
当前执行节点返回 Fail,退出当前节点
继续随机一个未执行的节点开始执行
当前执行节点返回 Running, 记录当前节点
向父节点返回 Running,下次执行直接从该节点开始
如果所有节点都返回Fail,执行完所有节点后
向父节点返回 Fail
4.随机顺序节点
随机顺序节点:(参考顺序节点)
每次随机一个未执行的节点,总随机次数为子节点个数
当前执行节点返回 Success,继续随机一个未执行的节点
当前执行节点返回 Fail,退出停止
向父节点返回 Fail
当前执行节点返回 Running, 记录当前节点
向父节点返回 Running,下次执行直接从该节点开始
如果所有节点都返回 Success
向父节点返回 Success
5.随机权重节点
随机权重节点:(参考随机选择节点)
每次根据节点权重随机一个未执行的节点
总随机次数为子节点个数
当前执行节点返回 Success,退出停止
向父节点返回 Success
当前执行节点返回 Fail,退出当前节点
继续随机一个未执行的节点开始执行
当前执行节点返回 Running, 记录当前节点
向父节点返回 Running
下次执行直接从该节点开始
如果所有节点都返回Fail,执行完所有节点后
向父节点返回 Fail
6.并行节点
并行节点:依次从头顺次遍历执行所有子节点
当前执行节点返回 Fail,退出停止,向父节点
返回 Fail
当前执行节点返回 Success,记录当前节点,继续
执行下一个节点,记录所有返回 Success 的节点
当前执行节点返回 Running, 记录当前节点,继续
执行下一个节点,记录所有返回 Running 的节点
如果没有节点返回 Fail
如果所有节点都返回 Success 向父节点返回 Success
否则向父节点返回 Running
7.并行执行所有节点
并行执行所有节点:依次从头顺次遍历执行所有子节点
当前执行节点返回 Success、 Fail、Running 都继续
执行下一个节点,分别记录返回三种结果的节点个数
执行完所有节点后
如果所有节点都返回 Success 向父节点返回 Success
如果所有节点都返回 Fail 向父节点返回 Fail
否则一定有节点返回了Running 向父节点返回 Running
8.if 判断并行节点
if判断并行节点:
只能有 二或者三个子节点
第一个为判断节点只能返回Success、Fail
如下方配置三个节点
第一个节点返回 Success时,执行 第二个节点
第一个节点返回 Fail 时,执行 第三个节点
或者配置两个节点
第一个节点返回 Success时,执行 第二个节点
因为是并行节点,每次执行都会先执行第一个节点
根据第一个节点返回 (Success 或者 Fail)选择执行第M个节点
执行第一个条件节点,记录返回结果 result
根据配置 判断 执行第 M(二、三) 节点
if N 是空 then 执行 第 M 节点的 Enter elseif N 不等于 M then 执行 第 N 节点的 OnExit 执行 第 M 节点的 Enter end 记录当前执行节点:令 N = M 执行 第 N 节点的 Execute 并记录结果 result
9.if 判断顺序节点
if判断顺序节点:
只能有 二或者三个子节点
第一个为判断节点只能返回Success、Fail
配置同上第8条
因为是顺序节点,每次执行时
如果当前有正在执行的第二、第三个节点则
直接执行它的 Execute
如果没有,则执行第一个节点,根据第一个节点返回
根据第一个节点返回 (Success 或者 Fail)选择执行第M个节点
if result == Success then 令 N = nil return 向父节点返回 Success elseif result == Fail then 令 N = nil return 向父节点返回 Fail else -- result == Running return 向父节点返回 Running end
10.修饰节点取反
取反修饰节点 Inverter 对子节点执行结果取反
11.修饰节点重复
修饰节点_重复:
开始执行该节点时,将记录次数清零
顺序执行所有子节点(记为 1 次),不关心节点返回结果
如果 执行次数 < 配置执行次数 向父节点返回 Running
如果 执行次数 >= 配置执行次数 向父节点返回 Success
12.修饰节点_返回 Fail
修饰_返回Fail:
执行节点,无论节点返回 Success、Fail、Running
执行结束后永远向父节点返回 Fail
13.修饰节点_返回 Success
修饰_返回Success:
执行节点,无论节点返回 Success、Fail、Running
执行结束后永远向父节点返回 Success
14.修饰节点_直到 Fail
修饰_直到Fail:
执行节点
如果节点返回结果不是 Fail
向父节点返回 Running
直到节点返回 Fail,向父节点返回 Success
15.修饰节点_直到 Success
修饰_直到Success:
执行节点
如果节点返回结果不是 Success
向父节点返回 Running
直到节点返回 Success,向父节点返回 Success
==================================================================================
Groot
官方文档:
github:https://github.com/BehaviorTree/Groot
主页:https://www.behaviortree.dev/groot/
说明
BehaviorTree行为树是树状的结构,它的逻辑流程是由xml
文件描述的。
用其配套的工具Groot
来可视化行为树。
Groot is a Graphical Editor, written in C++ and Qt, to create BehaviorTrees.
It is compliant with the the library BehaviorTree.CPP.
如下图所示:
可视化和序列化表达行为树
QT界面显示效果