[Bugfix / Refactor] Further Simulation Bugfixes / Streamlining

- Fixed bugs in the simulation event handling:
  -- removed extraneous BURNOUT checks
  -- added MotorClusterState.burnOut(..) update calls on BURNOUT event
  -- added MotorClusterState.expend(..) update calls on EJECTION_CHARGE event
- MotorInstanceId -> MotorConfigurationId (to reflect actual usage)
  -- removed name field (unnecessary)
- changed FlightConfiguration behavior to cache ALL motors, and return active motors as requested
  -- updated corresponding active-motor-list updating through to the simulation layers
This commit is contained in:
Daniel_M_Williams 2016-03-11 19:16:41 -05:00
parent f6d9ad0487
commit d0cb8ab99f
26 changed files with 232 additions and 228 deletions

View File

@ -90,7 +90,7 @@ class MotorMountHandler extends AbstractElementHandler {
return;
}
MotorConfiguration inst = mount.getMotorInstance(fcid);
MotorConfiguration inst = mount.getMotorConfig(fcid);
inst.setIgnitionDelay(ignitionConfigHandler.ignitionDelay);
inst.setIgnitionEvent(ignitionConfigHandler.ignitionEvent);
return;
@ -109,7 +109,7 @@ class MotorMountHandler extends AbstractElementHandler {
return;
}
mount.getDefaultMotorInstance().setIgnitionEvent(event);
mount.getDefaultMotorConfig().setIgnitionEvent(event);
return;
}
@ -123,7 +123,7 @@ class MotorMountHandler extends AbstractElementHandler {
return;
}
mount.getDefaultMotorInstance().setIgnitionDelay(d);
mount.getDefaultMotorConfig().setIgnitionDelay(d);
return;
}

View File

@ -179,7 +179,7 @@ public class RocketComponentSaver {
List<String> elements = new ArrayList<String>();
MotorConfiguration defaultInstance = mount.getDefaultMotorInstance();
MotorConfiguration defaultInstance = mount.getDefaultMotorConfig();
elements.add("<motormount>");
@ -192,7 +192,7 @@ public class RocketComponentSaver {
for( FlightConfigurationId fcid : rkt.getIds()){
MotorConfiguration motorInstance = mount.getMotorInstance(fcid);
MotorConfiguration motorInstance = mount.getMotorConfig(fcid);
// Nothing is stored if no motor loaded
if( motorInstance.isEmpty()){
continue;

View File

@ -69,7 +69,7 @@ public class MotorDescriptionSubstitutor implements RocketSubstitutor {
} else if (c instanceof MotorMount) {
MotorMount mount = (MotorMount) c;
MotorConfiguration inst = mount.getMotorInstance(fcid);
MotorConfiguration inst = mount.getMotorConfig(fcid);
Motor motor = inst.getMotor();
if (mount.isMotorMount() && motor != null) {

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.motor;
import net.sf.openrocket.rocketcomponent.FlightConfigurableParameter;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Coordinate;
@ -13,12 +14,13 @@ import net.sf.openrocket.util.Inertia;
*/
public class MotorConfiguration implements FlightConfigurableParameter<MotorConfiguration> {
public static final String EMPTY_DESCRIPTION = "Empty Configuration";
public static final String EMPTY_DESCRIPTION = "Empty Configuration".intern();
protected final MotorMount mount;
protected final FlightConfigurationId fcid;
protected final MotorInstanceId id;
protected final MotorConfigurationId id;
protected String name = "";
protected Motor motor = null;
protected double ejectionDelay = 0.0;
@ -29,9 +31,16 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
protected int modID = 0;
public MotorConfiguration( final MotorMount _mount, final FlightConfigurationId _fcid ) {
if (null == _mount ) {
throw new NullPointerException("Provided MotorMount was null");
}
if (null == _fcid ) {
throw new NullPointerException("Provided FlightConfigurationId was null");
}
this.mount = _mount;
this.fcid = _fcid;
this.id = new MotorInstanceId( _mount, _fcid);
this.id = new MotorConfigurationId( _mount, _fcid );
this.motor = null;
ejectionDelay = 0.0;
@ -52,12 +61,13 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
}
}
public MotorInstanceId getID() {
public MotorConfigurationId getID() {
return this.id;
}
public void setMotor(Motor motor){
this.motor = motor;
updateName();
}
public Motor getMotor() {
@ -110,13 +120,9 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
}
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);
}
RocketComponent comp = (RocketComponent) mount;
double delta_x = comp.getLength() + mount.getMotorOverhang() - this.motor.getLength();
return new Coordinate(delta_x, 0, 0);
}
public double getUnitLongitudinalInertia() {
@ -188,6 +194,21 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
@Override
public void update(){
}
private void updateName(){
if( null != motor ){
this.name = this.mount.getID() + "-"+ getDescription();
}
}
public int getMotorCount() {
if( mount instanceof InnerTube ){
InnerTube inner = (InnerTube) mount;
return inner.getClusterConfiguration().getClusterCount();
}else{
return 1;
}
}
}

View File

@ -12,18 +12,16 @@ import net.sf.openrocket.rocketcomponent.MotorMount;
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public final class MotorInstanceId {
public final class MotorConfigurationId {
private final String name ;
private final UUID key;
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 final static String ERROR_ID_TEXT = "MotorInstance Error Id".intern();
private final static UUID ERROR_KEY = new UUID( 62274413, 56768908);
public final static MotorConfigurationId ERROR_ID = new MotorConfigurationId();
private MotorInstanceId( ) {
this.name = MotorInstanceId.ERROR_ID_TEXT;
this.key = MotorInstanceId.ERROR_KEY;
private MotorConfigurationId( ) {
this.key = MotorConfigurationId.ERROR_KEY;
}
/**
@ -32,18 +30,17 @@ public final class MotorInstanceId {
* @param componentName the component ID, must not be null
* @param number a positive motor number
*/
public MotorInstanceId(final MotorMount _mount, final FlightConfigurationId _fcid ) {
public MotorConfigurationId(final MotorMount _mount, final FlightConfigurationId _fcid) {
if (null == _mount ) {
throw new IllegalArgumentException("Provided MotorConfiguration was null");
throw new NullPointerException("Provided MotorMount was null");
}
if (null == _fcid ) {
throw new IllegalArgumentException("Provided MotorConfiguration was null");
throw new NullPointerException("Provided FlightConfigurationId was null");
}
// Use intern so comparison can be done using == instead of equals()
this.name = _mount.getID()+"-"+_fcid.toShortKey();
final long upper = _mount.getID().hashCode() << 32;
final long lower = _fcid.key.getMostSignificantBits();
final long upper = ((long)_mount.getID().hashCode()) << 32;
final long lower = _fcid.key.getLeastSignificantBits();
this.key = new UUID( upper, lower);
}
@ -53,10 +50,10 @@ public final class MotorInstanceId {
if (this == other)
return true;
if (!(other instanceof MotorInstanceId))
if (!(other instanceof MotorConfigurationId))
return false;
MotorInstanceId otherId = (MotorInstanceId) other;
MotorConfigurationId otherId = (MotorConfigurationId) other;
return ( this.key.equals( otherId.key));
}
@ -67,10 +64,10 @@ public final class MotorInstanceId {
@Override
public String toString(){
if( this.key == MotorInstanceId.ERROR_KEY){
return MotorInstanceId.ERROR_ID_TEXT;
if( this.key == MotorConfigurationId.ERROR_KEY){
return MotorConfigurationId.ERROR_ID_TEXT;
}else{
return name;
return key.toString();
}
}
}

View File

@ -363,12 +363,12 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
//////////////// Motor mount /////////////////
@Override
public MotorConfiguration getDefaultMotorInstance(){
public MotorConfiguration getDefaultMotorConfig(){
return this.motors.getDefault();
}
@Override
public MotorConfiguration getMotorInstance( final FlightConfigurationId fcid){
public MotorConfiguration getMotorConfig( final FlightConfigurationId fcid){
return this.motors.get(fcid);
}

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.rocketcomponent;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.Set;
@ -11,7 +12,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
@ -28,8 +29,8 @@ import net.sf.openrocket.util.Monitorable;
public class FlightConfiguration implements FlightConfigurableParameter<FlightConfiguration>, Monitorable {
private static final Logger log = LoggerFactory.getLogger(FlightConfiguration.class);
public final static String DEFAULT_CONFIGURATION_NAME = "Default Configuration";
public final static String NO_MOTORS_TEXT = "[No Motors Defined]";
public final static String DEFAULT_CONFIGURATION_NAME = "Default Configuration".intern();
public final static String NO_MOTORS_TEXT = "[No Motors Defined]".intern();
protected String configurationName=null;
@ -63,7 +64,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
/* Cached data */
final protected HashMap<Integer, StageFlags> stages = new HashMap<Integer, StageFlags>();
protected final HashMap<MotorInstanceId, MotorConfiguration> motors = new HashMap<MotorInstanceId, MotorConfiguration>();
final protected HashMap<MotorConfigurationId, MotorConfiguration> motors = new HashMap<MotorConfigurationId, MotorConfiguration>();
private int boundsModID = -1;
private ArrayList<Coordinate> cachedBounds = new ArrayList<Coordinate>();
@ -306,7 +307,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
for ( RocketComponent comp : getActiveComponents() ){
if (( comp instanceof MotorMount )&&( ((MotorMount)comp).isMotorMount())){
MotorMount mount = (MotorMount)comp;
MotorConfiguration motorConfig = mount.getMotorInstance( fcid);
MotorConfiguration motorConfig = mount.getMotorConfig( fcid);
if( first ){
first = false;
@ -343,7 +344,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
if( motorConfig.isEmpty() ){
throw new IllegalArgumentException("MotorInstance is empty.");
}
MotorInstanceId id = motorConfig.getID();
MotorConfigurationId id = motorConfig.getID();
if (this.motors.containsKey(id)) {
throw new IllegalArgumentException("FlightConfiguration already " +
"contains a motor with id " + id);
@ -353,11 +354,11 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
modID++;
}
public Set<MotorInstanceId> getMotorIDs() {
public Set<MotorConfigurationId> getMotorIDs() {
return motors.keySet();
}
public MotorConfiguration getMotorInstance(MotorInstanceId id) {
public MotorConfiguration getMotorInstance(MotorConfigurationId id) {
return motors.get(id);
}
@ -365,22 +366,35 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
return (0 < motors.size());
}
public Collection<MotorConfiguration> getAllMotors() {
return this.motors.values();
}
public Collection<MotorConfiguration> getActiveMotors() {
return motors.values();
Collection<MotorConfiguration> activeMotors = new ArrayList<MotorConfiguration>();
for( MotorConfiguration config : this.motors.values() ){
if( isComponentActive( config.getMount() )){
activeMotors.add( config );
}
}
return activeMotors;
}
protected void updateMotors() {
this.motors.clear();
for ( RocketComponent compMount : getActiveComponents() ){
if (( compMount instanceof MotorMount )&&( ((MotorMount)compMount).isMotorMount())){
MotorMount mount = (MotorMount)compMount;
MotorConfiguration sourceConfig = mount.getMotorInstance( fcid);
if( sourceConfig.isEmpty()){
Iterator<RocketComponent> iter = rocket.iterator(false);
while( iter.hasNext() ){
RocketComponent comp = iter.next();
if (( comp instanceof MotorMount )&&( ((MotorMount)comp).isMotorMount())){
MotorMount mount = (MotorMount)comp;
MotorConfiguration motorConfig = mount.getMotorConfig( fcid);
if( motorConfig.isEmpty()){
continue;
}
this.motors.put( sourceConfig.getID(), sourceConfig);
this.motors.put( motorConfig.getID(), motorConfig);
}
}
}
@ -394,12 +408,16 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
/////////////// Helper methods ///////////////
/**
* Return whether a component is in the currently active stages.
* Return whether a component is in a currently active stages.
*/
public boolean isComponentActive(final RocketComponent c) {
int stageNum = c.getStageNumber();
return this.isStageActive( stageNum );
}
public boolean isComponentActive(final MotorMount c) {
return isComponentActive( (RocketComponent) c);
}
/**
* Return the bounds of the current configuration. The bounds are cached.

View File

@ -12,9 +12,9 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
private final static long DEFAULT_MOST_SIG_BITS = 0xF4F2F1F0;
private final static UUID ERROR_UUID = new UUID( DEFAULT_MOST_SIG_BITS, 2489);
private final static String ERROR_KEY_NAME = "ErrorKey";
private final static String ERROR_KEY_NAME = "ErrorKey".intern();
private final static UUID DEFAULT_VALUE_UUID = new UUID( DEFAULT_MOST_SIG_BITS, 5676);
private final static String DEFAULT_VALUE_NAME = "DefaultKey";
private final static String DEFAULT_VALUE_NAME = "DefaultKey".intern();
public final static FlightConfigurationId ERROR_FCID = new FlightConfigurationId( FlightConfigurationId.ERROR_UUID);
public final static FlightConfigurationId DEFAULT_VALUE_FCID = new FlightConfigurationId( FlightConfigurationId.DEFAULT_VALUE_UUID );

View File

@ -271,12 +271,12 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra
//////////////// Motor mount /////////////////
@Override
public MotorConfiguration getDefaultMotorInstance(){
public MotorConfiguration getDefaultMotorConfig(){
return this.motors.getDefault();
}
@Override
public MotorConfiguration getMotorInstance( final FlightConfigurationId fcid){
public MotorConfiguration getMotorConfig( final FlightConfigurationId fcid){
return this.motors.get(fcid);
}

View File

@ -45,7 +45,7 @@ public interface MotorMount extends ChangeSource, FlightConfigurableComponent {
*
* @return The default MotorInstance
*/
public MotorConfiguration getDefaultMotorInstance();
public MotorConfiguration getDefaultMotorConfig();
/**
* Default implementatino supplied by RocketComponent (returns 1);
@ -73,7 +73,7 @@ public interface MotorMount extends ChangeSource, FlightConfigurableComponent {
* @param fcid id for which to return the motor (null retrieves the default)
* @return requested motorInstance (which may also be the default motor instance)
*/
public MotorConfiguration getMotorInstance( final FlightConfigurationId fcid);
public MotorConfiguration getMotorConfig( final FlightConfigurationId fcid);
/**
*

View File

@ -191,6 +191,10 @@ public class Rocket extends RocketComponent {
public Collection<AxialStage> getStageList() {
return this.stageMap.values();
}
public AxialStage getStage( final int stageNumber ) {
return this.stageMap.get( stageNumber);
}
/*
* Returns the stage at the top of the central stack
@ -662,7 +666,7 @@ public class Rocket extends RocketComponent {
MotorMount mount = (MotorMount) c;
if (!mount.isMotorMount())
continue;
if (mount.getMotorInstance(fcid).getMotor() != null) {
if (mount.getMotorConfig(fcid).getMotor() != null) {
return true;
}
}

View File

@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
@ -86,7 +86,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
currentStatus = toSimulate.pop();
log.info(">>Starting simulation of branch: "+currentStatus.getFlightData().getBranchName());
FlightDataBranch dataBranch = simulateLoop();
flightData.addBranch(dataBranch);
flightData.getWarningSet().addAll(currentStatus.getWarnings());
@ -190,16 +190,15 @@ public class BasicEventSimulationEngine implements SimulationEngine {
currentStatus.getConfiguration().getRocket()));
}
// Check for burnt out motors
for( MotorClusterState state : currentStatus.getMotors()){
//state.update( currentStatus.getSimulationTime() );
if ( state.isFinishedThrusting()){
MotorInstanceId motorId = state.getID();
addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, currentStatus.getSimulationTime(),
(RocketComponent) state.getMount(), motorId));
}
}
// //@Obsolete
// //@Redundant
// // Check for burnt out motors
// for( MotorClusterState state : currentStatus.getActiveMotors()){
// if ( state.isSpent()){
// addEvent(new FlightEvent(FlightEvent.Type.BURNOUT, currentStatus.getSimulationTime(),
// (RocketComponent) state.getMount(), state));
// }
// }
// Check for Tumbling
// Conditions for transision are:
@ -274,16 +273,8 @@ 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 (MotorClusterState state : currentStatus.getAllMotors() ){
for (MotorClusterState state : currentStatus.getActiveMotors() ){
if( state.testForIgnition(event )){
final double simulationTime = currentStatus.getSimulationTime() ;
MotorClusterState sourceState = (MotorClusterState) event.getData();
@ -295,10 +286,8 @@ public class BasicEventSimulationEngine implements SimulationEngine {
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());
log.info("Queueing Ignition Event for: "+state.toDescription()+" @: "+ignitionTime);
//log.info(" Because of "+event.getType().name()+" @"+event.getTime()+" from: "+event.getSource().getName());
addEvent(new FlightEvent(FlightEvent.Type.IGNITION, ignitionTime, mount, state ));
}
@ -342,9 +331,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
case IGNITION: {
MotorClusterState motorState = (MotorClusterState) event.getData();
System.err.println(" >> Igniting motor: "+motorState.getMotor().getDesignation()
+" @"+currentStatus.getSimulationTime()
+" ("+motorState.getMount().getName());
log.info(" Igniting motor: "+motorState.toDescription()+" @"+currentStatus.getSimulationTime());
motorState.ignite( event.getTime());
// Ignite the motor
@ -353,19 +340,17 @@ public class BasicEventSimulationEngine implements SimulationEngine {
// ... 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();
MotorConfigurationId 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;
}
@ -390,13 +375,15 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
// Add ejection charge event
MotorClusterState state = (MotorClusterState) event.getData();
AxialStage stage = state.getMount().getStage();
MotorClusterState motorState = (MotorClusterState) event.getData();
motorState.burnOut( event.getTime() );
AxialStage stage = motorState.getMount().getStage();
log.debug( " adding EJECTION_CHARGE event for stage "+stage.getStageNumber()+": "+stage.getName());
log.debug( " .... for motor "+state.getMotor().getDesignation());
log.debug( " .... for motor "+motorState.getMotor().getDesignation());
double delay = state.getEjectionDelay();
if ( state.hasEjectionCharge() ){
double delay = motorState.getEjectionDelay();
if ( motorState.hasEjectionCharge() ){
addEvent(new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, currentStatus.getSimulationTime() + delay,
stage, event.getData()));
}
@ -405,6 +392,8 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
case EJECTION_CHARGE: {
MotorClusterState motorState = (MotorClusterState) event.getData();
motorState.expend( event.getTime() );
currentStatus.getFlightData().addEvent(event);
break;
}
@ -414,17 +403,20 @@ public class BasicEventSimulationEngine implements SimulationEngine {
currentStatus.getFlightData().addEvent(event);
RocketComponent boosterStage = event.getSource();
int stageNumber = boosterStage.getStageNumber();
final int stageNumber = boosterStage.getStageNumber();
// Prepare the booster status for simulation.
// Mark the status as having dropped the booster
currentStatus.getConfiguration().clearStage( stageNumber);
// Prepare the simulation branch
SimulationStatus boosterStatus = new SimulationStatus(currentStatus);
boosterStatus.setFlightData(new FlightDataBranch(boosterStage.getName(), FlightDataType.TYPE_TIME));
// Mark the booster status as only having the booster.
boosterStatus.getConfiguration().setOnlyStage(stageNumber);
toSimulate.add(boosterStatus);
// Mark the status as having dropped the booster
currentStatus.getConfiguration().clearStage( stageNumber);
log.info(String.format("==>> @ %g; from Branch: %s ---- Branching: %s ---- \n",
currentStatus.getSimulationTime(),
currentStatus.getFlightData().getBranchName(), boosterStatus.getFlightData().getBranchName()));
break;
}
@ -591,14 +583,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
SimulationConditions conds = currentStatus.getSimulationConditions().clone();
conds.getSimulationListenerList().add(OptimumCoastListener.INSTANCE);
BasicEventSimulationEngine e = new BasicEventSimulationEngine();
// log.error(" cloned simConditions: "+conds.toString()
// +" ... "+conds.getRocket().getName()
// +" ... "+conds.getFlightConfigurationID().toShortKey());
// FlightConfigurationID dbid = conds.getFlightConfigurationID();
// FlightConfiguration cloneConfig = conds.getRocket().getFlightConfiguration( dbid );
// System.err.println(" configId: "+dbid.toShortKey());
// System.err.println(" motors detail: "+cloneConfig.toMotorDetail());
FlightData d = e.simulate(conds);
return d;
} catch (Exception e) {

View File

@ -1,21 +1,15 @@
package net.sf.openrocket.simulation;
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.InnerTube;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
public class MotorClusterState {
private static final Logger log = LoggerFactory.getLogger(MotorClusterState.class);
// for reference: set at initialization ONLY.
final protected Motor motor;
final protected MotorConfiguration config;
@ -26,35 +20,18 @@ public class MotorClusterState {
protected double ignitionTime = Double.NaN;
protected double cutoffTime = Double.NaN;
protected double ejectionTime = Double.NaN;
protected ThrustState currentState = ThrustState.PREFLIGHT;
protected ThrustState currentState = ThrustState.ARMED;
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.motor = this.config.getMotor();
this.motorCount = this.config.getMotorCount();
this.thrustDuration = this.motor.getBurnTimeEstimate();
this.resetToPreflight();
this.reset();
}
public void arm( final double _armTime ){
if( ThrustState.PREFLIGHT == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_armTime);
//this.ignitionTime = _ignitionTime;
this.currentState = this.currentState.getNext();
}else{
throw new IllegalStateException("Attempted to arm a motor with status="+this.currentState.getName());
}
}
public double getIgnitionTime() {
return ignitionTime;
}
@ -65,31 +42,31 @@ public class MotorClusterState {
public void ignite( final double _ignitionTime ){
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());
// }else{
// System.err.println("!! Attempted to ignite motor "+toDescription()
// +" with current status="+this.currentState.getName()+" ... Ignoring.");
}
}
public void burnOut( final double _burnOutTime ){
if( ThrustState.THRUSTING == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_burnOutTime);
this.ignitionTime = _burnOutTime;
this.currentState = this.currentState.getNext();
}else{
throw new IllegalStateException("Attempted to stop thrust (burn-out) a motor state with status="+this.currentState.getName());
// }else{
// System.err.println("!! Attempted to turn off motor state "+toDescription()+" with current status="
// +this.currentState.getName()+" ... Ignoring.");
}
}
public void fireEjectionCharge( final double _ejectionTime ){
public void expend( final double _ejectionTime ){
if( ThrustState.DELAYING == currentState ){
log.info( "igniting motor: "+this.toString()+" at t="+_ejectionTime);
this.ejectionTime = _ejectionTime;
this.currentState = this.currentState.getNext();
}else{
throw new IllegalStateException("Attempted to fire an ejection charge in motor state: "+this.currentState.getName());
// }else{
// System.err.println("!! Attempted to mark as spent motor state "+toDescription()+" with current status="
// +this.currentState.getName()+" ... Ignoring.");
}
}
@ -104,7 +81,7 @@ public class MotorClusterState {
return config.getEjectionDelay();
}
public MotorInstanceId getID() {
public MotorConfigurationId getID() {
return config.getID();
}
@ -145,24 +122,20 @@ public class MotorClusterState {
return ! isPlugged();
}
public boolean isFinishedThrusting(){
return currentState.isAfter( ThrustState.THRUSTING );
public boolean isSpent(){
return currentState == ThrustState.SPENT;
}
/**
* alias to 'resetToPreflight()'
*/
public void reset(){
resetToPreflight();
}
public void resetToPreflight(){
// i.e. in the "future"
ignitionTime = Double.POSITIVE_INFINITY;
cutoffTime = Double.POSITIVE_INFINITY;
ejectionTime = Double.POSITIVE_INFINITY;
currentState = ThrustState.PREFLIGHT;
currentState = ThrustState.ARMED;
}
public boolean testForIgnition( final FlightEvent _event ){
@ -170,25 +143,17 @@ public class MotorClusterState {
return getIgnitionEvent().isActivationEvent( _event, mount);
}
public String toDescription(){
return String.format("%32s / %4s - %s",
getMount().getName(), this.motor.getDesignation(), this.currentState.getName());
}
@Override
public String toString(){
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

@ -10,7 +10,7 @@ import java.util.Set;
import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
@ -48,7 +48,8 @@ public class SimulationStatus implements Monitorable {
private double effectiveLaunchRodLength;
// Set of all motors
List<MotorClusterState> motorStateList = new ArrayList<MotorClusterState>();
private List<MotorClusterState> motorStateList = new ArrayList<MotorClusterState>();
/** Nanosecond time when the simulation was started. */
private long simulationStartWallTime = Long.MIN_VALUE;
@ -147,11 +148,7 @@ public class SimulationStatus implements Monitorable {
this.launchRodCleared = false;
this.apogeeReached = false;
for( MotorConfiguration motorConfig : this.configuration.getActiveMotors() ) {
MotorClusterState simMotor = new MotorClusterState( motorConfig);
simMotor.arm( this.time );
this.motorStateList.add( simMotor);
}
this.populateMotors();
this.warnings = new WarningSet();
}
@ -189,7 +186,6 @@ public class SimulationStatus implements Monitorable {
this.deployedRecoveryDevices.clear();
this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices);
// FIXME - is this right?
this.motorStateList.clear();
this.motorStateList.addAll(orig.motorStateList);
@ -215,13 +211,7 @@ public class SimulationStatus implements Monitorable {
public double getSimulationTime() {
return time;
}
public void armAllMotors(){
for( MotorClusterState motor : this.motorStateList ){
motor.resetToPreflight();
}
}
public void setConfiguration(FlightConfiguration configuration) {
if (this.configuration != null)
this.modIDadd += this.configuration.getModID();
@ -233,21 +223,17 @@ public class SimulationStatus implements Monitorable {
return motorStateList;
}
public Collection<MotorClusterState> getAllMotors() {
return motorStateList;
public Collection<MotorClusterState> getActiveMotors() {
List<MotorClusterState> activeList = new ArrayList<MotorClusterState>();
for( MotorClusterState state: this.motorStateList ){
if(( ! state.isSpent()) && (this.configuration.isComponentActive( state.getMount()))){
activeList.add( state );
}
}
return activeList;
}
// public Collection<MotorInstance> getActiveMotors() {
// List<MotorInstance> activeList = new ArrayList<MotorInstance>();
// for( MotorInstance inst : this.motorStateList ){
// if( inst.isActive() ){
// activeList.add( inst );
// }
// }
//
// return activeList;
// }
public FlightConfiguration getConfiguration() {
return configuration;
}
@ -309,7 +295,7 @@ public class SimulationStatus implements Monitorable {
}
public boolean moveBurntOutMotor( final MotorInstanceId motor) {
public boolean moveBurntOutMotor( final MotorConfigurationId motor) {
// get motor from normal list
// remove motor from 'normal' list
// add to spent list
@ -460,12 +446,10 @@ public class SimulationStatus implements Monitorable {
this.simulationConditions = simulationConditions;
}
public SimulationConditions getSimulationConditions() {
return simulationConditions;
}
/**
* Store extra data available for use by simulation listeners. The data can be retrieved
* using {@link #getExtraData(String)}.
@ -506,7 +490,6 @@ public class SimulationStatus implements Monitorable {
}
}
@Override
public int getModID() {
return (modID + modIDadd + simulationConditions.getModID() + configuration.getModID() +
@ -514,5 +497,35 @@ public class SimulationStatus implements Monitorable {
eventQueue.getModID() + warnings.getModID());
}
public String toEventDebug(){
final StringBuilder buf = new StringBuilder("");
for ( FlightEvent event : this.eventQueue){
buf.append(" [t:"+event.getType()+" @"+ event.getTime());
if( null != event.getSource()){
buf.append(" src:"+event.getSource().getName());
}
if( null != event.getData()){
buf.append(" data:"+event.getData().getClass().getSimpleName());
}
buf.append("]\n");
}
return buf.toString();
}
public String toMotorsDebug(){
final StringBuilder buf = new StringBuilder("MotorState list:\n");
for ( MotorClusterState state : this.motorStateList){
buf.append(" ["+state.toDescription()+"]\n");
}
return buf.toString();
}
private void populateMotors(){
motorStateList.clear();
for( MotorConfiguration motorConfig : this.configuration.getAllMotors() ) {
MotorClusterState simMotor = new MotorClusterState( motorConfig);
this.motorStateList.add( simMotor);
}
}
}

View File

@ -2,7 +2,7 @@ package net.sf.openrocket.simulation;
public enum ThrustState {
SPENT("Finished with sequence.", "Finished Producing thrust.", null)
SPENT("Spent", "Finished Producing thrust.", null)
,DELAYING("Delaying", " After Burnout, but before ejection", SPENT){
@Override
public boolean needsSimulation(){ return true;}
@ -14,7 +14,6 @@ public enum ThrustState {
public boolean needsSimulation(){ return true;}
}
,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

View File

@ -13,7 +13,7 @@ import net.sf.openrocket.aerodynamics.AerodynamicForces;
import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.masscalc.MassData;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.AccelerationData;
@ -105,7 +105,7 @@ public class ScriptingSimulationListener implements SimulationListener, Simulati
}
@Override
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorClusterState instance) throws SimulationException {
public boolean motorIgnition(SimulationStatus status, MotorConfigurationId motorId, MotorMount mount, MotorClusterState instance) throws SimulationException {
return invoke(Boolean.class, true, "motorIgnition", status, motorId, mount, instance);
}

View File

@ -4,7 +4,7 @@ import net.sf.openrocket.aerodynamics.AerodynamicForces;
import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.masscalc.MassData;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.AccelerationData;
@ -72,7 +72,7 @@ public class AbstractSimulationListener implements SimulationListener, Simulatio
}
@Override
public boolean motorIgnition(SimulationStatus status, MotorInstanceId motorId, MotorMount mount, MotorClusterState instance) throws SimulationException {
public boolean motorIgnition(SimulationStatus status, MotorConfigurationId motorId, MotorMount mount, MotorClusterState instance) throws SimulationException {
return true;
}

View File

@ -1,6 +1,6 @@
package net.sf.openrocket.simulation.listeners;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.FlightEvent;
@ -43,7 +43,7 @@ public interface SimulationEventListener {
* @param instance the motor instance being ignited
* @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, MotorConfigurationId motorId, MotorMount mount,
MotorClusterState instance) throws SimulationException;

View File

@ -9,7 +9,7 @@ import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.masscalc.MassData;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.MotorConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.simulation.AccelerationData;
@ -167,7 +167,7 @@ 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,
public static boolean fireMotorIgnition(SimulationStatus status, MotorConfigurationId motorId, MotorMount mount,
MotorClusterState instance) throws SimulationException {
boolean result;
int modID = status.getModID(); // Contains also motor instance

View File

@ -9,6 +9,7 @@ import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.ParallelStage;
@ -299,7 +300,8 @@ public class MassCalculatorTest extends BaseTestCase {
Rocket rocket = TestRockets.makeEstesAlphaIII();
InnerTube mmt = (InnerTube) rocket.getChild(0).getChild(1).getChild(2);
Motor activeMotor = mmt.getMotorInstance( rocket.getSelectedConfiguration().getId()).getMotor();
FlightConfigurationId fcid = rocket.getSelectedConfiguration().getId();
Motor activeMotor = mmt.getMotorConfig( fcid ).getMotor();
String desig = activeMotor.getDesignation();
double expLaunchMass = 0.0164; // kg

View File

@ -69,7 +69,7 @@ public class MotorConfig extends JPanel {
//// Ignition at:
panel.add(new JLabel(trans.get("MotorCfg.lbl.Ignitionat") + " " + CommonStrings.dagger), "");
MotorConfiguration motorInstance = mount.getDefaultMotorInstance();
MotorConfiguration motorInstance = mount.getDefaultMotorConfig();
final EnumModel<IgnitionEvent> igEvModel = new EnumModel<IgnitionEvent>(motorInstance, "IgnitionEvent", IgnitionEvent.values());
final JComboBox<IgnitionEvent> eventBox = new JComboBox<IgnitionEvent>( igEvModel);

View File

@ -47,7 +47,7 @@ public class IgnitionSelectionDialog extends JDialog {
public IgnitionSelectionDialog(Window parent, final FlightConfigurationId curFCID, MotorMount _mount) {
super(parent, trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL);
curMount = _mount;
curMotorInstance = curMount.getMotorInstance(curFCID);
curMotorInstance = curMount.getMotorConfig(curFCID);
startIgnitionEvent = curMotorInstance.getIgnitionEvent();
startIgnitionDelay = curMotorInstance.getIgnitionDelay();
JPanel panel = new JPanel(new MigLayout("fill"));
@ -106,7 +106,7 @@ public class IgnitionSelectionDialog extends JDialog {
IgnitionEvent cie = curMotorInstance.getIgnitionEvent();
// update the default instance
final MotorConfiguration defaultMotorInstance = curMount.getDefaultMotorInstance();
final MotorConfiguration defaultMotorInstance = curMount.getDefaultMotorConfig();
defaultMotorInstance.setIgnitionDelay( cid);
defaultMotorInstance.setIgnitionEvent( cie);

View File

@ -325,7 +325,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
}
motorFilterPanel.setMotorMount(mountToEdit);
MotorConfiguration curMotorInstance = mountToEdit.getMotorInstance(_fcid);
MotorConfiguration curMotorInstance = mountToEdit.getMotorConfig(_fcid);
selectedMotor = null;
selectedMotorSet = null;
selectedDelay = 0;

View File

@ -425,7 +425,7 @@ public class PhotoPanel extends JPanel implements GLEventListener {
continue;
}
final Motor motor = mount.getMotorInstance(motorID).getMotor();
final Motor motor = mount.getMotorConfig(motorID).getMotor();
final double length = motor.getLength();
Coordinate[] position = ((RocketComponent) mount)

View File

@ -215,7 +215,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
Motor mtr = motorChooserDialog.getSelectedMotor();
double d = motorChooserDialog.getSelectedDelay();
if (mtr != null) {
MotorConfiguration curConfig = curMount.getMotorInstance(fcid);
MotorConfiguration curConfig = curMount.getMotorConfig(fcid);
curConfig.setMotor(mtr);
curConfig.setEjectionDelay(d);
curConfig.setIgnitionEvent( IgnitionEvent.NEVER);
@ -261,7 +261,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
if ( (null == fcid )||( null == curMount )){
return;
}
MotorConfiguration curInstance = curMount.getMotorInstance(fcid);
MotorConfiguration curInstance = curMount.getMotorConfig(fcid);
curInstance.useDefaultIgnition();
@ -277,7 +277,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
JLabel label = new JLabel();
label.setLayout(new BoxLayout(label, BoxLayout.X_AXIS));
MotorConfiguration curMotor = mount.getMotorInstance( configId);
MotorConfiguration curMotor = mount.getMotorConfig( configId);
String motorString = getMotorSpecification( curMotor );
JLabel motorDescriptionLabel = new JLabel(motorString);
@ -309,8 +309,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
}
private JLabel getIgnitionEventString(FlightConfigurationId id, MotorMount mount) {
MotorConfiguration defInstance = mount.getDefaultMotorInstance();
MotorConfiguration curInstance = mount.getMotorInstance(id);
MotorConfiguration defInstance = mount.getDefaultMotorConfig();
MotorConfiguration curInstance = mount.getMotorConfig(id);
IgnitionEvent ignitionEvent = curInstance.getIgnitionEvent();
Double ignitionDelay = curInstance.getIgnitionDelay();

View File

@ -356,8 +356,8 @@ public class DesignReport {
MotorMount mount = (MotorMount) c;
// TODO: refactor this... it's redundant with containing if, and could probably be simplified
if (mount.isMotorMount() && (mount.getMotorInstance(motorId) != null) &&(null != mount.getMotorInstance(motorId).getMotor())) {
Motor motor = mount.getMotorInstance(motorId).getMotor();
if (mount.isMotorMount() && (mount.getMotorConfig(motorId) != null) &&(null != mount.getMotorConfig(motorId).getMotor())) {
Motor motor = mount.getMotorConfig(motorId).getMotor();
int motorCount = mount.getMotorCount();