(no commit message)
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / Burn.java
index 6be9861fa4f22acec53b41e7b08cbb76bf033d5a..e101d8154b7edb12858277f4d9533ac783a2fad9 100644 (file)
@@ -3,6 +3,8 @@ package com.billkuker.rocketry.motorsim;
 \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
@@ -33,14 +35,20 @@ public class Burn {
        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
@@ -60,6 +68,8 @@ public class Burn {
        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
@@ -68,7 +78,7 @@ public class Burn {
        }\r
 \r
        public Amount<Duration> burnTime(){\r
-               return data.lastKey();\r
+               return getData().lastKey();\r
        }\r
        \r
        public Burn(Motor m){\r
@@ -78,22 +88,26 @@ public class Burn {
                        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
@@ -136,10 +150,12 @@ public class Burn {
                        \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
@@ -219,9 +235,11 @@ public class Burn {
                        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
@@ -229,6 +247,10 @@ public class Burn {
 \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
@@ -243,11 +265,11 @@ public class Burn {
        }\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