splintered-reality / py_trees

Python implementation of behaviour trees.
Other
433 stars 143 forks source link

Selector weird behavior, unsure #412

Closed ShrutheeshIR closed 1 year ago

ShrutheeshIR commented 1 year ago

Hello, thanks for this great package! I'm not sure if this issue is a py_trees issue or the py_trees_ros issue. I'm trying to use a selector node, with a ros service instead of an action client, (sort of as a precondition). The service is similar to the actions.py file, but just creating the necessary call changes.

I've inherited the service class, and then changed the status in the update by using the an attribute that is always returned by my service response_object.service_result as :

    def update(self):
        status = super().update()
        if status != py_trees.Status.RUNNING:
            status = py_trees.Status.SUCCESS if self.response_object.service_result else py_trees.Status.FAILURE
        return status

I can see that this update works fairly well.

I have a selector node S, of two conditions, A and B. Here is the sequence of actions that happens:

  1. S is ticked, and thus A is ticked. Since A has not sent any goal => a goal is sent. Thus status of S and A is RUNNING.
  2. S is ticked, status of S is RUNNING 2.1 A is ticked, and A returns failure (which is correct since my condition fails). In the update, status FAILURE is set and returned. A is set to be terminated with status FAILURE 2.2 B is ticked. It is first initialized with goal, and then goal is sent. Status of B is RUNNING Here's where it fails
  3. S is ticked, status of S is RUNNING. 3.1 A is ticked. Because of L437. Also, A is initialized because of this Why should a failed node be ticked? This sets A to be RUNNING again, and the entire thing crumbles. This thus invalidates the goal B and is stuck in a loop.

I'm not sure if I am doing something wrong here.

Thanks

stonier commented 1 year ago

Did you try configuring the selector with memory=True?

The behaviour you describe above is for a memory-less selector. It always goes back to the first child and ticks from the front. That gives you the ability to enable higher priority conditions to interrupt a running condition.

What you seem to be looking for is a selector that locks in a choice until it terminates.

stonier commented 1 year ago

Also, what version of the library are you using? There were recent changes that fixed a few problems with memory/memory-less composites.

ShrutheeshIR commented 1 year ago

Apologies for the delayed response. I've had to use a fairly old version (0.7), since I'm working with ROS melodic, and I've tried to get the important functionality from the newer ones into it. Could you briefly give an overview of the memory/memory-less composite problem fixes?

stonier commented 1 year ago

There was only a Selector without memory back in 0.7. For something akin to the Selector with memory, it had a class called the Chooser. Try that one. This evolved into the Selector with memory form in release 2.2.x

ShrutheeshIR commented 1 year ago

That worked for a toy example. Thanks, I'll dig into it more!