Skip to main content

异步行为树框架 - 现代化、模块化、易于集成的异步行为树框架

Project description

ABTree - Asynchronous Behavior Tree Framework

Python 3.8+ License: MIT Code style: black

ABTree (Asynchronous Behavior Tree) is a high-performance asynchronous behavior tree framework built on Python asyncio, supporting concurrent, sequential, conditional logic, and various control mechanisms. The framework includes built-in blackboard mechanism and asynchronous event system for cross-node data sharing and module decoupling. It supports import/export of behavior tree structures for visual configuration and system integration, helping to build flexible and extensible intelligent decision-making systems.

✨ Core Features

  • 🚀 Asynchronous Execution: Asynchronous node scheduling based on asyncio, supporting concurrent and sequential control
  • 🧩 Modular Architecture: Support for custom node type registration and dynamic construction
  • 📊 Blackboard System: Built-in cross-node data sharing mechanism
  • 🎯 Event System: Support for event listening and context awareness
  • 📝 XML Support: Support for loading and exporting behavior trees from XML files
  • 🛠️ CLI Tools: Command-line tools for debugging and testing

🚀 Quick Start

Installation

pip install abtree

Basic Usage

Method 1: Programmatic Construction

import asyncio
from abtree import BehaviorTree, Sequence, Selector, Action, Condition
from abtree.core import Status

# Define action nodes
class OpenDoor(Action):
    async def execute(self, blackboard):
        print("Opening door")
        return Status.SUCCESS

class CloseDoor(Action):
    async def execute(self, blackboard):
        print("Closing door")
        return Status.SUCCESS

class ChangeBattery(Action):
    async def execute(self, blackboard):
        print("Automatically changing battery")
        return Status.SUCCESS

# Define condition nodes
class IsDoorOpen(Condition):
    async def evaluate(self, blackboard):
        return blackboard.get("door_open", False)

class IsBatteryLow(Condition):
    async def evaluate(self, blackboard):
        battery_level = blackboard.get("battery_level", 100)
        return battery_level < 20

# Build behavior tree
root = Selector("Robot Decision")
root.add_child(Sequence("Door Control Sequence"))
root.children[0].add_child(IsDoorOpen("Check Door Status"))
root.children[0].add_child(CloseDoor("Close Door"))

root.add_child(Sequence("Battery Change Sequence"))
root.children[1].add_child(IsBatteryLow("Check Battery Level"))
root.children[1].add_child(ChangeBattery("Change Battery"))

# Create behavior tree instance
tree = BehaviorTree(root)

# Execute
async def main():
    blackboard = tree.blackboard
    blackboard.set("door_open", True)
    blackboard.set("battery_level", 15)
    
    result = await tree.tick()
    print(f"Execution result: {result}")

asyncio.run(main())

Method 2: Load from XML String

import asyncio
from abtree import load_from_xml_string, Status

# Define XML string
xml_string = '''<BehaviorTree name="Robot Decision" description="Simple robot behavior tree">
    <Selector name="Robot Decision">
        <Sequence name="Door Control Sequence">
            <CheckBlackboard name="Check Door Status" key="door_open" expected_value="true" />
            <Log name="Close Door Log" message="Door detected open, preparing to close" />
            <Wait name="Close Door Wait" duration="1.0" />
        </Sequence>
        <Sequence name="Battery Change Sequence">
            <Log name="Battery Change Log" message="Checking battery status" />
            <Wait name="Battery Change Wait" duration="2.0" />
        </Sequence>
    </Selector>
</BehaviorTree>'''

# Load behavior tree from XML string
tree = load_from_xml_string(xml_string)

# Execute
async def main():
    blackboard = tree.blackboard
    blackboard.set("door_open", True)
    
    result = await tree.tick()
    print(f"Execution result: {result}")

asyncio.run(main())

Method 3: Complex XML Configuration Example

import asyncio
from abtree import load_from_xml_string, Status

# Complex robot AI XML configuration
xml_string = '''<BehaviorTree name="Robot AI" description="Intelligent robot behavior tree">
    <Selector name="Main Decision">
        <!-- Door control branch -->
        <Sequence name="Door Control Sequence">
            <CheckBlackboard name="Check Door Status" key="door_open" expected_value="true" />
            <Compare name="Check Door Sensor" key="door_sensor" operator="==" value="true" />
            <Log name="Start Closing Door" message="Door detected open, preparing to close!" />
            <Wait name="Close Door Delay" duration="0.5" />
            <SetBlackboard name="Set Door Closing Status" key="is_closing_door" value="true" />
        </Sequence>
        
        <!-- Patrol branch -->
        <Sequence name="Patrol Sequence">
            <CheckBlackboard name="Check Door Closed" key="door_open" expected_value="false" />
            <Log name="Start Patrol" message="Door closed, starting patrol..." />
            <Wait name="Patrol Time" duration="2.0" />
            <SetBlackboard name="Set Patrol Status" key="is_patrolling" value="true" />
        </Sequence>
        
        <!-- Battery change branch -->
        <Sequence name="Battery Change Sequence">
            <Compare name="Check Battery Level" key="battery_level" operator="&lt;=" value="20" />
            <Log name="Start Battery Change" message="Battery level low, preparing to change battery..." />
            <Wait name="Battery Change Time" duration="3.0" />
            <SetBlackboard name="Replenish Battery" key="battery_level" value="100" />
        </Sequence>
    </Selector>
</BehaviorTree>'''

# Load behavior tree from XML string
tree = load_from_xml_string(xml_string)

# Execute
async def main():
    blackboard = tree.blackboard
    blackboard.set("door_open", True)
    blackboard.set("battery_level", 15)
    
    for i in range(3):
        result = await tree.tick()
        print(f"Tick {i+1}: {result}")
        print(f"Status: Closing door={blackboard.get('is_closing_door')}, Patrolling={blackboard.get('is_patrolling')}")

asyncio.run(main())

📚 Documentation

🛠️ Development

Install Development Dependencies

pip install -e ".[dev]"

Run Tests

pytest tests/

Code Formatting

black abtree/
isort abtree/

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🤝 Contributing

Welcome to submit Issues and Pull Requests!

📞 Contact

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

abtree-0.1.1.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

abtree-0.1.1-py3-none-any.whl (40.5 kB view details)

Uploaded Python 3

File details

Details for the file abtree-0.1.1.tar.gz.

File metadata

  • Download URL: abtree-0.1.1.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for abtree-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a4996c960d53d8801ee7185c29eab5cf1d06d0b0ce1dfe65190dc40feec925fd
MD5 8ec1b44fe251796cd1883002d1c8fade
BLAKE2b-256 7e18951f985035d34a092851761e0beffcc53307a42ab35abf10923562b423af

See more details on using hashes here.

File details

Details for the file abtree-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: abtree-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 40.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for abtree-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8281e8a32333ad42f9c307f3d8006f167daf169b2407d278b499755ff1900b29
MD5 2532a66bc337b95ff83bf8cebf800be1
BLAKE2b-256 32f4cb0f9a06ecd0856683e68a33993ee87e554ea1c4d75fd3f4316a605cb591

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page