Writing a softdevice: ball detection

Algorithms that require intense computation can be written in C++ but still be useable within URBI: they acquire their data using UVar referencing other modules’s variables, and output their results to other UVar. Let’s consider the case of a ball detector device that takes an image as input, and outputs the coordinates of a ball if one is found.

The header is defined like:

// inherit from UObject
class BallTracker : public urbi::UObject
{
public:
  //the class must have a single constructor taking a string
  BallTracker (const std::string&);

  // URBI constructor
  int init (const std::string& varname);

  // is the ball visible ?
  urbi::UVar visible;

  // ball coordinates
  urbi::UVar x;
  urbi::UVar y;
 };

The constructor only registers init:

//the constructor registers init only
BallTracker::BallTracker (const::string& s)
  : urbi::UObject (s)
{
  //register init
  UBindFunction (BallTracker, init);
}

The init function binds the variables and a callback on update of the image variable passed as a argument.

int
BallTracker::init (const std::string& cameraval)
{
  UBindVar (BallTracker, visible);
  UBindVar (BallTracker, x);
  UBindVar (BallTracker, y);
  UNotifyChange (cameraval, &BallTracker::newImage);

  visible = 0;

  return 0;
}

The newImage function runs the detection algorithm on the image in its argument, and updates the variables.

int
BallTracker::newImage (urbi::UVar &v)
{
  //cast to UImage
  urbi::UImage i = v;
  int px,py;
  bool found = detectBall (i.data, i.width, i.height, &px, &py);

  if (found)
  {
    visible = 1;
    x = px / i.width;
    y = py / i.height;
  }
  else
    visible = 0;

  return 0;
}