MARVIN’s Head Pt 3 — Subsumption
continued from previous article …
What is Subsumption Architecture?
Subsumption Architecture is a concept that originated with Dr. Rodney Brooks. At its core, the basic idea is to have “levels” of behavior where simpler behaviors get overridden by more complex ones based on input from the environment.
A simple example might be a robot that wanders around randomly until it sees a piece of cheese, at which point the more complicated “seek cheese” behavior activates, suppressing the previous behavior and causing the robot to seek out the cheese it just saw. A fully worked example of this approach can be seen in Minimalist Mobile Robotics by Johnathan H. Connel.
How its Used in MARVIN
As mentioned in previous articles, I am not a “purist” when it comes to subsumption — primarily because it doesn’t make sense to be so rigid for my application. Much of the sensory processing will be done well before the “Subsumption” portion of the system is involved, and there will be a representation of the environment that can be shared between all processes (the Blackboard described in the article preceding this).
Subsumption will be applied to handle the decision making process as to which of MARVIN capabilities will be active at any given time. To this end I will be splitting up MARVIN’s behaviors (Explore, Navigate, Remote Control, etc) into separate subsumption “trees”. Each tree represent a related set of behaviors that can act independently from the behaviors in the other subsumption trees.
Lets look at the way I am handling the navigation behaviors as an example. Currently by default the Remote Control behavior is active. If the user asks the robot to perform an action — say go to the living room — the navigation behavior activates and suppresses the Remote Controls. This remains until the MARVIN either reaches its destination, or for some reason deems the task impossible to complete. At this point the navigation behavior deactivates and the lower level Remote Control behavior is released, allowing it to run again.
This is demonstrated in the diagram below.
How do I do this in ROS?
There are a few approaches I was able to find on how this could be done in the literature:
- Subsumption Model Implemented for ROS Mobile Robotics
- Behavior Trees
- Implementation of a Subsumption based Architecture using Model-Driven Development
None of these really jived 100% with how I think about ROS and Subsumption. While normally I would be wary of this as “Not Invented Here” style thinking I believe that for my purposes this change in approach is acceptable. The reader is free to disagree, and would be perfectly justified in doing so.
None the less, I am doing it my way. Rather than use finite state machines, or build changes on the way messages are passed around in ROS, I choose to include a “Subsumption” class in each of the relevant behaviors. This class monitors for messages sent by other Subsumption classes and works via the following rules:
- If the node is activated and suppressed, it simply updates its own internal state to active and does nothing else. When the host node checks if it is active, it will return false since the node is still suppressed.
- If the node is activated and *not* suppressed it will set itself as active and broadcast a suppression message to anyone in its branch along with the nodes current level. If the host node queries about being active in this case, it will return true.
- If it receives a suppression message from a node with a lower level than itself, it will ignore it.
- If it receives a suppression message from a node with a higher level than itself, it will mark itself as suppressed.
- If it receives a release message from a node with a level exactly one higher than itself, it will mark itself as unsupressed. Further more if the it is not currently marked active it will broadcast its own release message to the branch alongside its level. If it is active, it will do nothing.
I believe this has a few advantages.
- It is decentralized — there is no need for a central finite state machine to take control of the system.
- It does not require any changes to ROS itself.
- It keeps the subsumption logic separate from the nodes themselves. This makes it easy to design each system as a stand alone entity and then simply turn it on and off using the Subsumption class.
Downsides include:
- There may end up being a lot of messages past around — this could prove inefficient.
- Each node has to have a Subsumption class instance in order to participate in the subsumption design.
- Each behavior requires an interface for activating and deactivating itself that can be updated during the ROS loop.
That pretty much wraps up what I want to say about Subsumption for now. Further details may be covered in a later article.
Next article, I want to cover the ROS middleware and briefly discuss ReThink Robotics ROSNodejs interface.