optimization updates
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Fri, 12 Aug 2011 18:56:24 +0000 (18:56 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Fri, 12 Aug 2011 18:56:24 +0000 (18:56 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@150 180e2498-e6e9-4542-8430-84ac67f01cd8

l10n/messages.properties
src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java
src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java
src/net/sf/openrocket/gui/dialogs/optimization/OptimizationPlotDialog.java
src/net/sf/openrocket/gui/main/ExceptionHandler.java
src/net/sf/openrocket/gui/main/SimulationRunDialog.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java
src/net/sf/openrocket/simulation/AbstractSimulationStepper.java
src/net/sf/openrocket/simulation/RK4SimulationStepper.java
src/net/sf/openrocket/simulation/exception/SimulationCalculationException.java [new file with mode: 0644]

index 692248a1eaf1b4de8f14124c08307cb14253f753..9353c4d8fff5e50786a0f14cb6ef4a7f99bd8ada 100644 (file)
@@ -1344,7 +1344,7 @@ optimization.modifier.trapezoidfinset.height.desc = Optimize the height (semi-sp
 optimization.modifier.ellipticalfinset.length = Root chord
 optimization.modifier.ellipticalfinset.length.desc = Optimize the root chord length of the fin set.
 optimization.modifier.ellipticalfinset.height = Height
-optimization.modifier.ellipticalfinset.height = Optimize the height (semi-span) of the fin set.
+optimization.modifier.ellipticalfinset.height.desc = Optimize the height (semi-span) of the fin set.
 
 optimization.modifier.finset.cant = Cant angle
 optimization.modifier.finset.cant.desc = Optimize the cant angle of the fin set.
@@ -1471,6 +1471,7 @@ OptimizationPlotDialog.plot2d.title = Optimization path
 OptimizationPlotDialog.plot2d.path = Optimization path
 OptimizationPlotDialog.plot2d.evals = Evaluations
 OptimizationPlotDialog.plot.ttip.stability = Stability:
+OptimizationPlotDialog.plot.label.optimum = Optimum
 
 ! Optimization parameters
 MaximumAltitudeParameter.name = Apogee altitude
index ecafae1e46922163ed6ef3c7b47037564f475c20..f15539c1fe75ae1faddc8b5dc97b097eb3c57cfb 100644 (file)
@@ -140,6 +140,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
                total.setCm(total.getCm() - total.getPitchDampingMoment());
                total.setCyaw(total.getCyaw() - total.getYawDampingMoment());
                
+
                return total;
        }
        
@@ -648,6 +649,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
                double yaw = conditions.getYawRate();
                double vel = conditions.getVelocity();
                
+               vel = MathUtil.max(vel, 1);
+               
                //                      double Cm = total.Cm - total.CN * total.cg.x / conditions.getRefLength();
                //                      System.out.printf("Damping pitch/yaw, mul=%.4f pitch rate=%.4f "+
                //                                      "Cm=%.4f / %.4f effect=%.4f aoa=%.4f\n", mul, pitch, total.Cm, Cm, 
@@ -660,7 +663,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
                //                      total.Cyaw -= mul * yaw / pow2(vel);
                total.setPitchDampingMoment(mul * MathUtil.sign(pitch) * pow2(pitch / vel));
                total.setYawDampingMoment(mul * MathUtil.sign(yaw) * pow2(yaw / vel));
-               
        }
        
        // TODO: MEDIUM: Are the rotation etc. being added correctly?  sin/cos theta?
index f60c720d80e17bce2594e194120cd533fae66b0f..de5ad2cacdc893cc04fce4c1c914177fc20ea5e7 100644 (file)
@@ -37,6 +37,7 @@ import javax.swing.JSpinner;
 import javax.swing.JTable;
 import javax.swing.JToggleButton;
 import javax.swing.ListSelectionModel;
+import javax.swing.Timer;
 import javax.swing.border.TitledBorder;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
@@ -95,7 +96,6 @@ import net.sf.openrocket.util.TextUtil;
 
 import com.itextpdf.text.Font;
 
-// FIXME: Override to zero mass produces NaN in simulation
 
 /**
  * General rocket optimization dialog.
@@ -791,6 +791,18 @@ public class GeneralOptimizationDialog extends JDialog {
                                
                                worker = null;
                                stopOptimization();
+                               
+                               // Disable the start/stop button for a short while after ending the simulation
+                               // to prevent accidentally starting a new optimization when trying to stop it
+                               startButton.setEnabled(false);
+                               Timer timer = new Timer(750, new ActionListener() {
+                                       @Override
+                                       public void actionPerformed(ActionEvent e) {
+                                               startButton.setEnabled(true);
+                                       }
+                               });
+                               timer.setRepeats(false);
+                               timer.start();
                        }
                        
                        @Override
index c3f9c0cbf9855836a82cbc230f0d7f56a691ce05..ab9c9c94c284f50349097b2d04a757e316dab6bf 100644 (file)
@@ -34,6 +34,9 @@ import net.sf.openrocket.util.MathUtil;
 import org.jfree.chart.ChartFactory;
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
+import org.jfree.chart.annotations.XYBoxAnnotation;
+import org.jfree.chart.annotations.XYLineAnnotation;
+import org.jfree.chart.annotations.XYPointerAnnotation;
 import org.jfree.chart.axis.AxisLocation;
 import org.jfree.chart.axis.NumberAxis;
 import org.jfree.chart.labels.CustomXYToolTipGenerator;
@@ -47,6 +50,7 @@ import org.jfree.data.xy.DefaultXYZDataset;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
 import org.jfree.ui.RectangleEdge;
+import org.jfree.ui.TextAnchor;
 
 /**
  * A class that plots the path of an optimization.
@@ -57,8 +61,7 @@ public class OptimizationPlotDialog extends JDialog {
        private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
-       // FIXME:  Set range to optimization range
-       
+
        private static final LinearInterpolator RED = new LinearInterpolator(
                        new double[] { 0.0, 1.0 }, new double[] { 0.0, 1.0 }
                        );
@@ -155,6 +158,37 @@ public class OptimizationPlotDialog extends JDialog {
                                false); // Urls
                
 
+               // Set the scale of the plot to the limits
+               double x1 = xUnit.toUnit(modX.getMinValue());
+               double x2 = xUnit.toUnit(modX.getMaxValue());
+               
+               chart.getXYPlot().getDomainAxis().setRange(x1, x2);
+               
+               // Add lines to show optimization limits
+               XYLineAnnotation line = new XYLineAnnotation(x1, -1e19, x1, 1e19);
+               chart.getXYPlot().addAnnotation(line);
+               line = new XYLineAnnotation(x2, -1e19, x2, 1e19);
+               chart.getXYPlot().addAnnotation(line);
+               
+               // Mark the optimum point
+               Point optimum = path.get(path.size() - 1);
+               FunctionEvaluationData data = evaluations.get(optimum);
+               if (data != null) {
+                       if (data.getParameterValue() != null) {
+                               Value[] state = data.getState();
+                               double x = xUnit.toUnit(state[0].getValue());
+                               double y = yUnit.toUnit(data.getParameterValue().getValue());
+                               
+                               XYPointerAnnotation text = new XYPointerAnnotation(trans.get("plot.label.optimum"),
+                                               x, y, Math.PI / 2);
+                               text.setTextAnchor(TextAnchor.TOP_LEFT);
+                               chart.getXYPlot().addAnnotation(text);
+                       }
+               } else {
+                       log.error("Could not find evaluation data for point " + optimum);
+               }
+               
+
                XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer(true, true);
                lineRenderer.setBaseShapesVisible(true);
                lineRenderer.setSeriesShapesFilled(0, false);
@@ -191,13 +225,13 @@ public class OptimizationPlotDialog extends JDialog {
                Unit yUnit = modY.getUnitGroup().getDefaultUnit();
                
                // Create the optimization path dataset
-               XYSeries series = new XYSeries(trans.get("plot2d.path"), false, true);
+               XYSeries pathSeries = new XYSeries(trans.get("plot2d.path"), false, true);
                List<String> pathTooltips = new ArrayList<String>();
                for (Point p : path) {
                        FunctionEvaluationData data = evaluations.get(p);
                        if (data != null) {
                                Value[] state = data.getState();
-                               series.add(xUnit.toUnit(state[0].getValue()), yUnit.toUnit(state[1].getValue()));
+                               pathSeries.add(xUnit.toUnit(state[0].getValue()), yUnit.toUnit(state[1].getValue()));
                                pathTooltips.add(getTooltip(data, parameter));
                        } else {
                                log.error("Could not find evaluation data for point " + p);
@@ -256,13 +290,24 @@ public class OptimizationPlotDialog extends JDialog {
                                false); // Urls
                
 
-               chart.getXYPlot().getDomainAxis().setRange(xUnit.toUnit(modX.getMinValue()),
-                               xUnit.toUnit(modX.getMaxValue()));
+               // Set the scale of the plot to the limits
+               double x1 = xUnit.toUnit(modX.getMinValue());
+               double x2 = xUnit.toUnit(modX.getMaxValue());
+               double y1 = yUnit.toUnit(modY.getMinValue());
+               double y2 = yUnit.toUnit(modY.getMaxValue());
                
-               chart.getXYPlot().getRangeAxis().setRange(yUnit.toUnit(modY.getMinValue()),
-                               yUnit.toUnit(modY.getMaxValue()));
+               chart.getXYPlot().getDomainAxis().setRange(x1, x2);
+               chart.getXYPlot().getRangeAxis().setRange(y1, y2);
+               
+               XYBoxAnnotation box = new XYBoxAnnotation(x1, y1, x2, y2);
+               chart.getXYPlot().addAnnotation(box);
+               
+               int n = pathSeries.getItemCount();
+               XYPointerAnnotation text = new XYPointerAnnotation(trans.get("plot.label.optimum"),
+                               (Double) pathSeries.getX(n - 1), (Double) pathSeries.getY(n - 1), -Math.PI / 5);
+               text.setTextAnchor(TextAnchor.BASELINE_LEFT);
+               chart.getXYPlot().addAnnotation(text);
                
-
                PaintScale paintScale = new GradientScale(min, max);
                
                XYShapeRenderer shapeRenderer = new XYShapeRenderer();
@@ -290,7 +335,7 @@ public class OptimizationPlotDialog extends JDialog {
 
                XYPlot plot = chart.getXYPlot();
                
-               plot.setDataset(0, new XYSeriesCollection(series));
+               plot.setDataset(0, new XYSeriesCollection(pathSeries));
                plot.setRenderer(lineRenderer);
                
                plot.setDataset(1, evalDataset);
index a3d51de3a66131a04fa9a9a179895912f998f7a3..74f3091757ad4dc1cbcf6136228668d489ae7549 100644 (file)
@@ -113,7 +113,7 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
         * @param message       the error message.
         * @param exception     the exception that occurred.
         */
-       public static void handleErrorCondition(String message, Exception exception) {
+       public static void handleErrorCondition(String message, Throwable exception) {
                log.error(1, message, exception);
                handleErrorCondition(new InternalException(message, exception));
        }
@@ -128,7 +128,7 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
         * 
         * @param exception             the exception that occurred.
         */
-       public static void handleErrorCondition(final Exception exception) {
+       public static void handleErrorCondition(final Throwable exception) {
                try {
                        if (!(exception instanceof InternalException)) {
                                log.error(1, "Error occurred", exception);
index 1788515e78f62b0a16beb18e43d9145cd4994d8b..4405bdb50d622d18b98c29ed87db1edc7544fe86 100644 (file)
@@ -409,50 +409,15 @@ public class SimulationRunDialog extends JDialog {
                                                },
                                                stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
                                
-                       } else if (t instanceof Exception) {
-                               
-                               // TODO: MEDIUM: Check the exception handling here...
-                               t.printStackTrace();
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
-                                               new Object[] {
-                                                               //// An exception occurred during the simulation:
-                                                               trans.get("SimuRunDlg.msg.AnException1"),
-                                                               t.getMessage(),
-                                                               simulation.getSimulationListeners().isEmpty() ?
-                                                                               trans.get("SimuRunDlg.msg.AnException2") : ""
-                                               },
-                                               stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
-                               
-                       } else if (t instanceof AssertionError) {
-                               
-                               t.printStackTrace();
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
-                                               new Object[] {
-                                                               //// A computation error occurred during the simulation.
-                                                               trans.get("SimuRunDlg.msg.AssertionError1"),
-                                                               //// Please report this as a bug along with the details below.
-                                                               trans.get("SimuRunDlg.msg.AssertionError2")
-                                               },
-                                               stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
-                               
                        } else {
                                
-                               // Probably an Error
-                               DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
-                                               new Object[] {
-                                                               //// An unknown error was encountered during the simulation.
-                                                               trans.get("SimuRunDlg.msg.unknownerror1"),
-                                                               //// The program may be unstable, you should save all your designs and restart OpenRocket now!
-                                                               trans.get("SimuRunDlg.msg.unknownerror2")
-                                               },
-                                               stackTrace, simulation.getName(), JOptionPane.ERROR_MESSAGE);
+                               ExceptionHandler.handleErrorCondition("An exception occurred during the simulation", t);
                                
                        }
                        simulationDone();
                }
                
                
-
                private void setSimulationProgress(double p) {
                        int exact = Math.max(progress, (int) (100 * p + 0.5));
                        progress = MathUtil.clamp(exact, 0, 100);
index 807be9427710db82b165c12858ea9b16fdb8c75e..e814dd305d51e49e812e145b8e4121cc1aaa3130 100644 (file)
@@ -8,6 +8,7 @@ import net.sf.openrocket.optimization.general.OptimizationException;
 import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
 import net.sf.openrocket.simulation.FlightData;
 import net.sf.openrocket.simulation.exception.MotorIgnitionException;
+import net.sf.openrocket.simulation.exception.SimulationCalculationException;
 import net.sf.openrocket.simulation.exception.SimulationCancelledException;
 import net.sf.openrocket.simulation.exception.SimulationException;
 import net.sf.openrocket.simulation.exception.SimulationLaunchException;
@@ -44,6 +45,9 @@ public abstract class SimulationBasedParameter implements OptimizableParameter {
                } catch (SimulationLaunchException e) {
                        // Other launch exceptions result in illegal value
                        return Double.NaN;
+               } catch (SimulationCalculationException e) {
+                       // Calculation errors result in illegal value
+                       return Double.NaN;
                } catch (SimulationCancelledException e) {
                        // Simulation cancellation stops the optimization
                        throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
index 7b33ae04874937e02d3ac70757b66f3c837a31b4..e39d6e6a77a4eec4b1d5c2e553e082e0e0778fe5 100644 (file)
@@ -208,7 +208,7 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
         */
        protected void checkNaN(Coordinate c) {
                if (c.isNaN()) {
-                       throw new BugException("Simulation resulted in not-a-number (NaN) value, please report a bug.");
+                       throw new BugException("Simulation resulted in not-a-number (NaN) value, please report a bug, c=" + c);
                }
        }
        
@@ -221,7 +221,7 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
         */
        protected void checkNaN(Quaternion q) {
                if (q.isNaN()) {
-                       throw new BugException("Simulation resulted in not-a-number (NaN) value, please report a bug.");
+                       throw new BugException("Simulation resulted in not-a-number (NaN) value, please report a bug, q=" + q);
                }
        }
 }
index 8d5e27dbf94264479d1d27bea78074e420a57e0a..07020f2252c0c3eda1a3c64755c4d083a4b7206b 100644 (file)
@@ -8,6 +8,7 @@ import net.sf.openrocket.aerodynamics.FlightConditions;
 import net.sf.openrocket.aerodynamics.WarningSet;
 import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
+import net.sf.openrocket.simulation.exception.SimulationCalculationException;
 import net.sf.openrocket.simulation.exception.SimulationException;
 import net.sf.openrocket.simulation.listeners.SimulationListenerHelper;
 import net.sf.openrocket.startup.Application;
@@ -255,6 +256,13 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
                status.setSimulationTime(status.getSimulationTime() + store.timestep);
                
                status.setPreviousTimeStep(store.timestep);
+               
+               // Verify that values don't run out of range
+               if (status.getRocketVelocity().length2() > 1e18 ||
+                               status.getRocketPosition().length2() > 1e18 ||
+                               status.getRocketRotationVelocity().length2() > 1e18) {
+                       throw new SimulationCalculationException("Simulation values exceeded limits");
+               }
        }
        
        
@@ -360,7 +368,8 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
                        
                        // Compute acceleration in rocket coordinates
                        store.angularAcceleration = new Coordinate(momX / store.massData.getLongitudinalInertia(),
-                                               momY / store.massData.getLongitudinalInertia(), momZ / store.massData.getRotationalInertia());
+                                               momY / store.massData.getLongitudinalInertia(),
+                                               momZ / store.massData.getRotationalInertia());
                        
                        store.rollAcceleration = store.angularAcceleration.z;
                        // TODO: LOW: This should be hypot, but does it matter?
diff --git a/src/net/sf/openrocket/simulation/exception/SimulationCalculationException.java b/src/net/sf/openrocket/simulation/exception/SimulationCalculationException.java
new file mode 100644 (file)
index 0000000..3bd6115
--- /dev/null
@@ -0,0 +1,30 @@
+package net.sf.openrocket.simulation.exception;
+
+/**
+ * An exception that indicates that a computation problem has occurred during
+ * the simulation, for example that some values have exceed reasonable bounds.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class SimulationCalculationException extends SimulationException {
+       
+       public SimulationCalculationException() {
+               // TODO Auto-generated constructor stub
+       }
+       
+       public SimulationCalculationException(String message) {
+               super(message);
+               // TODO Auto-generated constructor stub
+       }
+       
+       public SimulationCalculationException(Throwable cause) {
+               super(cause);
+               // TODO Auto-generated constructor stub
+       }
+       
+       public SimulationCalculationException(String message, Throwable cause) {
+               super(message, cause);
+               // TODO Auto-generated constructor stub
+       }
+       
+}