Skip to content

Behavior Trees

vultron.bt

vultron.bt.base

This package implements a basic Behavior Tree library.

vultron.bt.behaviors

file: behaviors author: adh created_at: 4/26/22 1:49 PM

vultron.bt.fuzzer

file: cvd_proto_fuzzer author: adh created_at: 4/26/22 10:59 AM

vultron.bt.states

Provides state management for the Vultron Behavior Tree

vultron.bt.errors

file: errors author: adh created_at: 5/23/22 11:59 AM

vultron.bt.common

This module provides common Behavior Tree nodes for the Vultron package.

EnumStateTransition dataclass

Represents a transition between two states in an enum-based state machine

Source code in vultron/bt/common.py
37
38
39
40
41
42
43
44
@dataclass
class EnumStateTransition:
    """
    Represents a transition between two states in an enum-based state machine
    """

    start_states: List[Enum]
    end_state: Enum

show_graph(node_cls)

Show the graph for the given node_cls

Source code in vultron/bt/common.py
136
137
138
def show_graph(node_cls):
    """Show the graph for the given node_cls"""
    nx.write_network_text(node_cls().to_graph(), ascii_only=True)

state_change(key, transition)

Factory method that returns a FallbackNode object that returns SUCCESS when the blackboard[key] starts in one of start_states and changes to end_state, and FAILURE otherwise

Source code in vultron/bt/common.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def state_change(
    key: str, transition: EnumStateTransition
) -> Type[FallbackNode]:
    """Factory method that returns a FallbackNode object that returns SUCCESS when the blackboard[key]
    starts in one of start_states and changes to end_state, and FAILURE otherwise
    """
    start_states = transition.start_states
    end_state = transition.end_state

    # check that the end_state is in the start_states
    start_state_checks = fallback_node(
        f"allowed_start_states_for_{key}_{end_state}",
        f"""SUCCESS when the current {key} is in one of {(s.name for s in start_states)}. FAILURE otherwise.""",
        *[state_in(key, state) for state in start_states],
    )

    # transition to the end_state
    sc_seq = sequence_node(
        f"transition_to_{key}_{end_state}_if_allowed",
        f"""Check for a valid start state in {(s.name for s in start_states)} and transition to {end_state}""",
        start_state_checks,
        to_end_state_factory(key, end_state),
    )

    # ensure we wind up in the end_state
    _state_change = fallback_node(
        f"transition_{key}_to_{end_state}",
        f"""Transition from (one of) {(s.name for s in start_states)} to {end_state}""",
        state_in(key, end_state),
        sc_seq,
    )

    return _state_change

state_in(key, state)

Factory method that returns a ConditionCheck class that checks if the blackboard[key] == state

Parameters:

Name Type Description Default
key str

the blackboard key to check

required
state Enum

the state to check for

required

Returns:

Type Description
Type[ConditionCheck]

A ConditionCheck class that checks if the blackboard[key] == state

Source code in vultron/bt/common.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def state_in(
    key: str,
    state: Enum,
) -> Type[ConditionCheck]:
    """
    Factory method that returns a ConditionCheck class that checks if the blackboard[key] == state

    Args:
        key: the blackboard key to check
        state: the state to check for

    Returns:
        A ConditionCheck class that checks if the blackboard[key] == state
    """

    def func(obj: BtNode) -> bool:
        f"""True if the node's blackboard[{key}] == {state}"""
        return getattr(obj.bb, key) == state

    node_cls = condition_check(f"{key}_in_{state}", func)

    # add some attributes to the node_cls so we can test it later
    node_cls.key = key
    node_cls.state = state
    return node_cls

to_end_state_factory(key, state)

Factory method that returns an ActionNode class that updates key to state.

Source code in vultron/bt/common.py
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def to_end_state_factory(key: str, state: Enum) -> Type[ActionNode]:
    """Factory method that returns an ActionNode class that updates key to state."""

    def _func(obj: BtNode) -> bool:
        # remember where we were so we can log the change
        before = getattr(obj.bb, key)

        setattr(obj.bb, key, state)

        # record this bb in history
        histkey = f"{key}_history"
        history = list(getattr(obj.bb, histkey))
        if len(history) == 0 or (history[-1] != state):
            history.append(state)
        setattr(obj.bb, histkey, history)

        logger.debug(f"Transition {before} -> {state}")
        return True

    node_cls = action_node(
        f"{key}_to_{state}",
        _func,
    )

    return node_cls