Writing a FallbackNode

Overview

This tutorial demonstrates the careBT FallbackNode. Therefore the SimpleFallback node is implemented which has three child nodes of the same type (AddTwoNumbersActionWithFailures). By ‘playing around’ with the input parameters, the ‘RESULT_TOO_LARGE’ contingency can be provoked in each of the three children. This allows to observe the functionality of the FallbackNode.

Create the SimpleFallback node

Create a file named fallback.py with following content. Or use the provided file: fallback.py

 1from carebt import FallbackNode
 2from carebt.examples.sequence_with_contingencies import AddTwoNumbersActionWithFailures
 3
 4
 5class SimpleFallback(FallbackNode):
 6    """The `SimpleFallback` example node.
 7
 8    The `SimpleFallback` has three input parameters and contains three child
 9    nodes of the same type (`AddTwoNumbersActionWithFailures`). Each of the child
10    nodes has the first input parameter fixed and the second one is taken from the
11    input of the `SimpleFallback`. This structure allows to provoke a failure in
12    each of the child nodes, for example, by setting the input (*?b1 ?b2 ?b3*) to
13    a number that the sum of this value and the fixed one is greater than ten.
14
15
16    Input Parameters
17    ----------------
18    ?b1 : int
19        The first value
20    ?b2 : int
21        The second value
22    ?b3 : int
23        The second value
24
25    """
26
27    def __init__(self, bt_runner):
28        super().__init__(bt_runner, '?b1 ?b2 ?b3')
29
30    def on_init(self) -> None:
31        self.append_child(AddTwoNumbersActionWithFailures, '1 ?b1 => ?c1')
32        self.append_child(AddTwoNumbersActionWithFailures, '2 ?b2 => ?c2')
33        self.append_child(AddTwoNumbersActionWithFailures, '3 ?b3 => ?c3')

The code explained

The AddTwoNumbersActionWithFailures node was already introduced in Understanding contingency-handlers and is just reused in this example.

The constructor (__init__) of the SimpleFallback needs to call the constructor (super().__init__) of the FallbackNode and passes the bt_runner and the signature as arguments. The signature defines three input parameter called ?b1 ?b2 ?b3.

    def __init__(self, bt_runner):
        super().__init__(bt_runner, '?b1 ?b2 ?b3')

In the on_init function the three child nodes are added.

    def on_init(self) -> None:
        self.append_child(AddTwoNumbersActionWithFailures, '1 ?b1 => ?c1')
        self.append_child(AddTwoNumbersActionWithFailures, '2 ?b2 => ?c2')
        self.append_child(AddTwoNumbersActionWithFailures, '3 ?b3 => ?c3')

Run the example

Start the Python interpreter and run the SimpleFallback node:

>>> import carebt
>>> from carebt.examples.fallback import SimpleFallback
>>> bt_runner = carebt.BehaviorTreeRunner()
>>> bt_runner.run(SimpleFallback, '1 2 3')
AddTwoNumbersActionWithFailures: calculating: 1 + 1 = 2
>>> bt_runner.run(SimpleFallback, '10 2 3')
AddTwoNumbersActionWithFailures: calculating: 1 + 10 = 11 -> RESULT_TOO_LARGE
AddTwoNumbersActionWithFailures: calculating: 2 + 2 = 4
>>> bt_runner.run(SimpleFallback, '10 20 3')
AddTwoNumbersActionWithFailures: calculating: 1 + 10 = 11 -> RESULT_TOO_LARGE
AddTwoNumbersActionWithFailures: calculating: 2 + 20 = 22 -> RESULT_TOO_LARGE
AddTwoNumbersActionWithFailures: calculating: 3 + 3 = 6
>>> bt_runner.run(SimpleFallback, '10 20 30')
AddTwoNumbersActionWithFailures: calculating: 1 + 10 = 11 -> RESULT_TOO_LARGE
AddTwoNumbersActionWithFailures: calculating: 2 + 20 = 22 -> RESULT_TOO_LARGE
AddTwoNumbersActionWithFailures: calculating: 3 + 30 = 33 -> RESULT_TOO_LARGE
2021-11-30 20:55:46 WARN ---------------------------------------------------
2021-11-30 20:55:46 WARN bt execution finished
2021-11-30 20:55:46 WARN status:  NodeStatus.FAILURE
2021-11-30 20:55:46 WARN contingency-message: RESULT_TOO_LARGE
2021-11-30 20:55:46 WARN ---------------------------------------------------

In the first execution of the SimpleFallback node the first child already completes with SUCCESS and thus the whole SimpleFallback node completes with SUCCESS. In the second execution the first child fails (with RESULT_TOO_LARGE) and thus the second one is executed, which succeeds. Thus also the whole SimpleFallback node completes with SUCCESS. In the third execution all three children fail and as a consequence the whole SimpleFallback node fails with the contingency-message RESULT_TOO_LARGE.