Quote:
Originally Posted by Ether
Did you do an analysis to determine whether the piecewise linear code plus the conditional logic it requires executes faster than the single polynomial ?
If speed is what you need, it's hard to beat a complete lookup table (no interpolation required):
http://www.chiefdelphi.com/forums/sh...1&postcount=12
|
They aren't using a single polynomial, they're using a 5th order poly and 7th order poly, then averaging the two.
The only reason I asked the question is because I looked at their code, and it seemed pretty involved for something that needs to be calculated every time you want to send an output to a motor controller.
Code:
double RobotState::victor_linearize(double goal_speed)
{
const double deadband_value = 0.082;
if (goal_speed > deadband_value)
goal_speed -= deadband_value;
else if (goal_speed < -deadband_value)
goal_speed += deadband_value;
else
goal_speed = 0.0;
goal_speed = goal_speed / (1.0 - deadband_value);
double goal_speed2 = goal_speed * goal_speed;
double goal_speed3 = goal_speed2 * goal_speed;
double goal_speed4 = goal_speed3 * goal_speed;
double goal_speed5 = goal_speed4 * goal_speed;
double goal_speed6 = goal_speed5 * goal_speed;
double goal_speed7 = goal_speed6 * goal_speed;
// Constants for the 5th order polynomial
double victor_fit_e1 = 0.437239;
double victor_fit_c1 = -1.56847;
double victor_fit_a1 = (- (125.0 * victor_fit_e1 + 125.0 * victor_fit_c1 - 116.0) / 125.0);
double answer_5th_order = (victor_fit_a1 * goal_speed5
+ victor_fit_c1 * goal_speed3
+ victor_fit_e1 * goal_speed);
// Constants for the 7th order polynomial
double victor_fit_c2 = -5.46889;
double victor_fit_e2 = 2.24214;
double victor_fit_g2 = -0.042375;
double victor_fit_a2 = (- (125.0 * (victor_fit_c2 + victor_fit_e2 + victor_fit_g2) - 116.0) / 125.0);
double answer_7th_order = (victor_fit_a2 * goal_speed7
+ victor_fit_c2 * goal_speed5
+ victor_fit_e2 * goal_speed3
+ victor_fit_g2 * goal_speed);
// Average the 5th and 7th order polynomials
double answer = 0.85 * 0.5 * (answer_7th_order + answer_5th_order)
+ .15 * goal_speed * (1.0 - deadband_value);
if (answer > 0.001)
answer += deadband_value;
else if (answer < -0.001)
answer -= deadband_value;
return answer;
}
They clearly have a handle on things, so I was wondering if this approach provided them something over what I teach my kids (the piecewise linear approach described previously)
here's the code one of my kids came up with as part of a pre-season homework assignment a few weeks ago. "scale" is a 2d array of points characterizing the piecewise function. The benefit of implementing it this way is that you can modify your array of points at any time, to tweak behavior, without having to modify your code.
Code:
static double getInterpolatedAxis(double input){
for(int i=0;i<scale.length-1;i++){
if(input<scale[i][0]&&input>scale[i+1][0]){
double slope=(scale[i+1][1]-scale[i][1])/(scale[i+1][0]-scale[i][0]);//get slope
double intercept = (-1*slope*scale[i][0])+scale[i][1];
return (slope*input)+intercept;
}
}
}
Anyone who's been through an Algebra 1 class should be able to quickly grasp the math. Added bonus of them getting to apply existing classroom knowledge.