Decentralized Subsumption

Gene Foxwell
5 min readMay 23, 2018

--

A core design approach my robotics prototype has been Subsumption Architecture. While it is a well known approach to robotics, the Robot Operating System (ROS) does not appear to have very good support for it. In this article I will be diverging from my usual discussion of MARVIN and focusing on the details of how I am currently solving this problem.

Overview

First what I’ll implement here won’t be pure subsumption as it was originally described. What will be used is a set of behaviors that all get their state information from the same source (which I will refer to as the Blackboard). The Blackboard contains a representation of the world, which can be updated by other behaviors rather than directly updating the robots state.

Information about the world (sensory input etc) is processed by pattern recognition systems (for example VGG-16) which are used to update the Blackboard. Information about the robots current state is sent from the Blackboard to the Subsumption processes, which in turn can themselves update the Blackboard.

This approach has been extended one step further, rather than simply having a single colossal subsumption system, I am allowing for multiple independent sets of subsumption systems to exist within the same robot, all sharing the same Blackboard / external inputs. These “higher order” systems can either function without any knowledge of their contemporaries or through Blackboard (or other by configuring a behavior) they can even subsume each other as needed. Using this approach allows me to simplify thinking about subsumption.

Implementation

I laid out the basic rules each subsumption system needs to follow in this article, but it worth repeating here for completeness:

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 unsuppressed. 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 am achieved this in ROS by means of “Subsumption Nodes”. These are simply a utility class that I am adding to each custom ROS node that needs to handle an individual behavior. (So it wouldn’t be added to nodes whose sole responsibility is generating output for the UX and the like). I’ve included the class definition below, but the full code (as it currently exists) can be found on my github.

class SubsumptionNode {
private:
string branchName;
string messageData;
int level;
bool active;
bool supressed;
ros::Subscriber supressionSub;
ros::Subscriber releaseSub;
ros::Publisher supressPub;
ros::Publisher releasePub;
void supress(const std_msgs::String::ConstPtr& msg);
void release(const std_msgs::String::ConstPtr& msg);
public: SubsumptionNode(string branchName, int level);
bool isActive();
void activate();
void deActivate();
void start(ros::NodeHandle nh);
};

Each node tracks two Boolean states, active and suppressed. These track whether a node wants to be active, and whether the node has been suppressed by a higher level behavior within its subsumption system.

Two topics are subscribed to for the purpose:

  1. /subsumption_release - is broadcasted whenever a currently active behavior that is not suppressed becomes inactive.
  2. /subsumption_supress - is broadcasted when a non-supressed behavior becomes active, or when an active behavior becomes non-supressed.

Each of these topics expects a string as message. This string should be of the form: {networkname}-{level}. The networkname part of the string identifies which subsumption network this node is currently working with, while the level part identifies what priority this behavior has on that network.

Aside: A potential that this setup allows, but not currently explored by MARVIN is to allow a behavior to “change” what subsumption network it is part of. Since none of the nodes are aware of where they are with respect to the others, all a node would need to do is change which network it was broadcasting / listening to. This could be useful in more complex scenarios like a swarm to allow for dynamically re-configuring the systems behavior. It’s a bit much to explore this in this article, but I may explore it further in a future one.

It may help to look at a detailed example from MARVIN. Lets say the user presses the “Auto Explore” button in MARVIN’s Web Interface. This is sent to the middleware module, which in turn publishes true on the /activate_explore topic. This tells the explore module to activate, so it in turn calls the activate member function on its subsumption node. Since this node is not suppressed, it publishes a “navigation-1” message on its subsumption network. This is captured by the remote control node which at level 0 on this network. The subsumption node for Remote Control then marks itself as “suppressed” which in turn causes the Remote Control node to be disabled (it no longer publishes velocities on the /cmd_vel topic).

If the user in turn presses the “Auto Explore” again, this deactivates the Explore node and the same series of events as above are repeated sending the release message instead following the algorithm already explained.

That covers how decentralized subsumption works and how MARVIN is currently using it. It’s hard to decide on a next step, but I think its useful to extend MARVIN’s ability to utilize AWS Lex. For that I am going to need snowboy — a hotword detection system. I think I’ll get that implemented and then publish how that works in my next article. It may be a few days.

--

--

Gene Foxwell

Experienced Software Developer interested in Robotics, Artificial Intelligence, and UX