package me.drton.flightplot.processors.tools;
/**
* User: ton Date: 20.06.13 Time: 7:13
*/
public class PID {
public static enum MODE {
DERIVATIVE_SET,
DERIVATIVE_CALC,
DERIVATIVE_CALC_NO_SP,
}
private double kP = 0.0;
private double kI = 0.0;
private double kD = 0.0;
private double limit = 0.0;
private double integral = 0.0;
private double errorLast = 0.0;
private MODE mode = MODE.DERIVATIVE_CALC;
public void setK(double kP, double kI, double kD, double limit, MODE mode) {
this.kP = kP;
this.kI = kI;
this.kD = kD;
this.limit = limit;
this.mode = mode;
}
public void reset() {
errorLast = 0.0;
integral = 0.0;
}
public double getIntegral() {
return integral;
}
public void setIntegral(double integral) {
this.integral = integral;
}
private double limitValue(double value) {
if (limit == 0.0)
return value;
else
return Math.max(-limit, Math.min(limit, value));
}
public double getOutput(double err, double dt) {
if (mode != MODE.DERIVATIVE_CALC)
throw new RuntimeException("Can't use this method in mode " + mode);
double d = (err - errorLast) / dt;
errorLast = err;
double pd = err * kP + d * kD;
integral += pd / kP * kI * dt;
integral = limitValue(integral);
return limitValue(pd + integral);
}
public double getOutput(double err, double derivative, double dt) {
if (mode != MODE.DERIVATIVE_SET)
throw new RuntimeException("Can't use this method in mode " + mode);
errorLast = err;
double pd = err * kP + derivative * kD;
integral += pd / kP * kI * dt;
integral = limitValue(integral);
return limitValue(pd + integral);
}
public double getOutput(double sp, double value, double derivative, double dt, double awuW) {
double err = sp - value;
double d;
if (mode == MODE.DERIVATIVE_SET) {
d = derivative;
errorLast = err;
} else if (mode == MODE.DERIVATIVE_CALC) {
d = (err - errorLast) / dt;
errorLast = err;
} else if (mode == MODE.DERIVATIVE_CALC_NO_SP) {
d = (-value - errorLast) / dt;
errorLast = -value;
} else {
d = 0.0;
errorLast = 0.0;
}
double pd = err * kP + d * kD;
double i = integral + err * kI * dt * awuW;
if (limit == 0.0 || (Math.abs(i) < limit && Math.abs(pd + i) < limit))
integral = limitValue(i);
return limitValue(pd + integral);
}
}