Merge pull request #782 from JoePfeiffer/fix-768a
Only consider active stages when calculating drag
This commit is contained in:
commit
2a46d67097
@ -1632,7 +1632,7 @@ FlightDataType.TYPE_ROLL_RATE = Roll rate
|
|||||||
FlightDataType.TYPE_PITCH_RATE = Pitch rate
|
FlightDataType.TYPE_PITCH_RATE = Pitch rate
|
||||||
FlightDataType.TYPE_YAW_RATE = Yaw rate
|
FlightDataType.TYPE_YAW_RATE = Yaw rate
|
||||||
FlightDataType.TYPE_MASS = Mass
|
FlightDataType.TYPE_MASS = Mass
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = Propellant mass
|
FlightDataType.TYPE_MOTOR_MASS = Motor mass
|
||||||
FlightDataType.TYPE_LONGITUDINAL_INERTIA = Longitudinal moment of inertia
|
FlightDataType.TYPE_LONGITUDINAL_INERTIA = Longitudinal moment of inertia
|
||||||
FlightDataType.TYPE_ROTATIONAL_INERTIA = Rotational moment of inertia
|
FlightDataType.TYPE_ROTATIONAL_INERTIA = Rotational moment of inertia
|
||||||
FlightDataType.TYPE_CP_LOCATION = CP location
|
FlightDataType.TYPE_CP_LOCATION = CP location
|
||||||
|
@ -314,7 +314,7 @@ FlightDataType.TYPE_POSITION_X = Posici\u00f3n contra el viento
|
|||||||
FlightDataType.TYPE_POSITION_XY = Distancia lateral
|
FlightDataType.TYPE_POSITION_XY = Distancia lateral
|
||||||
FlightDataType.TYPE_POSITION_Y = Posici\u00f3n a favor del viento
|
FlightDataType.TYPE_POSITION_Y = Posici\u00f3n a favor del viento
|
||||||
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = Presi\u00f3n del Coeficiente de rozamiento
|
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = Presi\u00f3n del Coeficiente de rozamiento
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = Masa del propulsor
|
FlightDataType.TYPE_MOTOR_MASS = Masa del propulsor
|
||||||
FlightDataType.TYPE_REFERENCE_AREA = \u00c1rea de referencia
|
FlightDataType.TYPE_REFERENCE_AREA = \u00c1rea de referencia
|
||||||
FlightDataType.TYPE_REFERENCE_LENGTH = Longitud de referencia
|
FlightDataType.TYPE_REFERENCE_LENGTH = Longitud de referencia
|
||||||
FlightDataType.TYPE_REYNOLDS_NUMBER = N\u00famero de Reynolds
|
FlightDataType.TYPE_REYNOLDS_NUMBER = N\u00famero de Reynolds
|
||||||
|
@ -305,7 +305,7 @@ FlightDataType.TYPE_POSITION_X = Position contre le vent
|
|||||||
FlightDataType.TYPE_POSITION_XY = Distance lat\u00E9rale
|
FlightDataType.TYPE_POSITION_XY = Distance lat\u00E9rale
|
||||||
FlightDataType.TYPE_POSITION_Y = Position parall\u00E8le au vent
|
FlightDataType.TYPE_POSITION_Y = Position parall\u00E8le au vent
|
||||||
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = Coefficient de tra\u00EEn\u00E9e de pression
|
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = Coefficient de tra\u00EEn\u00E9e de pression
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = Masse du propergol
|
FlightDataType.TYPE_MOTOR_MASS = Masse du propergol
|
||||||
FlightDataType.TYPE_REFERENCE_AREA = Surface de r\u00E9f\u00E9rence
|
FlightDataType.TYPE_REFERENCE_AREA = Surface de r\u00E9f\u00E9rence
|
||||||
FlightDataType.TYPE_REFERENCE_LENGTH = Longueur de r\u00E9f\u00E9rence
|
FlightDataType.TYPE_REFERENCE_LENGTH = Longueur de r\u00E9f\u00E9rence
|
||||||
FlightDataType.TYPE_REYNOLDS_NUMBER = Nombre de Reynolds
|
FlightDataType.TYPE_REYNOLDS_NUMBER = Nombre de Reynolds
|
||||||
|
@ -1385,7 +1385,7 @@ FlightDataType.TYPE_ROLL_RATE = \u89D2\u901F\u5EA6\uFF08\u30ED\u30FC\u30EB\uFF0
|
|||||||
FlightDataType.TYPE_PITCH_RATE = \u89D2\u901F\u5EA6\uFF08\u30D4\u30C3\u30C1\uFF09
|
FlightDataType.TYPE_PITCH_RATE = \u89D2\u901F\u5EA6\uFF08\u30D4\u30C3\u30C1\uFF09
|
||||||
FlightDataType.TYPE_YAW_RATE = \u89D2\u901F\u5EA6\uFF08\u30E8\u30FC\uFF09
|
FlightDataType.TYPE_YAW_RATE = \u89D2\u901F\u5EA6\uFF08\u30E8\u30FC\uFF09
|
||||||
FlightDataType.TYPE_MASS = \u8CEA\u91CF
|
FlightDataType.TYPE_MASS = \u8CEA\u91CF
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = \u8EF8\u65B9\u5411\u6163\u6027\u30E2\u30FC\u30E1\u30F3\u30C8
|
FlightDataType.TYPE_MOTOR_MASS = \u8EF8\u65B9\u5411\u6163\u6027\u30E2\u30FC\u30E1\u30F3\u30C8
|
||||||
FlightDataType.TYPE_LONGITUDINAL_INERTIA = \u9577\u624B\u65B9\u5411\u6163\u6027\u30E2\u30FC\u30E1\u30F3\u30C8
|
FlightDataType.TYPE_LONGITUDINAL_INERTIA = \u9577\u624B\u65B9\u5411\u6163\u6027\u30E2\u30FC\u30E1\u30F3\u30C8
|
||||||
FlightDataType.TYPE_ROTATIONAL_INERTIA = \u30ED\u30FC\u30EB\u65B9\u5411\u6163\u6027\u30E2\u30FC\u30E1\u30F3\u30C8
|
FlightDataType.TYPE_ROTATIONAL_INERTIA = \u30ED\u30FC\u30EB\u65B9\u5411\u6163\u6027\u30E2\u30FC\u30E1\u30F3\u30C8
|
||||||
FlightDataType.TYPE_CP_LOCATION = CP\u4F4D\u7F6E
|
FlightDataType.TYPE_CP_LOCATION = CP\u4F4D\u7F6E
|
||||||
|
@ -294,7 +294,7 @@ FlightDataType.TYPE_POSITION_X = Posi\u00e7\u00e3o a favor do ve
|
|||||||
FlightDataType.TYPE_POSITION_XY = Dist\u00e2ncia lateral
|
FlightDataType.TYPE_POSITION_XY = Dist\u00e2ncia lateral
|
||||||
FlightDataType.TYPE_POSITION_Y = Posi\u00e7\u00e3o paralela ao vento
|
FlightDataType.TYPE_POSITION_Y = Posi\u00e7\u00e3o paralela ao vento
|
||||||
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = Coeficiente de arrasto de press\u00e3o
|
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = Coeficiente de arrasto de press\u00e3o
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = Massa do propelente
|
FlightDataType.TYPE_MOTOR_MASS = Massa do propelente
|
||||||
FlightDataType.TYPE_REFERENCE_AREA = \u00c1rea de refer\u00eancia
|
FlightDataType.TYPE_REFERENCE_AREA = \u00c1rea de refer\u00eancia
|
||||||
FlightDataType.TYPE_REFERENCE_LENGTH = Comprimento de refer\u00eancia
|
FlightDataType.TYPE_REFERENCE_LENGTH = Comprimento de refer\u00eancia
|
||||||
FlightDataType.TYPE_REYNOLDS_NUMBER = N\u00famero de Reynolds
|
FlightDataType.TYPE_REYNOLDS_NUMBER = N\u00famero de Reynolds
|
||||||
|
@ -1477,7 +1477,7 @@ FlightDataType.TYPE_ROLL_RATE = \u0423\u0433\u043b\u043e\u0432\u0430\u044f \u044
|
|||||||
FlightDataType.TYPE_PITCH_RATE = \u0423\u0433\u043b\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0442\u0430\u043d\u0433\u0430\u0436\u0430
|
FlightDataType.TYPE_PITCH_RATE = \u0423\u0433\u043b\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0442\u0430\u043d\u0433\u0430\u0436\u0430
|
||||||
FlightDataType.TYPE_YAW_RATE = \u0423\u0433\u043b\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u044b\u0441\u043a\u0430\u043d\u044c\u044f
|
FlightDataType.TYPE_YAW_RATE = \u0423\u0433\u043b\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u044b\u0441\u043a\u0430\u043d\u044c\u044f
|
||||||
FlightDataType.TYPE_MASS = \u041c\u0430\u0441\u0441\u0430
|
FlightDataType.TYPE_MASS = \u041c\u0430\u0441\u0441\u0430
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = \u041c\u0430\u0441\u0441\u0430 \u0442\u043e\u043f\u043b\u0438\u0432\u0430
|
FlightDataType.TYPE_MOTOR_MASS = \u041c\u0430\u0441\u0441\u0430 \u0442\u043e\u043f\u043b\u0438\u0432\u0430
|
||||||
FlightDataType.TYPE_LONGITUDINAL_INERTIA = \u041f\u0440\u043e\u0434\u043e\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043d\u0435\u0440\u0446\u0438\u0438
|
FlightDataType.TYPE_LONGITUDINAL_INERTIA = \u041f\u0440\u043e\u0434\u043e\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043d\u0435\u0440\u0446\u0438\u0438
|
||||||
FlightDataType.TYPE_ROTATIONAL_INERTIA = \u041a\u0440\u0443\u0442\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043d\u0435\u0440\u0446\u0438\u0438
|
FlightDataType.TYPE_ROTATIONAL_INERTIA = \u041a\u0440\u0443\u0442\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043d\u0435\u0440\u0446\u0438\u0438
|
||||||
FlightDataType.TYPE_CP_LOCATION = \u041f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0426\u0414
|
FlightDataType.TYPE_CP_LOCATION = \u041f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0426\u0414
|
||||||
|
@ -1483,7 +1483,7 @@ FlightDataType.TYPE_ROLL_RATE = Roll rate
|
|||||||
FlightDataType.TYPE_PITCH_RATE = Pitch rate
|
FlightDataType.TYPE_PITCH_RATE = Pitch rate
|
||||||
FlightDataType.TYPE_YAW_RATE = Yaw rate
|
FlightDataType.TYPE_YAW_RATE = Yaw rate
|
||||||
FlightDataType.TYPE_MASS = Mass
|
FlightDataType.TYPE_MASS = Mass
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = Propellant mass
|
FlightDataType.TYPE_MOTOR_MASS = Motor mass
|
||||||
FlightDataType.TYPE_LONGITUDINAL_INERTIA = Longitudinal moment of inertia
|
FlightDataType.TYPE_LONGITUDINAL_INERTIA = Longitudinal moment of inertia
|
||||||
FlightDataType.TYPE_ROTATIONAL_INERTIA = Rotational moment of inertia
|
FlightDataType.TYPE_ROTATIONAL_INERTIA = Rotational moment of inertia
|
||||||
FlightDataType.TYPE_CP_LOCATION = CP location
|
FlightDataType.TYPE_CP_LOCATION = CP location
|
||||||
|
@ -330,7 +330,7 @@ FlightDataType.TYPE_POSITION_X = \u8FCE\u98CE\u4F4D\u7F6E
|
|||||||
FlightDataType.TYPE_POSITION_XY = \u6A2A\u5411\u8DE8\u8DDD
|
FlightDataType.TYPE_POSITION_XY = \u6A2A\u5411\u8DE8\u8DDD
|
||||||
FlightDataType.TYPE_POSITION_Y = \u5E73\u884C\u98CE\u4F4D\u7F6E
|
FlightDataType.TYPE_POSITION_Y = \u5E73\u884C\u98CE\u4F4D\u7F6E
|
||||||
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = \u538B\u5DEE\u963B\u529B\u7CFB\u6570
|
FlightDataType.TYPE_PRESSURE_DRAG_COEFF = \u538B\u5DEE\u963B\u529B\u7CFB\u6570
|
||||||
FlightDataType.TYPE_PROPELLANT_MASS = \u63A8\u8FDB\u5242\u8D28\u91CF
|
FlightDataType.TYPE_MOTOR_MASS = \u63A8\u8FDB\u5242\u8D28\u91CF
|
||||||
FlightDataType.TYPE_REFERENCE_AREA = \u53C2\u8003\u9762\u79EF
|
FlightDataType.TYPE_REFERENCE_AREA = \u53C2\u8003\u9762\u79EF
|
||||||
FlightDataType.TYPE_REFERENCE_LENGTH = \u53C2\u8003\u957F\u5EA6
|
FlightDataType.TYPE_REFERENCE_LENGTH = \u53C2\u8003\u957F\u5EA6
|
||||||
FlightDataType.TYPE_REYNOLDS_NUMBER = \u96F7\u8BFA\u6570
|
FlightDataType.TYPE_REYNOLDS_NUMBER = \u96F7\u8BFA\u6570
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package net.sf.openrocket.masscalc;
|
package net.sf.openrocket.masscalc;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.openrocket.motor.Motor;
|
import net.sf.openrocket.motor.Motor;
|
||||||
import net.sf.openrocket.motor.MotorConfiguration;
|
import net.sf.openrocket.motor.MotorConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.*;
|
import net.sf.openrocket.rocketcomponent.*;
|
||||||
|
import net.sf.openrocket.simulation.MotorClusterState;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import net.sf.openrocket.util.Transformation;
|
import net.sf.openrocket.util.Transformation;
|
||||||
@ -71,7 +73,7 @@ public class MassCalculation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MassCalculation copy( final RocketComponent _root, final Transformation _transform){
|
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() {
|
public Coordinate getCM() {
|
||||||
@ -108,12 +110,14 @@ public class MassCalculation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MassCalculation( final Type _type, final FlightConfiguration _config, final double _time,
|
public MassCalculation( final Type _type, final FlightConfiguration _config, final double _time,
|
||||||
|
final Collection<MotorClusterState> _activeMotorList,
|
||||||
final RocketComponent _root, final Transformation _transform,
|
final RocketComponent _root, final Transformation _transform,
|
||||||
Map<Integer, CMAnalysisEntry> _map)
|
Map<Integer, CMAnalysisEntry> _map)
|
||||||
{
|
{
|
||||||
type = _type;
|
type = _type;
|
||||||
config = _config;
|
config = _config;
|
||||||
simulationTime = _time;
|
simulationTime = _time;
|
||||||
|
activeMotorList = _activeMotorList;
|
||||||
root = _root;
|
root = _root;
|
||||||
transform = _transform;
|
transform = _transform;
|
||||||
analysisMap = _map;
|
analysisMap = _map;
|
||||||
@ -156,6 +160,7 @@ public class MassCalculation {
|
|||||||
// === package-private ===
|
// === package-private ===
|
||||||
final FlightConfiguration config;
|
final FlightConfiguration config;
|
||||||
final double simulationTime;
|
final double simulationTime;
|
||||||
|
final Collection<MotorClusterState> activeMotorList;
|
||||||
final RocketComponent root;
|
final RocketComponent root;
|
||||||
final Transformation transform;
|
final Transformation transform;
|
||||||
final Type type;
|
final Type type;
|
||||||
@ -182,11 +187,24 @@ public class MassCalculation {
|
|||||||
|
|
||||||
final MotorMount mount = (MotorMount)root;
|
final MotorMount mount = (MotorMount)root;
|
||||||
MotorConfiguration motorConfig = mount.getMotorConfig( config.getId() );
|
MotorConfiguration motorConfig = mount.getMotorConfig( config.getId() );
|
||||||
final Motor motor = motorConfig.getMotor();
|
|
||||||
if( motorConfig.isEmpty() ){
|
if( motorConfig.isEmpty() ){
|
||||||
return this;
|
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;
|
final double mountXPosition = root.getPosition().x;
|
||||||
|
|
||||||
@ -199,14 +217,14 @@ public class MassCalculation {
|
|||||||
double eachCMx; // CoM from beginning of motor
|
double eachCMx; // CoM from beginning of motor
|
||||||
|
|
||||||
if ( this.type.includesMotorCasing && this.type.includesPropellant ){
|
if ( this.type.includesMotorCasing && this.type.includesPropellant ){
|
||||||
eachMass = motor.getTotalMass( simulationTime );
|
eachMass = motor.getTotalMass( motorTime );
|
||||||
eachCMx = motor.getCMx( simulationTime);
|
eachCMx = motor.getCMx( motorTime);
|
||||||
}else if( this.type.includesMotorCasing ) {
|
}else if( this.type.includesMotorCasing ) {
|
||||||
eachMass = motor.getTotalMass( Motor.PSEUDO_TIME_BURNOUT );
|
eachMass = motor.getTotalMass( Motor.PSEUDO_TIME_BURNOUT );
|
||||||
eachCMx = motor.getCMx( Motor.PSEUDO_TIME_BURNOUT );
|
eachCMx = motor.getCMx( Motor.PSEUDO_TIME_BURNOUT );
|
||||||
} else {
|
} else {
|
||||||
final double eachMotorMass = motor.getTotalMass( simulationTime );
|
final double eachMotorMass = motor.getTotalMass( motorTime );
|
||||||
final double eachMotorCMx = motor.getCMx( simulationTime); // CoM from beginning of motor
|
final double eachMotorCMx = motor.getCMx( motorTime ); // CoM from beginning of motor
|
||||||
final double eachCasingMass = motor.getBurnoutMass();
|
final double eachCasingMass = motor.getBurnoutMass();
|
||||||
final double eachCasingCMx = motor.getBurnoutCGx();
|
final double eachCasingCMx = motor.getBurnoutCGx();
|
||||||
|
|
||||||
@ -214,7 +232,7 @@ public class MassCalculation {
|
|||||||
eachCMx = (eachMotorCMx*eachMotorMass - eachCasingCMx*eachCasingMass)/eachMass;
|
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.
|
// coordinates in rocket frame; Ir, It about CoM.
|
||||||
@ -390,15 +408,15 @@ public class MassCalculation {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (component.isMotorMount()) {
|
if (component.isMotorMount()) {
|
||||||
MassCalculation propellant = this.copy(component, parentTransform);
|
MassCalculation motor = this.copy(component, parentTransform);
|
||||||
|
|
||||||
propellant.calculateMountData();
|
motor.calculateMountData();
|
||||||
|
|
||||||
this.merge( propellant );
|
this.merge( motor );
|
||||||
|
|
||||||
// // vvv DEBUG
|
// // vvv DEBUG
|
||||||
// if( 0 < propellant.getMass() ) {
|
// if( 0 < motor.getMass() ) {
|
||||||
// System.err.println(String.format( "%s........++ propellantData: %s", prefix, propellant.toCMDebug()));
|
// System.err.println(String.format( "%s........++ motorData: %s", prefix, propellant.toCMDebug()));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package net.sf.openrocket.masscalc;
|
package net.sf.openrocket.masscalc;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.openrocket.motor.Motor;
|
import net.sf.openrocket.motor.Motor;
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.simulation.MotorClusterState;
|
||||||
import net.sf.openrocket.simulation.SimulationStatus;
|
import net.sf.openrocket.simulation.SimulationStatus;
|
||||||
import net.sf.openrocket.util.*;
|
import net.sf.openrocket.util.*;
|
||||||
|
|
||||||
@ -19,7 +21,7 @@ public class MassCalculator implements Monitorable {
|
|||||||
*/
|
*/
|
||||||
// private HashMap< Integer, MassData> stageMassCache = new HashMap<Integer, MassData >();
|
// private HashMap< Integer, MassData> stageMassCache = new HashMap<Integer, MassData >();
|
||||||
// private MassData rocketSpentMassCache;
|
// private MassData rocketSpentMassCache;
|
||||||
// private MassData propellantMassCache;
|
// private MassData motorMassCache;
|
||||||
|
|
||||||
private int modId = 0;
|
private int modId = 0;
|
||||||
|
|
||||||
@ -97,20 +99,23 @@ public class MassCalculator implements Monitorable {
|
|||||||
////////////////// Mass property Wrappers ///////////////////
|
////////////////// Mass property Wrappers ///////////////////
|
||||||
// all mass calculation calls should probably call through one of these two 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 ){
|
public static RigidBody calculate( final MassCalculation.Type _type, final SimulationStatus status ){
|
||||||
final FlightConfiguration config = status.getConfiguration();
|
final FlightConfiguration config = status.getConfiguration();
|
||||||
final double time = status.getSimulationTime();
|
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();
|
calculation.calculateAssembly();
|
||||||
RigidBody result = calculation.calculateMomentOfInertia();
|
RigidBody result = calculation.calculateMomentOfInertia();
|
||||||
return result;
|
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){
|
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();
|
calculation.calculateAssembly();
|
||||||
return calculation.calculateMomentOfInertia();
|
return calculation.calculateMomentOfInertia();
|
||||||
}
|
}
|
||||||
@ -141,6 +146,7 @@ public class MassCalculator implements Monitorable {
|
|||||||
MassCalculation.Type.LAUNCH,
|
MassCalculation.Type.LAUNCH,
|
||||||
config,
|
config,
|
||||||
Motor.PSEUDO_TIME_LAUNCH,
|
Motor.PSEUDO_TIME_LAUNCH,
|
||||||
|
null,
|
||||||
config.getRocket(),
|
config.getRocket(),
|
||||||
Transformation.IDENTITY,
|
Transformation.IDENTITY,
|
||||||
analysisMap);
|
analysisMap);
|
||||||
|
@ -204,7 +204,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
*/
|
*/
|
||||||
public boolean isStageActive(int stageNumber) {
|
public boolean isStageActive(int stageNumber) {
|
||||||
if( -1 == stageNumber ) {
|
if( -1 == stageNumber ) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stages.get(stageNumber).active;
|
return stages.get(stageNumber).active;
|
||||||
@ -289,15 +289,17 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
*/
|
*/
|
||||||
public InstanceMap getActiveInstances() {
|
public InstanceMap getActiveInstances() {
|
||||||
InstanceMap contexts = new InstanceMap();
|
InstanceMap contexts = new InstanceMap();
|
||||||
getContextListAt( this.rocket, contexts, Transformation.IDENTITY);
|
getActiveContextListAt( this.rocket, contexts, Transformation.IDENTITY);
|
||||||
return contexts;
|
return contexts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstanceMap getContextListAt(final RocketComponent component, final InstanceMap results, final Transformation parentTransform ){
|
private InstanceMap getActiveContextListAt(final RocketComponent component, final InstanceMap results, final Transformation parentTransform ){
|
||||||
|
final boolean active = this.isComponentActive(component);
|
||||||
|
if (!active)
|
||||||
|
return results;
|
||||||
final int instanceCount = component.getInstanceCount();
|
final int instanceCount = component.getInstanceCount();
|
||||||
final Coordinate[] allOffsets = component.getInstanceOffsets();
|
final Coordinate[] allOffsets = component.getInstanceOffsets();
|
||||||
final double[] allAngles = component.getInstanceAngles();
|
final double[] allAngles = component.getInstanceAngles();
|
||||||
final boolean active = this.isComponentActive(component);
|
|
||||||
|
|
||||||
final Transformation compLocTransform = Transformation.getTranslationTransform( component.getPosition() );
|
final Transformation compLocTransform = Transformation.getTranslationTransform( component.getPosition() );
|
||||||
final Transformation componentTransform = parentTransform.applyTransformation(compLocTransform);
|
final Transformation componentTransform = parentTransform.applyTransformation(compLocTransform);
|
||||||
@ -307,13 +309,13 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
final Transformation offsetTransform = Transformation.getTranslationTransform( allOffsets[currentInstanceNumber] );
|
final Transformation offsetTransform = Transformation.getTranslationTransform( allOffsets[currentInstanceNumber] );
|
||||||
final Transformation angleTransform = Transformation.getAxialRotation(allAngles[currentInstanceNumber]);
|
final Transformation angleTransform = Transformation.getAxialRotation(allAngles[currentInstanceNumber]);
|
||||||
final Transformation currentTransform = componentTransform.applyTransformation(offsetTransform)
|
final Transformation currentTransform = componentTransform.applyTransformation(offsetTransform)
|
||||||
.applyTransformation(angleTransform);
|
.applyTransformation(angleTransform);
|
||||||
|
|
||||||
// constructs entry in-place
|
// constructs entry in-place
|
||||||
results.emplace(component, active, currentInstanceNumber, currentTransform);
|
results.emplace(component, active, currentInstanceNumber, currentTransform);
|
||||||
|
|
||||||
for(RocketComponent child : component.getChildren()) {
|
for(RocketComponent child : component.getChildren()) {
|
||||||
getContextListAt(child, results, currentTransform);
|
getActiveContextListAt(child, results, currentTransform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class BasicLandingStepper extends AbstractSimulationStepper {
|
|||||||
data.setValue(FlightDataType.TYPE_MACH_NUMBER, mach);
|
data.setValue(FlightDataType.TYPE_MACH_NUMBER, mach);
|
||||||
|
|
||||||
data.setValue(FlightDataType.TYPE_MASS, mass);
|
data.setValue(FlightDataType.TYPE_MASS, mass);
|
||||||
data.setValue(FlightDataType.TYPE_PROPELLANT_MASS, 0.0); // Is this a reasonable assumption? Probably.
|
data.setValue(FlightDataType.TYPE_MOTOR_MASS, 0.0); // Is this a reasonable assumption? Probably.
|
||||||
|
|
||||||
data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0);
|
data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0);
|
||||||
data.setValue(FlightDataType.TYPE_DRAG_FORCE, dragForce);
|
data.setValue(FlightDataType.TYPE_DRAG_FORCE, dragForce);
|
||||||
|
@ -121,7 +121,7 @@ public class BasicTumbleStepper extends AbstractSimulationStepper {
|
|||||||
data.setValue(FlightDataType.TYPE_MACH_NUMBER, mach);
|
data.setValue(FlightDataType.TYPE_MACH_NUMBER, mach);
|
||||||
|
|
||||||
data.setValue(FlightDataType.TYPE_MASS, mass);
|
data.setValue(FlightDataType.TYPE_MASS, mass);
|
||||||
data.setValue(FlightDataType.TYPE_PROPELLANT_MASS, 0.0); // Is this a reasonable assumption? Probably.
|
data.setValue(FlightDataType.TYPE_MOTOR_MASS, 0.0); // Is this a reasonable assumption? Probably.
|
||||||
|
|
||||||
data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0);
|
data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0);
|
||||||
data.setValue(FlightDataType.TYPE_DRAG_FORCE, dragForce);
|
data.setValue(FlightDataType.TYPE_DRAG_FORCE, dragForce);
|
||||||
|
@ -91,8 +91,8 @@ public class FlightDataType implements Comparable<FlightDataType> {
|
|||||||
//// Stability information
|
//// Stability information
|
||||||
//// Mass
|
//// Mass
|
||||||
public static final FlightDataType TYPE_MASS = newType(trans.get("FlightDataType.TYPE_MASS"), "m", UnitGroup.UNITS_MASS, 50);
|
public static final FlightDataType TYPE_MASS = newType(trans.get("FlightDataType.TYPE_MASS"), "m", UnitGroup.UNITS_MASS, 50);
|
||||||
//// Propellant mass
|
//// Motor mass
|
||||||
public static final FlightDataType TYPE_PROPELLANT_MASS = newType(trans.get("FlightDataType.TYPE_PROPELLANT_MASS"), "mp", UnitGroup.UNITS_MASS, 51);
|
public static final FlightDataType TYPE_MOTOR_MASS = newType(trans.get("FlightDataType.TYPE_MOTOR_MASS"), "mp", UnitGroup.UNITS_MASS, 51);
|
||||||
//// Longitudinal moment of inertia
|
//// Longitudinal moment of inertia
|
||||||
public static final FlightDataType TYPE_LONGITUDINAL_INERTIA = newType(trans.get("FlightDataType.TYPE_LONGITUDINAL_INERTIA"), "Il", UnitGroup.UNITS_INERTIA, 52);
|
public static final FlightDataType TYPE_LONGITUDINAL_INERTIA = newType(trans.get("FlightDataType.TYPE_LONGITUDINAL_INERTIA"), "Il", UnitGroup.UNITS_INERTIA, 52);
|
||||||
//// Rotational moment of inertia
|
//// Rotational moment of inertia
|
||||||
@ -209,7 +209,7 @@ public class FlightDataType implements Comparable<FlightDataType> {
|
|||||||
TYPE_PITCH_RATE,
|
TYPE_PITCH_RATE,
|
||||||
TYPE_YAW_RATE,
|
TYPE_YAW_RATE,
|
||||||
TYPE_MASS,
|
TYPE_MASS,
|
||||||
TYPE_PROPELLANT_MASS,
|
TYPE_MOTOR_MASS,
|
||||||
TYPE_LONGITUDINAL_INERTIA,
|
TYPE_LONGITUDINAL_INERTIA,
|
||||||
TYPE_ROTATIONAL_INERTIA,
|
TYPE_ROTATIONAL_INERTIA,
|
||||||
TYPE_CP_LOCATION,
|
TYPE_CP_LOCATION,
|
||||||
|
@ -62,7 +62,7 @@ public class GroundStepper extends AbstractSimulationStepper {
|
|||||||
data.setValue(FlightDataType.TYPE_MACH_NUMBER, 0.0);
|
data.setValue(FlightDataType.TYPE_MACH_NUMBER, 0.0);
|
||||||
|
|
||||||
data.setValue(FlightDataType.TYPE_MASS, calculateStructureMass(status).getMass());
|
data.setValue(FlightDataType.TYPE_MASS, calculateStructureMass(status).getMass());
|
||||||
data.setValue(FlightDataType.TYPE_PROPELLANT_MASS, 0.0); // Is this a reasonable assumption? Probably.
|
data.setValue(FlightDataType.TYPE_MOTOR_MASS, 0.0); // Is this a reasonable assumption? Probably.
|
||||||
|
|
||||||
data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0.0);
|
data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0.0);
|
||||||
data.setValue(FlightDataType.TYPE_DRAG_FORCE, 0.0);
|
data.setValue(FlightDataType.TYPE_DRAG_FORCE, 0.0);
|
||||||
|
@ -115,7 +115,7 @@ public class MotorClusterState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public double getMotorTime( final double _simulationTime ){
|
public double getMotorTime( final double _simulationTime ){
|
||||||
return _simulationTime - this.getIgnitionTime();
|
return Math.max(_simulationTime - this.getIgnitionTime(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -613,9 +613,9 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( null != store.motorMass ){
|
if( null != store.motorMass ){
|
||||||
data.setValue(FlightDataType.TYPE_PROPELLANT_MASS, store.motorMass.getMass());
|
data.setValue(FlightDataType.TYPE_MOTOR_MASS, store.motorMass.getMass());
|
||||||
//data.setValue(FlightDataType.TYPE_PROPELLANT_LONGITUDINAL_INERTIA, store.propellantMassData.getLongitudinalInertia());
|
//data.setValue(FlightDataType.TYPE_MOTOR_LONGITUDINAL_INERTIA, store.motorMassData.getLongitudinalInertia());
|
||||||
//data.setValue(FlightDataType.TYPE_PROPELLANT_ROTATIONAL_INERTIA, store.propellantMassData.getRotationalInertia());
|
//data.setValue(FlightDataType.TYPE_MOTOR_ROTATIONAL_INERTIA, store.motorMassData.getRotationalInertia());
|
||||||
}
|
}
|
||||||
if (store.rocketMass != null) {
|
if (store.rocketMass != null) {
|
||||||
// N.B.: These refer to total mass
|
// N.B.: These refer to total mass
|
||||||
|
@ -41,7 +41,7 @@ public class DampingMoment extends AbstractSimulationListener {
|
|||||||
// dm/dt = (thrust - ma)/v
|
// dm/dt = (thrust - ma)/v
|
||||||
FlightDataBranch data = status.getFlightData();
|
FlightDataBranch data = status.getFlightData();
|
||||||
|
|
||||||
List<Double> mpAll = data.get(FlightDataType.TYPE_PROPELLANT_MASS);
|
List<Double> mpAll = data.get(FlightDataType.TYPE_MOTOR_MASS);
|
||||||
List<Double> time = data.get(FlightDataType.TYPE_TIME);
|
List<Double> time = data.get(FlightDataType.TYPE_TIME);
|
||||||
if (mpAll == null || time == null) {
|
if (mpAll == null || time == null) {
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
|
@ -2,6 +2,8 @@ package net.sf.openrocket.masscalc;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import net.sf.openrocket.rocketcomponent.*;
|
import net.sf.openrocket.rocketcomponent.*;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AngleMethod;
|
import net.sf.openrocket.rocketcomponent.position.AngleMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
@ -9,6 +11,7 @@ import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.sf.openrocket.motor.Motor;
|
import net.sf.openrocket.motor.Motor;
|
||||||
|
import net.sf.openrocket.simulation.MotorClusterState;
|
||||||
import net.sf.openrocket.simulation.SimulationConditions;
|
import net.sf.openrocket.simulation.SimulationConditions;
|
||||||
import net.sf.openrocket.simulation.SimulationStatus;
|
import net.sf.openrocket.simulation.SimulationStatus;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
@ -135,26 +138,31 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
|
|
||||||
// this is probably not enough for a full-up simulation, but it IS enough for a motor-mass calculation.
|
// this is probably not enough for a full-up simulation, but it IS enough for a motor-mass calculation.
|
||||||
SimulationStatus status = new SimulationStatus(config, new SimulationConditions());
|
SimulationStatus status = new SimulationStatus(config, new SimulationConditions());
|
||||||
|
|
||||||
|
// Ignite motor at 1.0 seconds
|
||||||
|
MotorClusterState currentMotorState = ((List<MotorClusterState>) status.getMotors()).get(0);
|
||||||
|
final double ignitionTime = 1.0;
|
||||||
|
currentMotorState.ignite(ignitionTime);
|
||||||
|
|
||||||
{
|
{
|
||||||
final double simTime = 0.03; // almost launch
|
final double simTime = 1.03; // almost launch
|
||||||
status.setSimulationTime(simTime);
|
status.setSimulationTime(simTime);
|
||||||
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
||||||
double expMass = activeMotor.getTotalMass(simTime);
|
double expMass = activeMotor.getTotalMass(simTime - ignitionTime);
|
||||||
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final double simTime = 1.03; // middle
|
final double simTime = 2.03; // middle
|
||||||
status.setSimulationTime(simTime);
|
status.setSimulationTime(simTime);
|
||||||
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
||||||
double expMass = activeMotor.getTotalMass(simTime);
|
double expMass = activeMotor.getTotalMass(simTime - ignitionTime);
|
||||||
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final double simTime = 2.03; // after burnout
|
final double simTime = 3.03; // after burnout
|
||||||
status.setSimulationTime(simTime);
|
status.setSimulationTime(simTime);
|
||||||
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
||||||
double expMass = activeMotor.getTotalMass(simTime);
|
double expMass = activeMotor.getTotalMass(simTime - ignitionTime);
|
||||||
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,6 +350,7 @@ public class FlightConfigurationTest extends BaseTestCase {
|
|||||||
FlightConfiguration selected = rocket.getSelectedConfiguration();
|
FlightConfiguration selected = rocket.getSelectedConfiguration();
|
||||||
|
|
||||||
selected.clearAllStages();
|
selected.clearAllStages();
|
||||||
|
selected.toggleStage(1);
|
||||||
selected.toggleStage(2);
|
selected.toggleStage(2);
|
||||||
|
|
||||||
// vvvv Test Target vvvv
|
// vvvv Test Target vvvv
|
||||||
|
@ -145,7 +145,7 @@ public class DesignReport {
|
|||||||
private static final String MAX_THRUST = "Max Thrust";
|
private static final String MAX_THRUST = "Max Thrust";
|
||||||
private static final String TOTAL_IMPULSE = "Total Impulse";
|
private static final String TOTAL_IMPULSE = "Total Impulse";
|
||||||
private static final String THRUST_TO_WT = "Thrust to Wt";
|
private static final String THRUST_TO_WT = "Thrust to Wt";
|
||||||
private static final String PROPELLANT_WT = "Propellant Wt";
|
private static final String MOTOR_WT = "Motor Wt";
|
||||||
private static final String SIZE = "Size";
|
private static final String SIZE = "Size";
|
||||||
private static final String ALTITUDE = "Altitude";
|
private static final String ALTITUDE = "Altitude";
|
||||||
private static final String FLIGHT_TIME = "Flight Time";
|
private static final String FLIGHT_TIME = "Flight Time";
|
||||||
@ -377,7 +377,7 @@ public class DesignReport {
|
|||||||
motorTable.addCell(ITextHelper.createCell(MAX_THRUST, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
motorTable.addCell(ITextHelper.createCell(MAX_THRUST, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
||||||
motorTable.addCell(ITextHelper.createCell(TOTAL_IMPULSE, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
motorTable.addCell(ITextHelper.createCell(TOTAL_IMPULSE, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
||||||
motorTable.addCell(ITextHelper.createCell(THRUST_TO_WT, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
motorTable.addCell(ITextHelper.createCell(THRUST_TO_WT, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
||||||
motorTable.addCell(ITextHelper.createCell(PROPELLANT_WT, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
motorTable.addCell(ITextHelper.createCell(MOTOR_WT, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
||||||
motorTable.addCell(ITextHelper.createCell(SIZE, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
motorTable.addCell(ITextHelper.createCell(SIZE, PdfPCell.BOTTOM, PrintUtilities.SMALL));
|
||||||
|
|
||||||
DecimalFormat ttwFormat = new DecimalFormat("0.00");
|
DecimalFormat ttwFormat = new DecimalFormat("0.00");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user