[Bugfix / Refactor] Fixing simulation bugs and oddities.

- *Adjusted event handling in BasicEventSimulationEngine*
  -- combined redundant event-handling for IGNITION FlightEvent
  -- adjusted parameters for throwing IGNITION FlightEvents
- Added validation method internal to FlightEvent class.
  -- documents assumptions about classes are expected for what types of flight events.
- renamed MotorState -> MotorSimulation -> MotorClusterState
- renamed MotorState enums -> ThrustState
- Adjusted MotorConfigurations to be init-linked to a mount, and FCID
  -- these are final member fields, and required for construction. And immutable.
- moved IgnitionEvent to motor package
- Adjusted MotorInstanceId to represent a motorCluster key
  -- wraps a UUID, and uniquely keyed to its: mount, FCID
- fixed AxialStage methods isLaunchStage() and getPreviousStage()
- added methods to MotorMount interface to reduce extraneous, always-true casts
- various miscellaneous fixes to reflect method changes
- various test fixes
  -- added test to verify 'getPreviousStage()' method
This commit is contained in:
Daniel_M_Williams 2016-02-13 19:35:02 -05:00 committed by Daniel_M_Williams
parent 28689825a4
commit f6d9ad0487
41 changed files with 544 additions and 410 deletions

View File

@ -74,8 +74,8 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
type = motor.getMotorType();
// Add "Plugged" option if hybrid
if (type == Motor.Type.HYBRID) {
if (!delays.contains(Motor.PLUGGED)) {
delays.add(Motor.PLUGGED);
if (!delays.contains(Motor.PLUGGED_DELAY)) {
delays.add(Motor.PLUGGED_DELAY);
}
}
}

View File

@ -108,7 +108,7 @@ public class RASPMotorLoader extends AbstractMotorLoader {
for (int i = 0; i < buf.length; i++) {
if (buf[i].equalsIgnoreCase("P") ||
buf[i].equalsIgnoreCase("plugged")) {
delays.add(Motor.PLUGGED);
delays.add(Motor.PLUGGED_DELAY);
} else if (buf[i].matches("[0-9]+")) {
// Many RASP files have "100" as an only delay
double d = Double.parseDouble(buf[i]);

View File

@ -173,12 +173,12 @@ public class RockSimMotorLoader extends AbstractMotorLoader {
double d = Double.parseDouble(delay);
if (d >= DELAY_LIMIT)
d = Motor.PLUGGED;
d = Motor.PLUGGED_DELAY;
delayList.add(d);
} catch (NumberFormatException e) {
if (str.equalsIgnoreCase("P") || str.equalsIgnoreCase("plugged")) {
delayList.add(Motor.PLUGGED);
delayList.add(Motor.PLUGGED_DELAY);
}
}
}

View File

@ -10,7 +10,7 @@ import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.motor.IgnitionEvent;
class IgnitionConfigurationHandler extends AbstractElementHandler {

View File

@ -51,7 +51,7 @@ class MotorHandler extends AbstractElementHandler {
public double getDelay(WarningSet warnings) {
if (Double.isNaN(delay)) {
warnings.add(Warning.fromString("Motor delay not specified, assuming no ejection charge."));
return Motor.PLUGGED;
return Motor.PLUGGED_DELAY;
}
return delay;
}
@ -124,7 +124,7 @@ class MotorHandler extends AbstractElementHandler {
// Delay
delay = Double.NaN;
if (content.equals("none")) {
delay = Motor.PLUGGED;
delay = Motor.PLUGGED_DELAY;
} else {
try {
delay = Double.parseDouble(content.trim());

View File

@ -10,11 +10,10 @@ import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.motor.IgnitionEvent;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -72,19 +71,15 @@ class MotorMountHandler extends AbstractElementHandler {
return;
}
Motor motor = motorHandler.getMotor(warnings);
MotorConfiguration motorConfig = new MotorConfiguration( mount, fcid);
motorConfig.setMotor(motor);
motorConfig.setEjectionDelay(motorHandler.getDelay(warnings));
MotorConfiguration motorInstance = new MotorConfiguration();
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);
mount.setMotorConfig( motorConfig, fcid);
Rocket rkt = ((RocketComponent)mount).getRocket();
rkt.createFlightConfiguration(fcid);
rkt.getFlightConfiguration(fcid).addMotor(motorInstance);
rkt.getFlightConfiguration(fcid).addMotor(motorConfig);
return;
}

View File

@ -214,7 +214,7 @@ public class RocketComponentSaver {
elements.add(" <length>" + motor.getLength() + "</length>");
// Motor delay
if (motorInstance.getEjectionDelay() == Motor.PLUGGED) {
if (motorInstance.getEjectionDelay() == Motor.PLUGGED_DELAY) {
elements.add(" <delay>none</delay>");
} else {
elements.add(" <delay>" + motorInstance.getEjectionDelay() + "</delay>");

View File

@ -1,8 +1,10 @@
package net.sf.openrocket.rocketcomponent;
package net.sf.openrocket.motor;
import java.util.Locale;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.startup.Application;
@ -11,18 +13,13 @@ 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.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);
public boolean isActivationEvent(FlightEvent testEvent, RocketComponent targetComponent) {
AxialStage targetStage = (AxialStage)targetComponent.getStage();
if ( targetStage.isLaunchStage() ){
return LAUNCH.isActivationEvent(testEvent, targetComponent);
} else {
return EJECTION_CHARGE.isActivationEvent(testEvent, targetComponent);
}
}
},
@ -34,24 +31,27 @@ public enum IgnitionEvent {
},
EJECTION_CHARGE ("EJECTION_CHARGE", "MotorMount.IgnitionEvent.EJECTION_CHARGE"){
@Override
public boolean isActivationEvent( FlightEvent fe, RocketComponent source){
if (fe.getType() != FlightEvent.Type.EJECTION_CHARGE){
public boolean isActivationEvent( FlightEvent testEvent, RocketComponent targetComponent){
if (testEvent.getType() != FlightEvent.Type.EJECTION_CHARGE){
return false;
}
int charge = fe.getSource().getStageNumber();
int mount = source.getStageNumber();
return (mount + 1 == charge);
AxialStage targetStage = (AxialStage)targetComponent.getStage();
AxialStage eventStage = (AxialStage)testEvent.getSource().getStage();
AxialStage eventParentStage = eventStage.getPreviousStage();
return ( targetStage.equals(eventParentStage));
}
},
BURNOUT ("BURNOUT", "MotorMount.IgnitionEvent.BURNOUT"){
@Override
public boolean isActivationEvent( FlightEvent fe, RocketComponent source){
if (fe.getType() != FlightEvent.Type.BURNOUT)
public boolean isActivationEvent( FlightEvent testEvent, RocketComponent targetComponent){
if (testEvent.getType() != FlightEvent.Type.BURNOUT)
return false;
int charge = fe.getSource().getStageNumber();
int mount = source.getStageNumber();
return (mount + 1 == charge);
AxialStage targetStage = (AxialStage)targetComponent.getStage();
AxialStage eventStage = (AxialStage)testEvent.getSource().getStage();
AxialStage eventParentStage = eventStage.getPreviousStage();
return ( targetStage.equals(eventParentStage));
}
},
NEVER("NEVER", "MotorMount.IgnitionEvent.NEVER")

View File

@ -50,7 +50,7 @@ public interface Motor extends Cloneable {
* Ejection charge delay value signifying a "plugged" motor with no ejection charge.
* The value is that of <code>Double.POSITIVE_INFINITY</code>.
*/
public static final double PLUGGED = Double.POSITIVE_INFINITY;
public static final double PLUGGED_DELAY = Double.POSITIVE_INFINITY;
/**

View File

@ -1,7 +1,7 @@
package net.sf.openrocket.motor;
import net.sf.openrocket.rocketcomponent.FlightConfigurableParameter;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Coordinate;
@ -15,26 +15,25 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
public static final String EMPTY_DESCRIPTION = "Empty Configuration";
// set at config time
protected MotorMount mount = null;
protected final MotorMount mount;
protected final FlightConfigurationId fcid;
protected final MotorInstanceId id;
protected Motor motor = null;
protected double ejectionDelay = 0.0;
protected MotorInstanceId id = null;
protected boolean ignitionOveride = false;
protected double ignitionDelay = 0.0;
protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER;
protected int modID = 0;
public MotorConfiguration( Motor motor ) {
this();
this.motor = motor;
}
public MotorConfiguration() {
this.id = MotorInstanceId.EMPTY_ID;
public MotorConfiguration( final MotorMount _mount, final FlightConfigurationId _fcid ) {
this.mount = _mount;
this.fcid = _fcid;
this.id = new MotorInstanceId( _mount, _fcid);
this.motor = null;
ejectionDelay = 0.0;
ignitionEvent = IgnitionEvent.LAUNCH;
ignitionDelay = 0.0;
@ -56,11 +55,7 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
public MotorInstanceId getID() {
return this.id;
}
public void setID(final MotorInstanceId _id) {
this.id = _id;
}
public void setMotor(Motor motor){
this.motor = motor;
}
@ -73,10 +68,6 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
return mount;
}
public void setMount(MotorMount mount) {
this.mount = mount;
}
public double getEjectionDelay() {
return this.ejectionDelay;
}
@ -181,9 +172,8 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
*/
@Override
public MotorConfiguration clone( ) {
MotorConfiguration clone = new MotorConfiguration();
MotorConfiguration clone = new MotorConfiguration( this.mount, this.fcid);
clone.motor = this.motor;
clone.mount = this.mount;
clone.ejectionDelay = this.ejectionDelay;
clone.ignitionOveride = this.ignitionOveride;
clone.ignitionDelay = this.ignitionDelay;
@ -198,4 +188,6 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
@Override
public void update(){
}
}

View File

@ -1,8 +1,9 @@
package net.sf.openrocket.motor;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.FlightConfigurableParameterSet;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
/**
@ -12,8 +13,8 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
public class MotorConfigurationSet extends FlightConfigurableParameterSet<MotorConfiguration> {
public static final int DEFAULT_MOTOR_EVENT_TYPE = ComponentChangeEvent.MOTOR_CHANGE | ComponentChangeEvent.EVENT_CHANGE;
public MotorConfigurationSet(RocketComponent component ) {
super( new MotorConfiguration());
public MotorConfigurationSet(final MotorMount mount ) {
super( new MotorConfiguration( mount, FlightConfigurationId.DEFAULT_VALUE_FCID ));
}
/**

View File

@ -1,5 +1,10 @@
package net.sf.openrocket.motor;
import java.util.UUID;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
/**
* An immutable identifier for a motor instance in a MotorInstanceConfiguration.
* The motor is identified by the ID of its mounting component and a
@ -9,84 +14,63 @@ package net.sf.openrocket.motor;
*/
public final class MotorInstanceId {
private final String componentId;
private final int number;
private final String name ;
private final UUID key;
private final static String ERROR_COMPONENT_TEXT = "Error Motor Id";
private final static int ERROR_NUMBER = 1;
public final static MotorInstanceId ERROR_ID = new MotorInstanceId(ERROR_COMPONENT_TEXT, ERROR_NUMBER);
private final static String EMPTY_COMPONENT_TEXT = "Empty Motor Id";
private final static int EMPTY_NUMBER = 1;
public final static MotorInstanceId EMPTY_ID = new MotorInstanceId(EMPTY_COMPONENT_TEXT, EMPTY_NUMBER);
private final static String ERROR_ID_TEXT = "MotorInstance Error Id";
private final static UUID ERROR_KEY = new UUID( 6227, 5676);
public final static MotorInstanceId ERROR_ID = new MotorInstanceId();
private MotorInstanceId( ) {
this.name = MotorInstanceId.ERROR_ID_TEXT;
this.key = MotorInstanceId.ERROR_KEY;
}
/**
* Sole constructor.
*
* @param componentId the component ID, must not be null
* @param componentName the component ID, must not be null
* @param number a positive motor number
*/
public MotorInstanceId(String componentId, int number) {
if (componentId == null) {
throw new IllegalArgumentException("Component ID was null");
public MotorInstanceId(final MotorMount _mount, final FlightConfigurationId _fcid ) {
if (null == _mount ) {
throw new IllegalArgumentException("Provided MotorConfiguration was null");
}
if (number <= 0) {
throw new IllegalArgumentException("Number must be positive, n=" + number);
if (null == _fcid ) {
throw new IllegalArgumentException("Provided MotorConfiguration was null");
}
// Use intern so comparison can be done using == instead of equals()
this.componentId = componentId.intern();
this.number = number;
this.name = _mount.getID()+"-"+_fcid.toShortKey();
final long upper = _mount.getID().hashCode() << 32;
final long lower = _fcid.key.getMostSignificantBits();
this.key = new UUID( upper, lower);
}
public String getComponentId() {
return componentId;
}
public int getInstanceNumber() {
return number;
}
@Override
public boolean equals(Object o) {
if (this == o)
public boolean equals(Object other) {
if (this == other)
return true;
if (!(o instanceof MotorInstanceId))
if (!(other instanceof MotorInstanceId))
return false;
MotorInstanceId other = (MotorInstanceId) o;
// Comparison with == ok since string is intern()'ed
return this.componentId == other.componentId && this.number == other.number;
MotorInstanceId otherId = (MotorInstanceId) other;
return ( this.key.equals( otherId.key));
}
@Override
public int hashCode() {
return componentId.hashCode() + (number << 12);
}
public String toShortKey(){
if( this == ERROR_ID){
return "ERROR_ID";
}else if( this == EMPTY_ID){
return "EMPTY_ID";
}else{
final String result = toString();
return result.substring(0, Math.min(8, result.length()));
}
return key.hashCode();
}
@Override
public String toString(){
if( this == ERROR_ID){
return "ERROR_ID";
}else if( this == EMPTY_ID){
return "EMPTY_ID";
if( this.key == MotorInstanceId.ERROR_KEY){
return MotorInstanceId.ERROR_ID_TEXT;
}else{
return Integer.toString( this.hashCode());
return name;
}
}
}

View File

@ -579,7 +579,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
////////// Static methods
/**
* Return a String representation of a delay time. If the delay is {@link #PLUGGED},
* Return a String representation of a delay time. If the delay is {@link #PLUGGED_DELAY},
* returns "P".
*
* @param delay the delay time.
@ -590,7 +590,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
}
/**
* Return a String representation of a delay time. If the delay is {@link #PLUGGED},
* Return a String representation of a delay time. If the delay is {@link #PLUGGED_DELAY},
* <code>plugged</code> is returned.
*
* @param delay the delay time.
@ -598,7 +598,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* @return the String representation.
*/
public static String getDelayString(double delay, String plugged) {
if (delay == PLUGGED)
if (delay == PLUGGED_DELAY)
return plugged;
delay = Math.rint(delay * 10) / 10;
if (MathUtil.equals(delay, Math.rint(delay)))

View File

@ -117,7 +117,8 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
}
public boolean isLaunchStage(){
return ( getRocket().getBottomCoreStage().equals(this));
return ( this instanceof ParallelStage )
||( getRocket().getBottomCoreStage().equals(this));
}
public void setStageNumber(final int newStageNumber) {
@ -143,6 +144,20 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
buff.append( this.separations.toDebug() );
return buff.toString();
}
public AxialStage getPreviousStage() {
if( this instanceof ParallelStage ){
return (AxialStage) this.parent;
}
AxialStage thisStage = this.getStage(); // necessary in case of pods or other assemblies
if( thisStage.parent instanceof Rocket ){
final int thisIndex = parent.getChildPosition( thisStage );
if( 0 < thisIndex ){
return (AxialStage)thisStage.parent.getChild(thisIndex-1);
}
}
return null;
}

View File

@ -7,7 +7,6 @@ import java.util.Iterator;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationSet;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.startup.Application;
@ -374,17 +373,15 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
}
@Override
public void setMotorInstance(final FlightConfigurationId fcid, final MotorConfiguration newMotorInstance){
if((null == newMotorInstance)){
public void setMotorConfig( final MotorConfiguration newMotorConfig, final FlightConfigurationId fcid){
if(null == newMotorConfig){
this.motors.set( fcid, null);
}else{
if( null == newMotorInstance.getMount()){
newMotorInstance.setMount(this);
}else if( !this.equals( newMotorInstance.getMount())){
throw new BugException(" attempt to add a MotorInstance to a second mount, when it's already owned by another mount!");
if( this != newMotorConfig.getMount() ){
throw new BugException(" attempt to add a MotorConfig to a second mount! ");
}
newMotorInstance.setID(new MotorInstanceId( this.getID(), 1));
this.motors.set(fcid,newMotorInstance);
this.motors.set(fcid,newMotorConfig);
}
this.isActingMount=true;

View File

@ -336,19 +336,19 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
/**
* Add a motor instance to this configuration.
*
* @param motor the motor instance.
* @param motorConfig the motor instance.
* @throws IllegalArgumentException if a motor with the specified ID already exists.
*/
public void addMotor(MotorConfiguration motor) {
if( motor.isEmpty() ){
public void addMotor(MotorConfiguration motorConfig) {
if( motorConfig.isEmpty() ){
throw new IllegalArgumentException("MotorInstance is empty.");
}
MotorInstanceId id = motor.getID();
MotorInstanceId id = motorConfig.getID();
if (this.motors.containsKey(id)) {
throw new IllegalArgumentException("MotorInstanceConfiguration already " +
throw new IllegalArgumentException("FlightConfiguration already " +
"contains a motor with id " + id);
}
this.motors.put(id, motor);
this.motors.put(id, motorConfig);
modID++;
}
@ -526,13 +526,14 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
// DEBUG / DEVEL
public String toMotorDetail(){
StringBuilder buf = new StringBuilder();
buf.append(String.format("\nDumping %2d Motors for configuration %s: (#: %s)\n", this.motors.size(), this, this.instanceNumber));
final String fmt = " ..[%-8s] <%6s> %-12s %-20s\n";
buf.append(String.format("\nDumping %2d Motors for configuration %s: (#: %s)\n",
this.motors.size(), this.getFlightConfigurationID().toFullKey(), this.instanceNumber));
final String fmt = " ..[%-8s] %-12s %-20s\n";
buf.append(String.format(fmt, "Motor Id", "Mtr Desig","Mount"));
for( MotorConfiguration curConfig : this.motors.values() ){
MotorMount mount = curConfig.getMount();
String motorId = curConfig.getID().toShortKey();
String motorId = curConfig.getID().toString();
String motorDesig;
if( curConfig.isEmpty() ){
motorDesig = "(empty)";

View File

@ -65,7 +65,7 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
}
}
public String getFullKeyText(){
public String toFullKey(){
return this.key.toString();
}

View File

@ -1,5 +1,7 @@
package net.sf.openrocket.rocketcomponent;
import net.sf.openrocket.motor.IgnitionEvent;
public class IgnitionConfiguration implements FlightConfigurableParameter<IgnitionConfiguration> {
protected double ignitionDelay = 0.0;

View File

@ -11,7 +11,6 @@ import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorConfigurationSet;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
@ -282,16 +281,14 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra
}
@Override
public void setMotorInstance(final FlightConfigurationId fcid, final MotorConfiguration newMotorConfig){
public void setMotorConfig( final MotorConfiguration newMotorConfig, final FlightConfigurationId fcid){
if((null == newMotorConfig)){
this.motors.set( fcid, null);
}else{
if( null == newMotorConfig.getMount()){
newMotorConfig.setMount(this);
}else if( !this.equals( newMotorConfig.getMount())){
throw new BugException(" attempt to add a MotorInstance to a second mount, when it's already owned by another mount!");
if( this != newMotorConfig.getMount() ){
throw new BugException(" attempt to add a MotorConfig to a second mount!");
}
newMotorConfig.setID(new MotorInstanceId( this.getID(), 1));
this.motors.set(fcid, newMotorConfig);
}

View File

@ -60,8 +60,14 @@ public interface MotorMount extends ChangeSource, FlightConfigurableComponent {
* @return
*/
public double getLength();
// duplicate of RocketComponent
public String getID();
public String getName();
// duplicate of RocketComponent
public AxialStage getStage();
/**
*
* @param fcid id for which to return the motor (null retrieves the default)
@ -74,7 +80,7 @@ public interface MotorMount extends ChangeSource, FlightConfigurableComponent {
* @param fcid index the supplied motor against this flight configuration
* @param newMotorInstance motor instance to store
*/
public void setMotorInstance(final FlightConfigurationId fcid, final MotorConfiguration newMotorInstance);
public void setMotorConfig( final MotorConfiguration newMotorConfig, final FlightConfigurationId fcid);
/**
* Get the number of motors available for all flight configurations

View File

@ -817,11 +817,11 @@ public class Rocket extends RocketComponent {
public String toDebugConfigs(){
StringBuilder buf = new StringBuilder();
buf.append(String.format("====== Dumping %d Configurations from rocket: \n", this.getConfigurationCount(), this.getName()));
final String fmt = " [%-12s]: %s\n";
final String fmt = " [%12s]: %s\n";
for( FlightConfiguration config : this.configSet.values() ){
String shortKey = config.getId().toShortKey();
if( this.selectedConfiguration.equals( config)){
shortKey = shortKey+"<=";
shortKey = "=>" + shortKey;
}
buf.append(String.format(fmt, shortKey, config.getName() ));
}

View File

@ -170,12 +170,8 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
thrust = 0;
final double currentTime = status.getSimulationTime() + timestep;
Collection<MotorSimulation> activeMotorList = status.getMotors();
for (MotorSimulation currentMotorState : activeMotorList ) {
if ( !stepMotors ) {
currentMotorState = currentMotorState.clone();
}
Collection<MotorClusterState> activeMotorList = status.getMotors();
for (MotorClusterState currentMotorState : activeMotorList ) {
thrust += currentMotorState.getThrust( currentTime, atmosphericConditions );
}

View File

@ -9,14 +9,12 @@ import org.slf4j.LoggerFactory;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -194,17 +192,10 @@ public class BasicEventSimulationEngine implements SimulationEngine {
// Check for burnt out motors
for( MotorSimulation state : currentStatus.getAllMotors()){
state.isFinishedThrusting( );
MotorInstanceId motorId = state.getID();
for( MotorClusterState state : currentStatus.getMotors()){
//state.update( currentStatus.getSimulationTime() );
if ( state.isFinishedThrusting()){
// TODO : implement me!
//currentStatus.moveBurntOutMotor( motorId);
currentStatus.addBurntOutMotor(motorId);
MotorInstanceId motorId = state.getID();
addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, currentStatus.getSimulationTime(),
(RocketComponent) state.getMount(), motorId));
}
@ -276,18 +267,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
continue;
}
if (event.getType() != FlightEvent.Type.ALTITUDE) {
log.trace("BasicEventSimulationEngine: Handling event " + event);
}
if (event.getType() == FlightEvent.Type.IGNITION) {
MotorMount mount = (MotorMount) event.getSource();
MotorInstanceId motorId = (MotorInstanceId) event.getData();
MotorSimulation instance = currentStatus.getMotor(motorId);
if (!SimulationListenerHelper.fireMotorIgnition(currentStatus, motorId, mount, instance)) {
continue;
}
}
if (event.getType() == FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT) {
RecoveryDevice device = (RecoveryDevice) event.getSource();
if (!SimulationListenerHelper.fireRecoveryDeviceDeployment(currentStatus, device)) {
@ -295,19 +274,33 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
}
// // DEBUG:
// if(( event.getType() == FlightEvent.Type.BURNOUT)|| ( event.getType() == FlightEvent.Type.EJECTION_CHARGE)){
// System.err.println("@simulationTime: "+currentStatus.getSimulationTime());
// System.err.println(" Processing "+event.getType().name()+" @"+event.getTime()+" from: "+event.getSource().getName());
// MotorClusterState eventState = (MotorClusterState) event.getData();
// System.err.println(" and motor: "+eventState.getMotor().getDesignation()+" in:"+eventState.getMount().getName()
// +" @: "+eventState.getEjectionDelay());
// }
// Check for motor ignition events, add ignition events to queue
for (MotorSimulation inst : currentStatus.getAllMotors() ){
IgnitionEvent ignitionEvent = inst.getIgnitionEvent();
MotorMount mount = inst.getMount();
RocketComponent component = (RocketComponent) mount;
if (ignitionEvent.isActivationEvent(event, component)) {
double ignitionDelay = inst.getIgnitionDelay();
// TODO: this event seems to get enque'd multiple times -- more than necessary...
//System.err.println("Queueing ignition of mtr:"+inst.getMotor().getDesignation()+" @"+currentStatus.getSimulationTime());
addEvent(new FlightEvent(FlightEvent.Type.IGNITION,
currentStatus.getSimulationTime() + ignitionDelay,
component, inst.getID() ));
for (MotorClusterState state : currentStatus.getAllMotors() ){
if( state.testForIgnition(event )){
final double simulationTime = currentStatus.getSimulationTime() ;
MotorClusterState sourceState = (MotorClusterState) event.getData();
double ignitionDelay = 0;
if(( event.getType() == FlightEvent.Type.BURNOUT)|| ( event.getType() == FlightEvent.Type.EJECTION_CHARGE)){
ignitionDelay = sourceState.getEjectionDelay();
}
final double ignitionTime = currentStatus.getSimulationTime() + ignitionDelay;
final RocketComponent mount = (RocketComponent)state.getMount();
// TODO: this event seems to get enqueue'd multiple times ...
System.err.println("@simulationTime: "+simulationTime);
System.err.println("Queueing motorIgnitionEvent: "+state.getMotor().getDesignation()+" in:"+state.getMount().getName()
+" @: "+ignitionTime);
System.err.println(" Because of "+event.getType().name()+" @"+event.getTime()+" from: "+event.getSource().getName());
addEvent(new FlightEvent(FlightEvent.Type.IGNITION, ignitionTime, mount, state ));
}
}
@ -347,15 +340,32 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
case IGNITION: {
// Ignite the motor
MotorInstanceId motorId = (MotorInstanceId) event.getData();
MotorSimulation inst = currentStatus.getMotor( motorId);
inst.ignite( event.getTime());
//System.err.println("Igniting motor: "+inst.getMotor().getDesignation()+" @"+currentStatus.getSimulationTime());
MotorClusterState motorState = (MotorClusterState) event.getData();
System.err.println(" >> Igniting motor: "+motorState.getMotor().getDesignation()
+" @"+currentStatus.getSimulationTime()
+" ("+motorState.getMount().getName());
motorState.ignite( event.getTime());
// Ignite the motor
currentStatus.setMotorIgnited(true);
currentStatus.getFlightData().addEvent(event);
// ... ignite ...uhh, again?
// TBH, I'm not sure what this call is for. It seems to be mostly a bunch of event distribution.
MotorInstanceId motorId = motorState.getID();
MotorMount mount = (MotorMount) event.getSource();
if (!SimulationListenerHelper.fireMotorIgnition(currentStatus, motorId, mount, motorState)) {
continue;
}
// and queue up the burnout for this motor, as well.
double duration = motorState.getMotor().getBurnTimeEstimate();
double burnout = currentStatus.getSimulationTime() + duration;
addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, burnout,
event.getSource(), motorState ));
break;
}
@ -380,12 +390,15 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
// Add ejection charge event
MotorInstanceId motorId = (MotorInstanceId) event.getData();
MotorSimulation state = currentStatus.getMotor( motorId);
MotorClusterState state = (MotorClusterState) event.getData();
AxialStage stage = state.getMount().getStage();
log.debug( " adding EJECTION_CHARGE event for stage "+stage.getStageNumber()+": "+stage.getName());
log.debug( " .... for motor "+state.getMotor().getDesignation());
double delay = state.getEjectionDelay();
if (delay != Motor.PLUGGED) {
if ( state.hasEjectionCharge() ){
addEvent(new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, currentStatus.getSimulationTime() + delay,
event.getSource(), event.getData()));
stage, event.getData()));
}
currentStatus.getFlightData().addEvent(event);
break;
@ -483,6 +496,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
break;
case ALTITUDE:
log.trace("BasicEventSimulationEngine: Handling event " + event);
break;
case TUMBLE:

View File

@ -279,7 +279,7 @@ public class FlightDataBranch implements Monitorable {
*/
public void addEvent(FlightEvent event) {
mutable.check();
events.add(event.resetSourceAndData());
events.add(event);
modID++;
}

View File

@ -1,6 +1,8 @@
package net.sf.openrocket.simulation;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
@ -102,23 +104,26 @@ public class FlightEvent implements Comparable<FlightEvent> {
private final Object data;
public FlightEvent(Type type, double time) {
this(type, time, null);
public FlightEvent( final Type type, final double time) {
this(type, time, null, null);
}
public FlightEvent(Type type, double time, RocketComponent source) {
public FlightEvent( final Type type, final double time, final RocketComponent source) {
this(type, time, source, null);
}
public FlightEvent(Type type, double time, RocketComponent source, Object data) {
public FlightEvent(final FlightEvent _sourceEvent, final RocketComponent _comp, final Object _data) {
this(_sourceEvent.type, _sourceEvent.time, _comp, _data);
}
public FlightEvent( final Type type, final double time, final RocketComponent source, final Object data) {
this.type = type;
this.time = time;
this.source = source;
this.data = data;
validate();
}
public Type getType() {
return type;
}
@ -136,16 +141,7 @@ public class FlightEvent implements Comparable<FlightEvent> {
}
/**
* Return a new FlightEvent with the same information as the current event
* but with <code>null</code> source. This is used to avoid memory leakage by
* retaining references to obsolete components.
*
* @return a new FlightEvent with same type, time and data.
*/
public FlightEvent resetSourceAndData() {
return new FlightEvent(type, time, null, null);
}
/**
@ -167,4 +163,78 @@ public class FlightEvent implements Comparable<FlightEvent> {
return "FlightEvent[type=" + type.name() + ",time=" + time + ",source=" + source + ",data=" + String.valueOf(data) + "]";
}
/**
* verify that this event's state is well-formed.
*
* User actions should not cause these.
*
* @return
*/
public void validate(){
if( this.time == Double.NaN ){
throw new IllegalStateException(type.name()+" event has a NaN time!");
}
switch( this.type ){
case BURNOUT:
if( null != this.source){
if( ! ( this.source instanceof MotorMount)){
throw new IllegalStateException(type.name()+" events should have "
+MotorMount.class.getSimpleName()+" type data payloads, instead of"
+this.getSource().getClass().getSimpleName());
}
}
if( null != this.data ){
if( ! ( this.data instanceof MotorClusterState)){
throw new IllegalStateException(type.name()+" events should have "
+MotorClusterState.class.getSimpleName()+" type data payloads");
}
}
break;
case IGNITION:
if( null != this.source){
if( ! ( this.getSource() instanceof MotorMount)){
throw new IllegalStateException(type.name()+" events should have "
+MotorMount.class.getSimpleName()+" type data payloads, instead of"
+this.getSource().getClass().getSimpleName());
}
}
if( null != this.data ){
if( ! ( this.data instanceof MotorClusterState)){
throw new IllegalStateException(type.name()+"events should have "
+MotorClusterState.class.getSimpleName()+" type data payloads");
}
}
break;
case EJECTION_CHARGE:
if( null != this.source){
if( ! ( this.getSource() instanceof AxialStage)){
throw new IllegalStateException(type.name()+" events should have "
+AxialStage.class.getSimpleName()+" type data payloads, instead of"
+this.getSource().getClass().getSimpleName());
}
}
if( null != this.data ){
if( ! ( this.data instanceof MotorClusterState)){
throw new IllegalStateException(type.name()+" events should have "
+MotorClusterState.class.getSimpleName()+" type data payloads");
}
}
break;
case LAUNCH:
case LIFTOFF:
case LAUNCHROD:
case STAGE_SEPARATION:
case APOGEE:
case RECOVERY_DEVICE_DEPLOYMENT:
case GROUND_HIT:
case SIMULATION_END:
case ALTITUDE:
case TUMBLE:
case EXCEPTION:
default:
}
}
}

View File

@ -4,49 +4,49 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.IgnitionEvent;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.rocketcomponent.RocketComponent;
public class MotorSimulation {
public class MotorClusterState {
private static final Logger log = LoggerFactory.getLogger(MotorSimulation.class);
private static final Logger log = LoggerFactory.getLogger(MotorClusterState.class);
// for reference: set at initialization ONLY.
final protected Motor motor;
final protected MotorConfiguration config;
final protected int motorCount;
final protected double thrustDuration;
// for state:
protected double ignitionTime = Double.NaN;
protected double cutoffTime = Double.NaN;
protected double ejectionTime = Double.NaN;
protected MotorState currentState = MotorState.PREFLIGHT;
protected ThrustState currentState = ThrustState.PREFLIGHT;
public MotorSimulation(final MotorConfiguration _config) {
public MotorClusterState(final MotorConfiguration _config) {
log.debug(" Creating motor instance of " + _config.getDescription());
this.config = _config;
this.motor = _config.getMotor();
MotorMount mount = this.config.getMount();
if( mount instanceof InnerTube ){
InnerTube inner = (InnerTube) mount;
this.motorCount = inner.getClusterConfiguration().getClusterCount();
}else{
this.motorCount =0;
}
thrustDuration = this.motor.getBurnTimeEstimate();
this.resetToPreflight();
}
@Override
public MotorSimulation clone() {
try {
return (MotorSimulation) super.clone();
} catch (CloneNotSupportedException e) {
throw new BugException("CloneNotSupportedException", e);
}
}
public void arm( final double _armTime ){
if( MotorState.PREFLIGHT == currentState ){
if( ThrustState.PREFLIGHT == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_armTime);
//this.ignitionTime = _ignitionTime;
this.currentState = this.currentState.getNext();
@ -55,10 +55,6 @@ public class MotorSimulation {
}
}
public boolean isFinishedThrusting(){
return currentState.isAfter( MotorState.THRUSTING );
}
public double getIgnitionTime() {
return ignitionTime;
}
@ -67,19 +63,18 @@ public class MotorSimulation {
return config.getIgnitionEvent();
}
public void ignite( final double _ignitionTime ){
if( MotorState.ARMED == currentState ){
if( ThrustState.ARMED == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_ignitionTime);
this.ignitionTime = _ignitionTime;
this.currentState = this.currentState.getNext();
}else{
throw new IllegalStateException("Attempted to ignite a motor state with status="+this.currentState.getName());
}
}
}
public void burnOut( final double _burnOutTime ){
if( MotorState.THRUSTING == currentState ){
if( ThrustState.THRUSTING == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_burnOutTime);
this.ignitionTime = _burnOutTime;
this.currentState = this.currentState.getNext();
@ -89,7 +84,7 @@ public class MotorSimulation {
}
public void fireEjectionCharge( final double _ejectionTime ){
if( MotorState.DELAYING == currentState ){
if( ThrustState.DELAYING == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_ejectionTime);
this.ejectionTime = _ejectionTime;
this.currentState = this.currentState.getNext();
@ -98,16 +93,12 @@ public class MotorSimulation {
}
}
/*
/**
* Alias for "burnOut(double)"
*/
public void cutOff( final double _cutoffTime ){
burnOut( _cutoffTime );
}
public double getIgnitionDelay() {
return config.getEjectionDelay();
}
public double getEjectionDelay() {
return config.getEjectionDelay();
@ -120,11 +111,7 @@ public class MotorSimulation {
public double getPropellantMass(){
return (motor.getLaunchMass() - motor.getBurnoutMass());
}
// public boolean isActive( ) {
// return this.currentState.isActive();
// }
public MotorMount getMount(){
return config.getMount();
}
@ -136,20 +123,51 @@ public class MotorSimulation {
double getCutOffTime(){
return this.cutoffTime;
}
public double getMotorTime( final double _simulationTime ){
return _simulationTime - this.getIgnitionTime();
}
public double getThrust( final double simTime, final AtmosphericConditions cond){
public double getThrust( final double simulationTime, final AtmosphericConditions cond){
if( this.currentState.isThrusting() ){
return motor.getThrustAtMotorTime( simTime - this.getIgnitionTime());
double motorTime = this.getMotorTime( simulationTime);
return this.motorCount * motor.getThrustAtMotorTime( motorTime );
}else{
return 0.0;
}
}
public boolean isPlugged(){
return ( this.config.getEjectionDelay() == Motor.PLUGGED_DELAY);
}
public boolean hasEjectionCharge(){
return ! isPlugged();
}
public boolean isFinishedThrusting(){
return currentState.isAfter( ThrustState.THRUSTING );
}
/**
* alias to 'resetToPreflight()'
*/
public void reset(){
resetToPreflight();
}
public void resetToPreflight(){
ignitionTime = Double.NaN;
cutoffTime = Double.NaN;
ejectionTime = Double.NaN;
currentState = MotorState.PREFLIGHT;
// i.e. in the "future"
ignitionTime = Double.POSITIVE_INFINITY;
cutoffTime = Double.POSITIVE_INFINITY;
ejectionTime = Double.POSITIVE_INFINITY;
currentState = ThrustState.PREFLIGHT;
}
public boolean testForIgnition( final FlightEvent _event ){
RocketComponent mount = (RocketComponent) this.getMount();
return getIgnitionEvent().isActivationEvent( _event, mount);
}
@Override
@ -157,4 +175,20 @@ public class MotorSimulation {
return this.motor.getDesignation();
}
}
// public void update( final double simulationTime ){
// final double motorTime = this.getMotorTime( simulationTime );
// log.debug("Attempt to update this motorClusterSimulation with: ");
// log.debug(" this.ignitionTime= "+this.ignitionTime);
// log.debug(" this.thrustDuration= "+this.thrustDuration);
// log.debug(" simTime = "+simulationTime);
// log.debug(" motorTime= "+motorTime );
//
// log.debug( " time array = "+((ThrustCurveMotor)this.getMotor()).getTimePoints() );
//
// switch( this.currentState ){
//
// }
}

View File

@ -3,7 +3,6 @@ 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;
@ -48,10 +47,8 @@ public class SimulationStatus implements Monitorable {
private double effectiveLaunchRodLength;
// Set of burnt out motors
Set<MotorInstanceId> spentMotors = new HashSet<MotorInstanceId>();
List<MotorSimulation> motorStateList = new ArrayList<MotorSimulation>();
// Set of all motors
List<MotorClusterState> motorStateList = new ArrayList<MotorClusterState>();
/** Nanosecond time when the simulation was started. */
private long simulationStartWallTime = Long.MIN_VALUE;
@ -108,6 +105,8 @@ public class SimulationStatus implements Monitorable {
double angle = -cond.getTheta() - (Math.PI / 2.0 - this.simulationConditions.getLaunchRodDirection());
o = Quaternion.rotation(new Coordinate(0, 0, angle));
// Launch rod angle and direction
o = o.multiplyLeft(Quaternion.rotation(new Coordinate(0, this.simulationConditions.getLaunchRodAngle(), 0)));
o = o.multiplyLeft(Quaternion.rotation(new Coordinate(0, 0, Math.PI / 2.0 - this.simulationConditions.getLaunchRodDirection())));
@ -149,7 +148,9 @@ public class SimulationStatus implements Monitorable {
this.apogeeReached = false;
for( MotorConfiguration motorConfig : this.configuration.getActiveMotors() ) {
this.motorStateList.add( new MotorSimulation( motorConfig) );
MotorClusterState simMotor = new MotorClusterState( motorConfig);
simMotor.arm( this.time );
this.motorStateList.add( simMotor);
}
this.warnings = new WarningSet();
}
@ -184,7 +185,6 @@ public class SimulationStatus implements Monitorable {
this.launchRodCleared = orig.launchRodCleared;
this.apogeeReached = orig.apogeeReached;
this.tumbling = orig.tumbling;
this.spentMotors = orig.spentMotors;
this.deployedRecoveryDevices.clear();
this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices);
@ -216,6 +216,11 @@ public class SimulationStatus implements Monitorable {
return time;
}
public void armAllMotors(){
for( MotorClusterState motor : this.motorStateList ){
motor.resetToPreflight();
}
}
public void setConfiguration(FlightConfiguration configuration) {
if (this.configuration != null)
@ -224,11 +229,11 @@ public class SimulationStatus implements Monitorable {
this.configuration = configuration;
}
public Collection<MotorSimulation> getMotors() {
public Collection<MotorClusterState> getMotors() {
return motorStateList;
}
public Collection<MotorSimulation> getAllMotors() {
public Collection<MotorClusterState> getAllMotors() {
return motorStateList;
}
@ -263,15 +268,6 @@ public class SimulationStatus implements Monitorable {
return flightData;
}
public MotorSimulation getMotor( final MotorInstanceId motorId ){
for( MotorSimulation state : motorStateList ) {
if ( motorId.equals(state.getID() )) {
return state;
}
}
return null;
}
public double getPreviousTimeStep() {
return previousTimeStep;
}
@ -318,12 +314,7 @@ public class SimulationStatus implements Monitorable {
// remove motor from 'normal' list
// add to spent list
return false;
}
public boolean addBurntOutMotor(MotorInstanceId motor) {
return spentMotors.add(motor);
}
}
public Quaternion getRocketOrientationQuaternion() {
return orientation;

View File

@ -1,9 +1,9 @@
package net.sf.openrocket.simulation;
public enum MotorState {
FINISHED("Finished with sequence.", "Finished Producing thrust.", null)
,DELAYING("Delaying", " After Burnout, but before ejection", FINISHED){
public enum ThrustState {
SPENT("Finished with sequence.", "Finished Producing thrust.", null)
,DELAYING("Delaying", " After Burnout, but before ejection", SPENT){
@Override
public boolean needsSimulation(){ return true;}
}
@ -13,8 +13,8 @@ public enum MotorState {
@Override
public boolean needsSimulation(){ return true;}
}
,ARMED("Armed", "Armed, but not yet lit.", FINISHED)
,PREFLIGHT("Pre-Launch", "Safed and inactive, prior to launch.", FINISHED)
,ARMED("Armed", "Armed, but not yet lit.", THRUSTING)
,PREFLIGHT("Pre-Launch", "Safed and inactive, prior to launch.", ARMED)
;
private final static int SEQUENCE_NUMBER_END = 10; // arbitrary number
@ -22,9 +22,9 @@ public enum MotorState {
private final String name;
private final String description;
private final int sequenceNumber;
private final MotorState nextState;
private final ThrustState nextState;
MotorState( final String name, final String description, final MotorState _nextState) {
ThrustState( final String name, final String description, final ThrustState _nextState) {
this.name = name;
this.description = description;
if( null == _nextState ){
@ -43,13 +43,12 @@ public enum MotorState {
public String getName() {
return this.name;
}
/*
*
* @Return a MotorState enum telling what state should follow this one.
* @Return a MotorState which should follow this one
*/
public MotorState getNext( ){
public ThrustState getNext( ){
return this.nextState;
}
@ -72,14 +71,14 @@ public enum MotorState {
return this.sequenceNumber;
}
public boolean isAfter( final MotorState other ){
return this.getSequenceNumber() > other.getSequenceNumber();
}
public boolean isBefore( final MotorState other ){
return this.getSequenceNumber() < other.getSequenceNumber();
public boolean isAfter( final ThrustState other ){
return this.sequenceNumber > other.sequenceNumber;
}
public boolean isBefore( final ThrustState other ){
return this.sequenceNumber < other.sequenceNumber;
}
/*
* If this motor is in a state which produces thrust
*/

View File

@ -18,7 +18,7 @@ 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.MotorSimulation;
import net.sf.openrocket.simulation.MotorClusterState;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.simulation.exception.SimulationListenerException;
@ -105,7 +105,7 @@ public class ScriptingSimulationListener implements SimulationListener, Simulati
}
@Override
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorSimulation instance) throws SimulationException {
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorClusterState instance) throws SimulationException {
return invoke(Boolean.class, true, "motorIgnition", status, motorId, mount, instance);
}

View File

@ -9,7 +9,7 @@ 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.MotorSimulation;
import net.sf.openrocket.simulation.MotorClusterState;
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, MotorSimulation instance) throws SimulationException {
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorClusterState instance) throws SimulationException {
return true;
}

View File

@ -4,7 +4,7 @@ import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.MotorSimulation;
import net.sf.openrocket.simulation.MotorClusterState;
import net.sf.openrocket.simulation.SimulationStatus;
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
*/
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount,
MotorSimulation instance) throws SimulationException;
MotorClusterState instance) throws SimulationException;
/**

View File

@ -14,7 +14,7 @@ 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.MotorSimulation;
import net.sf.openrocket.simulation.MotorClusterState;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.util.Coordinate;
@ -168,18 +168,18 @@ public class SimulationListenerHelper {
* @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,
MotorSimulation instance) throws SimulationException {
boolean b;
MotorClusterState instance) throws SimulationException {
boolean result;
int modID = status.getModID(); // Contains also motor instance
for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
if (l instanceof SimulationEventListener) {
b = ((SimulationEventListener) l).motorIgnition(status, motorId, mount, instance);
result = ((SimulationEventListener) l).motorIgnition(status, motorId, mount, instance);
if (modID != status.getModID()) {
warn(status, l);
modID = status.getModID();
}
if (b == false) {
if ( false == result ) {
warn(status, l);
return false;
}
@ -196,17 +196,17 @@ public class SimulationListenerHelper {
*/
public static boolean fireRecoveryDeviceDeployment(SimulationStatus status, RecoveryDevice device)
throws SimulationException {
boolean b;
boolean result;
int modID = status.getModID(); // Contains also motor instance
for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
if (l instanceof SimulationEventListener) {
b = ((SimulationEventListener) l).recoveryDeviceDeployment(status, device);
result = ((SimulationEventListener) l).recoveryDeviceDeployment(status, device);
if (modID != status.getModID()) {
warn(status, l);
modID = status.getModID();
}
if (b == false) {
if (false == result) {
warn(status, l);
return false;
}

View File

@ -12,7 +12,6 @@ import net.sf.openrocket.material.Material.Type;
import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.ComponentPresetFactory;
@ -97,7 +96,7 @@ public class TestRockets {
}
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
private static MotorConfiguration generateMotorInstance_A8_18mm(){
private static Motor generateMotor_A8_18mm(){
// public ThrustCurveMotor(Manufacturer manufacturer, String designation, String description,
// Motor.Type type, double[] delays, double diameter, double length,
// double[] time, double[] thrust,
@ -109,11 +108,11 @@ public class TestRockets {
new Coordinate[] {
new Coordinate(0.035, 0, 0, 0.0164),new Coordinate(.035, 0, 0, 0.0145),new Coordinate(.035, 0, 0, 0.0131)},
"digest A8 test");
return new MotorConfiguration(mtr);
return mtr;
}
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
private static MotorConfiguration generateMotorInstance_B4_18mm(){
private static Motor generateMotor_B4_18mm(){
// public ThrustCurveMotor(Manufacturer manufacturer, String designation, String description,
// Motor.Type type, double[] delays, double diameter, double length,
// double[] time, double[] thrust,
@ -125,11 +124,11 @@ public class TestRockets {
new Coordinate[] {
new Coordinate(0.035, 0, 0, 0.0195),new Coordinate(.035, 0, 0, 0.0155),new Coordinate(.035, 0, 0, 0.013)},
"digest B4 test");
return new MotorConfiguration(mtr);
return mtr;
}
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
private static MotorConfiguration generateMotorInstance_C6_18mm(){
private static Motor generateMotor_C6_18mm(){
// public ThrustCurveMotor(Manufacturer manufacturer, String designation, String description,
// Motor.Type type, double[] delays, double diameter, double length,
// double[] time, double[] thrust,
@ -141,11 +140,11 @@ public class TestRockets {
new Coordinate[] {
new Coordinate(0.035, 0, 0, 0.0227),new Coordinate(.035, 0, 0, 0.0165),new Coordinate(.035, 0, 0, 0.012)},
"digest C6 test");
return new MotorConfiguration(mtr);
return mtr;
}
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
private static MotorConfiguration generateMotorInstance_D21_18mm(){
private static Motor generateMotor_D21_18mm(){
ThrustCurveMotor mtr = new ThrustCurveMotor(
Manufacturer.getManufacturer("AeroTech"),"D21", "Desc",
Motor.Type.SINGLE, new double[] {}, 0.018, 0.07,
@ -153,11 +152,11 @@ public class TestRockets {
new Coordinate[] {
new Coordinate(.035, 0, 0, 0.025),new Coordinate(.035, 0, 0, .020),new Coordinate(.035, 0, 0, 0.0154)},
"digest D21 test");
return new MotorConfiguration(mtr);
return mtr;
}
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
private static MotorConfiguration generateMotorInstance_M1350_75mm(){
private static Motor generateMotor_M1350_75mm(){
// public ThrustCurveMotor(Manufacturer manufacturer, String designation, String description,
// Motor.Type type, double[] delays, double diameter, double length,
// double[] time, double[] thrust,
@ -169,11 +168,11 @@ 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 new MotorConfiguration(mtr);
return mtr;
}
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
private static MotorConfiguration generateMotorInstance_G77_29mm(){
private static Motor generateMotor_G77_29mm(){
// public ThrustCurveMotor(Manufacturer manufacturer, String designation, String description,
// Motor.Type type, double[] delays, double diameter, double length,
// double[] time, double[] thrust,
@ -185,7 +184,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 new MotorConfiguration(mtr);
return mtr;
}
//
@ -461,34 +460,39 @@ public class TestRockets {
inner.setMotorMount( true);
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_A8_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[0]);
Motor mtr = TestRockets.generateMotor_A8_18mm();
motorConfig.setMotor( mtr);
motorConfig.setEjectionDelay(0.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
inner.setMotorInstance( fcid[0], motorConfig);
inner.setMotorConfig( motorConfig, fcid[0]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_B4_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[1]);
Motor mtr = TestRockets.generateMotor_B4_18mm();
motorConfig.setMotor( mtr);
motorConfig.setEjectionDelay(3.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
inner.setMotorInstance( fcid[1], motorConfig);
inner.setMotorConfig( motorConfig, fcid[1]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_C6_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[2]);
Motor mtr = TestRockets.generateMotor_C6_18mm();
motorConfig.setEjectionDelay(3.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
inner.setMotorInstance( fcid[2], motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[2]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_C6_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[3]);
Motor mtr = TestRockets.generateMotor_C6_18mm();
motorConfig.setEjectionDelay(5.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
inner.setMotorInstance( fcid[3], motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[3]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_C6_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[4]);
Motor mtr = TestRockets.generateMotor_C6_18mm();
motorConfig.setEjectionDelay(7.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
inner.setMotorInstance( fcid[4], motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[4]);
}
}
@ -532,6 +536,12 @@ public class TestRockets {
AxialStage sustainerStage = new AxialStage();
sustainerStage.setName("Sustainer Stage");
rocket.addChild(sustainerStage);
FlightConfigurationId fcid[] = new FlightConfigurationId[5];
for( int i=0; i< fcid.length; ++i){
fcid[i] = new FlightConfigurationId();
rocket.createFlightConfiguration(fcid[i]);
}
FlightConfiguration selectedConfiguration = rocket.getFlightConfiguration(fcid[0]);
double noseconeLength = 0.07;
double noseconeRadius = 0.012;
@ -593,39 +603,39 @@ public class TestRockets {
inner.setMotorMount( true);
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_A8_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[0]);
Motor mtr = TestRockets.generateMotor_A8_18mm();
motorConfig.setEjectionDelay(0.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
FlightConfigurationId motorConfigId = rocket.getSelectedConfiguration().getFlightConfigurationID();
inner.setMotorInstance( motorConfigId, motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[0]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_B4_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[1]);
Motor mtr = TestRockets.generateMotor_B4_18mm();
motorConfig.setEjectionDelay(3.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
FlightConfigurationId motorConfigId = new FlightConfigurationId();
inner.setMotorInstance( motorConfigId, motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[1]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_C6_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[2]);
Motor mtr = TestRockets.generateMotor_C6_18mm();
motorConfig.setEjectionDelay(3.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
FlightConfigurationId motorConfigId = new FlightConfigurationId();
inner.setMotorInstance( motorConfigId, motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[2]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_C6_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[3]);
Motor mtr = TestRockets.generateMotor_C6_18mm();
motorConfig.setEjectionDelay(5.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
FlightConfigurationId motorConfigId = new FlightConfigurationId();
inner.setMotorInstance( motorConfigId, motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[3]);
}
{
MotorConfiguration motorConfig = TestRockets.generateMotorInstance_C6_18mm();
MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[4]);
Motor mtr = TestRockets.generateMotor_C6_18mm();
motorConfig.setEjectionDelay(7.0);
motorConfig.setID( new MotorInstanceId( inner.getName(), 1) );
FlightConfigurationId motorConfigId = new FlightConfigurationId();
inner.setMotorInstance( motorConfigId, motorConfig);
motorConfig.setMotor( mtr);
inner.setMotorConfig( motorConfig, fcid[4]);
}
}
@ -696,14 +706,15 @@ public class TestRockets {
boosterMMT.setMotorMount(true);
{
FlightConfigurationId mcid = rocket.getSelectedConfiguration().getFlightConfigurationID();
MotorConfiguration motorConfig= generateMotorInstance_D21_18mm();
motorConfig.setID( new MotorInstanceId( boosterMMT.getName(), 1) );
boosterMMT.setMotorInstance( mcid, motorConfig);
MotorConfiguration motorConfig= new MotorConfiguration(boosterMMT,fcid[0]);
Motor mtr = generateMotor_D21_18mm();
motorConfig.setMotor(mtr);
boosterMMT.setMotorConfig( motorConfig, fcid[0]);
}
}
rocket.getSelectedConfiguration().setAllStages();
rocket.setSelectedConfiguration( selectedConfiguration );
rocket.enableEvents();
return rocket;
}
@ -750,10 +761,11 @@ public class TestRockets {
FlightConfigurationId fcid = config.getFlightConfigurationID();
ThrustCurveMotor motor = getTestMotor();
MotorConfiguration instance = new MotorConfiguration(motor);
MotorConfiguration instance = new MotorConfiguration( bodytube, fcid );
instance.setMotor( motor);
instance.setEjectionDelay(5);
bodytube.setMotorInstance(fcid, instance);
bodytube.setMotorConfig( instance, fcid);
bodytube.setMotorOverhang(0.005);
config.setAllStages();
@ -1017,7 +1029,8 @@ public class TestRockets {
public static Rocket makeFalcon9Heavy() {
Rocket rocket = new Rocket();
rocket.setName("Falcon9H Scale Rocket");
FlightConfiguration config = rocket.getSelectedConfiguration();
FlightConfiguration selConfig = rocket.getSelectedConfiguration();
FlightConfigurationId selFCID = selConfig.getFlightConfigurationID();
// ====== Payload Stage ======
// ====== ====== ====== ======
@ -1092,11 +1105,12 @@ public class TestRockets {
coreBody.setMotorMount(true);
coreStage.addChild( coreBody);
{
MotorConfiguration motorInstance = TestRockets.generateMotorInstance_M1350_75mm();
motorInstance.setID( new MotorInstanceId( coreBody.getName(), 1) );
MotorConfiguration motorConfig = new MotorConfiguration(coreBody, selFCID);
Motor mtr = TestRockets.generateMotor_M1350_75mm();
motorConfig.setMotor( mtr);
coreBody.setMotorMount( true);
FlightConfigurationId motorConfigId = config.getFlightConfigurationID();
coreBody.setMotorInstance( motorConfigId, motorInstance);
FlightConfigurationId motorConfigId = selConfig.getFlightConfigurationID();
coreBody.setMotorConfig( motorConfig, motorConfigId);
}
TrapezoidFinSet coreFins = new TrapezoidFinSet();
@ -1153,18 +1167,19 @@ public class TestRockets {
boosterMotorTubes.setClusterScale(1.0);
boosterBody.addChild( boosterMotorTubes);
FlightConfigurationId motorConfigId = config.getFlightConfigurationID();
MotorConfiguration motorInstance = TestRockets.generateMotorInstance_G77_29mm();
motorInstance.setID( new MotorInstanceId( boosterMotorTubes.getName(), 1) );
boosterMotorTubes.setMotorInstance( motorConfigId, motorInstance);
FlightConfigurationId motorConfigId = selConfig.getFlightConfigurationID();
MotorConfiguration motorConfig = new MotorConfiguration( boosterMotorTubes, selFCID);
Motor mtr = TestRockets.generateMotor_G77_29mm();
motorConfig.setMotor(mtr);
boosterMotorTubes.setMotorConfig( motorConfig, motorConfigId);
boosterMotorTubes.setMotorOverhang(0.01234);
}
}
}
rocket.enableEvents();
rocket.setSelectedConfiguration(config);
config.setAllStages();
rocket.setSelectedConfiguration(selConfig);
selConfig.setAllStages();
return rocket;
}
@ -1271,11 +1286,12 @@ public class TestRockets {
// create motor config and add a motor to it
ThrustCurveMotor motor = getTestMotor();
MotorConfiguration motorInst = new MotorConfiguration(motor);
motorInst.setEjectionDelay(5);
MotorConfiguration motorConfig = new MotorConfiguration(innerTube, fcid);
motorConfig.setMotor(motor);
motorConfig.setEjectionDelay(5);
// add motor config to inner tube (motor mount)
innerTube.setMotorInstance(fcid, motorInst);
innerTube.setMotorConfig( motorConfig, fcid);
rocket.enableEvents();
return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
@ -1307,11 +1323,12 @@ public class TestRockets {
// create motor config and add a motor to it
ThrustCurveMotor motor = getTestMotor();
MotorConfiguration motorConfig = new MotorConfiguration(motor);
MotorConfiguration motorConfig = new MotorConfiguration(innerTube, fcid);
motorConfig.setMotor(motor);
motorConfig.setEjectionDelay(5);
// add motor config to inner tube (motor mount)
innerTube.setMotorInstance(fcid, motorConfig);
innerTube.setMotorConfig(motorConfig, fcid);
OpenRocketDocument rocketDoc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
@ -1465,12 +1482,14 @@ public class TestRockets {
bodyTube.addChild(innerTube);
// make inner tube with motor mount flag set
MotorConfiguration inst = new MotorConfiguration(getTestMotor());
innerTube.setMotorInstance(fcid, inst);
MotorConfiguration motorConfig = new MotorConfiguration(innerTube, fcid);
Motor mtr = getTestMotor();
motorConfig.setMotor( mtr);
innerTube.setMotorConfig(motorConfig,fcid);
// set ignition parameters for motor mount
// inst.setIgnitionEvent( IgnitionEvent.AUTOMATIC);
inst.setIgnitionDelay(2);
motorConfig.setIgnitionDelay(2);
rocket.enableEvents();
return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);

View File

@ -34,7 +34,7 @@ public class ThrustCurveMotorSetTest {
private static final ThrustCurveMotor motor3 = new ThrustCurveMotor(
Manufacturer.getManufacturer("A"),
"F12", "Desc", Motor.Type.UNKNOWN, new double[] { 0, Motor.PLUGGED },
"F12", "Desc", Motor.Type.UNKNOWN, new double[] { 0, Motor.PLUGGED_DELAY },
0.024, 0.07, new double[] { 0, 1, 2 }, new double[] { 0, 2, 0 },
new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL }, "digestC");
@ -114,7 +114,7 @@ public class ThrustCurveMotorSetTest {
assertEquals(motor3, set.getMotors().get(0));
assertEquals(motor2, set.getMotors().get(1));
assertEquals(motor1, set.getMotors().get(2));
assertEquals(Arrays.asList(0.0, 5.0, Motor.PLUGGED), set.getDelays());
assertEquals(Arrays.asList(0.0, 5.0, Motor.PLUGGED_DELAY), set.getDelays());
// Test that adding motor4 fails
assertFalse(set.matches(motor4));

View File

@ -16,7 +16,7 @@ public class ThrustCurveMotorTest {
private final ThrustCurveMotor motor =
new ThrustCurveMotor(Manufacturer.getManufacturer("foo"),
"X6", "Description of X6", Motor.Type.RELOAD,
new double[] {0, 2, Motor.PLUGGED}, radius*2, length,
new double[] {0, 2, Motor.PLUGGED_DELAY}, radius*2, length,
new double[] {0, 1, 3, 4}, // time
new double[] {0, 2, 3, 0}, // thrust
new Coordinate[] {

View File

@ -9,6 +9,7 @@ import org.junit.Test;
import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.TestRockets;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
public class ParallelStageTest extends BaseTestCase {
@ -204,6 +205,25 @@ public class ParallelStageTest extends BaseTestCase {
}
@Test
public void testStageAncestry() {
RocketComponent rocket = TestRockets.makeFalcon9Heavy();
AxialStage sustainer = (AxialStage) rocket.getChild(0);
AxialStage core = (AxialStage) rocket.getChild(1);
AxialStage booster = (AxialStage) core.getChild(1);
AxialStage sustainerPrev = sustainer.getPreviousStage();
assertThat("sustainer parent is not found correctly: ", sustainerPrev, equalTo(null));
AxialStage corePrev = core.getPreviousStage();
assertThat("core parent is not found correctly: ", corePrev, equalTo(sustainer));
AxialStage boosterPrev = booster.getPreviousStage();
assertThat("booster parent is not found correctly: ", boosterPrev, equalTo(core));
}
@Test
public void testSetStagePosition_topOfStack() {
// setup

View File

@ -21,8 +21,8 @@ import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.IgnitionEvent;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;

View File

@ -22,9 +22,9 @@ import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.EnumModel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.IgnitionEvent;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;

View File

@ -181,7 +181,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
String sel = (String) delayBox.getSelectedItem();
//// None
if (sel.equalsIgnoreCase(trans.get("TCMotorSelPan.equalsIgnoreCase.None"))) {
selectedDelay = Motor.PLUGGED;
selectedDelay = Motor.PLUGGED_DELAY;
} else {
try {
selectedDelay = Double.parseDouble(sel);

View File

@ -25,10 +25,10 @@ import net.sf.openrocket.gui.components.StyledLabel.Style;
import net.sf.openrocket.gui.dialogs.flightconfiguration.IgnitionSelectionDialog;
import net.sf.openrocket.gui.dialogs.flightconfiguration.MotorMountConfigurationPanel;
import net.sf.openrocket.gui.dialogs.motor.MotorChooserDialog;
import net.sf.openrocket.motor.IgnitionEvent;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.unit.UnitGroup;
@ -215,10 +215,11 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
Motor mtr = motorChooserDialog.getSelectedMotor();
double d = motorChooserDialog.getSelectedDelay();
if (mtr != null) {
MotorConfiguration curInstance = new MotorConfiguration(mtr);
curInstance.setEjectionDelay(d);
curInstance.setIgnitionEvent( IgnitionEvent.NEVER);
curMount.setMotorInstance( fcid, curInstance);
MotorConfiguration curConfig = curMount.getMotorInstance(fcid);
curConfig.setMotor(mtr);
curConfig.setEjectionDelay(d);
curConfig.setIgnitionEvent( IgnitionEvent.NEVER);
curMount.setMotorConfig( curConfig, fcid);
}
fireTableDataChanged();
@ -231,7 +232,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
return;
}
curMount.setMotorInstance( fcid, null);
curMount.setMotorConfig( null, fcid);
fireTableDataChanged();
}

View File

@ -33,9 +33,9 @@ import net.sf.openrocket.gui.dialogs.DetailDialog;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.IgnitionEvent;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.IgnitionEvent;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.customexpression.CustomExpression;