FSMs有什么问题?对反应性和模块化的需求
-
模块化(一个系统的组件可以被划分成不同的模块,并重新组合成的能力):如果删除了一个组件,则需要修改到该组件的每个转换
-
反应性(对变化做出快速有效反应的能力):组件之间需要进行许多转换,而许多转换意味着许多单向控制传输
行为树的运行
-
BT是一种有向根树,其中内部节点称为控制流节点,叶节点称为执行节点。对于每个连接节点,我们使用父节点和子节点的通用术语。根是没有父节点的节点;所有其他节点都有一个父节点。控制流节点至少有一个子节点。
-
BT从根节点开始执行,根节点生成一个有一定频率的允许节点执行的信号,这个信号可以称为滴嗒,该信号被发送给它的子节点。当且仅当节点接收到信号时才执行节点。如果正在执行,则子进程立即返回到父进程,如果已经达到目标,则返回成功,否则返回失败。
-
经典行为树框架:四类控制节点(Sequence、Selector、Parallel和Decorator)和两类执行节点(Action和Condition)。
-
序列节点执行算法,将信号从左边传到它的子节点,直到它找到一个返回Failure或Running的子节点,然后它返回Failure或Running到它自己的父节点。当且仅当它的所有子元素都返回成功时,它才返回成功。注意,当一个子节点返回Running或Failure时,序列节点不会将信号传到下一个子节点(如果有的话)。
for i←1 to N do
childStatus ← Tick(child(i))
if childStatus = Running then
return Running
else if childStatus = Failure then
return Failure
return Success
- 回退节点执行算法,将信号从左边路由到它的子节点,直到它找到一个返回成功或正在运行的子节点,然后它返回Success或Running到它自己的父节点。当且仅当它的所有子元素都返回Failure时,它才返回Failure。注意,当一个子节点返回Running或Success时,回退节点不会将信号路传到下一个子节点(如果有的话)。
for i←1 to N do
childStatus ← Tick(child(i))
if childStatus = Running then
return Running
else if childStatus = Success then
return Success
return Failure
- 并行节点执行算法,将信号传给所有子节点;它返回Success如果M个子节点返回Success;它将返回Failure如果N−M + 1个子节点返回Failure;否则返回Running。其中N是子节点数量,M≤N是一个用户定义的阈值。
for i←1 to N do
childStatus(i) ← Tick(child(i))
if Σi:childStatus(i)=Success1 ≥ M then
return Success
else if Σi:childStatus(i)=Failure1 > N − M then
return Failure
return Running
-
行为节点当接收到信号时,执行一个命令。如果执行正确完成,则返回Success;如果执行失败,则返回Failure。当行为正在进行时,它返回Running。
-
条件节点当接收到信号时,检查命题。根据条件的成立与否返回成功或失败。注意,条件节点从不返回Running。
-
装饰节点是一个控制流节点,有一个单独的子节点。该节点根据用户定义的规则操作子节点的返回状态,并根据一些预定义的规则有选择地标记子节点。
-
举例说明:球的抓取行为树
-
具有内存的节点,为了避免不必要的某些节点的重新执行。带有内存的控制流节点始终记住子节点是否返回了Success或Failure,避免子节点的重新执行,直到整个序列节点或回退节点以Success或Failure告终。当父节点返回成功或失败时,内存将被清除,以便在下一次激活时考虑所有的子节点。
-
举例说明:机器人抓取绿色木块放到制定地点