Data Flow

In most cases it is not enough to concatinate RAFCON states in the right order. They also need to be associated with data. Also a plan, generated by a planner, does not contain objects but rather kind of identifiers, e.g. “move robot kitchen”. So there are two problems to overcome: At first, how to hand over identifiers to states. That is explained in section Parameter Passing. Secondly, how to map identifiers to ibjects. This is what section Runtime Data is about.

Parameter Passing

To pass a parameter from the plan to a state, the state needs to have an input port of type “str”, which has a corresponding parameter in the pddl action. The only difference is, that input port does not have an questionmark at the beginning, e.g. the pddl action parameter “?myParam” would match a states input port “myParam”. But not any action parameter has to have a corresponding state parameter and vice versa.

For example if the state “move_state” has the following input ports:

Port Name   Data Type
food   str
time   int

and is annotated with the following pddl action:

(:action cook 
 :Parameters (?chef - Person ?food - Food)
 [...])

The action paramter “?food” would match with the input port “food”, and any value assigned to it will be passed to the state. So if “pizza” was assigned to “?food” in the plan, this would be the value of the corresponding input port “food”.

Runtime Data

As seen above, parameters can be passed to states. But most of the time, that’s only half the way, because these parameters are often only object identifiers. In order to give also access to the objects, the “Runtime Data” field of the setup form provides the possibility to name a file, in which this objects are defined. This file has to contain a (nested) json dictionary. For example, a “pizza” object is needed. It has a “size”, a “dough” and a list of “toppings”. The file, in which the pizza was specified could look like thisː

{
"pizza":{"size":31,
         "dough":"yeast",
         "toppings":["cheese","ham","cheese","tomato","cheese"]
        }
}

When starting to execute the state machine, these definitions are copied into a global variable named rtpp_data in the global variable manager (gvm) of RAFCON. So when an identifier was passed to a state, the corresponding object can be read from this dictionary. For example, reading the size of the passed food, e.g. the pizza, in an execution state would work like this:

 def execute(self, inputs, outputs, gvm):
   identifier = inputs['food'] # identifier → pizza
   rtpp_data = gvm.get_variable('rtpp_data') # rtpp_data → data provided in runtime data file
   food = rtpp_data[identifier] # the pizza object
   size = food['size'] # the size of the pizza