Correct motor mass calculation for motor ignition time

Adds the MotorClusterState from the current SimulationState to the MassCalculation constructor.  The ignition time of each motor is subtracted from the current simulationTime to calculate its current mass.

MassCalculation is also used for static analysis; in this case a synthetic time is passed (and there is no SimulationState).  In this case, a null is passed in to the MassCalculation constructor; whether or not this the case is used to determine whether or not to calculate a motor time based on its ignition time.

Also clamp motorTime from MotorClusterState to be no less than 0 when calculating motor mass.
This commit is contained in:
JoePfeiffer 2020-09-06 20:08:30 -06:00
parent b64a3b3fa8
commit f5d56f6e99
3 changed files with 36 additions and 12 deletions

View File

@ -1,11 +1,13 @@
package net.sf.openrocket.masscalc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.*;
import net.sf.openrocket.simulation.MotorClusterState;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Transformation;
@ -71,7 +73,7 @@ public class MassCalculation {
}
public MassCalculation copy( final RocketComponent _root, final Transformation _transform){
return new MassCalculation( this.type, this.config, this.simulationTime, _root, _transform, this.analysisMap);
return new MassCalculation( this.type, this.config, this.simulationTime, this.activeMotorList, _root, _transform, this.analysisMap);
}
public Coordinate getCM() {
@ -108,12 +110,14 @@ public class MassCalculation {
}
public MassCalculation( final Type _type, final FlightConfiguration _config, final double _time,
final Collection<MotorClusterState> _activeMotorList,
final RocketComponent _root, final Transformation _transform,
Map<Integer, CMAnalysisEntry> _map)
{
type = _type;
config = _config;
simulationTime = _time;
activeMotorList = _activeMotorList;
root = _root;
transform = _transform;
analysisMap = _map;
@ -156,6 +160,7 @@ public class MassCalculation {
// === package-private ===
final FlightConfiguration config;
final double simulationTime;
final Collection<MotorClusterState> activeMotorList;
final RocketComponent root;
final Transformation transform;
final Type type;
@ -182,11 +187,24 @@ public class MassCalculation {
final MotorMount mount = (MotorMount)root;
MotorConfiguration motorConfig = mount.getMotorConfig( config.getId() );
final Motor motor = motorConfig.getMotor();
if( motorConfig.isEmpty() ){
return this;
}
final Motor motor = motorConfig.getMotor();
// If we don't have any MotorClusterStates,
// we're using a synthetic time to do a static analysis.
// If we do have MotorClusterStates, we need to adjust
// time according to motor ignition time.
double motorTime = simulationTime;
if (activeMotorList != null) {
for (MotorClusterState currentMotorState : activeMotorList ) {
if (currentMotorState.getMotor() == motor) {
motorTime = currentMotorState.getMotorTime(simulationTime);
break;
}
}
}
final double mountXPosition = root.getPosition().x;
@ -199,14 +217,14 @@ public class MassCalculation {
double eachCMx; // CoM from beginning of motor
if ( this.type.includesMotorCasing && this.type.includesPropellant ){
eachMass = motor.getTotalMass( simulationTime );
eachCMx = motor.getCMx( simulationTime);
eachMass = motor.getTotalMass( motorTime );
eachCMx = motor.getCMx( motorTime);
}else if( this.type.includesMotorCasing ) {
eachMass = motor.getTotalMass( Motor.PSEUDO_TIME_BURNOUT );
eachCMx = motor.getCMx( Motor.PSEUDO_TIME_BURNOUT );
} else {
final double eachMotorMass = motor.getTotalMass( simulationTime );
final double eachMotorCMx = motor.getCMx( simulationTime); // CoM from beginning of motor
final double eachMotorMass = motor.getTotalMass( motorTime );
final double eachMotorCMx = motor.getCMx( motorTime ); // CoM from beginning of motor
final double eachCasingMass = motor.getBurnoutMass();
final double eachCasingCMx = motor.getBurnoutCGx();
@ -214,7 +232,7 @@ public class MassCalculation {
eachCMx = (eachMotorCMx*eachMotorMass - eachCasingCMx*eachCasingMass)/eachMass;
}
// System.err.println(String.format("%-40s|Motor: %s.... Mass @%f = %.6f", prefix, motorConfig.toDescription(), simulationTime, eachMass ));
// System.err.println(String.format("%-40s|Motor: %s.... Mass @%f = %.6f", prefix, motorConfig.toDescription(), motorTime, eachMass ));
// coordinates in rocket frame; Ir, It about CoM.

View File

@ -1,11 +1,13 @@
package net.sf.openrocket.masscalc;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.MotorClusterState;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.util.*;
@ -97,20 +99,23 @@ public class MassCalculator implements Monitorable {
////////////////// Mass property Wrappers ///////////////////
// all mass calculation calls should probably call through one of these two wrappers.
// convenience wrapper -- use this to implicitly create a plain MassCalculation object with common parameters
// convenience wrapper -- use this to implicitly create a plain MassCalculation object with common parameters,
// for calculations in the course of a simulation
public static RigidBody calculate( final MassCalculation.Type _type, final SimulationStatus status ){
final FlightConfiguration config = status.getConfiguration();
final double time = status.getSimulationTime();
MassCalculation calculation= new MassCalculation( _type, config, time, config.getRocket(), Transformation.IDENTITY, null);
final Collection<MotorClusterState> activeMotorList = status.getMotors();
MassCalculation calculation= new MassCalculation( _type, config, time, activeMotorList, config.getRocket(), Transformation.IDENTITY, null);
calculation.calculateAssembly();
RigidBody result = calculation.calculateMomentOfInertia();
return result;
}
// convenience wrapper -- use this to implicitly create a plain MassCalculation object with common parameters
// convenience wrapper -- use this to implicitly create a plain MassCalculation object with common parameters,
// for static mass calculations
public static RigidBody calculate( final MassCalculation.Type _type, final FlightConfiguration _config, double _time){
MassCalculation calculation = new MassCalculation( _type, _config, _time, _config.getRocket(), Transformation.IDENTITY, null);
MassCalculation calculation = new MassCalculation( _type, _config, _time, null, _config.getRocket(), Transformation.IDENTITY, null);
calculation.calculateAssembly();
return calculation.calculateMomentOfInertia();
}
@ -141,6 +146,7 @@ public class MassCalculator implements Monitorable {
MassCalculation.Type.LAUNCH,
config,
Motor.PSEUDO_TIME_LAUNCH,
null,
config.getRocket(),
Transformation.IDENTITY,
analysisMap);

View File

@ -115,7 +115,7 @@ public class MotorClusterState {
}
public double getMotorTime( final double _simulationTime ){
return _simulationTime - this.getIgnitionTime();
return Math.max(_simulationTime - this.getIgnitionTime(), 0.0);
}
/**