Usage - northern-bites/robograms GitHub Wiki

Creating a Module

All modules must inherit from Module:

class ExampleModule : public robograms::Module
{
}

A module's input and output interfaces are determined by what types of portals it has:

public:
    robograms::InPortal<MsgType1> infoIn;
    robograms::OutPortal<MsgType2> infoOut;

So the module containing the above definitions would require input of MsgType1 and output MsgType2. These can be any C++ class, although Google Protocol Buffers work particularly well. Portals must be declared public because you will likely want to wire them together from outside the class.

All modules must override the run_() function from Module:

void ExampleModule::run_()
{
     infoIn.latch()
     // perform some computation using infoIn.message(), create newOutput
     infoOut.setMessage(newOutput)
}

This method can call other methods of the class, but it is the only one that will be called by the architecture when the module is run.

Creating a Diagram

A RoboGram (aka RoboCup Wiring Diagram) is the overarching structure that contains several modules and runs all of them. It is like a graph containing Modules:

robograms::RoboGram gram;
ExampleModule mod;
gram.add(mod);

Wiring Modules Together

If two modules have been added to a RoboGram as above, their inputs and outputs can be connected to provide dataflow links. If the modules are defined as follows:

class ModuleA : public robograms::Module
{
 public:
     robograms::OutPortal<MsgType> out;
}

class ModuleB : public robograms::Module
{
 public:
     robograms::InPortal<MsgType> in;
}

Then their portals can be wired together as follows:

  robograms::RoboGram gram;  
  ModuleA a;  
  ModuleB b;  
  gram.add(a);  
  gram.add(b);  
  b.in.wireTo(a.out);  

Note that the adds can happen in any order because the architecture ensures that modules are run in topological order. B requires input from A, so A will run first when gram is run.

Asynchronous Wires

The above example is simple because the diagram is a Directed Acyclic Graph. The call to wireTo requires no additional parameters, and it will be made synchronous by default. There are two cases where, instead, this call should be:

b.in.wireTo(a.out, true);

This will make the wire asynchronous, meaning that A is not run every time B requires data. The two cases are:

A and B are in different RoboGrams: This means that A should not always run before B, aka they are not run synchronously.
The edge creates a loop in the graph: We don't want to create infinite execution loops, so if the edge is a backedge, it must be marked asynchronous.

Extended Example

See the test program included in this repository for an example of RoboGrams in action.

⚠️ **GitHub.com Fallback** ⚠️