Skip to content

Semantics of sequence without memory are wrong #329

@siteks

Description

@siteks

In 2.1.5 it's good to see sequence without memory, but the semantics seem to be wrong. From [1], I would expect the tree:

root = py_trees.composites.Sequence(memory=False)
root.add_child(py_trees.behaviours.TickCounter(1))
root.add_child(py_trees.behaviours.Success('Reached second child'))

to return RUNNING on the first tick, then SUCCESS on the second. But what actually happens is that the running leaf node is invalidated on the second tick and so always returns RUNNING. It seems to me it should behave analogously to selector without memory, in that a previously RUNNING child node should not be invalidated unless the sel/seq receives no tick.

Or, sequence and selector should be semantically identical if you flip SUCCESS and FAILURE:

inv(sel(inv(c1), inv(c2)) = seq(c1, c2)

The code below illustrates this, with the inverted selector without memory returning SUCCESS on the second tick:

import py_trees

py_trees.logging.level = py_trees.logging.level.DEBUG

root = py_trees.composites.Sequence(memory=False)
root.add_child(py_trees.behaviours.TickCounter(1))
root.add_child(py_trees.behaviours.Success('Reached second child'))

print('### Built in sequence without memory')
for i in range(2):
    root.tick_once()
    print(root.status)

class FakeSequence(py_trees.decorators.Inverter):
    def __init__(self, **kwargs):
        super(FakeSequence, self).__init__(child=py_trees.composites.Selector(**kwargs))
    def add_child(self, child):
        self.decorated.add_child(py_trees.decorators.Inverter(child))

root = FakeSequence(memory=False)
root.add_child(py_trees.behaviours.TickCounter(1))
root.add_child(py_trees.behaviours.Success('Reached second child'))

print('### Inverted selector without memory')
for i in range(2):
    root.tick_once()
    print(root.status)

Giving the result

### Built in sequence without memory
[DEBUG] Sequence             : Sequence.tick()
[DEBUG] TickCounter          : TickCounter.tick()
Status.RUNNING
[DEBUG] Sequence             : Sequence.tick()
[DEBUG] TickCounter          : TickCounter.stop(Status.RUNNING->Status.INVALID)
[DEBUG] TickCounter          : TickCounter.tick()
Status.RUNNING
### Inverted selector without memory
[DEBUG] FakeSequence         : FakeSequence.tick()
[DEBUG] Selector             : Selector.tick()
[DEBUG] Selector             : Selector.tick() [!RUNNING->reset current_child]
[DEBUG] Inverter             : Inverter.tick()
[DEBUG] TickCounter          : TickCounter.tick()
Status.RUNNING
[DEBUG] FakeSequence         : FakeSequence.tick()
[DEBUG] Selector             : Selector.tick()
[DEBUG] Inverter             : Inverter.tick()
[DEBUG] TickCounter          : TickCounter.tick()
[DEBUG] TickCounter          : TickCounter.stop(Status.RUNNING->Status.SUCCESS)
[DEBUG] Inverter             : Inverter.stop(Status.FAILURE)
[DEBUG] Inverter             : Inverter.tick()
[DEBUG] Reached second child : Success.tick()
[DEBUG] Reached second child : Success.update()
[DEBUG] Reached second child : Success.stop(Status.INVALID->Status.SUCCESS)
[DEBUG] Inverter             : Inverter.stop(Status.FAILURE)
[DEBUG] FakeSequence         : FakeSequence.stop(Status.SUCCESS)
Status.SUCCESS

[1] Alejandro Marzinotto, Michele Colledanchise, Colin Smith, and Petter Ogren. Towards a unified behavior trees framework for robot control. In Robotics and Automation (ICRA), 2014

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions