[Bugfix] Fixed Simulations bugs - Sim should be operational now.
Motors are now cloned for each new simulation (including background and foreground runs) -> motors are now cloned within the configuration clone method. -> MotorInstance.reset() resets instance to launch state Removed spurious negative time-step check in ThrustCurveMotorInstance:154 -> was triggered during normal simulation operations. Added MotorInstance time updates to AbstractSimulationStepper: -> moved from MotorInstanceConfiguration.step(...) Misc variable name changes to be more descriptive
This commit is contained in:
parent
65ddd1b2a2
commit
1988ee4266
@ -1,5 +1,6 @@
|
|||||||
package net.sf.openrocket.document;
|
package net.sf.openrocket.document;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.EventListener;
|
import java.util.EventListener;
|
||||||
import java.util.EventObject;
|
import java.util.EventObject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -281,10 +282,9 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FlightConfiguration config = rocket.getFlightConfiguration(options.getId());
|
FlightConfiguration config = rocket.getFlightConfiguration(options.getId());
|
||||||
List<MotorInstance> motorList = config.getActiveMotors();
|
|
||||||
|
|
||||||
//Make sure this simulation has motors.
|
//Make sure this simulation has motors.
|
||||||
if (0 == motorList.size()){
|
if ( ! config.hasMotors() ){
|
||||||
status = Status.CANT_RUN;
|
status = Status.CANT_RUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,14 +337,11 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
|
|
||||||
// Set simulated info after simulation, will not be set in case of exception
|
// Set simulated info after simulation, will not be set in case of exception
|
||||||
simulatedConditions = options.clone();
|
simulatedConditions = options.clone();
|
||||||
final FlightConfiguration configuration = this.rocket.getFlightConfiguration( options.getId());
|
simulatedConfigurationDescription = descriptor.format( this.rocket, options.getId());
|
||||||
|
|
||||||
simulatedConfigurationDescription = descriptor.format(configuration.getRocket(), configuration.getFlightConfigurationID());
|
|
||||||
simulatedRocketID = rocket.getFunctionalModID();
|
simulatedRocketID = rocket.getFunctionalModID();
|
||||||
|
|
||||||
status = Status.UPTODATE;
|
status = Status.UPTODATE;
|
||||||
fireChangeEvent();
|
fireChangeEvent();
|
||||||
configuration.release();
|
|
||||||
} finally {
|
} finally {
|
||||||
mutex.unlock("simulate");
|
mutex.unlock("simulate");
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
|
|||||||
*
|
*
|
||||||
* @return the Method instance, or null
|
* @return the Method instance, or null
|
||||||
*/
|
*/
|
||||||
private static Method getMethod(RocketComponent component, String name, Class[] args) {
|
private static Method getMethod(RocketComponent component, String name, Class<?>[] args) {
|
||||||
Method method = null;
|
Method method = null;
|
||||||
try {
|
try {
|
||||||
method = component.getClass().getMethod(name, args);
|
method = component.getClass().getMethod(name, args);
|
||||||
|
@ -155,7 +155,7 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
|
|||||||
* @param acceleration the average acceleration during the step.
|
* @param acceleration the average acceleration during the step.
|
||||||
* @param cond the average atmospheric conditions during the step.
|
* @param cond the average atmospheric conditions during the step.
|
||||||
*/
|
*/
|
||||||
public abstract void step(double time, double acceleration, AtmosphericConditions cond);
|
public abstract void step(double newTime, double acceleration, AtmosphericConditions cond);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,6 +255,8 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toDebug(){ return toString();}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return MotorInstanceId.EMPTY_ID.getComponentId();
|
return MotorInstanceId.EMPTY_ID.getComponentId();
|
||||||
@ -264,4 +266,8 @@ public abstract class MotorInstance implements FlightConfigurableParameter<Motor
|
|||||||
return modID;
|
return modID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,17 +41,12 @@ public class ThrustCurveMotorInstance extends MotorInstance {
|
|||||||
|
|
||||||
public ThrustCurveMotorInstance(final ThrustCurveMotor source) {
|
public ThrustCurveMotorInstance(final ThrustCurveMotor source) {
|
||||||
//log.debug( Creating motor instance of " + ThrustCurveMotor.this);
|
//log.debug( Creating motor instance of " + ThrustCurveMotor.this);
|
||||||
timeIndex = 0;
|
this.motor = source;
|
||||||
prevTime = 0;
|
this.reset();
|
||||||
instThrust = 0;
|
|
||||||
stepThrust = 0;
|
|
||||||
instCG = source.getLaunchCG();
|
|
||||||
stepCG = source.getLaunchCG();
|
|
||||||
|
|
||||||
unitRotationalInertia = Inertia.filledCylinderRotational(source.getDiameter() / 2);
|
unitRotationalInertia = Inertia.filledCylinderRotational(source.getDiameter() / 2);
|
||||||
unitLongitudinalInertia = Inertia.filledCylinderLongitudinal(source.getDiameter() / 2, source.getLength());
|
unitLongitudinalInertia = Inertia.filledCylinderLongitudinal(source.getDiameter() / 2, source.getLength());
|
||||||
|
|
||||||
this.motor = source;
|
|
||||||
this.id = MotorInstanceId.ERROR_ID;
|
this.id = MotorInstanceId.ERROR_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,12 +148,6 @@ public class ThrustCurveMotorInstance extends MotorInstance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void step(double nextTime, double acceleration, AtmosphericConditions cond) {
|
public void step(double nextTime, double acceleration, AtmosphericConditions cond) {
|
||||||
|
|
||||||
if (!(nextTime >= prevTime)) {
|
|
||||||
// Also catches NaN
|
|
||||||
throw new IllegalArgumentException("Stepping backwards in time, current=" +
|
|
||||||
prevTime + " new=" + nextTime);
|
|
||||||
}
|
|
||||||
if (MathUtil.equals(prevTime, nextTime)) {
|
if (MathUtil.equals(prevTime, nextTime)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -241,11 +230,37 @@ public class ThrustCurveMotorInstance extends MotorInstance {
|
|||||||
clone.ignitionDelay = this.ignitionDelay;
|
clone.ignitionDelay = this.ignitionDelay;
|
||||||
clone.ejectionDelay = this.ejectionDelay;
|
clone.ejectionDelay = this.ejectionDelay;
|
||||||
clone.position = this.position;
|
clone.position = this.position;
|
||||||
this.ignitionTime = Double.POSITIVE_INFINITY;
|
clone.ignitionTime = Double.POSITIVE_INFINITY;
|
||||||
|
//clone.ignitionTime = this.ignitionTime;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset(){
|
||||||
|
timeIndex = 0;
|
||||||
|
prevTime = 0;
|
||||||
|
instThrust = 0;
|
||||||
|
stepThrust = 0;
|
||||||
|
instCG = motor.getLaunchCG();
|
||||||
|
stepCG = instCG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toDebug(){
|
||||||
|
String prefix = " ";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
final RocketComponent mountComp = (RocketComponent)this.mount;
|
||||||
|
|
||||||
|
sb.append(String.format("%sMotor= %s(%s)(in %s)\n", prefix, this.motor.getDesignation(), this.id.toShortKey(), mountComp.getName()));
|
||||||
|
sb.append(String.format("%s Ignite: %s at %+f\n",prefix, this.ignitionEvent.name, this.ignitionDelay));
|
||||||
|
//sb.append(String.format("%s Eject at: %+f\n",prefix, this.ejectionDelay));
|
||||||
|
sb.append(String.format("%s L:%f W:%f @:%f mm\n",prefix, motor.getLength(), motor.getDiameter(), this.position.multiply(1000).x ));
|
||||||
|
sb.append(String.format("%s currentTimem: %f\n", prefix, this.prevTime));
|
||||||
|
sb.append("\n");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return this.id.toString();
|
return this.id.toString();
|
||||||
|
@ -5,7 +5,6 @@ import java.util.Collection;
|
|||||||
import java.util.EventListener;
|
import java.util.EventListener;
|
||||||
import java.util.EventObject;
|
import java.util.EventObject;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@ -14,7 +13,6 @@ import java.util.Set;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
|
|
||||||
import net.sf.openrocket.motor.MotorInstance;
|
import net.sf.openrocket.motor.MotorInstance;
|
||||||
import net.sf.openrocket.motor.MotorInstanceId;
|
import net.sf.openrocket.motor.MotorInstanceId;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
import net.sf.openrocket.util.ArrayList;
|
||||||
@ -68,8 +66,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
|
|
||||||
private int modID = 0;
|
private int modID = 0;
|
||||||
|
|
||||||
private boolean debug = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new configuration with the specified <code>Rocket</code>.
|
* Create a new configuration with the specified <code>Rocket</code>.
|
||||||
*
|
*
|
||||||
@ -91,10 +87,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
rocket.addComponentChangeListener(this);
|
rocket.addComponentChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableDebugging(){
|
|
||||||
this.debug=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rocket getRocket() {
|
public Rocket getRocket() {
|
||||||
return rocket;
|
return rocket;
|
||||||
}
|
}
|
||||||
@ -305,9 +297,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateStages() {
|
private void updateStages() {
|
||||||
if( debug){
|
|
||||||
System.err.println("updating config stages");
|
|
||||||
}
|
|
||||||
if (this.rocket.getStageCount() == this.stages.size()) {
|
if (this.rocket.getStageCount() == this.stages.size()) {
|
||||||
// no changes needed
|
// no changes needed
|
||||||
return;
|
return;
|
||||||
@ -364,7 +353,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
// DEBUG / DEVEL
|
// DEBUG / DEVEL
|
||||||
public String toMotorDetail(){
|
public String toMotorDetail(){
|
||||||
StringBuilder buff = new StringBuilder();
|
StringBuilder buff = new StringBuilder();
|
||||||
buff.append(String.format("\nDumping %2d Motors for configuration %s: \n", this.motors.size(), this.fcid.toShortKey()));
|
buff.append(String.format("\nDumping %2d Motors for configuration %s: \n", this.motors.size(), this));
|
||||||
for( MotorInstance curMotor : this.motors.values() ){
|
for( MotorInstance curMotor : this.motors.values() ){
|
||||||
if( curMotor.isEmpty() ){
|
if( curMotor.isEmpty() ){
|
||||||
buff.append( String.format( " ..[%8s] <empty> \n", curMotor.getID().toShortKey()));
|
buff.append( String.format( " ..[%8s] <empty> \n", curMotor.getID().toShortKey()));
|
||||||
@ -490,21 +479,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
return (0 < motors.size());
|
return (0 < motors.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Collection<MotorInstance> getActiveMotors() {
|
||||||
* Step all of the motor instances to the specified time minus their ignition time.
|
|
||||||
* @param time the "global" time
|
|
||||||
*/
|
|
||||||
public void step(double time, double acceleration, AtmosphericConditions cond) {
|
|
||||||
for (MotorInstance inst : motors.values()) {
|
|
||||||
double t = time - inst.getIgnitionTime();
|
|
||||||
if (t >= 0) {
|
|
||||||
inst.step(t, acceleration, cond);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modID++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MotorInstance> getActiveMotors() {
|
|
||||||
List<MotorInstance> activeList = new ArrayList<MotorInstance>();
|
List<MotorInstance> activeList = new ArrayList<MotorInstance>();
|
||||||
for( MotorInstance inst : this.motors.values() ){
|
for( MotorInstance inst : this.motors.values() ){
|
||||||
if( inst.isActive() ){
|
if( inst.isActive() ){
|
||||||
@ -516,16 +491,13 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateMotors() {
|
public void updateMotors() {
|
||||||
if( debug){
|
|
||||||
System.err.println("updating config motors");
|
|
||||||
}
|
|
||||||
this.motors.clear();
|
this.motors.clear();
|
||||||
|
|
||||||
for ( RocketComponent comp : getActiveComponents() ){
|
for ( RocketComponent compMount : getActiveComponents() ){
|
||||||
if (( comp instanceof MotorMount )&&( ((MotorMount)comp).isMotorMount())){
|
if (( compMount instanceof MotorMount )&&( ((MotorMount)compMount).isMotorMount())){
|
||||||
MotorMount mount = (MotorMount)comp;
|
MotorMount mount = (MotorMount)compMount;
|
||||||
MotorInstance inst = mount.getMotorInstance( fcid);
|
MotorInstance sourceInstance = mount.getMotorInstance( fcid);
|
||||||
if( inst.isEmpty()){
|
if( sourceInstance.isEmpty()){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,30 +505,21 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
// int instancCount = comp.getInstanceCount();
|
// int instancCount = comp.getInstanceCount();
|
||||||
|
|
||||||
// this includes *all* the instancing between here and the rocket root.
|
// this includes *all* the instancing between here and the rocket root.
|
||||||
Coordinate[] instanceLocations= comp.getLocations();
|
Coordinate[] instanceLocations= compMount.getLocations();
|
||||||
|
|
||||||
if( debug){
|
sourceInstance.reset();
|
||||||
System.err.println(String.format(",,,,,,,, %s (%s)",
|
|
||||||
inst.getMotor().getDigest(), inst.getID() ));
|
|
||||||
}
|
|
||||||
int instanceNumber = 1;
|
int instanceNumber = 1;
|
||||||
final int instanceCount = instanceLocations.length;
|
//final int instanceCount = instanceLocations.length;
|
||||||
for ( Coordinate curMountLocation : instanceLocations ){
|
for ( Coordinate curMountLocation : instanceLocations ){
|
||||||
MotorInstance curInstance = inst.clone();
|
MotorInstance cloneInstance = sourceInstance.clone();
|
||||||
curInstance.setID( new MotorInstanceId( comp.getName(), instanceNumber) );
|
cloneInstance.setID( new MotorInstanceId( compMount.getName(), instanceNumber) );
|
||||||
|
|
||||||
// motor location w/in mount: parent.refpoint -> motor.refpoint
|
// motor location w/in mount: parent.refpoint -> motor.refpoint
|
||||||
Coordinate curMotorOffset = curInstance.getOffset();
|
Coordinate curMotorOffset = cloneInstance.getOffset();
|
||||||
curInstance.setPosition( curMountLocation.add(curMotorOffset) );
|
cloneInstance.setPosition( curMountLocation.add(curMotorOffset) );
|
||||||
this.motors.put( curInstance.getID(), curInstance);
|
this.motors.put( cloneInstance.getID(), cloneInstance);
|
||||||
|
|
||||||
// vvvv DEVEL vvvv
|
instanceNumber ++;
|
||||||
if(debug){
|
|
||||||
System.err.println(String.format(",,,,,,,, [%2d/%2d]: %s. (%s)",
|
|
||||||
instanceNumber, instanceCount, curInstance.getMotor().getDigest(), curInstance));
|
|
||||||
}
|
|
||||||
// ^^^^ DEVEL ^^^^
|
|
||||||
instanceNumber ++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -629,7 +592,9 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
clone.setName(this.fcid.toShortKey()+" - clone");
|
clone.setName(this.fcid.toShortKey()+" - clone");
|
||||||
clone.listenerList = new ArrayList<EventListener>();
|
clone.listenerList = new ArrayList<EventListener>();
|
||||||
clone.stages.putAll( (Map<Integer, StageFlags>) this.stages);
|
clone.stages.putAll( (Map<Integer, StageFlags>) this.stages);
|
||||||
clone.motors.putAll( (Map<MotorInstanceId, MotorInstance>) this.motors);
|
for( MotorInstance mi : this.motors.values()){
|
||||||
|
clone.motors.put( mi.getID(), mi.clone());
|
||||||
|
}
|
||||||
clone.cachedBounds = this.cachedBounds.clone();
|
clone.cachedBounds = this.cachedBounds.clone();
|
||||||
clone.modID = this.modID;
|
clone.modID = this.modID;
|
||||||
clone.boundsModID = -1;
|
clone.boundsModID = -1;
|
||||||
|
@ -55,7 +55,7 @@ public enum IgnitionEvent {
|
|||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
public final String name;
|
public final String name;
|
||||||
private final String key;
|
private final String translationKey;
|
||||||
protected String description=null;
|
protected String description=null;
|
||||||
|
|
||||||
//public static final IgnitionEvent[] events = {AUTOMATIC, LAUNCH, EJECTION_CHARGE, BURNOUT, NEVER};
|
//public static final IgnitionEvent[] events = {AUTOMATIC, LAUNCH, EJECTION_CHARGE, BURNOUT, NEVER};
|
||||||
@ -67,7 +67,7 @@ public enum IgnitionEvent {
|
|||||||
|
|
||||||
private IgnitionEvent(final String _name, final String _key) {
|
private IgnitionEvent(final String _name, final String _key) {
|
||||||
this.name = _name;
|
this.name = _name;
|
||||||
this.key = _key;
|
this.translationKey = _key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals( final String content){
|
public boolean equals( final String content){
|
||||||
@ -82,7 +82,7 @@ public enum IgnitionEvent {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if( null == this.description ){
|
if( null == this.description ){
|
||||||
this.description = trans.get(this.key);
|
this.description = trans.get(this.translationKey);
|
||||||
}
|
}
|
||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.sf.openrocket.simulation;
|
package net.sf.openrocket.simulation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
|
|
||||||
import net.sf.openrocket.masscalc.MassCalculator;
|
import net.sf.openrocket.masscalc.MassCalculator;
|
||||||
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
|
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
|
||||||
@ -170,22 +170,17 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
|
|||||||
return thrust;
|
return thrust;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlightConfiguration configuration = status.getConfiguration();
|
|
||||||
|
|
||||||
//MotorInstanceConfiguration mic = status.getMotorConfiguration();
|
|
||||||
// Iterate over the motors and calculate combined thrust
|
|
||||||
//if (!stepMotors) {
|
|
||||||
// mic = mic.clone();
|
|
||||||
//}
|
|
||||||
//mic.step(status.getSimulationTime() + timestep, acceleration, atmosphericConditions);
|
|
||||||
|
|
||||||
// now this is a valid reason for the MotorConfiguration :P
|
|
||||||
configuration.step(status.getSimulationTime() + timestep, acceleration, atmosphericConditions);
|
|
||||||
thrust = 0;
|
thrust = 0;
|
||||||
|
final double currentTime = status.getSimulationTime() + timestep;
|
||||||
|
Collection<MotorInstance> activeMotorList = status.getConfiguration().getActiveMotors();
|
||||||
|
for (MotorInstance currentMotorInstance : activeMotorList ) {
|
||||||
|
// old: transplanted from MotorInstanceConfiguration
|
||||||
|
double instanceTime = currentTime - currentMotorInstance.getIgnitionTime();
|
||||||
|
if (instanceTime >= 0) {
|
||||||
|
currentMotorInstance.step(instanceTime, acceleration, atmosphericConditions);
|
||||||
|
}
|
||||||
|
|
||||||
//?? needs to instance the motors...
|
// old: from here
|
||||||
List<MotorInstance> activeMotors = configuration.getActiveMotors();
|
|
||||||
for (MotorInstance currentMotorInstance : activeMotors) {
|
|
||||||
thrust += currentMotorInstance.getThrust();
|
thrust += currentMotorInstance.getThrust();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.sf.openrocket.simulation;
|
package net.sf.openrocket.simulation;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -56,15 +56,9 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
|
|
||||||
private FlightConfigurationID fcid;
|
private FlightConfigurationID fcid;
|
||||||
|
|
||||||
// old: protected Stack<SimulationStatus> stages = new Stack<SimulationStatus>();
|
|
||||||
// this variable was class member stack, but parallel staging breaks metaphor:
|
|
||||||
// parallel stages may ignite before OR after their 'inner' stages
|
|
||||||
|
|
||||||
|
|
||||||
// this is just a list of simulation branches to
|
// this is just a list of simulation branches to
|
||||||
Deque<SimulationStatus> toSimulate = new ArrayDeque<SimulationStatus>();
|
Deque<SimulationStatus> toSimulate = new ArrayDeque<SimulationStatus>();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlightData simulate(SimulationConditions simulationConditions) throws SimulationException {
|
public FlightData simulate(SimulationConditions simulationConditions) throws SimulationException {
|
||||||
|
|
||||||
@ -72,21 +66,17 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
FlightData flightData = new FlightData();
|
FlightData flightData = new FlightData();
|
||||||
|
|
||||||
// Set up rocket configuration
|
// Set up rocket configuration
|
||||||
this.fcid = simulationConditions.getConfigurationID();
|
this.fcid = simulationConditions.getFlightConfigurationID();
|
||||||
FlightConfiguration configuration = simulationConditions.getRocket().getFlightConfiguration( this.fcid);
|
FlightConfiguration simulationConfig = simulationConditions.getRocket().getFlightConfiguration( this.fcid).clone();
|
||||||
|
if ( ! simulationConfig.hasMotors() ) {
|
||||||
List<MotorInstance> activeMotors = configuration.getActiveMotors();
|
throw new MotorIgnitionException(trans.get("BasicEventSimulationEngine.error.noMotorsDefined"));
|
||||||
if ( activeMotors.isEmpty() ) {
|
|
||||||
final String errorMessage = trans.get("BasicEventSimulationEngine.error.noMotorsDefined");
|
|
||||||
log.info(errorMessage);
|
|
||||||
throw new MotorIgnitionException(errorMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentStatus = new SimulationStatus(configuration, simulationConditions);
|
currentStatus = new SimulationStatus(simulationConfig, simulationConditions);
|
||||||
currentStatus.getEventQueue().add(new FlightEvent(FlightEvent.Type.LAUNCH, 0, simulationConditions.getRocket()));
|
currentStatus.getEventQueue().add(new FlightEvent(FlightEvent.Type.LAUNCH, 0, simulationConditions.getRocket()));
|
||||||
{
|
{
|
||||||
// main simulation branch
|
// main simulation branch
|
||||||
final String branchName = configuration.getRocket().getTopmostStage().getName();
|
final String branchName = simulationConfig.getRocket().getTopmostStage().getName();
|
||||||
currentStatus.setFlightData(new FlightDataBranch( branchName, FlightDataType.TYPE_TIME));
|
currentStatus.setFlightData(new FlightDataBranch( branchName, FlightDataType.TYPE_TIME));
|
||||||
}
|
}
|
||||||
toSimulate.add(currentStatus);
|
toSimulate.add(currentStatus);
|
||||||
@ -103,19 +93,18 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
flightData.addBranch(dataBranch);
|
flightData.addBranch(dataBranch);
|
||||||
flightData.getWarningSet().addAll(currentStatus.getWarnings());
|
flightData.getWarningSet().addAll(currentStatus.getWarnings());
|
||||||
|
|
||||||
log.info(String.format("<<Finished simulating branch: %s at:%s",
|
log.info(String.format("<<Finished simulating branch: %s curTime:%s finTime:%s",
|
||||||
currentStatus.getFlightData().getBranchName(),
|
dataBranch.getBranchName(),
|
||||||
currentStatus.getFlightData().getLast(FlightDataType.TYPE_TIME)));
|
currentStatus.getSimulationTime(),
|
||||||
|
dataBranch.getLast(FlightDataType.TYPE_TIME)));
|
||||||
}while( ! toSimulate.isEmpty());
|
}while( ! toSimulate.isEmpty());
|
||||||
|
|
||||||
SimulationListenerHelper.fireEndSimulation(currentStatus, null);
|
SimulationListenerHelper.fireEndSimulation(currentStatus, null);
|
||||||
|
|
||||||
configuration.release();
|
|
||||||
|
|
||||||
if (!flightData.getWarningSet().isEmpty()) {
|
if (!flightData.getWarningSet().isEmpty()) {
|
||||||
log.info("Warnings at the end of simulation: " + flightData.getWarningSet());
|
log.info("Warnings at the end of simulation: " + flightData.getWarningSet());
|
||||||
}
|
}
|
||||||
|
simulationConfig.release();
|
||||||
return flightData;
|
return flightData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,12 +119,9 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
Coordinate originVelocity = currentStatus.getRocketVelocity();
|
Coordinate originVelocity = currentStatus.getRocketVelocity();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log.info(String.format(" >> Starting simulate loop."));
|
|
||||||
|
|
||||||
// Start the simulation
|
// Start the simulation
|
||||||
while (handleEvents()) {
|
while (handleEvents()) {
|
||||||
log.info(String.format(" >> Events Handled."));
|
|
||||||
|
|
||||||
// Take the step
|
// Take the step
|
||||||
double oldAlt = currentStatus.getRocketPosition().z;
|
double oldAlt = currentStatus.getRocketPosition().z;
|
||||||
|
|
||||||
@ -286,7 +272,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
log.trace("BasicEventSimulationEngine: Handling event " + event);
|
log.trace("BasicEventSimulationEngine: Handling event " + event);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.trace(String.format(" >> about to ignite motors events"));
|
|
||||||
if (event.getType() == FlightEvent.Type.IGNITION) {
|
if (event.getType() == FlightEvent.Type.IGNITION) {
|
||||||
MotorMount mount = (MotorMount) event.getSource();
|
MotorMount mount = (MotorMount) event.getSource();
|
||||||
MotorInstanceId motorId = (MotorInstanceId) event.getData();
|
MotorInstanceId motorId = (MotorInstanceId) event.getData();
|
||||||
@ -295,7 +280,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.trace(String.format(" >> about to fire motors (?) events"));
|
|
||||||
if (event.getType() == FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT) {
|
if (event.getType() == FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT) {
|
||||||
RecoveryDevice device = (RecoveryDevice) event.getSource();
|
RecoveryDevice device = (RecoveryDevice) event.getSource();
|
||||||
if (!SimulationListenerHelper.fireRecoveryDeviceDeployment(currentStatus, device)) {
|
if (!SimulationListenerHelper.fireRecoveryDeviceDeployment(currentStatus, device)) {
|
||||||
@ -303,8 +287,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.trace(String.format(" >> about to check for motors ignite events"));
|
|
||||||
|
|
||||||
// Check for motor ignition events, add ignition events to queue
|
// Check for motor ignition events, add ignition events to queue
|
||||||
for (MotorInstance motor : currentStatus.getFlightConfiguration().getActiveMotors() ){
|
for (MotorInstance motor : currentStatus.getFlightConfiguration().getActiveMotors() ){
|
||||||
MotorInstanceId mid = motor.getID();
|
MotorInstanceId mid = motor.getID();
|
||||||
@ -322,7 +304,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
|
|
||||||
|
|
||||||
// Check for stage separation event
|
// Check for stage separation event
|
||||||
|
|
||||||
for (AxialStage stage : currentStatus.getConfiguration().getActiveStages()) {
|
for (AxialStage stage : currentStatus.getConfiguration().getActiveStages()) {
|
||||||
int stageNo = stage.getStageNumber();
|
int stageNo = stage.getStageNumber();
|
||||||
if (stageNo == 0)
|
if (stageNo == 0)
|
||||||
@ -348,8 +329,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.trace(String.format(" >> about to handle events"));
|
|
||||||
|
|
||||||
// Handle event
|
// Handle event
|
||||||
switch (event.getType()) {
|
switch (event.getType()) {
|
||||||
|
|
||||||
@ -445,7 +424,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
// TODO: HIGH: Check stage activeness for other events as well?
|
// TODO: HIGH: Check stage activeness for other events as well?
|
||||||
|
|
||||||
// Check whether any motor in the active stages is active anymore
|
// Check whether any motor in the active stages is active anymore
|
||||||
List<MotorInstance> activeMotors = currentStatus.getConfiguration().getActiveMotors();
|
Collection<MotorInstance> activeMotors = currentStatus.getConfiguration().getActiveMotors();
|
||||||
for (MotorInstance curMotor : activeMotors) {
|
for (MotorInstance curMotor : activeMotors) {
|
||||||
RocketComponent comp = ((RocketComponent) curMotor.getMount());
|
RocketComponent comp = ((RocketComponent) curMotor.getMount());
|
||||||
int stageNumber = comp.getStageNumber();
|
int stageNumber = comp.getStageNumber();
|
||||||
@ -471,6 +450,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
// to determine the optimum altitude.
|
// to determine the optimum altitude.
|
||||||
if (currentStatus.getSimulationConditions().isCalculateExtras() && !currentStatus.isApogeeReached()) {
|
if (currentStatus.getSimulationConditions().isCalculateExtras() && !currentStatus.isApogeeReached()) {
|
||||||
FlightData coastStatus = computeCoastTime();
|
FlightData coastStatus = computeCoastTime();
|
||||||
|
|
||||||
currentStatus.getFlightData().setOptimumAltitude(coastStatus.getMaxAltitude());
|
currentStatus.getFlightData().setOptimumAltitude(coastStatus.getMaxAltitude());
|
||||||
currentStatus.getFlightData().setTimeToOptimumAltitude(coastStatus.getTimeToApogee());
|
currentStatus.getFlightData().setTimeToOptimumAltitude(coastStatus.getTimeToApogee());
|
||||||
}
|
}
|
||||||
@ -580,6 +560,13 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
SimulationConditions conds = currentStatus.getSimulationConditions().clone();
|
SimulationConditions conds = currentStatus.getSimulationConditions().clone();
|
||||||
conds.getSimulationListenerList().add(OptimumCoastListener.INSTANCE);
|
conds.getSimulationListenerList().add(OptimumCoastListener.INSTANCE);
|
||||||
BasicEventSimulationEngine e = new BasicEventSimulationEngine();
|
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);
|
FlightData d = e.simulate(conds);
|
||||||
return d;
|
return d;
|
||||||
|
@ -265,6 +265,10 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
|||||||
w = status.getSimulationConditions().getGeodeticComputation().addCoordinate(w, status.getRocketPosition());
|
w = status.getSimulationConditions().getGeodeticComputation().addCoordinate(w, status.getRocketPosition());
|
||||||
status.setRocketWorldPosition(w);
|
status.setRocketWorldPosition(w);
|
||||||
|
|
||||||
|
if (!(0 <= store.timestep)) {
|
||||||
|
// Also catches NaN
|
||||||
|
throw new IllegalArgumentException("Stepping backwards in time, timestep=" +store.timestep);
|
||||||
|
}
|
||||||
status.setSimulationTime(status.getSimulationTime() + store.timestep);
|
status.setSimulationTime(status.getSimulationTime() + store.timestep);
|
||||||
|
|
||||||
status.setPreviousTimeStep(store.timestep);
|
status.setPreviousTimeStep(store.timestep);
|
||||||
|
@ -28,7 +28,7 @@ import net.sf.openrocket.util.WorldCoordinate;
|
|||||||
public class SimulationConditions implements Monitorable, Cloneable {
|
public class SimulationConditions implements Monitorable, Cloneable {
|
||||||
|
|
||||||
private Rocket rocket;
|
private Rocket rocket;
|
||||||
private FlightConfigurationID configID= null;
|
private FlightConfigurationID configId= null;
|
||||||
|
|
||||||
private Simulation simulation; // The parent simulation
|
private Simulation simulation; // The parent simulation
|
||||||
|
|
||||||
@ -116,15 +116,15 @@ public class SimulationConditions implements Monitorable, Cloneable {
|
|||||||
|
|
||||||
|
|
||||||
public FlightConfigurationID getMotorConfigurationID() {
|
public FlightConfigurationID getMotorConfigurationID() {
|
||||||
return configID;
|
return configId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlightConfigurationID getConfigurationID() {
|
public FlightConfigurationID getFlightConfigurationID() {
|
||||||
return configID;
|
return configId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFlightConfigurationID(FlightConfigurationID _fcid) {
|
public void setFlightConfigurationID(FlightConfigurationID _fcid) {
|
||||||
this.configID = _fcid;
|
this.configId = _fcid;
|
||||||
this.modID++;
|
this.modID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,6 +327,9 @@ public class SimulationConditions implements Monitorable, Cloneable {
|
|||||||
for (SimulationListener listener : this.simulationListeners) {
|
for (SimulationListener listener : this.simulationListeners) {
|
||||||
clone.simulationListeners.add(listener.clone());
|
clone.simulationListeners.add(listener.clone());
|
||||||
}
|
}
|
||||||
|
clone.rocket = this.rocket; // the rocket should be read-only from this point
|
||||||
|
clone.configId = this.configId; // configIds are read-only
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
} catch (CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
throw new BugException(e);
|
throw new BugException(e);
|
||||||
|
@ -19,6 +19,9 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.event.TableModelEvent;
|
import javax.swing.event.TableModelEvent;
|
||||||
import javax.swing.event.TableModelListener;
|
import javax.swing.event.TableModelListener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sf.openrocket.gui.components.StyledLabel;
|
import net.sf.openrocket.gui.components.StyledLabel;
|
||||||
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
||||||
@ -35,7 +38,6 @@ import net.sf.openrocket.unit.UnitGroup;
|
|||||||
import net.sf.openrocket.util.Chars;
|
import net.sf.openrocket.util.Chars;
|
||||||
|
|
||||||
public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount> {
|
public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount> {
|
||||||
|
|
||||||
private static final long serialVersionUID = -5046535300435793744L;
|
private static final long serialVersionUID = -5046535300435793744L;
|
||||||
|
|
||||||
private static final String NONE = trans.get("edtmotorconfdlg.tbl.None");
|
private static final String NONE = trans.get("edtmotorconfdlg.tbl.None");
|
||||||
@ -250,14 +252,13 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this call also performs the update changes
|
||||||
IgnitionSelectionDialog ignitionDialog = new IgnitionSelectionDialog(
|
IgnitionSelectionDialog ignitionDialog = new IgnitionSelectionDialog(
|
||||||
SwingUtilities.getWindowAncestor(this.flightConfigurationPanel),
|
SwingUtilities.getWindowAncestor(this.flightConfigurationPanel),
|
||||||
fcid,
|
fcid,
|
||||||
curMount);
|
curMount);
|
||||||
ignitionDialog.setVisible(true);
|
ignitionDialog.setVisible(true);
|
||||||
|
|
||||||
// changes performed automatically within "new IgnitionSelectionDialog(...)"
|
|
||||||
|
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user