Now, suppose that, for our previous example, we can speed things up by sending all the servomotor commands at the same time, using the method setPositions (int count, int *ids, double * positions) that takes two arrays of ids and positions. A hub is the perfect way to handle this task. The UObject header stays the same. We add a hub declaration:
class servohub : public urbi::UObjectHub
{
public:
//the class must have a single constructor taking a string
servohub (const std::string&);
// called periodically
virtual int update ();
// called by servo
void addValue (int id, double val);
int* ids;
double* vals;
int size;
int count;
};
servo::update becomes a call to the addValue method of the hub:
int
servo::update()
{
((servohub*)getUObjectHub ("servohub"))->addValue (id, (double)val);
};
The following line can be added to the servo init methdd, although it has no use in our specific example:
URegister(servohub);
Finaly, the implementation of our hub methods is:
servohub::servohub (const std::string& s)
: UObjectHub (s),
ids (0),
vals (0),
size (0),
count (0)
{
// setup our timer
USetUpdate (1);
}
int
servohub::update ()
{
// called periodically
setPositions (count, ids, vals);
// reset position counter
count = 0;
return 0;
}
void
servohub::addValue (int id, double val)
{
if (count + 1 < size)
{
// allocate more memory
ids = (int*)realloc (ids, (count + 1) * sizeof (int);
vals = (double*)realloc (vals, (count + 1) * sizeof (double);
size = count + 1;
}
ids[count] = id;
vals[count++] = val;
}
UStartHub (servohub);
Periodically, the update method is called on each servo instance, which adds commands to the hub arrays, then the update method of the hub is called, actually sending the command and resetting the array.
Alternatively, to demonstrate the use of the members hub variable, we can entirely remove the update method in the servo class (and the USetUpdate() call in init), and rewrite the hub update method the following way:
int servohub::update()
{
//called periodically
for (UObjectList::iterator it = members.begin ();
it != members.end ();
it++)
{
addValue (((servo*)*it)->id,
(double)((servo*)*it)->val);
}
setPositions(count, ids, vals);
// reset position counter
count=0;
return 0;
}