From 88f84396d003160be73baa80b5f523eea0085ee5 Mon Sep 17 00:00:00 2001 From: Kevin Ruland Date: Mon, 14 Dec 2015 18:41:02 -0600 Subject: [PATCH] Initial refactoring of MotorInstance and ThrustCurveMotorInstance --- .../openrocket/importt/MotorMountHandler.java | 6 +- core/src/net/sf/openrocket/motor/Motor.java | 3 +- .../sf/openrocket/motor/MotorInstance.java | 255 ++++++++---------- .../src/net/sf/openrocket/motor/MotorSet.java | 4 +- .../sf/openrocket/motor/ThrustCurveMotor.java | 2 +- .../motor/ThrustCurveMotorInstance.java | 164 +++++------ .../motor/ThrustCurveMotorPlaceholder.java | 3 +- .../openrocket/rocketcomponent/BodyTube.java | 2 +- .../rocketcomponent/FlightConfiguration.java | 65 +---- .../IgnitionConfiguration.java | 72 +++++ .../rocketcomponent/IgnitionEvent.java | 34 +-- .../openrocket/rocketcomponent/InnerTube.java | 2 +- .../rocketcomponent/MotorConfiguration.java | 72 +++++ .../simulation/AbstractSimulationStepper.java | 4 +- .../BasicEventSimulationEngine.java | 10 +- .../sf/openrocket/simulation/MotorState.java | 31 +++ .../simulation/SimulationStatus.java | 36 ++- .../impl/ScriptingSimulationListener.java | 10 +- .../listeners/AbstractSimulationListener.java | 4 +- .../listeners/SimulationEventListener.java | 4 +- .../listeners/SimulationListenerHelper.java | 4 +- .../net/sf/openrocket/util/TestRockets.java | 15 +- .../sf/openrocket/utils/MotorCorrelation.java | 6 +- .../motor/ThrustCurveMotorTest.java | 5 +- .../rocketcomponent/ConfigurationTest.java | 8 +- .../MotorConfigurationPanel.java | 17 +- 26 files changed, 475 insertions(+), 363 deletions(-) create mode 100644 core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java create mode 100644 core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java create mode 100644 core/src/net/sf/openrocket/simulation/MotorState.java diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java index 7b7c8807e..09484754d 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java @@ -73,15 +73,17 @@ class MotorMountHandler extends AbstractElementHandler { } Motor motor = motorHandler.getMotor(warnings); - MotorInstance motorInstance = motor.getNewInstance(); + MotorInstance motorInstance = new MotorInstance(); + motorInstance.setMotor(motor); RocketComponent mountComponent = (RocketComponent)mount; + motorInstance.setMount(mount); motorInstance.setID( new MotorInstanceId(mountComponent.getID(), 1)); motorInstance.setEjectionDelay(motorHandler.getDelay(warnings)); mount.setMotorInstance(fcid, motorInstance); Rocket rkt = ((RocketComponent)mount).getRocket(); rkt.createFlightConfiguration(fcid); - + rkt.getFlightConfiguration(fcid).addMotor(motorInstance); return; } diff --git a/core/src/net/sf/openrocket/motor/Motor.java b/core/src/net/sf/openrocket/motor/Motor.java index d334d8d62..1b735da6a 100644 --- a/core/src/net/sf/openrocket/motor/Motor.java +++ b/core/src/net/sf/openrocket/motor/Motor.java @@ -1,5 +1,6 @@ package net.sf.openrocket.motor; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.util.Coordinate; public interface Motor { @@ -117,7 +118,7 @@ public interface Motor { public String getDigest(); - public MotorInstance getNewInstance(); + public MotorState getNewInstance(); public Coordinate getLaunchCG(); diff --git a/core/src/net/sf/openrocket/motor/MotorInstance.java b/core/src/net/sf/openrocket/motor/MotorInstance.java index 59797f96d..831c0b1ad 100644 --- a/core/src/net/sf/openrocket/motor/MotorInstance.java +++ b/core/src/net/sf/openrocket/motor/MotorInstance.java @@ -3,91 +3,77 @@ package net.sf.openrocket.motor; import java.util.EventObject; import java.util.List; -import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.rocketcomponent.FlightConfigurableParameter; import net.sf.openrocket.rocketcomponent.IgnitionEvent; import net.sf.openrocket.rocketcomponent.MotorMount; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.util.ArrayList; import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.util.Inertia; import net.sf.openrocket.util.StateChangeListener; /** * A single motor configuration. This includes the selected motor * and the ejection charge delay. */ -public abstract class MotorInstance implements FlightConfigurableParameter { +public class MotorInstance implements FlightConfigurableParameter { - // deferred to subclasses - //protected MotorMount mount = null; - //protected Motor motor = null; - - protected MotorInstanceId id = null; + protected MotorMount mount = null; + protected Motor motor = null; + protected Coordinate position = Coordinate.ZERO; protected double ejectionDelay = 0.0; + + protected MotorInstanceId id = null; + + protected boolean ignitionOveride = false; protected double ignitionDelay = 0.0; protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER; - protected Coordinate position = Coordinate.ZERO; protected double ignitionTime = 0.0; - protected int modID = 0; private final List listeners = new ArrayList(); - /** Immutable configuration with no motor and zero delay. */ - public static final MotorInstance EMPTY_INSTANCE = new MotorInstance(){ - @Override - public boolean equals( Object other ){ - return (this==other); - } - - @Override - public Motor getMotor() { - throw new UnsupportedOperationException("Retrieve a motor from an immutable no-motors instance"); - } - - @Override - public MotorMount getMount() { - throw new UnsupportedOperationException("Retrieve a mount from an immutable no-motors instance"); - } - - @Override - public double getThrust() { - throw new UnsupportedOperationException("Trying to get thrust from an empty motor instance."); - } - - @Override - public Coordinate getCM() { - throw new UnsupportedOperationException("Trying to get Center-of-Mass from an empty motor instance."); - } - - @Override - public double getPropellantMass(){ - throw new UnsupportedOperationException("Trying to get mass from an empty motor instance."); - } - - @Override - public double getLongitudinalInertia() { - throw new UnsupportedOperationException("Trying to get inertia from an empty motor instance."); - } - - @Override - public double getRotationalInertia() { - throw new UnsupportedOperationException("Trying to get inertia from an empty motor instance."); - } - - @Override - public void step(double time, double acceleration, AtmosphericConditions cond) { - throw new UnsupportedOperationException("Cannot step an abstract base class"); - } - }; + public MotorInstance( Motor motor ) { + this(); + this.motor = motor; + } - protected MotorInstance() { + public MotorInstance() { this.id = MotorInstanceId.EMPTY_ID; ejectionDelay = 0.0; - ignitionEvent = IgnitionEvent.NEVER; + ignitionEvent = IgnitionEvent.LAUNCH; ignitionDelay = 0.0; modID++; } + public MotorState getSimulationState() { + MotorState state = motor.getNewInstance(); + if( ignitionOveride ) { + state.setIgnitionTime( this.ignitionTime ); + state.setIgnitionEvent( this.ignitionEvent ); + state.setIgnitionDelay( this.ignitionDelay ); + state.setEjectionDelay( this.ejectionDelay ); + } else { + MotorInstance defInstance = mount.getDefaultMotorInstance(); + state.setIgnitionTime( defInstance.ignitionTime ); + state.setIgnitionEvent( defInstance.ignitionEvent ); + state.setIgnitionDelay( defInstance.ignitionDelay ); + state.setEjectionDelay( defInstance.ejectionDelay ); + } + state.setMount( mount ); + state.setId( id ); + return state; + } + + public boolean hasIgnitionOverride() { + return ignitionOveride; + } + + public boolean isActive() { + return motor != null; + } + public MotorInstanceId getID() { return this.id; } @@ -96,22 +82,30 @@ public abstract class MotorInstance implements FlightConfigurableParameter { public static final int DEFAULT_MOTOR_EVENT_TYPE = ComponentChangeEvent.MOTOR_CHANGE | ComponentChangeEvent.EVENT_CHANGE; public MotorSet(RocketComponent component ) { - super(component, DEFAULT_MOTOR_EVENT_TYPE, MotorInstance.EMPTY_INSTANCE); + super(component, DEFAULT_MOTOR_EVENT_TYPE, new MotorInstance()); } /** @@ -45,7 +45,7 @@ public class MotorSet extends ParameterSet { MotorInstance curInstance = this.map.get(loopFCID); String designation; - if( MotorInstance.EMPTY_INSTANCE == curInstance){ + if( null == curInstance.getMotor() ){ designation = "EMPTY_INSTANCE"; }else{ designation = curInstance.getMotor().getDesignation(curInstance.getEjectionDelay()); diff --git a/core/src/net/sf/openrocket/motor/ThrustCurveMotor.java b/core/src/net/sf/openrocket/motor/ThrustCurveMotor.java index c92b4b98c..23bd0d17f 100644 --- a/core/src/net/sf/openrocket/motor/ThrustCurveMotor.java +++ b/core/src/net/sf/openrocket/motor/ThrustCurveMotor.java @@ -250,7 +250,7 @@ public class ThrustCurveMotor implements Motor, Comparable, Se @Override - public MotorInstance getNewInstance() { + public ThrustCurveMotorInstance getNewInstance() { return new ThrustCurveMotorInstance(this); } diff --git a/core/src/net/sf/openrocket/motor/ThrustCurveMotorInstance.java b/core/src/net/sf/openrocket/motor/ThrustCurveMotorInstance.java index bcdc60efe..b59542894 100644 --- a/core/src/net/sf/openrocket/motor/ThrustCurveMotorInstance.java +++ b/core/src/net/sf/openrocket/motor/ThrustCurveMotorInstance.java @@ -1,19 +1,27 @@ package net.sf.openrocket.motor; import net.sf.openrocket.models.atmosphere.AtmosphericConditions; +import net.sf.openrocket.rocketcomponent.IgnitionEvent; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Inertia; import net.sf.openrocket.util.MathUtil; -import net.sf.openrocket.util.Utils; -public class ThrustCurveMotorInstance extends MotorInstance { +public class ThrustCurveMotorInstance implements MotorState { // private static final Logger log = LoggerFactory.getLogger(ThrustCurveMotorInstance.class); private int timeIndex = -1; protected MotorMount mount = null; + protected MotorInstanceId id = null; + private double ignitionTime; + private double ignitionDelay; + private IgnitionEvent ignitionEvent; + private double ejectionDelay; + + protected ThrustCurveMotor motor = null; // Previous time step value @@ -47,46 +55,88 @@ public class ThrustCurveMotorInstance extends MotorInstance { unitRotationalInertia = Inertia.filledCylinderRotational(source.getDiameter() / 2); unitLongitudinalInertia = Inertia.filledCylinderLongitudinal(source.getDiameter() / 2, source.getLength()); - this.id = MotorInstanceId.ERROR_ID; } @Override + public double getIgnitionTime() { + return ignitionTime; + } + + @Override + public void setIgnitionTime(double ignitionTime) { + this.ignitionTime = ignitionTime; + } + + @Override + public MotorMount getMount() { + return mount; + } + + @Override + public void setMount(MotorMount mount) { + this.mount = mount; + } + + @Override + public IgnitionEvent getIgnitionEvent() { + return ignitionEvent; + } + + @Override + public void setIgnitionEvent(IgnitionEvent event) { + this.ignitionEvent = event; + } + + @Override + public double getIgnitionDelay() { + return ignitionDelay; + } + + @Override + public void setIgnitionDelay(double delay) { + this.ignitionDelay = delay; + } + + @Override + public double getEjectionDelay() { + return ejectionDelay; + } + + @Override + public void setEjectionDelay(double delay) { + this.ejectionDelay = delay; + } + + @Override + public void setId(MotorInstanceId id) { + this.id = id; + } + + @Override + public MotorInstanceId getID() { + return id; + } + public double getTime() { return prevTime; } - @Override public Coordinate getCG() { return stepCG; } - @Override public Coordinate getCM() { return stepCG; } - @Override public double getPropellantMass(){ return (motor.getLaunchCG().weight - motor.getEmptyCG().weight); } - @Override - public Coordinate getOffset( ){ - if( null == mount ){ - return Coordinate.NaN; - }else{ - RocketComponent comp = (RocketComponent) mount; - double delta_x = comp.getLength() + mount.getMotorOverhang() - this.motor.getLength(); - return new Coordinate(delta_x, 0, 0); - } - } - - @Override public double getLongitudinalInertia() { return unitLongitudinalInertia * stepCG.weight; } - @Override public double getRotationalInertia() { return unitRotationalInertia * stepCG.weight; } @@ -100,60 +150,21 @@ public class ThrustCurveMotorInstance extends MotorInstance { public boolean isActive() { return prevTime < motor.getCutOffTime(); } - - @Override - public void setMotor(Motor motor) { - if( !( motor instanceof ThrustCurveMotor )){ - return; - } - if (Utils.equals(this.motor, motor)) { - return; - } - - this.motor = (ThrustCurveMotor)motor; - - fireChangeEvent(); - } - @Override public Motor getMotor(){ return this.motor; } - - @Override + public boolean isEmpty(){ return false; } - @Override - public MotorMount getMount() { - return this.mount; - } - - @Override - public void setMount(final MotorMount _mount) { - this.mount = _mount; - - } - - @Override - public void setEjectionDelay(double delay) { - if (MathUtil.equals(ejectionDelay, delay)) { - return; - } - this.ejectionDelay = delay; - fireChangeEvent(); - } - - @Override public void step(double nextTime, double acceleration, AtmosphericConditions cond) { if (MathUtil.equals(prevTime, nextTime)) { return; } - modID++; - double[] time = motor.getTimePoints(); double[] thrust = motor.getThrustPoints(); Coordinate[] cg = motor.getCGPoints(); @@ -220,23 +231,6 @@ public class ThrustCurveMotorInstance extends MotorInstance { prevTime = nextTime; } - @Override - public MotorInstance clone() { - ThrustCurveMotorInstance clone = new ThrustCurveMotorInstance( this.motor); - - clone.id = this.id; - clone.mount = this.mount; - clone.ignitionEvent = this.ignitionEvent; - clone.ignitionDelay = this.ignitionDelay; - clone.ejectionDelay = this.ejectionDelay; - clone.position = this.position; - clone.ignitionTime = Double.POSITIVE_INFINITY; - //clone.ignitionTime = this.ignitionTime; - - return clone; - } - - @Override public void reset(){ timeIndex = 0; prevTime = 0; @@ -246,25 +240,9 @@ public class ThrustCurveMotorInstance extends MotorInstance { stepCG = instCG; } - @Override - public String toDebug(){ - String prefix = " "; - StringBuilder sb = new StringBuilder(); - final RocketComponent mountComp = (RocketComponent)this.mount; - - sb.append(String.format("%sMotor= %s(%s)(in %s)\n", prefix, this.motor.getDesignation(), this.id.toShortKey(), mountComp.getName())); - sb.append(String.format("%s Ignite: %s at %+f\n",prefix, this.ignitionEvent.name, this.ignitionDelay)); - //sb.append(String.format("%s Eject at: %+f\n",prefix, this.ejectionDelay)); - sb.append(String.format("%s L:%f W:%f @:%f mm\n",prefix, motor.getLength(), motor.getDiameter(), this.position.multiply(1000).x )); - sb.append(String.format("%s currentTime: %f\n", prefix, this.prevTime)); - sb.append("\n"); - return sb.toString(); - } - @Override public String toString(){ - return this.motor.getDesignation() + this.id.toShortKey(); + return this.motor.getDesignation(); } } - \ No newline at end of file diff --git a/core/src/net/sf/openrocket/motor/ThrustCurveMotorPlaceholder.java b/core/src/net/sf/openrocket/motor/ThrustCurveMotorPlaceholder.java index 950cdba72..27d0346ff 100644 --- a/core/src/net/sf/openrocket/motor/ThrustCurveMotorPlaceholder.java +++ b/core/src/net/sf/openrocket/motor/ThrustCurveMotorPlaceholder.java @@ -1,5 +1,6 @@ package net.sf.openrocket.motor; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; @@ -74,7 +75,7 @@ public class ThrustCurveMotorPlaceholder implements Motor { } @Override - public MotorInstance getNewInstance() { + public MotorState getNewInstance() { throw new BugException("Called getInstance on PlaceholderMotor"); } diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java index 418ea8d7f..5a0811dc1 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java @@ -375,7 +375,7 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial @Override public void setMotorInstance(final FlightConfigurationID fcid, final MotorInstance newMotorInstance){ - if((null == newMotorInstance)||(newMotorInstance.equals( MotorInstance.EMPTY_INSTANCE ))){ + if((null == newMotorInstance)){ this.motors.set( fcid, null); }else{ if( null == newMotorInstance.getMount()){ diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index e0a694619..b61a7ed29 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -357,44 +357,6 @@ public class FlightConfiguration implements FlightConfigurableParameter \n", motorInstanceNumber+1, intanceCount, curMotor.getID().toShortKey())); - }else{ - buff.append( String.format( " ..[%2d/%2d](%6s) %-10s (in: %s)(id: %8s)\n", - motorInstanceNumber+1, intanceCount, - (curMotor.isActive()? "active": "inactv"),curMotor.getMotor().getDesignation(), - ((RocketComponent)curMotor.getMount()).getName(), curMotor.getID().toShortKey() )); - } - ++motorInstanceNumber; - } - return buff.toString(); - } - - public String getMotorsOneline(){ StringBuilder buff = new StringBuilder("["); boolean first = true; @@ -493,10 +455,6 @@ public class FlightConfiguration implements FlightConfigurableParameter motor.refpoint - Coordinate curMotorOffset = cloneInstance.getOffset(); - cloneInstance.setPosition( curMountLocation.add(curMotorOffset) ); - this.motors.put( cloneInstance.getID(), cloneInstance); - - motorInstanceNumber ++; - } - } } } diff --git a/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java new file mode 100644 index 000000000..567455aa9 --- /dev/null +++ b/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java @@ -0,0 +1,72 @@ +package net.sf.openrocket.rocketcomponent; + +import java.util.EventObject; +import java.util.List; + +import net.sf.openrocket.util.ArrayList; +import net.sf.openrocket.util.StateChangeListener; + +public class IgnitionConfiguration implements FlightConfigurableParameter { + + protected double ignitionDelay = 0.0; + protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER; + protected double ignitionTime = 0.0; + + private final List listeners = new ArrayList(); + + public double getIgnitionDelay() { + return ignitionDelay; + } + + public void setIgnitionDelay(double ignitionDelay) { + this.ignitionDelay = ignitionDelay; + fireChangeEvent(); + } + + public IgnitionEvent getIgnitionEvent() { + return ignitionEvent; + } + + public void setIgnitionEvent(IgnitionEvent ignitionEvent) { + this.ignitionEvent = ignitionEvent; + fireChangeEvent(); + } + + public double getIgnitionTime() { + return ignitionTime; + } + + public void setIgnitionTime(double ignitionTime) { + this.ignitionTime = ignitionTime; + fireChangeEvent(); + } + + @Override + public IgnitionConfiguration clone() { + IgnitionConfiguration clone = new IgnitionConfiguration(); + clone.ignitionDelay = this.ignitionDelay; + clone.ignitionEvent = this.ignitionEvent; + clone.ignitionTime = this.ignitionTime; + return clone; + } + + @Override + public void addChangeListener(StateChangeListener listener) { + listeners.add(listener); + } + + @Override + public void removeChangeListener(StateChangeListener listener) { + listeners.remove(listener); + } + + private void fireChangeEvent() { + EventObject event = new EventObject(this); + Object[] list = listeners.toArray(); + for (Object l : list) { + ((StateChangeListener) l).stateChanged(event); + } + } + + +} diff --git a/core/src/net/sf/openrocket/rocketcomponent/IgnitionEvent.java b/core/src/net/sf/openrocket/rocketcomponent/IgnitionEvent.java index 8a0eb7a08..9605a8cb6 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/IgnitionEvent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/IgnitionEvent.java @@ -9,23 +9,23 @@ import net.sf.openrocket.startup.Application; public enum IgnitionEvent { // //// Automatic (launch or ejection charge) -// AUTOMATIC( "AUTOMATIC", "MotorMount.IgnitionEvent.AUTOMATIC"){ -// @Override -// public boolean isActivationEvent(FlightEvent e, RocketComponent source) { -// int count = source.getRocket().getStageCount(); -// AxialStage stage = (AxialStage)source; -// -// if ( stage instanceof ParallelStage ){ -// return LAUNCH.isActivationEvent(e, source); -// }else if (????){ -// // no good option here. The non-sequential nature of -// // parallel stages prevents us from using the simple test as previousyl -// return LAUNCH.isActivationEvent(e, source); -// } else { -// return EJECTION_CHARGE.isActivationEvent(e, source); -// } -// } -// }, + AUTOMATIC( "AUTOMATIC", "MotorMount.IgnitionEvent.AUTOMATIC"){ + @Override + public boolean isActivationEvent(FlightEvent e, RocketComponent source) { + int count = source.getRocket().getStageCount(); + AxialStage stage = (AxialStage)source.getStage(); + + if ( stage instanceof ParallelStage ){ + return LAUNCH.isActivationEvent(e, source); + }else if (stage.getStageNumber() == count -1){ + // no good option here. The non-sequential nature of + // parallel stages prevents us from using the simple test as previousyl + return LAUNCH.isActivationEvent(e, source); + } else { + return EJECTION_CHARGE.isActivationEvent(e, source); + } + } + }, LAUNCH ( "LAUNCH", "MotorMount.IgnitionEvent.LAUNCH"){ @Override public boolean isActivationEvent( FlightEvent fe, RocketComponent source){ diff --git a/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java b/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java index 5b7fb50b8..36af5d3e9 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java @@ -283,7 +283,7 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra @Override public void setMotorInstance(final FlightConfigurationID fcid, final MotorInstance newMotorInstance){ - if((null == newMotorInstance)||(newMotorInstance== MotorInstance.EMPTY_INSTANCE )){ + if((null == newMotorInstance)){ this.motors.set( fcid, null); }else{ if( null == newMotorInstance.getMount()){ diff --git a/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java new file mode 100644 index 000000000..f115c9af9 --- /dev/null +++ b/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java @@ -0,0 +1,72 @@ +package net.sf.openrocket.rocketcomponent; + +import java.util.EventObject; +import java.util.List; + +import net.sf.openrocket.motor.Motor; +import net.sf.openrocket.util.ArrayList; +import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.util.StateChangeListener; + +public class MotorConfiguration implements FlightConfigurableParameter { + + protected Coordinate position = Coordinate.ZERO; + protected double ejectionDelay = 0.0; + protected Motor motor = null; + + private final List listeners = new ArrayList(); + + public Coordinate getPosition() { + return position; + } + + public void setPosition(Coordinate position) { + this.position = position; + fireChangeEvent(); + } + + public double getEjectionDelay() { + return ejectionDelay; + } + + public void setEjectionDelay(double ejectionDelay) { + this.ejectionDelay = ejectionDelay; + fireChangeEvent(); + } + + public Motor getMotor() { + return motor; + } + + public void setMotor(Motor motor) { + this.motor = motor; + fireChangeEvent(); + } + + @Override + public MotorConfiguration clone() { + MotorConfiguration clone = new MotorConfiguration(); + clone.position = this.position; + clone.ejectionDelay = this.ejectionDelay; + return clone; + } + + @Override + public void addChangeListener(StateChangeListener listener) { + listeners.add(listener); + } + + @Override + public void removeChangeListener(StateChangeListener listener) { + listeners.remove(listener); + } + + private void fireChangeEvent() { + EventObject event = new EventObject(this); + Object[] list = listeners.toArray(); + for (Object l : list) { + ((StateChangeListener) l).stateChanged(event); + } + } + +} diff --git a/core/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java b/core/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java index 8e751f4f1..890bb02c6 100644 --- a/core/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java +++ b/core/src/net/sf/openrocket/simulation/AbstractSimulationStepper.java @@ -172,8 +172,8 @@ public abstract class AbstractSimulationStepper implements SimulationStepper { thrust = 0; final double currentTime = status.getSimulationTime() + timestep; - Collection activeMotorList = status.getConfiguration().getActiveMotors(); - for (MotorInstance currentMotorInstance : activeMotorList ) { + Collection activeMotorList = status.getActiveMotors(); + for (MotorState currentMotorInstance : activeMotorList ) { // old: transplanted from MotorInstanceConfiguration double instanceTime = currentTime - currentMotorInstance.getIgnitionTime(); if (instanceTime >= 0) { diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java index 91d0f45c9..1f04c496c 100644 --- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java +++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java @@ -195,7 +195,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { // Check for burnt out motors - for( MotorInstance motor : currentStatus.getConfiguration().getAllMotors()){ + for( MotorState motor : currentStatus.getAllMotors()){ MotorInstanceId motorId = motor.getID(); if (!motor.isActive() && currentStatus.addBurntOutMotor(motorId)) { addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, currentStatus.getSimulationTime(), @@ -276,7 +276,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { if (event.getType() == FlightEvent.Type.IGNITION) { MotorMount mount = (MotorMount) event.getSource(); MotorInstanceId motorId = (MotorInstanceId) event.getData(); - MotorInstance instance = currentStatus.getMotor(motorId); + MotorState instance = currentStatus.getMotor(motorId); if (!SimulationListenerHelper.fireMotorIgnition(currentStatus, motorId, mount, instance)) { continue; } @@ -289,7 +289,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { } // Check for motor ignition events, add ignition events to queue - for (MotorInstance inst : currentStatus.getFlightConfiguration().getActiveMotors() ){ + for (MotorState inst : currentStatus.getActiveMotors() ){ IgnitionEvent ignitionEvent = inst.getIgnitionEvent(); MotorMount mount = inst.getMount(); RocketComponent component = (RocketComponent) mount; @@ -342,7 +342,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { case IGNITION: { // Ignite the motor MotorInstanceId motorId = (MotorInstanceId) event.getData(); - MotorInstance inst = currentStatus.getMotor( motorId); + MotorState inst = currentStatus.getMotor( motorId); inst.setIgnitionTime(event.getTime()); //System.err.println("Igniting motor: "+inst.getMotor().getDesignation()+" @"+currentStatus.getSimulationTime()); @@ -373,7 +373,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { } // Add ejection charge event MotorInstanceId motorId = (MotorInstanceId) event.getData(); - MotorInstance motor = currentStatus.getMotor( motorId); + MotorState motor = currentStatus.getMotor( motorId); double delay = motor.getEjectionDelay(); if (delay != Motor.PLUGGED) { addEvent(new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, currentStatus.getSimulationTime() + delay, diff --git a/core/src/net/sf/openrocket/simulation/MotorState.java b/core/src/net/sf/openrocket/simulation/MotorState.java new file mode 100644 index 000000000..a1bde98d0 --- /dev/null +++ b/core/src/net/sf/openrocket/simulation/MotorState.java @@ -0,0 +1,31 @@ +package net.sf.openrocket.simulation; + +import net.sf.openrocket.models.atmosphere.AtmosphericConditions; +import net.sf.openrocket.motor.MotorInstanceId; +import net.sf.openrocket.rocketcomponent.IgnitionEvent; +import net.sf.openrocket.rocketcomponent.MotorMount; + +public interface MotorState { + + public void step(double nextTime, double acceleration, AtmosphericConditions cond); + public double getThrust(); + public boolean isActive(); + + public double getIgnitionTime(); + public void setIgnitionTime( double ignitionTime ); + + public void setMount(MotorMount mount); + public MotorMount getMount(); + + public void setId(MotorInstanceId id); + public MotorInstanceId getID(); + + public IgnitionEvent getIgnitionEvent(); + public void setIgnitionEvent( IgnitionEvent event ); + + public double getIgnitionDelay(); + public void setIgnitionDelay( double delay ); + + public double getEjectionDelay(); + public void setEjectionDelay( double delay); +} diff --git a/core/src/net/sf/openrocket/simulation/SimulationStatus.java b/core/src/net/sf/openrocket/simulation/SimulationStatus.java index b8b87b701..dcbe2727d 100644 --- a/core/src/net/sf/openrocket/simulation/SimulationStatus.java +++ b/core/src/net/sf/openrocket/simulation/SimulationStatus.java @@ -1,7 +1,10 @@ package net.sf.openrocket.simulation; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -27,7 +30,7 @@ import net.sf.openrocket.util.WorldCoordinate; */ public class SimulationStatus implements Monitorable { - + private SimulationConditions simulationConditions; private FlightConfiguration configuration; private FlightDataBranch flightData; @@ -48,6 +51,7 @@ public class SimulationStatus implements Monitorable { // Set of burnt out motors Set motorBurntOut = new HashSet(); + List motorState = new ArrayList(); /** Nanosecond time when the simulation was started. */ private long simulationStartWallTime = Long.MIN_VALUE; @@ -144,6 +148,9 @@ public class SimulationStatus implements Monitorable { this.launchRodCleared = false; this.apogeeReached = false; + for( MotorInstance motorInstance : this.configuration.getActiveMotors() ) { + this.motorState.add( motorInstance.getSimulationState() ); + } this.warnings = new WarningSet(); } @@ -183,6 +190,10 @@ public class SimulationStatus implements Monitorable { this.deployedRecoveryDevices.clear(); this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices); + // FIXME - is this right? + this.motorState.clear(); + this.motorState.addAll(orig.motorState); + this.eventQueue.clear(); this.eventQueue.addAll(orig.eventQueue); @@ -214,6 +225,20 @@ public class SimulationStatus implements Monitorable { this.configuration = configuration; } + public Collection getAllMotors() { + return motorState; + } + + public Collection getActiveMotors() { + List activeList = new ArrayList(); + for( MotorState inst : this.motorState ){ + if( inst.isActive() ){ + activeList.add( inst ); + } + } + + return activeList; + } public FlightConfiguration getConfiguration() { return configuration; @@ -235,8 +260,13 @@ public class SimulationStatus implements Monitorable { return flightData; } - public MotorInstance getMotor( final MotorInstanceId motorId ){ - return this.getFlightConfiguration().getMotorInstance(motorId); + public MotorState getMotor( final MotorInstanceId motorId ){ + for( MotorState state : motorState ) { + if ( motorId.equals(state.getID() )) { + return state; + } + } + return null; } public double getPreviousTimeStep() { diff --git a/core/src/net/sf/openrocket/simulation/extension/impl/ScriptingSimulationListener.java b/core/src/net/sf/openrocket/simulation/extension/impl/ScriptingSimulationListener.java index 21e7f96aa..0cc613708 100644 --- a/core/src/net/sf/openrocket/simulation/extension/impl/ScriptingSimulationListener.java +++ b/core/src/net/sf/openrocket/simulation/extension/impl/ScriptingSimulationListener.java @@ -6,16 +6,19 @@ import java.util.Set; import javax.script.Invocable; import javax.script.ScriptException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.sf.openrocket.aerodynamics.AerodynamicForces; import net.sf.openrocket.aerodynamics.FlightConditions; import net.sf.openrocket.masscalc.MassData; import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.motor.MotorInstanceId; -import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.simulation.AccelerationData; import net.sf.openrocket.simulation.FlightEvent; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.simulation.exception.SimulationListenerException; @@ -25,9 +28,6 @@ import net.sf.openrocket.simulation.listeners.SimulationListener; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class ScriptingSimulationListener implements SimulationListener, SimulationComputationListener, SimulationEventListener, Cloneable { private final static Logger logger = LoggerFactory.getLogger(ScriptingSimulationListener.class); @@ -105,7 +105,7 @@ public class ScriptingSimulationListener implements SimulationListener, Simulati } @Override - public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorInstance instance) throws SimulationException { + public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorState instance) throws SimulationException { return invoke(Boolean.class, true, "motorIgnition", status, motorId, mount, instance); } diff --git a/core/src/net/sf/openrocket/simulation/listeners/AbstractSimulationListener.java b/core/src/net/sf/openrocket/simulation/listeners/AbstractSimulationListener.java index 03c55bf0a..bc875c0c6 100644 --- a/core/src/net/sf/openrocket/simulation/listeners/AbstractSimulationListener.java +++ b/core/src/net/sf/openrocket/simulation/listeners/AbstractSimulationListener.java @@ -5,11 +5,11 @@ import net.sf.openrocket.aerodynamics.FlightConditions; import net.sf.openrocket.masscalc.MassData; import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.motor.MotorInstanceId; -import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.simulation.AccelerationData; import net.sf.openrocket.simulation.FlightEvent; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.util.BugException; @@ -72,7 +72,7 @@ public class AbstractSimulationListener implements SimulationListener, Simulatio } @Override - public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorInstance instance) throws SimulationException { + public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorState instance) throws SimulationException { return true; } diff --git a/core/src/net/sf/openrocket/simulation/listeners/SimulationEventListener.java b/core/src/net/sf/openrocket/simulation/listeners/SimulationEventListener.java index 5c0e481f8..c725309ec 100644 --- a/core/src/net/sf/openrocket/simulation/listeners/SimulationEventListener.java +++ b/core/src/net/sf/openrocket/simulation/listeners/SimulationEventListener.java @@ -1,10 +1,10 @@ package net.sf.openrocket.simulation.listeners; import net.sf.openrocket.motor.MotorInstanceId; -import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.simulation.FlightEvent; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.exception.SimulationException; @@ -44,7 +44,7 @@ public interface SimulationEventListener { * @return true to ignite the motor, false to abort ignition */ public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, - MotorInstance instance) throws SimulationException; + MotorState instance) throws SimulationException; /** diff --git a/core/src/net/sf/openrocket/simulation/listeners/SimulationListenerHelper.java b/core/src/net/sf/openrocket/simulation/listeners/SimulationListenerHelper.java index d6417471f..bd004c743 100644 --- a/core/src/net/sf/openrocket/simulation/listeners/SimulationListenerHelper.java +++ b/core/src/net/sf/openrocket/simulation/listeners/SimulationListenerHelper.java @@ -10,11 +10,11 @@ import net.sf.openrocket.aerodynamics.Warning; import net.sf.openrocket.masscalc.MassData; import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.motor.MotorInstanceId; -import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.simulation.AccelerationData; import net.sf.openrocket.simulation.FlightEvent; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.util.Coordinate; @@ -168,7 +168,7 @@ public class SimulationListenerHelper { * @return true to handle the event normally, false to skip event. */ public static boolean fireMotorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, - MotorInstance instance) throws SimulationException { + MotorState instance) throws SimulationException { boolean b; int modID = status.getModID(); // Contains also motor instance diff --git a/core/src/net/sf/openrocket/util/TestRockets.java b/core/src/net/sf/openrocket/util/TestRockets.java index 5ba0a6a40..7ddbccce8 100644 --- a/core/src/net/sf/openrocket/util/TestRockets.java +++ b/core/src/net/sf/openrocket/util/TestRockets.java @@ -101,7 +101,7 @@ public class TestRockets { new Coordinate[] { new Coordinate(.311, 0, 0, 4.808),new Coordinate(.311, 0, 0, 3.389),new Coordinate(.311, 0, 0, 1.970)}, "digest M1350 test"); - return mtr.getNewInstance(); + return new MotorInstance(mtr); } // This function is used for unit, integration tests, DO NOT CHANGE (without updating tests). @@ -117,7 +117,7 @@ public class TestRockets { new Coordinate[] { new Coordinate(.062, 0, 0, 0.123),new Coordinate(.062, 0, 0, .0935),new Coordinate(.062, 0, 0, 0.064)}, "digest G77 test"); - return mtr.getNewInstance(); + return new MotorInstance(mtr); } // @@ -420,10 +420,11 @@ public class TestRockets { new Coordinate(0.0035,0,0,30.0), new Coordinate(0.0035,0,0,21.0)}, "digest_D12"); - MotorInstance inst = motor.getNewInstance(); + MotorInstance inst = new MotorInstance(motor); inst.setEjectionDelay(5); return inst; } + public static Rocket makeSmallFlyable() { double noseconeLength = 0.10, noseconeRadius = 0.01; double bodytubeLength = 0.20, bodytubeRadius = 0.01, bodytubeThickness = 0.001; @@ -465,7 +466,7 @@ public class TestRockets { FlightConfigurationID fcid = config.getFlightConfigurationID(); ThrustCurveMotor motor = getTestMotor(); - MotorInstance instance = motor.getNewInstance(); + MotorInstance instance = new MotorInstance(motor); instance.setEjectionDelay(5); bodytube.setMotorInstance(fcid, instance); @@ -979,7 +980,7 @@ public class TestRockets { // create motor config and add a motor to it ThrustCurveMotor motor = getTestMotor(); - MotorInstance motorInst = motor.getNewInstance(); + MotorInstance motorInst = new MotorInstance(motor); motorInst.setEjectionDelay(5); // add motor config to inner tube (motor mount) @@ -1014,7 +1015,7 @@ public class TestRockets { // create motor config and add a motor to it ThrustCurveMotor motor = getTestMotor(); - MotorInstance motorConfig = motor.getNewInstance(); + MotorInstance motorConfig = new MotorInstance(motor); motorConfig.setEjectionDelay(5); // add motor config to inner tube (motor mount) @@ -1171,7 +1172,7 @@ public class TestRockets { bodyTube.addChild(innerTube); // make inner tube with motor mount flag set - MotorInstance inst = getTestMotor().getNewInstance(); + MotorInstance inst = new MotorInstance(getTestMotor()); innerTube.setMotorInstance(fcid, inst); // set ignition parameters for motor mount diff --git a/core/src/net/sf/openrocket/utils/MotorCorrelation.java b/core/src/net/sf/openrocket/utils/MotorCorrelation.java index 93dc1d75a..e1c5eb846 100644 --- a/core/src/net/sf/openrocket/utils/MotorCorrelation.java +++ b/core/src/net/sf/openrocket/utils/MotorCorrelation.java @@ -10,8 +10,8 @@ import net.sf.openrocket.file.motor.GeneralMotorLoader; import net.sf.openrocket.file.motor.MotorLoader; import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.motor.Motor; -import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.motor.ThrustCurveMotor; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.MathUtil; @@ -61,8 +61,8 @@ public class MotorCorrelation { * @return the scaled cross-correlation of the two thrust curves. */ public static double crossCorrelation(Motor motor1, Motor motor2) { - MotorInstance m1 = motor1.getNewInstance(); - MotorInstance m2 = motor2.getNewInstance(); + MotorState m1 = motor1.getNewInstance(); + MotorState m2 = motor2.getNewInstance(); AtmosphericConditions cond = new AtmosphericConditions(); diff --git a/core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java b/core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java index 43115005d..60be43c6c 100644 --- a/core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java +++ b/core/test/net/sf/openrocket/motor/ThrustCurveMotorTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; +import net.sf.openrocket.simulation.MotorState; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Inertia; @@ -41,7 +42,7 @@ public class ThrustCurveMotorTest { @Test public void testInstance() { - MotorInstance instance = motor.getNewInstance(); + ThrustCurveMotorInstance instance = motor.getNewInstance(); verify(instance, 0, 0.05, 0.02); instance.step(0.0, 0, null); @@ -63,7 +64,7 @@ public class ThrustCurveMotorTest { verify(instance, 0, 0.03, 0.03); } - private void verify(MotorInstance instance, double thrust, double mass, double cgx) { + private void verify(ThrustCurveMotorInstance instance, double thrust, double mass, double cgx) { assertEquals("Testing thrust", thrust, instance.getThrust(), EPS); assertEquals("Testing mass", mass, instance.getCG().weight, EPS); assertEquals("Testing cg x", cgx, instance.getCG().x, EPS); diff --git a/core/test/net/sf/openrocket/rocketcomponent/ConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/ConfigurationTest.java index f063c18b4..7ba1cb279 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/ConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/ConfigurationTest.java @@ -195,8 +195,8 @@ public class ConfigurationTest extends BaseTestCase { // test explicitly setting all stages up to second stage active config.setOnlyStage(1); - assertThat(config.toStageListDetail() + "Setting single stage active: ", config.isStageActive(0), equalTo(false)); - assertThat(config.toStageListDetail() + "Setting single stage active: ", config.isStageActive(1), equalTo(true)); + assertThat("Setting single stage active: ", config.isStageActive(0), equalTo(false)); + assertThat("Setting single stage active: ", config.isStageActive(1), equalTo(true)); config.clearStage(0); assertThat(" deactivate stage #0: ", config.isStageActive(0), equalTo(false)); @@ -560,7 +560,7 @@ public class ConfigurationTest extends BaseTestCase { InnerTube sustainerMount = (InnerTube) rocket.getChild(0).getChild(1).getChild(3); sustainerMount.setMotorMount(true); - sustainerMount.setMotorInstance(fcid, sustainerMotor.getNewInstance()); + sustainerMount.setMotorInstance(fcid, new MotorInstance(sustainerMotor)); } { @@ -577,7 +577,7 @@ public class ConfigurationTest extends BaseTestCase { "digest D21 test"); InnerTube boosterMount = (InnerTube) rocket.getChild(1).getChild(0).getChild(2); boosterMount.setMotorMount(true); - boosterMount.setMotorInstance(fcid, boosterMotor.getNewInstance()); + boosterMount.setMotorInstance(fcid, new MotorInstance(boosterMotor)); boosterMount.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[1]); // double-mount } return rocket; diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java index bf727a413..70e35e014 100644 --- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java @@ -215,7 +215,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel Motor mtr = motorChooserDialog.getSelectedMotor(); double d = motorChooserDialog.getSelectedDelay(); if (mtr != null) { - MotorInstance curInstance = mtr.getNewInstance(); + MotorInstance curInstance = new MotorInstance(mtr); curInstance.setEjectionDelay(d); curInstance.setIgnitionEvent( IgnitionEvent.NEVER); curMount.setMotorInstance( fcid, curInstance); @@ -262,9 +262,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel } MotorInstance curInstance = curMount.getMotorInstance(fcid); - MotorInstance defInstance = curInstance.getMount().getDefaultMotorInstance(); - curInstance.setIgnitionDelay( defInstance.getIgnitionDelay()); - curInstance.setIgnitionEvent( defInstance.getIgnitionEvent()); + curInstance.useDefaultIgnition(); fireTableDataChanged(); } @@ -315,14 +313,19 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel IgnitionEvent ignitionEvent = curInstance.getIgnitionEvent(); Double ignitionDelay = curInstance.getIgnitionDelay(); - boolean isDefault = (defInstance.getIgnitionEvent() == curInstance.getIgnitionEvent()); - + boolean useDefault = !curInstance.hasIgnitionOverride(); + + if ( useDefault ) { + ignitionEvent = defInstance.getIgnitionEvent(); + ignitionDelay = defInstance.getIgnitionDelay(); + } + JLabel label = new JLabel(); String str = trans.get("MotorMount.IgnitionEvent.short." + ignitionEvent.name()); if (ignitionEvent != IgnitionEvent.NEVER && ignitionDelay > 0.001) { str = str + " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(ignitionDelay); } - if (isDefault) { + if (useDefault) { shaded(label); String def = trans.get("MotorConfigurationTableModel.table.ignition.default"); str = def.replace("{0}", str);