Initial refactoring of MotorInstance and ThrustCurveMotorInstance

This commit is contained in:
Kevin Ruland 2015-12-14 18:41:02 -06:00
parent d12f7b596f
commit 88f84396d0
26 changed files with 475 additions and 363 deletions

View File

@ -73,15 +73,17 @@ class MotorMountHandler extends AbstractElementHandler {
} }
Motor motor = motorHandler.getMotor(warnings); Motor motor = motorHandler.getMotor(warnings);
MotorInstance motorInstance = motor.getNewInstance(); MotorInstance motorInstance = new MotorInstance();
motorInstance.setMotor(motor);
RocketComponent mountComponent = (RocketComponent)mount; RocketComponent mountComponent = (RocketComponent)mount;
motorInstance.setMount(mount);
motorInstance.setID( new MotorInstanceId(mountComponent.getID(), 1)); motorInstance.setID( new MotorInstanceId(mountComponent.getID(), 1));
motorInstance.setEjectionDelay(motorHandler.getDelay(warnings)); motorInstance.setEjectionDelay(motorHandler.getDelay(warnings));
mount.setMotorInstance(fcid, motorInstance); mount.setMotorInstance(fcid, motorInstance);
Rocket rkt = ((RocketComponent)mount).getRocket(); Rocket rkt = ((RocketComponent)mount).getRocket();
rkt.createFlightConfiguration(fcid); rkt.createFlightConfiguration(fcid);
rkt.getFlightConfiguration(fcid).addMotor(motorInstance);
return; return;
} }

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.motor; package net.sf.openrocket.motor;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
public interface Motor { public interface Motor {
@ -117,7 +118,7 @@ public interface Motor {
public String getDigest(); public String getDigest();
public MotorInstance getNewInstance(); public MotorState getNewInstance();
public Coordinate getLaunchCG(); public Coordinate getLaunchCG();

View File

@ -3,91 +3,77 @@ package net.sf.openrocket.motor;
import java.util.EventObject; import java.util.EventObject;
import java.util.List; import java.util.List;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.rocketcomponent.FlightConfigurableParameter; import net.sf.openrocket.rocketcomponent.FlightConfigurableParameter;
import net.sf.openrocket.rocketcomponent.IgnitionEvent; import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount; 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.ArrayList;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Inertia;
import net.sf.openrocket.util.StateChangeListener; import net.sf.openrocket.util.StateChangeListener;
/** /**
* A single motor configuration. This includes the selected motor * A single motor configuration. This includes the selected motor
* and the ejection charge delay. * and the ejection charge delay.
*/ */
public abstract class MotorInstance implements FlightConfigurableParameter<MotorInstance> { public class MotorInstance implements FlightConfigurableParameter<MotorInstance> {
// deferred to subclasses protected MotorMount mount = null;
//protected MotorMount mount = null; protected Motor motor = null;
//protected Motor motor = null; protected Coordinate position = Coordinate.ZERO;
protected MotorInstanceId id = null;
protected double ejectionDelay = 0.0; protected double ejectionDelay = 0.0;
protected MotorInstanceId id = null;
protected boolean ignitionOveride = false;
protected double ignitionDelay = 0.0; protected double ignitionDelay = 0.0;
protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER; protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER;
protected Coordinate position = Coordinate.ZERO;
protected double ignitionTime = 0.0; protected double ignitionTime = 0.0;
protected int modID = 0; protected int modID = 0;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>(); private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
/** Immutable configuration with no motor and zero delay. */ public MotorInstance( Motor motor ) {
public static final MotorInstance EMPTY_INSTANCE = new MotorInstance(){ this();
@Override this.motor = motor;
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");
}
};
protected MotorInstance() { public MotorInstance() {
this.id = MotorInstanceId.EMPTY_ID; this.id = MotorInstanceId.EMPTY_ID;
ejectionDelay = 0.0; ejectionDelay = 0.0;
ignitionEvent = IgnitionEvent.NEVER; ignitionEvent = IgnitionEvent.LAUNCH;
ignitionDelay = 0.0; ignitionDelay = 0.0;
modID++; 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() { public MotorInstanceId getID() {
return this.id; return this.id;
} }
@ -96,22 +82,30 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
this.id = _id; this.id = _id;
} }
public void setMotor(Motor motor){
this.motor = motor;
fireChangeEvent();
}
public Motor getMotor() {
return motor;
}
public MotorMount getMount() {
return mount;
}
public void setMount(MotorMount mount) {
this.mount = mount;
}
public double getEjectionDelay() { public double getEjectionDelay() {
return this.ejectionDelay; return this.ejectionDelay;
} }
public void setMotor(Motor motor){} public void setEjectionDelay(double delay) {
this.ejectionDelay = delay;
public abstract Motor getMotor(); fireChangeEvent();
public void setEjectionDelay(double delay) {}
public abstract MotorMount getMount();
public void setMount(final MotorMount _mount){}
public Coordinate getOffset(){
return this.position;
} }
public Coordinate getPosition() { public Coordinate getPosition() {
@ -121,15 +115,22 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
public void setPosition(Coordinate _position) { public void setPosition(Coordinate _position) {
this.position = _position; this.position = _position;
modID++; modID++;
fireChangeEvent();
} }
public double getIgnitionTime() { public double getIgnitionTime() {
return this.ignitionTime; return this.ignitionTime;
} }
public void useDefaultIgnition() {
this.ignitionOveride = false;
}
public void setIgnitionTime(double _time) { public void setIgnitionTime(double _time) {
this.ignitionTime = _time; this.ignitionTime = _time;
this.ignitionOveride = true;
modID++; modID++;
fireChangeEvent();
} }
public double getIgnitionDelay() { public double getIgnitionDelay() {
@ -138,6 +139,8 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
public void setIgnitionDelay(final double _delay) { public void setIgnitionDelay(final double _delay) {
this.ignitionDelay = _delay; this.ignitionDelay = _delay;
this.ignitionOveride = true;
fireChangeEvent();
} }
public IgnitionEvent getIgnitionEvent() { public IgnitionEvent getIgnitionEvent() {
@ -146,66 +149,47 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
public void setIgnitionEvent(final IgnitionEvent _event) { public void setIgnitionEvent(final IgnitionEvent _event) {
this.ignitionEvent = _event; this.ignitionEvent = _event;
this.ignitionOveride = true;
fireChangeEvent();
} }
/** public Coordinate getOffset( ){
* Step the motor instance forward in time. if( null == mount ){
* return Coordinate.NaN;
* @param time the time to step to, from motor ignition. }else{
* @param acceleration the average acceleration during the step. RocketComponent comp = (RocketComponent) mount;
* @param cond the average atmospheric conditions during the step. double delta_x = comp.getLength() + mount.getMotorOverhang() - this.motor.getLength();
*/ return new Coordinate(delta_x, 0, 0);
public abstract void step(double newTime, double acceleration, AtmosphericConditions cond); }
/**
* Return the time to which this motor has been stepped.
* @return the current step time.
*/
public double getTime() {
return 0;
} }
/** public double getLongitudinalInertia() {
* Return the average thrust during the last step. if ( motor != null ) {
*/ double unitLongitudinalInertia = Inertia.filledCylinderLongitudinal(motor.getDiameter() / 2, motor.getLength());
public abstract double getThrust(); return unitLongitudinalInertia * Coordinate.ZERO.weight;
}
/** return 0.0;
* Return the average CG location during the last step.
*/
public Coordinate getCG() {
return this.getCM();
} }
public abstract Coordinate getCM(); public double getRotationalInertia() {
if ( motor != null ) {
public abstract double getPropellantMass(); double unitRotationalInertia = Inertia.filledCylinderRotational(motor.getDiameter() / 2);
return unitRotationalInertia * Coordinate.ZERO.weight;
/** }
* Return the average longitudinal moment of inertia during the last step. return 0.0;
* This is the actual inertia, not the unit inertia!
*/
public abstract double getLongitudinalInertia();
/**
* Return the average rotational moment of inertia during the last step.
* This is the actual inertia, not the unit inertia!
*/
public abstract double getRotationalInertia();
/**
* Return whether this motor still produces thrust. If this method returns false
* the motor has burnt out, and will not produce any significant thrust anymore.
*/
public boolean isActive() {
return false;
}
public boolean isEmpty(){
return true;
} }
public double getPropellantMass(){
if ( motor != null ) {
return (motor.getLaunchCG().weight - motor.getEmptyCG().weight);
}
return 0.0;
}
public boolean isEmpty(){
return motor == null;
}
public boolean hasMotor(){ public boolean hasMotor(){
return ! this.isEmpty(); return ! this.isEmpty();
} }
@ -222,7 +206,7 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
} }
return false; return false;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return this.id.hashCode(); return this.id.hashCode();
@ -233,8 +217,16 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
* identical to this instance and can be used independently from this one. * identical to this instance and can be used independently from this one.
*/ */
@Override @Override
public MotorInstance clone( ){ public MotorInstance clone( ) {
return EMPTY_INSTANCE; MotorInstance clone = new MotorInstance();
clone.motor = this.motor;
clone.mount = this.mount;
clone.ejectionDelay = this.ejectionDelay;
clone.ignitionOveride = this.ignitionOveride;
clone.ignitionDelay = this.ignitionDelay;
clone.ignitionEvent = this.ignitionEvent;
clone.ignitionTime = this.ignitionTime;
return clone;
} }
@Override @Override
@ -255,19 +247,8 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
} }
} }
public String toDebug(){ return toString();}
@Override
public String toString(){
return MotorInstanceId.EMPTY_ID.getComponentId();
}
public int getModID() { public int getModID() {
return modID; return modID;
} }
public void reset() {
}
} }

View File

@ -13,7 +13,7 @@ public class MotorSet extends ParameterSet<MotorInstance> {
public static final int DEFAULT_MOTOR_EVENT_TYPE = ComponentChangeEvent.MOTOR_CHANGE | ComponentChangeEvent.EVENT_CHANGE; public static final int DEFAULT_MOTOR_EVENT_TYPE = ComponentChangeEvent.MOTOR_CHANGE | ComponentChangeEvent.EVENT_CHANGE;
public MotorSet(RocketComponent component ) { 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> {
MotorInstance curInstance = this.map.get(loopFCID); MotorInstance curInstance = this.map.get(loopFCID);
String designation; String designation;
if( MotorInstance.EMPTY_INSTANCE == curInstance){ if( null == curInstance.getMotor() ){
designation = "EMPTY_INSTANCE"; designation = "EMPTY_INSTANCE";
}else{ }else{
designation = curInstance.getMotor().getDesignation(curInstance.getEjectionDelay()); designation = curInstance.getMotor().getDesignation(curInstance.getEjectionDelay());

View File

@ -250,7 +250,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
@Override @Override
public MotorInstance getNewInstance() { public ThrustCurveMotorInstance getNewInstance() {
return new ThrustCurveMotorInstance(this); return new ThrustCurveMotorInstance(this);
} }

View File

@ -1,19 +1,27 @@
package net.sf.openrocket.motor; package net.sf.openrocket.motor;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Inertia; import net.sf.openrocket.util.Inertia;
import net.sf.openrocket.util.MathUtil; 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 static final Logger log = LoggerFactory.getLogger(ThrustCurveMotorInstance.class);
private int timeIndex = -1; private int timeIndex = -1;
protected MotorMount mount = null; protected MotorMount mount = null;
protected MotorInstanceId id = null;
private double ignitionTime;
private double ignitionDelay;
private IgnitionEvent ignitionEvent;
private double ejectionDelay;
protected ThrustCurveMotor motor = null; protected ThrustCurveMotor motor = null;
// Previous time step value // Previous time step value
@ -47,46 +55,88 @@ public class ThrustCurveMotorInstance extends MotorInstance {
unitRotationalInertia = Inertia.filledCylinderRotational(source.getDiameter() / 2); unitRotationalInertia = Inertia.filledCylinderRotational(source.getDiameter() / 2);
unitLongitudinalInertia = Inertia.filledCylinderLongitudinal(source.getDiameter() / 2, source.getLength()); unitLongitudinalInertia = Inertia.filledCylinderLongitudinal(source.getDiameter() / 2, source.getLength());
this.id = MotorInstanceId.ERROR_ID;
} }
@Override @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() { public double getTime() {
return prevTime; return prevTime;
} }
@Override
public Coordinate getCG() { public Coordinate getCG() {
return stepCG; return stepCG;
} }
@Override
public Coordinate getCM() { public Coordinate getCM() {
return stepCG; return stepCG;
} }
@Override
public double getPropellantMass(){ public double getPropellantMass(){
return (motor.getLaunchCG().weight - motor.getEmptyCG().weight); 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() { public double getLongitudinalInertia() {
return unitLongitudinalInertia * stepCG.weight; return unitLongitudinalInertia * stepCG.weight;
} }
@Override
public double getRotationalInertia() { public double getRotationalInertia() {
return unitRotationalInertia * stepCG.weight; return unitRotationalInertia * stepCG.weight;
} }
@ -100,60 +150,21 @@ public class ThrustCurveMotorInstance extends MotorInstance {
public boolean isActive() { public boolean isActive() {
return prevTime < motor.getCutOffTime(); 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(){ public Motor getMotor(){
return this.motor; return this.motor;
} }
@Override
public boolean isEmpty(){ public boolean isEmpty(){
return false; 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 @Override
public void step(double nextTime, double acceleration, AtmosphericConditions cond) { public void step(double nextTime, double acceleration, AtmosphericConditions cond) {
if (MathUtil.equals(prevTime, nextTime)) { if (MathUtil.equals(prevTime, nextTime)) {
return; return;
} }
modID++;
double[] time = motor.getTimePoints(); double[] time = motor.getTimePoints();
double[] thrust = motor.getThrustPoints(); double[] thrust = motor.getThrustPoints();
Coordinate[] cg = motor.getCGPoints(); Coordinate[] cg = motor.getCGPoints();
@ -220,23 +231,6 @@ public class ThrustCurveMotorInstance extends MotorInstance {
prevTime = nextTime; 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(){ public void reset(){
timeIndex = 0; timeIndex = 0;
prevTime = 0; prevTime = 0;
@ -246,25 +240,9 @@ public class ThrustCurveMotorInstance extends MotorInstance {
stepCG = instCG; 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 @Override
public String toString(){ public String toString(){
return this.motor.getDesignation() + this.id.toShortKey(); return this.motor.getDesignation();
} }
} }

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.motor; package net.sf.openrocket.motor;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
@ -74,7 +75,7 @@ public class ThrustCurveMotorPlaceholder implements Motor {
} }
@Override @Override
public MotorInstance getNewInstance() { public MotorState getNewInstance() {
throw new BugException("Called getInstance on PlaceholderMotor"); throw new BugException("Called getInstance on PlaceholderMotor");
} }

View File

@ -375,7 +375,7 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
@Override @Override
public void setMotorInstance(final FlightConfigurationID fcid, final MotorInstance newMotorInstance){ 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); this.motors.set( fcid, null);
}else{ }else{
if( null == newMotorInstance.getMount()){ if( null == newMotorInstance.getMount()){

View File

@ -357,44 +357,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
return this.fcid.toShortKey(); return this.fcid.toShortKey();
} }
// DEBUG / DEVEL
public String toDebug() {
return toMotorDetail();
}
// DEBUG / DEVEL
public String toStageListDetail() {
StringBuilder buf = new StringBuilder();
buf.append(String.format("\nDumping %d stages for config: %s: (#: %d)\n", this.stages.size(), this.getName(), this.instanceNumber));
for (StageFlags flags : this.stages.values()) {
AxialStage curStage = flags.stage;
buf.append(String.format(" [%2d]: %-24s: %4s\n", curStage.getStageNumber(), curStage.getName(), (flags.active?" on": "off")));
}
buf.append("\n\n");
return buf.toString();
}
// DEBUG / DEVEL
public String toMotorDetail(){
StringBuilder buff = new StringBuilder();
buff.append(String.format("\nDumping %2d Motors for configuration %s: (#: %s)\n", this.motors.size(), this, this.instanceNumber));
final int intanceCount = motors.size();
int motorInstanceNumber=0;
for( MotorInstance curMotor : this.motors.values() ){
if( curMotor.isEmpty() ){
buff.append( String.format( " ..[%2d/%2d][%8s] <empty> \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(){ public String getMotorsOneline(){
StringBuilder buff = new StringBuilder("["); StringBuilder buff = new StringBuilder("[");
boolean first = true; boolean first = true;
@ -493,10 +455,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
return getAllMotorCount(); return getAllMotorCount();
} }
public int getActiveMotorCount(){
return getActiveMotors().size();
}
public int getAllMotorCount(){ public int getAllMotorCount(){
return motors.size(); return motors.size();
} }
@ -523,7 +481,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
return activeList; return activeList;
} }
public void updateMotors() { public void updateMotors() {
this.motors.clear(); this.motors.clear();
@ -535,27 +493,8 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
continue; continue;
} }
// this merely accounts for instancing of *this* component: this.motors.put( sourceInstance.getID(), sourceInstance);
// int instancCount = comp.getInstanceCount();
// this includes *all* the instancing between here and the rocket root.
Coordinate[] instanceLocations= compMount.getLocations();
sourceInstance.reset();
int motorInstanceNumber = 1;
//final int instanceCount = instanceLocations.length;
for ( Coordinate curMountLocation : instanceLocations ){
MotorInstance cloneInstance = sourceInstance.clone();
cloneInstance.setID( new MotorInstanceId( compMount.getName(), motorInstanceNumber) );
// motor location w/in mount: parent.refpoint -> motor.refpoint
Coordinate curMotorOffset = cloneInstance.getOffset();
cloneInstance.setPosition( curMountLocation.add(curMotorOffset) );
this.motors.put( cloneInstance.getID(), cloneInstance);
motorInstanceNumber ++;
}
} }
} }
} }

View File

@ -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<IgnitionConfiguration> {
protected double ignitionDelay = 0.0;
protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER;
protected double ignitionTime = 0.0;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
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);
}
}
}

View File

@ -9,23 +9,23 @@ import net.sf.openrocket.startup.Application;
public enum IgnitionEvent { public enum IgnitionEvent {
// //// Automatic (launch or ejection charge) // //// Automatic (launch or ejection charge)
// AUTOMATIC( "AUTOMATIC", "MotorMount.IgnitionEvent.AUTOMATIC"){ AUTOMATIC( "AUTOMATIC", "MotorMount.IgnitionEvent.AUTOMATIC"){
// @Override @Override
// public boolean isActivationEvent(FlightEvent e, RocketComponent source) { public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
// int count = source.getRocket().getStageCount(); int count = source.getRocket().getStageCount();
// AxialStage stage = (AxialStage)source; AxialStage stage = (AxialStage)source.getStage();
//
// if ( stage instanceof ParallelStage ){ if ( stage instanceof ParallelStage ){
// return LAUNCH.isActivationEvent(e, source); return LAUNCH.isActivationEvent(e, source);
// }else if (????){ }else if (stage.getStageNumber() == count -1){
// // no good option here. The non-sequential nature of // no good option here. The non-sequential nature of
// // parallel stages prevents us from using the simple test as previousyl // parallel stages prevents us from using the simple test as previousyl
// return LAUNCH.isActivationEvent(e, source); return LAUNCH.isActivationEvent(e, source);
// } else { } else {
// return EJECTION_CHARGE.isActivationEvent(e, source); return EJECTION_CHARGE.isActivationEvent(e, source);
// } }
// } }
// }, },
LAUNCH ( "LAUNCH", "MotorMount.IgnitionEvent.LAUNCH"){ LAUNCH ( "LAUNCH", "MotorMount.IgnitionEvent.LAUNCH"){
@Override @Override
public boolean isActivationEvent( FlightEvent fe, RocketComponent source){ public boolean isActivationEvent( FlightEvent fe, RocketComponent source){

View File

@ -283,7 +283,7 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra
@Override @Override
public void setMotorInstance(final FlightConfigurationID fcid, final MotorInstance newMotorInstance){ public void setMotorInstance(final FlightConfigurationID fcid, final MotorInstance newMotorInstance){
if((null == newMotorInstance)||(newMotorInstance== MotorInstance.EMPTY_INSTANCE )){ if((null == newMotorInstance)){
this.motors.set( fcid, null); this.motors.set( fcid, null);
}else{ }else{
if( null == newMotorInstance.getMount()){ if( null == newMotorInstance.getMount()){

View File

@ -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<MotorConfiguration> {
protected Coordinate position = Coordinate.ZERO;
protected double ejectionDelay = 0.0;
protected Motor motor = null;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
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);
}
}
}

View File

@ -172,8 +172,8 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
thrust = 0; thrust = 0;
final double currentTime = status.getSimulationTime() + timestep; final double currentTime = status.getSimulationTime() + timestep;
Collection<MotorInstance> activeMotorList = status.getConfiguration().getActiveMotors(); Collection<MotorState> activeMotorList = status.getActiveMotors();
for (MotorInstance currentMotorInstance : activeMotorList ) { for (MotorState currentMotorInstance : activeMotorList ) {
// old: transplanted from MotorInstanceConfiguration // old: transplanted from MotorInstanceConfiguration
double instanceTime = currentTime - currentMotorInstance.getIgnitionTime(); double instanceTime = currentTime - currentMotorInstance.getIgnitionTime();
if (instanceTime >= 0) { if (instanceTime >= 0) {

View File

@ -195,7 +195,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
// Check for burnt out motors // Check for burnt out motors
for( MotorInstance motor : currentStatus.getConfiguration().getAllMotors()){ for( MotorState motor : currentStatus.getAllMotors()){
MotorInstanceId motorId = motor.getID(); MotorInstanceId motorId = motor.getID();
if (!motor.isActive() && currentStatus.addBurntOutMotor(motorId)) { if (!motor.isActive() && currentStatus.addBurntOutMotor(motorId)) {
addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, currentStatus.getSimulationTime(), addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, currentStatus.getSimulationTime(),
@ -276,7 +276,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
if (event.getType() == FlightEvent.Type.IGNITION) { if (event.getType() == FlightEvent.Type.IGNITION) {
MotorMount mount = (MotorMount) event.getSource(); MotorMount mount = (MotorMount) event.getSource();
MotorInstanceId motorId = (MotorInstanceId) event.getData(); MotorInstanceId motorId = (MotorInstanceId) event.getData();
MotorInstance instance = currentStatus.getMotor(motorId); MotorState instance = currentStatus.getMotor(motorId);
if (!SimulationListenerHelper.fireMotorIgnition(currentStatus, motorId, mount, instance)) { if (!SimulationListenerHelper.fireMotorIgnition(currentStatus, motorId, mount, instance)) {
continue; continue;
} }
@ -289,7 +289,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
} }
// Check for motor ignition events, add ignition events to queue // 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(); IgnitionEvent ignitionEvent = inst.getIgnitionEvent();
MotorMount mount = inst.getMount(); MotorMount mount = inst.getMount();
RocketComponent component = (RocketComponent) mount; RocketComponent component = (RocketComponent) mount;
@ -342,7 +342,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
case IGNITION: { case IGNITION: {
// Ignite the motor // Ignite the motor
MotorInstanceId motorId = (MotorInstanceId) event.getData(); MotorInstanceId motorId = (MotorInstanceId) event.getData();
MotorInstance inst = currentStatus.getMotor( motorId); MotorState inst = currentStatus.getMotor( motorId);
inst.setIgnitionTime(event.getTime()); inst.setIgnitionTime(event.getTime());
//System.err.println("Igniting motor: "+inst.getMotor().getDesignation()+" @"+currentStatus.getSimulationTime()); //System.err.println("Igniting motor: "+inst.getMotor().getDesignation()+" @"+currentStatus.getSimulationTime());
@ -373,7 +373,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
} }
// Add ejection charge event // Add ejection charge event
MotorInstanceId motorId = (MotorInstanceId) event.getData(); MotorInstanceId motorId = (MotorInstanceId) event.getData();
MotorInstance motor = currentStatus.getMotor( motorId); MotorState motor = currentStatus.getMotor( motorId);
double delay = motor.getEjectionDelay(); double delay = motor.getEjectionDelay();
if (delay != Motor.PLUGGED) { if (delay != Motor.PLUGGED) {
addEvent(new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, currentStatus.getSimulationTime() + delay, addEvent(new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, currentStatus.getSimulationTime() + delay,

View File

@ -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);
}

View File

@ -1,7 +1,10 @@
package net.sf.openrocket.simulation; package net.sf.openrocket.simulation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -27,7 +30,7 @@ import net.sf.openrocket.util.WorldCoordinate;
*/ */
public class SimulationStatus implements Monitorable { public class SimulationStatus implements Monitorable {
private SimulationConditions simulationConditions; private SimulationConditions simulationConditions;
private FlightConfiguration configuration; private FlightConfiguration configuration;
private FlightDataBranch flightData; private FlightDataBranch flightData;
@ -48,6 +51,7 @@ public class SimulationStatus implements Monitorable {
// Set of burnt out motors // Set of burnt out motors
Set<MotorInstanceId> motorBurntOut = new HashSet<MotorInstanceId>(); Set<MotorInstanceId> motorBurntOut = new HashSet<MotorInstanceId>();
List<MotorState> motorState = new ArrayList<MotorState>();
/** Nanosecond time when the simulation was started. */ /** Nanosecond time when the simulation was started. */
private long simulationStartWallTime = Long.MIN_VALUE; private long simulationStartWallTime = Long.MIN_VALUE;
@ -144,6 +148,9 @@ public class SimulationStatus implements Monitorable {
this.launchRodCleared = false; this.launchRodCleared = false;
this.apogeeReached = false; this.apogeeReached = false;
for( MotorInstance motorInstance : this.configuration.getActiveMotors() ) {
this.motorState.add( motorInstance.getSimulationState() );
}
this.warnings = new WarningSet(); this.warnings = new WarningSet();
} }
@ -183,6 +190,10 @@ public class SimulationStatus implements Monitorable {
this.deployedRecoveryDevices.clear(); this.deployedRecoveryDevices.clear();
this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices); this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices);
// FIXME - is this right?
this.motorState.clear();
this.motorState.addAll(orig.motorState);
this.eventQueue.clear(); this.eventQueue.clear();
this.eventQueue.addAll(orig.eventQueue); this.eventQueue.addAll(orig.eventQueue);
@ -214,6 +225,20 @@ public class SimulationStatus implements Monitorable {
this.configuration = configuration; this.configuration = configuration;
} }
public Collection<MotorState> getAllMotors() {
return motorState;
}
public Collection<MotorState> getActiveMotors() {
List<MotorState> activeList = new ArrayList<MotorState>();
for( MotorState inst : this.motorState ){
if( inst.isActive() ){
activeList.add( inst );
}
}
return activeList;
}
public FlightConfiguration getConfiguration() { public FlightConfiguration getConfiguration() {
return configuration; return configuration;
@ -235,8 +260,13 @@ public class SimulationStatus implements Monitorable {
return flightData; return flightData;
} }
public MotorInstance getMotor( final MotorInstanceId motorId ){ public MotorState getMotor( final MotorInstanceId motorId ){
return this.getFlightConfiguration().getMotorInstance(motorId); for( MotorState state : motorState ) {
if ( motorId.equals(state.getID() )) {
return state;
}
}
return null;
} }
public double getPreviousTimeStep() { public double getPreviousTimeStep() {

View File

@ -6,16 +6,19 @@ import java.util.Set;
import javax.script.Invocable; import javax.script.Invocable;
import javax.script.ScriptException; import javax.script.ScriptException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.aerodynamics.AerodynamicForces; import net.sf.openrocket.aerodynamics.AerodynamicForces;
import net.sf.openrocket.aerodynamics.FlightConditions; import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.masscalc.MassData; import net.sf.openrocket.masscalc.MassData;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceId; import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.AccelerationData; import net.sf.openrocket.simulation.AccelerationData;
import net.sf.openrocket.simulation.FlightEvent; import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.simulation.exception.SimulationListenerException; 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.BugException;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ScriptingSimulationListener implements SimulationListener, SimulationComputationListener, SimulationEventListener, Cloneable { public class ScriptingSimulationListener implements SimulationListener, SimulationComputationListener, SimulationEventListener, Cloneable {
private final static Logger logger = LoggerFactory.getLogger(ScriptingSimulationListener.class); private final static Logger logger = LoggerFactory.getLogger(ScriptingSimulationListener.class);
@ -105,7 +105,7 @@ public class ScriptingSimulationListener implements SimulationListener, Simulati
} }
@Override @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); return invoke(Boolean.class, true, "motorIgnition", status, motorId, mount, instance);
} }

View File

@ -5,11 +5,11 @@ import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.masscalc.MassData; import net.sf.openrocket.masscalc.MassData;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceId; import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.AccelerationData; import net.sf.openrocket.simulation.AccelerationData;
import net.sf.openrocket.simulation.FlightEvent; import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BugException;
@ -72,7 +72,7 @@ public class AbstractSimulationListener implements SimulationListener, Simulatio
} }
@Override @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; return true;
} }

View File

@ -1,10 +1,10 @@
package net.sf.openrocket.simulation.listeners; package net.sf.openrocket.simulation.listeners;
import net.sf.openrocket.motor.MotorInstanceId; import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.FlightEvent; import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.simulation.exception.SimulationException;
@ -44,7 +44,7 @@ public interface SimulationEventListener {
* @return <code>true</code> to ignite the motor, <code>false</code> to abort ignition * @return <code>true</code> to ignite the motor, <code>false</code> to abort ignition
*/ */
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount,
MotorInstance instance) throws SimulationException; MotorState instance) throws SimulationException;
/** /**

View File

@ -10,11 +10,11 @@ import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.masscalc.MassData; import net.sf.openrocket.masscalc.MassData;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceId; import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.AccelerationData; import net.sf.openrocket.simulation.AccelerationData;
import net.sf.openrocket.simulation.FlightEvent; import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.simulation.SimulationStatus; import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException; import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
@ -168,7 +168,7 @@ public class SimulationListenerHelper {
* @return <code>true</code> to handle the event normally, <code>false</code> to skip event. * @return <code>true</code> to handle the event normally, <code>false</code> to skip event.
*/ */
public static boolean fireMotorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, public static boolean fireMotorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount,
MotorInstance instance) throws SimulationException { MotorState instance) throws SimulationException {
boolean b; boolean b;
int modID = status.getModID(); // Contains also motor instance int modID = status.getModID(); // Contains also motor instance

View File

@ -101,7 +101,7 @@ public class TestRockets {
new Coordinate[] { new Coordinate[] {
new Coordinate(.311, 0, 0, 4.808),new Coordinate(.311, 0, 0, 3.389),new Coordinate(.311, 0, 0, 1.970)}, new Coordinate(.311, 0, 0, 4.808),new Coordinate(.311, 0, 0, 3.389),new Coordinate(.311, 0, 0, 1.970)},
"digest M1350 test"); "digest M1350 test");
return mtr.getNewInstance(); return new MotorInstance(mtr);
} }
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests). // 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[] {
new Coordinate(.062, 0, 0, 0.123),new Coordinate(.062, 0, 0, .0935),new Coordinate(.062, 0, 0, 0.064)}, new Coordinate(.062, 0, 0, 0.123),new Coordinate(.062, 0, 0, .0935),new Coordinate(.062, 0, 0, 0.064)},
"digest G77 test"); "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,30.0),
new Coordinate(0.0035,0,0,21.0)}, new Coordinate(0.0035,0,0,21.0)},
"digest_D12"); "digest_D12");
MotorInstance inst = motor.getNewInstance(); MotorInstance inst = new MotorInstance(motor);
inst.setEjectionDelay(5); inst.setEjectionDelay(5);
return inst; return inst;
} }
public static Rocket makeSmallFlyable() { public static Rocket makeSmallFlyable() {
double noseconeLength = 0.10, noseconeRadius = 0.01; double noseconeLength = 0.10, noseconeRadius = 0.01;
double bodytubeLength = 0.20, bodytubeRadius = 0.01, bodytubeThickness = 0.001; double bodytubeLength = 0.20, bodytubeRadius = 0.01, bodytubeThickness = 0.001;
@ -465,7 +466,7 @@ public class TestRockets {
FlightConfigurationID fcid = config.getFlightConfigurationID(); FlightConfigurationID fcid = config.getFlightConfigurationID();
ThrustCurveMotor motor = getTestMotor(); ThrustCurveMotor motor = getTestMotor();
MotorInstance instance = motor.getNewInstance(); MotorInstance instance = new MotorInstance(motor);
instance.setEjectionDelay(5); instance.setEjectionDelay(5);
bodytube.setMotorInstance(fcid, instance); bodytube.setMotorInstance(fcid, instance);
@ -979,7 +980,7 @@ public class TestRockets {
// create motor config and add a motor to it // create motor config and add a motor to it
ThrustCurveMotor motor = getTestMotor(); ThrustCurveMotor motor = getTestMotor();
MotorInstance motorInst = motor.getNewInstance(); MotorInstance motorInst = new MotorInstance(motor);
motorInst.setEjectionDelay(5); motorInst.setEjectionDelay(5);
// add motor config to inner tube (motor mount) // add motor config to inner tube (motor mount)
@ -1014,7 +1015,7 @@ public class TestRockets {
// create motor config and add a motor to it // create motor config and add a motor to it
ThrustCurveMotor motor = getTestMotor(); ThrustCurveMotor motor = getTestMotor();
MotorInstance motorConfig = motor.getNewInstance(); MotorInstance motorConfig = new MotorInstance(motor);
motorConfig.setEjectionDelay(5); motorConfig.setEjectionDelay(5);
// add motor config to inner tube (motor mount) // add motor config to inner tube (motor mount)
@ -1171,7 +1172,7 @@ public class TestRockets {
bodyTube.addChild(innerTube); bodyTube.addChild(innerTube);
// make inner tube with motor mount flag set // make inner tube with motor mount flag set
MotorInstance inst = getTestMotor().getNewInstance(); MotorInstance inst = new MotorInstance(getTestMotor());
innerTube.setMotorInstance(fcid, inst); innerTube.setMotorInstance(fcid, inst);
// set ignition parameters for motor mount // set ignition parameters for motor mount

View File

@ -10,8 +10,8 @@ import net.sf.openrocket.file.motor.GeneralMotorLoader;
import net.sf.openrocket.file.motor.MotorLoader; import net.sf.openrocket.file.motor.MotorLoader;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions; import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.motor.ThrustCurveMotor; import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.MathUtil;
@ -61,8 +61,8 @@ public class MotorCorrelation {
* @return the scaled cross-correlation of the two thrust curves. * @return the scaled cross-correlation of the two thrust curves.
*/ */
public static double crossCorrelation(Motor motor1, Motor motor2) { public static double crossCorrelation(Motor motor1, Motor motor2) {
MotorInstance m1 = motor1.getNewInstance(); MotorState m1 = motor1.getNewInstance();
MotorInstance m2 = motor2.getNewInstance(); MotorState m2 = motor2.getNewInstance();
AtmosphericConditions cond = new AtmosphericConditions(); AtmosphericConditions cond = new AtmosphericConditions();

View File

@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test; import org.junit.Test;
import net.sf.openrocket.simulation.MotorState;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Inertia; import net.sf.openrocket.util.Inertia;
@ -41,7 +42,7 @@ public class ThrustCurveMotorTest {
@Test @Test
public void testInstance() { public void testInstance() {
MotorInstance instance = motor.getNewInstance(); ThrustCurveMotorInstance instance = motor.getNewInstance();
verify(instance, 0, 0.05, 0.02); verify(instance, 0, 0.05, 0.02);
instance.step(0.0, 0, null); instance.step(0.0, 0, null);
@ -63,7 +64,7 @@ public class ThrustCurveMotorTest {
verify(instance, 0, 0.03, 0.03); 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 thrust", thrust, instance.getThrust(), EPS);
assertEquals("Testing mass", mass, instance.getCG().weight, EPS); assertEquals("Testing mass", mass, instance.getCG().weight, EPS);
assertEquals("Testing cg x", cgx, instance.getCG().x, EPS); assertEquals("Testing cg x", cgx, instance.getCG().x, EPS);

View File

@ -195,8 +195,8 @@ public class ConfigurationTest extends BaseTestCase {
// test explicitly setting all stages up to second stage active // test explicitly setting all stages up to second stage active
config.setOnlyStage(1); config.setOnlyStage(1);
assertThat(config.toStageListDetail() + "Setting single stage active: ", config.isStageActive(0), equalTo(false)); assertThat("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(1), equalTo(true));
config.clearStage(0); config.clearStage(0);
assertThat(" deactivate stage #0: ", config.isStageActive(0), equalTo(false)); 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); InnerTube sustainerMount = (InnerTube) rocket.getChild(0).getChild(1).getChild(3);
sustainerMount.setMotorMount(true); 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"); "digest D21 test");
InnerTube boosterMount = (InnerTube) rocket.getChild(1).getChild(0).getChild(2); InnerTube boosterMount = (InnerTube) rocket.getChild(1).getChild(0).getChild(2);
boosterMount.setMotorMount(true); boosterMount.setMotorMount(true);
boosterMount.setMotorInstance(fcid, boosterMotor.getNewInstance()); boosterMount.setMotorInstance(fcid, new MotorInstance(boosterMotor));
boosterMount.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[1]); // double-mount boosterMount.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[1]); // double-mount
} }
return rocket; return rocket;

View File

@ -215,7 +215,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
Motor mtr = motorChooserDialog.getSelectedMotor(); Motor mtr = motorChooserDialog.getSelectedMotor();
double d = motorChooserDialog.getSelectedDelay(); double d = motorChooserDialog.getSelectedDelay();
if (mtr != null) { if (mtr != null) {
MotorInstance curInstance = mtr.getNewInstance(); MotorInstance curInstance = new MotorInstance(mtr);
curInstance.setEjectionDelay(d); curInstance.setEjectionDelay(d);
curInstance.setIgnitionEvent( IgnitionEvent.NEVER); curInstance.setIgnitionEvent( IgnitionEvent.NEVER);
curMount.setMotorInstance( fcid, curInstance); curMount.setMotorInstance( fcid, curInstance);
@ -262,9 +262,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
} }
MotorInstance curInstance = curMount.getMotorInstance(fcid); MotorInstance curInstance = curMount.getMotorInstance(fcid);
MotorInstance defInstance = curInstance.getMount().getDefaultMotorInstance(); curInstance.useDefaultIgnition();
curInstance.setIgnitionDelay( defInstance.getIgnitionDelay());
curInstance.setIgnitionEvent( defInstance.getIgnitionEvent());
fireTableDataChanged(); fireTableDataChanged();
} }
@ -315,14 +313,19 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
IgnitionEvent ignitionEvent = curInstance.getIgnitionEvent(); IgnitionEvent ignitionEvent = curInstance.getIgnitionEvent();
Double ignitionDelay = curInstance.getIgnitionDelay(); 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(); JLabel label = new JLabel();
String str = trans.get("MotorMount.IgnitionEvent.short." + ignitionEvent.name()); String str = trans.get("MotorMount.IgnitionEvent.short." + ignitionEvent.name());
if (ignitionEvent != IgnitionEvent.NEVER && ignitionDelay > 0.001) { if (ignitionEvent != IgnitionEvent.NEVER && ignitionDelay > 0.001) {
str = str + " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(ignitionDelay); str = str + " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(ignitionDelay);
} }
if (isDefault) { if (useDefault) {
shaded(label); shaded(label);
String def = trans.get("MotorConfigurationTableModel.table.ignition.default"); String def = trans.get("MotorConfigurationTableModel.table.ignition.default");
str = def.replace("{0}", str); str = def.replace("{0}", str);