]> git.gag.com Git - debian/openrocket/commitdiff
Persist the Velocity at launch rod clearance in ork file. Added to column in Simulat...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Tue, 17 Jan 2012 02:46:49 +0000 (02:46 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Tue, 17 Jan 2012 02:46:49 +0000 (02:46 +0000)
Added l10n message keys for new column in SimulationPanel.

Added function MathUtil.interpolate which does linear interpolation of intermediate values.  This is used in FlightData for computing Velocity at deployment and Velocity at launch rod clearance.

git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@358 180e2498-e6e9-4542-8430-84ac67f01cd8

core/fileformat.txt
core/resources/l10n/messages.properties
core/src/net/sf/openrocket/file/openrocket/OpenRocketLoader.java
core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
core/src/net/sf/openrocket/gui/main/SimulationPanel.java
core/src/net/sf/openrocket/gui/print/DesignReport.java
core/src/net/sf/openrocket/simulation/FlightData.java
core/src/net/sf/openrocket/util/MathUtil.java
core/test/net/sf/openrocket/util/MathUtilTest.java

index 9e04dcfffc392a7bc469c1004f685e4d5dc7387a..17247f26dae59b5e92cc00867e0acf9bd0d8e4f8 100644 (file)
@@ -39,3 +39,5 @@ The following file format versions exist:
 1.3:  Introduced with OpenRocket 1.1.9.  Adds the <launchlongitude> and
       <geodeticmethod> parameters to the simulation conditions element.
 
+1.4:  Introduced with OpenRocket 1.1.10.  Adds the launchrodvelocity and
+      deploymentvelocity attributes to <flightdata> element.
\ No newline at end of file
index 3a51de44702e779f612f91ebda6affee4cddd9ee..e385eb94e8c4febbb76b30fb86ee5d8a510d2a5a 100644 (file)
@@ -378,6 +378,8 @@ simpanel.dlg.lbl.DeleteSim2 = <html><i>This operation cannot be undone.</i>
 simpanel.dlg.lbl.DeleteSim3 = Delete simulations
 simpanel.col.Name = Name
 simpanel.col.Motors = Motors
+simpanel.col.Velocityoffrod = Velocity off rod
+simpanel.col.Velocityatdeploy = Velocity at deployment
 simpanel.col.Apogee = Apogee
 simpanel.col.Maxvelocity = Max. velocity
 simpanel.col.Maxacceleration = Max. acceleration
index 518f1e44c6c080eecb07cc5f6da3d7def56d6088..475245ddbd5f9ac1b5df6bf310481d9aa15b0da4 100644 (file)
@@ -1517,6 +1517,8 @@ class FlightDataHandler extends ElementHandler {
                        double timeToApogee = Double.NaN;
                        double flightTime = Double.NaN;
                        double groundHitVelocity = Double.NaN;
+                       double launchRodVelocity = Double.NaN;
+                       double deploymentVelocity = Double.NaN;
                        
                        try {
                                maxAltitude = DocumentConfig.stringToDouble(attributes.get("maxaltitude"));
@@ -1547,10 +1549,18 @@ class FlightDataHandler extends ElementHandler {
                                                DocumentConfig.stringToDouble(attributes.get("groundhitvelocity"));
                        } catch (NumberFormatException ignore) {
                        }
+                       try {
+                               launchRodVelocity = DocumentConfig.stringToDouble(attributes.get("launchrodvelocity"));
+                       } catch (NumberFormatException ignore) {
+                       }
+                       try {
+                               deploymentVelocity = DocumentConfig.stringToDouble(attributes.get("deploymentvelocity"));
+                       } catch (NumberFormatException ignore) {
+                       }
                        
                        // TODO: HIGH: Store and load launchRodVelocity
                        data = new FlightData(maxAltitude, maxVelocity, maxAcceleration, maxMach,
-                                       timeToApogee, flightTime, groundHitVelocity, Double.NaN);
+                                       timeToApogee, flightTime, groundHitVelocity, launchRodVelocity, deploymentVelocity);
                }
                
                data.getWarningSet().addAll(warningSet);
index 7dbb2fce5467311aa707fe2c35416925c3965a59..c04cce9b2d0bdb0fc94ff76ce882441ac94891e7 100644 (file)
@@ -360,6 +360,10 @@ public class OpenRocketSaver extends RocketSaver {
                                str += " flighttime=\"" + TextUtil.doubleToString(data.getFlightTime()) + "\"";
                        if (!Double.isNaN(data.getGroundHitVelocity()))
                                str += " groundhitvelocity=\"" + TextUtil.doubleToString(data.getGroundHitVelocity()) + "\"";
+                       if (!Double.isNaN(data.getLaunchRodVelocity()))
+                               str += " launchrodvelocity=\"" + TextUtil.doubleToString(data.getLaunchRodVelocity()) + "\"";
+                       if (!Double.isNaN(data.getDeploymentVelocity()))
+                               str += " deploymentvelocity=\"" + TextUtil.doubleToString(data.getDeploymentVelocity()) + "\"";
                        str += ">";
                        writeln(str);
                        indent++;
index 11b707eac6fc00137f62acd8e33f6901b1360f34..719e1cf6a6a3cd3d00cd4e1c7eae45ae19566067 100644 (file)
@@ -311,6 +311,22 @@ public class SimulationPanel extends JPanel {
                                        }
                                },
 
+                               //// Launch rod velocity
+                               new Column(trans.get("simpanel.col.Velocityoffrod")) {
+                                       @Override
+                                       public Object getValueAt(int row) {
+                                               if (row < 0 || row >= document.getSimulationCount())
+                                                       return null;
+                                               
+                                               FlightData data = document.getSimulation(row).getSimulatedData();
+                                               if (data == null)
+                                                       return null;
+                                               
+                                               return UnitGroup.UNITS_VELOCITY.getDefaultUnit().toStringUnit(
+                                                               data.getLaunchRodVelocity());
+                                       }
+                               },
+
                                //// Apogee
                                new Column(trans.get("simpanel.col.Apogee")) {
                                        @Override
@@ -327,6 +343,22 @@ public class SimulationPanel extends JPanel {
                                        }
                                },
 
+                               //// Velocity at deployment
+                               new Column(trans.get("simpanel.col.Velocityatdeploy")) {
+                                       @Override
+                                       public Object getValueAt(int row) {
+                                               if (row < 0 || row >= document.getSimulationCount())
+                                                       return null;
+                                               
+                                               FlightData data = document.getSimulation(row).getSimulatedData();
+                                               if (data == null)
+                                                       return null;
+                                               
+                                               return UnitGroup.UNITS_VELOCITY.getDefaultUnit().toStringUnit(
+                                                               data.getDeploymentVelocity());
+                                       }
+                               },
+
                                //// Maximum velocity
                                new Column(trans.get("simpanel.col.Maxvelocity")) {
                                        @Override
index 886e225ad0f7b788db49ae8d5bbd5c370b4d68b3..e6290c3e906e6aee23db04d3ac7ad828c916457e 100644 (file)
@@ -117,6 +117,7 @@ public class DesignReport {
        private static final String TIME_TO_APOGEE = "Time to Apogee";
        private static final String VELOCITY_OFF_PAD = "Velocity off Pad";
        private static final String MAX_VELOCITY = "Max Velocity";
+       private static final String DEPLOYMENT_VELOCITY = "Velocity at Deployment";
        private static final String LANDING_VELOCITY = "Landing Velocity";
        private static final String ROCKET_DESIGN = "Rocket Design";
        private static final double GRAVITY_CONSTANT = 9.80665d;
@@ -469,6 +470,9 @@ public class DesignReport {
                                labelTable.addCell(ITextHelper.createCell(MAX_VELOCITY, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getMaxVelocity()), 2, 2));
                                
+                               labelTable.addCell(ITextHelper.createCell(DEPLOYMENT_VELOCITY, 2,2));
+                               labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getDeploymentVelocity()),2,2));
+                               
                                labelTable.addCell(ITextHelper.createCell(LANDING_VELOCITY, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getGroundHitVelocity()), 2, 2));
                                
index 839c658465c7f6fc0084ad437434d5873165f8ac..c0fb90e80dff2e7b33eb0ea4b1318fec33810b83 100644 (file)
@@ -49,6 +49,7 @@ public class FlightData {
        private double flightTime = Double.NaN;
        private double groundHitVelocity = Double.NaN;
        private double launchRodVelocity = Double.NaN;
+       private double deploymentVelocity = Double.NaN;
        
        
        /**
@@ -70,11 +71,12 @@ public class FlightData {
         * @param timeToApogee                  time to apogee.
         * @param flightTime                    total flight time.
         * @param groundHitVelocity             ground hit velocity.
-        * @param launchRodVelocity TODO
+        * @param launchRodVelocity     velocity at launch rod clearance
+        * @param deploymentVelocity    velocity at deployment
         */
        public FlightData(double maxAltitude, double maxVelocity, double maxAcceleration,
                        double maxMachNumber, double timeToApogee, double flightTime,
-                       double groundHitVelocity, double launchRodVelocity) {
+                       double groundHitVelocity, double launchRodVelocity, double deploymentVelocity) {
                this.maxAltitude = maxAltitude;
                this.maxVelocity = maxVelocity;
                this.maxAcceleration = maxAcceleration;
@@ -83,6 +85,7 @@ public class FlightData {
                this.flightTime = flightTime;
                this.groundHitVelocity = groundHitVelocity;
                this.launchRodVelocity = launchRodVelocity;
+               this.deploymentVelocity = deploymentVelocity;
        }
        
        
@@ -171,7 +174,11 @@ public class FlightData {
                return launchRodVelocity;
        }
        
-       
+
+       public double getDeploymentVelocity() {
+               return deploymentVelocity;
+       }
+
 
        /**
         * Calculate the max. altitude/velocity/acceleration, time to apogee, flight time
@@ -223,15 +230,11 @@ public class FlightData {
                        if (event.getType() == FlightEvent.Type.LAUNCHROD) {
                                double t = event.getTime();
                                List<Double> velocity = branch.get(FlightDataType.TYPE_VELOCITY_TOTAL);
-                               if (velocity == null) {
-                                       break;
-                               }
-                               for (int i = 0; i < velocity.size(); i++) {
-                                       if (time.get(i) >= t) {
-                                               launchRodVelocity = velocity.get(i);
-                                               break eventloop;
-                                       }
-                               }
+                               launchRodVelocity = MathUtil.interpolate( time, velocity, t);
+                       } else if ( event.getType() == FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT) {
+                               double t = event.getTime();
+                               List<Double> velocity = branch.get(FlightDataType.TYPE_VELOCITY_TOTAL);
+                               deploymentVelocity = MathUtil.interpolate( time, velocity, t);
                        }
                }
                
index dc2e105d63743f7c9c10246af6fc65d7f706b2dc..c88e85853562bc5907f64bfb4654d329b2140128 100644 (file)
@@ -11,9 +11,9 @@ import net.sf.openrocket.startup.Application;
 
 public class MathUtil {
        private static final LogHelper log = Application.getLogger();
-       
+
        public static final double EPSILON = 0.00000001; // 10mm^3 in m^3
-       
+
        /**
         * The square of x (x^2).  On Sun's JRE using this method is as fast as typing x*x. 
         * @param x  x
@@ -22,7 +22,7 @@ public class MathUtil {
        public static double pow2(double x) {
                return x * x;
        }
-       
+
        /**
         * The cube of x (x^3).
         * @param x  x
@@ -31,11 +31,11 @@ public class MathUtil {
        public static double pow3(double x) {
                return x * x * x;
        }
-       
+
        public static double pow4(double x) {
                return (x * x) * (x * x);
        }
-       
+
        /**
         * Clamps the value x to the range min - max.  
         * @param x    Original value.
@@ -50,7 +50,7 @@ public class MathUtil {
                        return max;
                return x;
        }
-       
+
        public static float clamp(float x, float min, float max) {
                if (x < min)
                        return min;
@@ -58,7 +58,7 @@ public class MathUtil {
                        return max;
                return x;
        }
-       
+
        public static int clamp(int x, int min, int max) {
                if (x < min)
                        return min;
@@ -66,8 +66,8 @@ public class MathUtil {
                        return max;
                return x;
        }
-       
-       
+
+
        /**
         * Maps a value from one value range to another.
         * 
@@ -90,8 +90,8 @@ public class MathUtil {
                }
                return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
        }
-       
-       
+
+
        /**
         * Maps a coordinate from one value range to another.
         * 
@@ -115,8 +115,8 @@ public class MathUtil {
                double a = (value - fromMin) / (fromMax - fromMin);
                return toMax.multiply(a).add(toMin.multiply(1 - a));
        }
-       
-       
+
+
        /**
         * Compute the minimum of two values.  This is performed by direct comparison. 
         * However, if one of the values is NaN and the other is not, the non-NaN value is
@@ -127,7 +127,7 @@ public class MathUtil {
                        return x;
                return (x < y) ? x : y;
        }
-       
+
        /**
         * Compute the maximum of two values.  This is performed by direct comparison. 
         * However, if one of the values is NaN and the other is not, the non-NaN value is
@@ -138,7 +138,7 @@ public class MathUtil {
                        return y;
                return (x < y) ? y : x;
        }
-       
+
        /**
         * Compute the minimum of three values.  This is performed by direct comparison. 
         * However, if one of the values is NaN and the other is not, the non-NaN value is
@@ -151,8 +151,8 @@ public class MathUtil {
                        return min(y, z);
                }
        }
-       
-       
+
+
 
        /**
         * Compute the minimum of three values.  This is performed by direct comparison. 
@@ -162,8 +162,8 @@ public class MathUtil {
        public static double min(double w, double x, double y, double z) {
                return min(min(w, x), min(y, z));
        }
-       
-       
+
+
        /**
         * Compute the maximum of three values.  This is performed by direct comparison. 
         * However, if one of the values is NaN and the other is not, the non-NaN value is
@@ -176,7 +176,7 @@ public class MathUtil {
                        return max(y, z);
                }
        }
-       
+
        /**
         * Calculates the hypotenuse <code>sqrt(x^2+y^2)</code>.  This method is SIGNIFICANTLY
         * faster than <code>Math.hypot(x,y)</code>.
@@ -184,7 +184,7 @@ public class MathUtil {
        public static double hypot(double x, double y) {
                return Math.sqrt(x * x + y * y);
        }
-       
+
        /**
         * Reduce the angle x to the range 0 - 2*PI.
         * @param x  Original angle.
@@ -194,7 +194,7 @@ public class MathUtil {
                double d = Math.floor(x / (2 * Math.PI));
                return x - d * 2 * Math.PI;
        }
-       
+
        /**
         * Reduce the angle x to the range -PI - PI.
         * 
@@ -207,8 +207,8 @@ public class MathUtil {
                double d = Math.rint(x / (2 * Math.PI));
                return x - d * 2 * Math.PI;
        }
-       
-       
+
+
        /**
         * Return the square root of a value.  If the value is negative, zero is returned.
         * This is safer in cases where rounding errors might make a value slightly negative.
@@ -225,20 +225,20 @@ public class MathUtil {
                }
                return Math.sqrt(d);
        }
-       
-       
+
+
 
        public static boolean equals(double a, double b) {
                double absb = Math.abs(b);
-               
+
                if (absb < EPSILON / 2) {
                        // Near zero
                        return Math.abs(a) < EPSILON / 2;
                }
                return Math.abs(a - b) < EPSILON * absb;
        }
-       
-       
+
+
        /**
         * Return the sign of the number.  This corresponds to Math.signum, but ignores
         * the special cases of zero and NaN.  The value returned for those is arbitrary.
@@ -251,20 +251,20 @@ public class MathUtil {
        public static double sign(double x) {
                return (x < 0) ? -1.0 : 1.0;
        }
-       
+
        /* Math.abs() is about 3x as fast as this:
-       
+
        public static double abs(double x) {
                return (x<0) ? -x : x;
        }
-       */
+        */
 
 
        public static double average(Collection<? extends Number> values) {
                if (values.isEmpty()) {
                        return Double.NaN;
                }
-               
+
                double avg = 0.0;
                int count = 0;
                for (Number n : values) {
@@ -273,12 +273,12 @@ public class MathUtil {
                }
                return avg / count;
        }
-       
+
        public static double stddev(Collection<? extends Number> values) {
                if (values.size() < 2) {
                        return Double.NaN;
                }
-               
+
                double avg = average(values);
                double stddev = 0.0;
                int count = 0;
@@ -289,12 +289,12 @@ public class MathUtil {
                stddev = Math.sqrt(stddev / (count - 1));
                return stddev;
        }
-       
+
        public static double median(Collection<? extends Number> values) {
                if (values.isEmpty()) {
                        return Double.NaN;
                }
-               
+
                List<Number> sorted = new ArrayList<Number>(values);
                Collections.sort(sorted, new Comparator<Number>() {
                        @Override
@@ -302,7 +302,7 @@ public class MathUtil {
                                return Double.compare(o1.doubleValue(), o2.doubleValue());
                        }
                });
-               
+
                int n = sorted.size();
                if (n % 2 == 0) {
                        return (sorted.get(n / 2).doubleValue() + sorted.get(n / 2 - 1).doubleValue()) / 2;
@@ -310,5 +310,58 @@ public class MathUtil {
                        return sorted.get(n / 2).doubleValue();
                }
        }
-       
+
+       /**
+        * Use interpolation to determine the value of the function at point t.
+        * Current implementation uses simple linear interpolation.   The domain
+        * and range lists must include the same number of values, t must be within
+        * the domain, and the domain list must be sorted.
+        * 
+        * @param domain list containing domain samples
+        * @param range list of corresponding range samples
+        * @param t domain value at which to interpolate
+        * @return returns Double.NaN if either list is null or empty or different size, or if t is outsize the domain.
+        */
+       public static double interpolate( List<Double> domain, List<Double> range, double t ) {
+
+               if ( domain == null || range == null || domain.size() != range.size() ) {
+                       return Double.NaN;
+               }
+
+               int length = domain.size();
+               if ( length <= 1 || t < domain.get(0) || t > domain.get( length-1 ) ) {
+                       return Double.NaN;
+               }
+
+               // Look for the index of the right end point.
+               int right = 1;
+               while( t > domain.get(right) ) {
+                       right ++;
+               }
+               int left = right -1;
+
+               // Points are:
+               
+               double deltax = domain.get(right) - domain.get(left);
+               double deltay = range.get(right) - range.get(left);
+
+               // For numerical stability, if deltax is small,
+               if ( Math.abs(deltax) < EPSILON ) {
+                       if ( deltay < -1.0 * EPSILON ) {
+                               // return neg infinity if deltay is negative
+                               return Double.NEGATIVE_INFINITY;
+                       }
+                       else if ( deltay > EPSILON ) {
+                               // return infinity if deltay is large
+                               return Double.POSITIVE_INFINITY;
+                       } else {
+                               // otherwise return 0
+                               return 0.0d;
+                       }
+               }
+               
+               return  range.get(left) + ( t - domain.get(left) ) * deltay / deltax;
+
+       }
+
 }
index 8b79aeca08536ad0b0002a6b8e8689fcd4faaaf5..f11ba89c3797d98ffe590853929b4e2412bfef80 100644 (file)
@@ -216,4 +216,64 @@ public class MathUtilTest {
                assertEquals(5.43, MathUtil.median(doubles), EPS);
        }
        
+       @Test
+       public void testInterpolate() {
+               double v;
+               List<Double> x;
+               List<Double> y;
+
+               x = new ArrayList<Double>();
+               y = new ArrayList<Double>();
+               y.add(1.0);
+               
+               v= MathUtil.interpolate(null, y, 0.0);
+               assertEquals("Failed to test for domain null", Double.NaN, v, EPS);
+               
+               v = MathUtil.interpolate(x, y, 0.0);
+               assertEquals("Failed to test for empty domain", Double.NaN, v, EPS);
+               
+               x = new ArrayList<Double>();
+               x.add(1.0);
+               y = new ArrayList<Double>();
+               
+               v = MathUtil.interpolate(x, null, 0.0);
+               assertEquals("Failed to test for range null", Double.NaN, v, EPS);
+               
+               v = MathUtil.interpolate(x, y, 0.0);
+               assertEquals("Failed to test for empty range", Double.NaN, v, EPS);
+               
+               x = new ArrayList<Double>();
+               x.add(1.0);
+               x.add(2.0);
+               y = new ArrayList<Double>();
+               y.add(15.0);
+               y.add(17.0);
+               
+               v = MathUtil.interpolate(x,y,0.0);
+               assertEquals("Failed to test t out of domain", Double.NaN, v, EPS);
+               
+               v = MathUtil.interpolate(x,y,5.0);
+               assertEquals("Failed to test t out of domain", Double.NaN, v, EPS);
+               
+               v = MathUtil.interpolate(x,y,1.0);
+               assertEquals("Failed to calculate left endpoint", 15.0, v, EPS);
+               v = MathUtil.interpolate(x,y,2.0);
+               assertEquals("Failed to calculate right endpoint", 17.0, v, EPS);
+               v = MathUtil.interpolate(x,y,1.5);
+               assertEquals("Failed to calculate center", 16.0, v, EPS);
+               
+               x = new ArrayList<Double>();
+               x.add(0.25);
+               x.add(0.5);
+               x.add(1.0);
+               x.add(2.0);
+               y = new ArrayList<Double>();
+               y.add(0.0);
+               y.add(0.0);
+               y.add(15.0);
+               y.add(17.0);
+               v = MathUtil.interpolate(x,y,1.5);
+               assertEquals("Failed to calculate center with longer list", 16.0, v, EPS);
+               
+       }
 }