<div dir="ltr"><div>David, Rud,</div><div><br></div><div>At Tuesday's RBNV you guys seemed to have agreed that the Subsumption architecture was a special case of behavior trees. I wanted to understand behavior trees, and to understand whether your assertion is correct. I found a basic explanation of behavior trees here:</div><div><a href="https://towardsdatascience.com/designing-ai-agents-behaviors-with-behavior-trees-b28aa1c3cf8a">https://towardsdatascience.com/designing-ai-agents-behaviors-with-behavior-trees-b28aa1c3cf8a</a></div><div><br></div><div>It's a good overview, but is missing sufficient detail to design a subsumption stack as a behavior tree. For example it's description of a sequence node is "A node that returns success if all children return SUCCESS" but it doesn't specify what happens if a child returns RUNNING - does it retry all previous nodes next tick time? It only describes one kind of decorator node (invert). It doesn't specify whether a Fallback node re-ticks all nodes next tick-time if a child after the first returns SUCCESS.</div><div><br></div><div>After some searching, I found this set of pages</div><div><a href="https://www.behaviortree.dev/">https://www.behaviortree.dev/</a></div><div>They describe an implementation by David Faconte (of PlotJuggler fame) of a behavior tree library that is general purpose, and doesn't depend on, but works well with ROS. In the "Learn the basics" section they describe variations on the sequence and fallback nodes which seem sufficient to design a subsumption robot behavior. The attached image is that design. I'd be interested in your thoughts on whether I'm on the right track here. <br></div><div><br></div><div>The following description of the design assumes the reader has read the Sequence Nodes and Fallback Nodes and Decorators Nodes pages, and it offers commentary on how the behavior tree implements the subsumption stack, including non-ballistic behavior.</div><div><br></div><div>ReactiveFallback always ticks all nodes below it until it gets the first SUCCESS. Thus, if Action ReverseTurn was running owing to a bumper press, and then BatteryLow becomes active (SUCCESS), the ReactiveFallback node calls HaltAllChildren() which propagates down the tree and halts (subsumes) the ReverseTurn action. (This implementation produces an abort behavior, but it's included to show that BumperPressed->ReverseTurn is subsumable, not ballistic.)</div><div><br></div><div>The subsumption behavior arises from the way ReactiveFallback stops ticking lower-priority (more rightward) nodes when any preceding nodes return SUCCESS. If no bumper is pressed, no IR detection is made, and battery isn't low, then the last action, "Drive toward goal" gets to run. But as soon as bumper or IRDetection is true (SUCCESS), the corresponding behavior is executed, and DriveTowardGoal is subsumed (doesn't run) until the corresponding Sequence node is done and returns FAILURE</div><div><br></div><div>If IRDetection returns SUCCESS (IR sensor detects object), Action "SteerAway" runs, and steers the robot away from the sensor with the detection. Once the sensor clears, IRDetection condition returns FAILURE, Action SteerAway doesn't run (is halted), and no longer subsumes DriveTowardGoal, which can then start running again. This behavior relies on ReactiveSequence ticking all nodes (starting at the beginning of its list of children), so the sensor gets checked each tick.</div><div><br></div><div>By contrast, BumperPressed is called by a regular Sequence, which doesn't tick all its children; if a child returns RUNNING (which will happen while ReverseTurn action is active), it will only tick the running child. Thus BumperPressed can become false as the robot backs away from the obstacle, but it won't be ticked, so it won't affect the "ReverseTurn" action that should run for some time after a bumper contact clears. The RepeatNode decorator runs ReverseTurn up to 40 times (2 seconds at 20 Hz tick rate) as long as ReverseTurn returns SUCCESS, then returns FAILURE (maybe - the documentation isn't clear on this point - it might not work as described). When it returns FAILURE the subsumption of lower priority actions ends.</div><div><br></div><div>The tree shown is a DriveToWaypoint behavior tree - it could be used as an element in a higher-level sequence that did something else after achieving the waypoint, like seek a cone.<br></div><div><br></div><div>This is of course all theoretical - may not work in practice - but it looks to me as if your assertion that Subsumption can be represented as a behavior tree is correct, and that a richer set of control-node behaviors is beneficial. The Fallback node acts like David's arbiter, running the highest priority behavior, as assessed by traversing the list of nodes and not running any beyond the first to report SUCCESS. It relies on its children to return FAILURE if they don't want to control the robot, so that arbitration can pass on down the line.</div><div><br></div><div>A very nice aspect of this library is it works with GROOT which apparently allows realtime and after-the-fact replay of state transitions (active behaviors).<br></div><div><br></div><div>Thanks for an interesting exploration down an avenue I've wondered about. I feel more knowledgeable now than I was.</div><div><br></div><div>Regards</div><div><br></div><div>Paul</div><div><br></div><div> <br></div></div>