I have a chunk of inverse kinematics code (for a robot) that I've been trying to optimize. I've posted it below as implemented with the software floating point library, as well as with the um-FPU 3.1.
I had hoped that the hardware FPU would speed it up, but either something is wrong with my implementation, or it is dramatically slower than the arduino fpu emulation.
The chunk of code takes approximately 600us on the arduino, and 1400us on the FPU using the user-defined functions on the FPU. I've verified that they are returning the same correct data. Ideally I'd want the execution time to be more like 100us. Any advice?
Arduino Code
int delta_calcAngleYZ(float x0, float y0, float z0, float &theta) {
float y1 = -0.5 * 0.57735 * f; // f/2 * tg 30
y0 -= 0.5 * 0.57735 * e; // shift center to edge
// z = a + b*y
float a = (x0*x0 + y0*y0 + z0*z0 +rf*rf - re*re - y1*y1)/(2*z0);
float b = (y1-y0)/z0;
// discriminant
float d = -(a+b*y1)*(a+b*y1)+rf*(b*b*rf+rf);
if (d < 0) return -1; // non-existing point
float yj = (y1 - a*b - sqrt(d))/(b*b + 1); // choosing outer point
float zj = a + b*yj;
theta = 180.0*atan(-zj/(y1 - yj))/pi + ((yj>y1)?180.0:0.0);
return 0;
}
Code using the FPU
int delta_calcAngleYZ(float x0, float y0, float z0, float &theta) {
// The registers are defined and constants are loaded earlier, the FPU custom function operates on the registers and replicates exactly the math sequence in the arduino implementation.
Fpu.write(SELECTA,fpu_x0); // load the input vars
Fpu.write(FWRITEA);
Fpu.writeFloat(x0);
Fpu.write(SELECTA,fpu_y0);
Fpu.write(FWRITEA);
Fpu.writeFloat(y0);
Fpu.write(SELECTA,fpu_z0);
Fpu.write(FWRITEA);
Fpu.writeFloat(z0);
Fpu.write(FCALL,1);// calculate d with function 1 stored on um-fpu
Fpu.write(FSTATUS,fpu_d); // get the status of register 15 (status of d)
if ( Fpu.readStatus() && STATUS_SIGN == 1 ) return -1;
Fpu.write(FCMP2,fpu_y1,fpu_yj); // compare yj and y1 in the fpu
// if yj > y1, define theta this way
if ( Fpu.readStatus() && STATUS_SIGN == 1 ) {
Fpu.write(SELECTA,fpu_theta);
Fpu.write(FCALL,2); // calculate version 1 of theta
} else {
Fpu.write(FCALL,3); // calculate version 2 of theta
}
Fpu.wait();
Fpu.write(FREADA);
theta = Fpu.readFloat();
return 0;
}