package mods.eln.sim; import mods.eln.item.regulator.IRegulatorDescriptor.RegulatorType; import mods.eln.misc.INBTTReady; import net.minecraft.nbt.NBTTagCompound; public abstract class RegulatorProcess implements IProcess, INBTTReady { RegulatorType type = RegulatorType.None; double target; double OnOffHysteresisDiv2; double P, I, D; double hitLast = 0, errorIntegrated = 0; boolean boot = true; String name; public void setManual() { type = RegulatorType.Manual; } public void setNone() { type = RegulatorType.None; } public void setOnOff(double OnOffHysteresisFactor, double workingPoint) { type = RegulatorType.OnOff; this.OnOffHysteresisDiv2 = OnOffHysteresisFactor * workingPoint / 2; boot = false; setCmd(0.0); } public void setAnalog(double P, double I, double D, double workingPoint) { P /= workingPoint; I /= workingPoint; D /= workingPoint; if (!boot && (this.P != P || this.I != I || this.D != D || type != RegulatorType.Analog)) { errorIntegrated = 0; hitLast = getHit(); } this.P = P; this.I = I; this.D = D; type = RegulatorType.Analog; boot = false; } public void setTarget(double target) { this.target = target; } public double getTarget() { return target; } protected abstract double getHit(); protected abstract void setCmd(double cmd); public RegulatorProcess(String name) { this.name = name; } @Override public void process(double time) { double hit = getHit(); switch (type) { case Manual: break; case None: setCmd(1.0); break; case Analog: double error = target - hit; double fP = error * P; double cmd = fP - (hit - hitLast) * D * time; errorIntegrated += error * time * I; if (errorIntegrated > 1.0 - fP) { errorIntegrated = 1.0 - fP; if (errorIntegrated < 0.0) errorIntegrated = 0.0; } else if (errorIntegrated < (-1.0 + fP)) { errorIntegrated = (-1.0 + fP); if (errorIntegrated > 0.0) errorIntegrated = 0.0; } cmd += errorIntegrated; if (cmd > 1.0) setCmd(1.0); else if (cmd < -1.0) setCmd(-1.0); else setCmd(cmd); hitLast = hit; break; case OnOff: if (hit > target + OnOffHysteresisDiv2) setCmd(0.0); if (hit < target - OnOffHysteresisDiv2) setCmd(1.0); break; default: break; } } @Override public void readFromNBT(NBTTagCompound nbt, String str) { errorIntegrated = nbt.getDouble(str + name + "errorIntegrated"); if (Double.isNaN(errorIntegrated)) errorIntegrated = 0; setTarget(nbt.getDouble(str + name + "target")); } @Override public void writeToNBT(NBTTagCompound nbt, String str) { nbt.setDouble(str + name + "errorIntegrated", errorIntegrated); nbt.setDouble(str + name + "target", target); } }