When writing reactive code that needs to send a new command every cycle, or use fresh sensor data, it can be helpful to synchronize with ALMotion’s cycles.
The ALMotion cycle contains the following steps:
The motion thread uses a real time priority just lower than the DCM, and will try to execute on the anniversary of start up time + CycleNumber * 20ms. Should we fall behind by more than 20ms we will stop trying to catch up, and continue from the present.
From a NAOqi module, perhaps made with the module generator, you have access to the broker, and can use it to create a connection to Motion’s preProcess or postProcess events. This allows being awakened at the beginning or end of each cycle to do some processing: get the current state of the robot, and prepare some commands.
// Your method that will be called
void YourModule::motionPreProcessCallback() {
// Do something very small every 20ms.
// You are in a real time thread, so beware.
// If you wish to do heavy processing, you should
// raise a signal that is consumed by another thread
}
void YourModule::subscribeMotionPreProcess() {
try {
// Register the callback
// The specialized proxy does not give access
// to the underlying module needed for this binding,
// so we get a generic proxy from the parent broker
getParentBroker()->getProxy("ALMotion")->getModule()->atPreProcess(
boost::bind(&YourModule::motionPreProcessCallback,this));
} catch(const AL::ALError& e) {
std::cout << "Motion preProcess callback registration failed" << std::endl;
}
}
After using DCM, ALMotion’s command angles are not updated to the internal model. To avoid jerky transition between using DCM and ALMotion, there are two options: