Description
In 51f92c4, ReactiveSequence
was updated with a new semantic around how it halts running children. Previously, it would halt all children after the current one. With this change, it now halts all children before the current. This change prevents a common design and implementation approach in BTs called backchaining. I think the change should be reconsidered and possibly reverted.
In this approach, synchronous condition nodes are replaced with (possibly asynchronous) subtrees of conditions and actions. The basic approach is to select a condition and refactoring it into the postcondition (the previous condition), an action to make this postcondition succeed, and preconditions to the action. Each of these conditions may be further backchained, continually evolving the reactivity of your behaviors. This pattern also combines with other design patterns such as implicit sequences, which create reactivity through an intuitive prioritization of postconditions (earlier children are prioritized over later children). More on this by Petter Ögren: How to create Behavior Trees using Backward Chaining. Also known as PPA for postcondition-precondition-action.
Since each additional action may be synchronous, when an earlier children's postcondition begins to fail, and its action begins to run, later children's actions should intuitively be preempted, as another action is running. As you've mentioned elsewhere, it only makes sense for one child to be running at a given time (unless you're using Parallel
). Without propagating the halt to later children, it leaves them in an ambiguous state: not preempted, but also not running (not being ticked).
The trees created by this are naturally reactive and intuitive. An excerp from that video:
(yellow is condition, green is action, ->
is reactive sequence, ?
is reactive fallback)
Other issues have come across this issue, and it's exception thrown in v4.x, when attempting to backchain.
In #573, the OP has a postcondition for quality sensor measurements, with an action to restart the sensor, and a precondition that the action has been attempted 5 or less times. Following the postcondition (quality measurements), some action is performed.
In #83, miccol demonstrated several examples of backchained BTs that have a reactive sequence of multiple asynchronous children. If the battery is not ok (postcondition), goto charging station (action).
In #736, the OP explicitly mentions the principle of backchaining and shows a tree following this approach. Your recommended pattern moves uses a memory Sequence
, which was not sufficient for OP. They also recommend the old behavior of preempting/halting all currently-running children.
I think what's missing in all of the responses is that these users are not attempting to run multiple nodes concurrently; the halting mechanism in BehaviorTree.CPP ensures this is the case. They are simply trying to construct reactive behaviors following established design patterns.
Parallel
is not a viable alternative to ReactiveSequence
for this pattern. Parallel
ticks all children, ticking the next if one returns RUNNING
. This would lead to multiple actions running concurrently, such as attempting to put a jacket on while searching the garden for a key and eating a banana.