简介
| 框架名称 | 核心特点 | 适用场景 |
|---|---|---|
| py_trees | ROS生态标准,纯Python实现,提供黑板、可视化工具(py_trees_js)和大量演示案例。 |
机器人、AI原型开发,以及与你的PySide项目集成。 |
| abtree | 高性能、异步行为树框架,支持"行为森林"协作。 | 对并发性能和执行效率有高要求的复杂Python应用。 |
| 框架名称 | 核心特点 | 适用场景 |
|---|---|---|
| BehaviorTree.CPP | C++领域的事实标准。支持异步、并发、XML动态加载,并提供了强大的图形化编辑器 Groot2。设计上强调数据流和运行时加载,与ROS生态深度集成。 | 游戏开发、机器人、高性能工业控制。 |
| 框架名称 | 核心特点 | 适用场景 |
|---|---|---|
| Unreal Engine | 引擎内置,非常成熟,与UE的AI感知、寻路系统、黑板和EQS(环境查询系统)无缝集成。 | 使用Unreal Engine开发的所有游戏。 |
| Unity | 非内置 ,通过Asset Store插件实现。最主流的是 Behavior Designer,功能强大,有活跃的社区。 | 使用Unity开发,且需要专业级行为树方案的项目。 |
通用学习路径参考:
-
理解核心 :搞懂
Sequence(顺序节点)、Selector(选择节点)、Parallel(并行节点)、Decorator(装饰节点)的运行逻辑。 -
动手实践:从创建一个简单的"巡逻-追击"AI开始。
-
掌握高级特性:学习使用黑板进行数据共享,理解服务的运行机制,并尝试使用框架提供的可视化工具。
📦 第一步:安装
在终端中执行以下命令安装py_trees:
python
pip install py_trees
安装完成后,可以通过运行官方演示来验证安装是否成功:
python
py-trees-demo-sequence
如果看到终端中输出行为树的执行过程和ASCII图形,说明安装成功。
🌳 第二步:理解节点类型
py_trees中最核心的三类节点如下:
| 节点类型 | 类名 | 功能说明 |
|---|---|---|
| 顺序节点 | py_trees.composites.Sequence |
按顺序执行子节点,所有子节点成功 才返回SUCCESS |
| 选择节点 | py_trees.composites.Selector |
按顺序尝试子节点,任意一个成功 即返回SUCCESS |
| 并行节点 | py_trees.composites.Parallel |
同时执行所有子节点,根据策略决定返回值 |
💻 第三步:第一个行为树(完整可运行代码)
python
#!/usr/bin/env python3
import py_trees as pt
import py_trees.composites as composites
import py_trees.behaviours as behaviours
import time
# ========== 1. 定义自定义行为 ==========
class CheckBatteryBehaviour(pt.behaviour.Behaviour):
"""检查电池电量的行为"""
def __init__(self, name: str, threshold: float = 30.0):
super().__init__(name)
self.threshold = threshold
self.battery_level = 100.0 # 模拟初始电量
def update(self) -> pt.common.Status:
"""每次tick时调用,返回状态"""
# 模拟电量缓慢下降
self.battery_level -= 0.5
if self.battery_level < 0:
self.battery_level = 0
self.feedback_message = f"当前电量: {self.battery_level:.1f}%"
print(f" [CheckBattery] {self.feedback_message}")
if self.battery_level < self.threshold:
return pt.common.Status.FAILURE # 电量低 -> 失败
return pt.common.Status.SUCCESS # 电量充足 -> 成功
class GoHomeBehaviour(pt.behaviour.Behaviour):
"""返回充电桩的行为"""
def __init__(self, name: str):
super().__init__(name)
def update(self) -> pt.common.Status:
print(" [GoHome] 正在返回充电桩...")
return pt.common.Status.SUCCESS
class DoWorkBehaviour(pt.behaviour.Behaviour):
"""执行正常工作"""
def __init__(self, name: str):
super().__init__(name)
self.tick_count = 0
def update(self) -> pt.common.Status:
self.tick_count += 1
print(f" [DoWork] 正在工作... (第{self.tick_count}次)")
if self.tick_count >= 3:
self.tick_count = 0
return pt.common.Status.SUCCESS
return pt.common.Status.RUNNING
# ========== 2. 构建行为树 ==========
def create_tree() -> pt.trees.BehaviourTree:
"""
构建行为树结构:
Selector (优先级选择)
/ \
Sequence (顺序) DoWork (正常工作)
/ \
CheckBattery GoHome
"""
# 创建叶子节点
check_battery = CheckBatteryBehaviour(name="CheckBattery", threshold=30.0)
go_home = GoHomeBehaviour(name="GoHome")
do_work = DoWorkBehaviour(name="DoWork")
# 创建组合节点
sequence = composites.Sequence(name="BatteryLowSequence", memory=False)
sequence.add_children([check_battery, go_home])
selector = composites.Selector(name="RootSelector", memory=False)
selector.add_children([sequence, do_work])
# 创建行为树
tree = pt.trees.BehaviourTree(root=selector)
return tree
# ========== 3. 主程序:驱动树运行 ==========
def main():
print("=" * 50)
print("行为树示例 - 机器人电量管理")
print("=" * 50)
print("逻辑: 电量低于30%时自动返回充电,否则正常工作\n")
tree = create_tree()
# 运行10个tick
for tick_idx in range(10):
print(f"\n--- Tick {tick_idx + 1} ---")
tree.tick()
time.sleep(0.5) # 模拟每0.5秒决策一次
if __name__ == "__main__":
main()
预期输出
python
==================================================
行为树示例 - 机器人电量管理
==================================================
逻辑: 电量低于30%时自动返回充电,否则正常工作
--- Tick 1 ---
[CheckBattery] 当前电量: 99.5%
[DoWork] 正在工作... (第1次)
--- Tick 2 ---
[CheckBattery] 当前电量: 99.0%
[DoWork] 正在工作... (第2次)
--- Tick 3 ---
[CheckBattery] 当前电量: 98.5%
[DoWork] 正在工作... (第3次)
[DoWork] 完成工作
--- Tick 4 ---
[CheckBattery] 当前电量: 98.0%
[DoWork] 正在工作... (第1次)
... (后续电量逐渐下降,直到低于30%时触发返回充电)
注:每个行为需要实现以下核心方法
python
class MyBehaviour(pt.behaviour.Behaviour):
def __init__(self, name):
"""一次性初始化,用于离线渲染dot图"""
super().__init__(name)
def setup(self, **kwargs):
"""延迟初始化,用于硬件/中间件连接"""
pass
def initialise(self):
"""每次行为开始执行前的初始化"""
pass
def update(self) -> pt.common.Status:
"""核心逻辑:每次tick调用,返回状态"""
# 可返回: SUCCESS / FAILURE / RUNNING
return pt.common.Status.SUCCESS
def terminate(self, new_status):
"""行为结束或被中断时的清理工作"""
pass