\r
\r
import java.util.Date;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
import java.util.SortedMap;\r
import java.util.TreeMap;\r
\r
private static final double regStepDecreaseFactor = .5;\r
private static final Amount<Pressure> chamberPressureMaxDelta = Amount.valueOf(.5, SI.MEGA(SI.PASCAL));\r
\r
+ private static final Amount<Pressure> endPressure = Amount.valueOf(.1, RocketScience.PSI);\r
+ \r
private static Logger log = Logger.getLogger(Burn.class);\r
protected final Motor motor;\r
\r
+ private boolean burning = false;\r
+ private boolean done = false;\r
+ \r
public interface BurnProgressListener{\r
public void setProgress(float p);\r
+ public void burnComplete();\r
}\r
\r
- private BurnProgressListener bpl = null;\r
+ private Set<BurnProgressListener> bpls = new HashSet<Burn.BurnProgressListener>();\r
\r
private static final Amount<Pressure> atmosphereicPressure = Amount.valueOf(101000, SI.PASCAL);\r
\r
protected SortedMap<Amount<Duration>,Interval> data = new TreeMap<Amount<Duration>, Interval>();\r
\r
public SortedMap<Amount<Duration>,Interval> getData(){\r
+ if ( !done )\r
+ throw new IllegalStateException("Burn not complete!");\r
return data;\r
}\r
\r
}\r
\r
public Amount<Duration> burnTime(){\r
- return data.lastKey();\r
+ return getData().lastKey();\r
}\r
\r
public Burn(Motor m){\r
throw new IllegalArgumentException("Invalid Motor: " + e.getMessage());\r
}\r
motor = m;\r
- burn();\r
}\r
\r
- public Burn(Motor m, BurnProgressListener bpl){\r
- try {\r
- m.validate();\r
- } catch (ValidationException e) {\r
- throw new IllegalArgumentException("Invalid Motor: " + e.getMessage());\r
- }\r
- motor = m;\r
- this.bpl = bpl;\r
- burn();\r
+ public void addBurnProgressListener( BurnProgressListener bpl ){\r
+ bpls.add(bpl);\r
+ if ( done )\r
+ bpl.burnComplete();\r
}\r
\r
- private void burn(){\r
+ public void burn(){\r
+ synchronized(this){\r
+ if ( burning )\r
+ throw new IllegalStateException("Already burning!");\r
+ burning = true;\r
+ }\r
log.info("Starting burn...");\r
+ for (BurnProgressListener bpl : bpls ){\r
+ bpl.setProgress(0);\r
+ }\r
+ \r
+ int endPressureSteps = 0;\r
long start = new Date().getTime();\r
\r
Amount<Length> regStep = Amount.valueOf(0.01, SI.MILLIMETER);\r
\r
log.debug("Regression: " + next.regression);\r
\r
- if ( bpl != null ){\r
- Amount<Dimensionless> a = next.regression.divide(motor.getGrain().webThickness()).to(Dimensionless.UNIT);\r
+ //Update BurnProgressListeners\r
+ Amount<Dimensionless> a = next.regression.divide(motor.getGrain().webThickness()).to(Dimensionless.UNIT);\r
+ for (BurnProgressListener bpl : bpls ){\r
bpl.setProgress((float)a.doubleValue(Dimensionless.UNIT));\r
}\r
+\r
\r
next.time = prev.time.plus(dt);\r
\r
next.thrust = motor.getNozzle().thrust(next.chamberPressure, atmosphereicPressure, atmosphereicPressure, motor.getFuel().getCombustionProduct().getRatioOfSpecificHeats2Phase());\r
assert(positive(next.thrust));\r
\r
- if ( i > 100 && next.chamberPressure.approximates(atmosphereicPressure)){\r
- log.info("Pressure at Patm on step " + i);\r
- break;\r
+ if ( i > 100 && next.chamberPressure.minus(atmosphereicPressure).abs().isLessThan(endPressure)){\r
+ log.info("Pressure at ~Patm on step " + i);\r
+ endPressureSteps++;\r
+ if ( endPressureSteps > 5 )\r
+ break;\r
}\r
\r
data.put(data.lastKey().plus(dt), next);\r
\r
long time = new Date().getTime() - start;\r
log.info("Burn took " + time + " millis.");\r
+ done = true;\r
+ for (BurnProgressListener bpl : bpls ){\r
+ bpl.burnComplete();\r
+ }\r
}\r
\r
@SuppressWarnings("unchecked")\r
}\r
\r
public Amount<Pressure> pressure(Amount<Duration> time){\r
- return data.get(time).chamberPressure;\r
+ return getData().get(time).chamberPressure;\r
}\r
\r
public Amount<Force> thrust(Amount<Duration> time){\r
- return data.get(time).thrust;\r
+ return getData().get(time).thrust;\r
}\r
\r
public Amount<Dimensionless> kn(Amount<Length> regression){\r