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;
}