From bc75b89ed43a676df56a654bfe5ad6f54cc83423 Mon Sep 17 00:00:00 2001 From: plaa Date: Fri, 12 Aug 2011 18:56:24 +0000 Subject: [PATCH] optimization updates git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@150 180e2498-e6e9-4542-8430-84ac67f01cd8 --- l10n/messages.properties | 3 +- .../aerodynamics/BarrowmanCalculator.java | 4 +- .../GeneralOptimizationDialog.java | 14 +++- .../optimization/OptimizationPlotDialog.java | 65 ++++++++++++++++--- .../openrocket/gui/main/ExceptionHandler.java | 4 +- .../gui/main/SimulationRunDialog.java | 37 +---------- .../parameters/SimulationBasedParameter.java | 4 ++ .../simulation/AbstractSimulationStepper.java | 4 +- .../simulation/RK4SimulationStepper.java | 11 +++- .../SimulationCalculationException.java | 30 +++++++++ 10 files changed, 122 insertions(+), 54 deletions(-) create mode 100644 src/net/sf/openrocket/simulation/exception/SimulationCalculationException.java diff --git a/l10n/messages.properties b/l10n/messages.properties index 692248a1..9353c4d8 100644 --- a/l10n/messages.properties +++ b/l10n/messages.properties @@ -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 diff --git a/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index ecafae1e..f15539c1 100644 --- a/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -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? diff --git a/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java b/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java index f60c720d..de5ad2ca 100644 --- a/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java @@ -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 diff --git a/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationPlotDialog.java b/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationPlotDialog.java index c3f9c0cb..ab9c9c94 100644 --- a/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationPlotDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationPlotDialog.java @@ -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 pathTooltips = new ArrayList(); 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); diff --git a/src/net/sf/openrocket/gui/main/ExceptionHandler.java b/src/net/sf/openrocket/gui/main/ExceptionHandler.java index a3d51de3..74f30917 100644 --- a/src/net/sf/openrocket/gui/main/ExceptionHandler.java +++ b/src/net/sf/openrocket/gui/main/ExceptionHandler.java @@ -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); diff --git a/src/net/sf/openrocket/gui/main/SimulationRunDialog.java b/src/net/sf/openrocket/gui/main/SimulationRunDialog.java index 1788515e..4405bdb5 100644 --- a/src/net/sf/openrocket/gui/main/SimulationRunDialog.java +++ b/src/net/sf/openrocket/gui/main/SimulationRunDialog.java @@ -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); diff --git a/src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java b/src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java index 807be942..e814dd30 100644 --- a/src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java +++ b/src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java @@ -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); diff --git a/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java b/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java index 7b33ae04..e39d6e6a 100644 --- a/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java +++ b/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java @@ -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); } } } diff --git a/src/net/sf/openrocket/simulation/RK4SimulationStepper.java b/src/net/sf/openrocket/simulation/RK4SimulationStepper.java index 8d5e27db..07020f22 100644 --- a/src/net/sf/openrocket/simulation/RK4SimulationStepper.java +++ b/src/net/sf/openrocket/simulation/RK4SimulationStepper.java @@ -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 index 00000000..3bd61154 --- /dev/null +++ b/src/net/sf/openrocket/simulation/exception/SimulationCalculationException.java @@ -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 + */ +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 + } + +} -- 2.30.2