folded AbstractMassCalculator into BasicMassCalculator

This commit is contained in:
Daniel_M_Williams 2015-09-05 11:39:47 -04:00
parent 54f1a4c672
commit 7978771e1b
2 changed files with 79 additions and 103 deletions

View File

@ -1,54 +0,0 @@
package net.sf.openrocket.masscalc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.rocketcomponent.Configuration;
/**
* Abstract base for mass calculators. Provides functionality for cacheing mass data.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public abstract class AbstractMassCalculator implements MassCalculator {
private static final Logger log = LoggerFactory.getLogger(AbstractMassCalculator.class);
private int rocketMassModID = -1;
private int rocketTreeModID = -1;
/**
* Check the current cache consistency. This method must be called by all
* methods that may use any cached data before any other operations are
* performed. If the rocket has changed since the previous call to
* <code>checkCache()</code>, then {@link #voidMassCache()} is called.
* <p>
* This method performs the checking based on the rocket's modification IDs,
* so that these method may be called from listeners of the rocket itself.
*
* @param configuration the configuration of the current call
*/
protected final void checkCache(Configuration configuration) {
if (rocketMassModID != configuration.getRocket().getMassModID() ||
rocketTreeModID != configuration.getRocket().getTreeModID()) {
rocketMassModID = configuration.getRocket().getMassModID();
rocketTreeModID = configuration.getRocket().getTreeModID();
log.debug("Voiding the mass cache");
voidMassCache();
}
}
/**
* Void cached mass data. This method is called whenever a change occurs in
* the rocket structure that affects the mass of the rocket and when a new
* Rocket is used. This method must be overridden to void any cached data
* necessary. The method must call <code>super.voidMassCache()</code> during
* its execution.
*/
protected void voidMassCache() {
// No-op
}
}

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.masscalc;
import static net.sf.openrocket.util.MathUtil.pow2; import static net.sf.openrocket.util.MathUtil.pow2;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -10,16 +11,24 @@ import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorId; import net.sf.openrocket.motor.MotorId;
import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.motor.MotorInstanceConfiguration; import net.sf.openrocket.motor.MotorInstanceConfiguration;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.MassData;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.MathUtil;
public class BasicMassCalculator extends AbstractMassCalculator { import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BasicMassCalculator implements MassCalculator {
private static final double MIN_MASS = 0.001 * MathUtil.EPSILON; private static final double MIN_MASS = 0.001 * MathUtil.EPSILON;
private static final Logger log = LoggerFactory.getLogger(MassCalculator.class);
private int rocketMassModID = -1;
private int rocketTreeModID = -1;
/* /*
* Cached data. All CG data is in absolute coordinates. All moments of inertia * Cached data. All CG data is in absolute coordinates. All moments of inertia
@ -238,21 +247,19 @@ public class BasicMassCalculator extends AbstractMassCalculator {
private void calculateStageCache(Configuration config) { private void calculateStageCache(Configuration config) {
if (cgCache == null) { if (cgCache == null) {
ArrayList<AxialStage> stageList = config.getRocket().getStageList();
int stageCount = stageList.size();
//int stages = config.getRocket().getStageCount(); cgCache = new Coordinate[stageCount];
// temporary fix . this undercounts the stages longitudinalInertiaCache = new double[stageCount];
int stages = config.getRocket().getChildCount(); rotationalInertiaCache = new double[stageCount];
cgCache = new Coordinate[stages]; for (int i = 0; i < stageCount; i++) {
longitudinalInertiaCache = new double[stages]; RocketComponent stage = stageList.get(i);
rotationalInertiaCache = new double[stages];
for (int i = 0; i < stages; i++) {
RocketComponent stage = config.getRocket().getChild(i);
MassData data = calculateAssemblyMassData(stage); MassData data = calculateAssemblyMassData(stage);
cgCache[i] = stage.toAbsolute(data.cg)[0]; cgCache[i] = stage.toAbsolute(data.getCG())[0];
longitudinalInertiaCache[i] = data.longitudinalInertia; longitudinalInertiaCache[i] = data.getLongitudinalInertia();
rotationalInertiaCache[i] = data.rotationalInetria; rotationalInertiaCache[i] = data.getRotationalInertia();
} }
} }
@ -266,24 +273,26 @@ public class BasicMassCalculator extends AbstractMassCalculator {
* of the specified component, not global coordinates. * of the specified component, not global coordinates.
*/ */
private MassData calculateAssemblyMassData(RocketComponent parent) { private MassData calculateAssemblyMassData(RocketComponent parent) {
MassData parentData = new MassData(); Coordinate parentCG = Coordinate.ZERO;
double longitudinalInertia = 0.0;
double rotationalInertia = 0.0;
// Calculate data for this component // Calculate data for this component
parentData.cg = parent.getComponentCG(); parentCG = parent.getComponentCG();
if (parentData.cg.weight < MIN_MASS) if (parentCG.weight < MIN_MASS)
parentData.cg = parentData.cg.setWeight(MIN_MASS); parentCG = parentCG.setWeight(MIN_MASS);
// Override only this component's data // Override only this component's data
if (!parent.getOverrideSubcomponents()) { if (!parent.getOverrideSubcomponents()) {
if (parent.isMassOverridden()) if (parent.isMassOverridden())
parentData.cg = parentData.cg.setWeight(MathUtil.max(parent.getOverrideMass(), MIN_MASS)); parentCG = parentCG.setWeight(MathUtil.max(parent.getOverrideMass(), MIN_MASS));
if (parent.isCGOverridden()) if (parent.isCGOverridden())
parentData.cg = parentData.cg.setXYZ(parent.getOverrideCG()); parentCG = parentCG.setXYZ(parent.getOverrideCG());
} }
parentData.longitudinalInertia = parent.getLongitudinalUnitInertia() * parentData.cg.weight; longitudinalInertia = parent.getLongitudinalUnitInertia() * parentCG.weight;
parentData.rotationalInetria = parent.getRotationalUnitInertia() * parentData.cg.weight; rotationalInertia = parent.getRotationalUnitInertia() * parentCG.weight;
// Combine data for subcomponents // Combine data for subcomponents
@ -293,68 +302,87 @@ public class BasicMassCalculator extends AbstractMassCalculator {
// Compute data of sibling // Compute data of sibling
MassData siblingData = calculateAssemblyMassData(sibling); MassData siblingData = calculateAssemblyMassData(sibling);
Coordinate[] siblingCGs = sibling.toRelative(siblingData.cg, parent); Coordinate[] siblingCGs = sibling.toRelative(siblingData.getCG(), parent);
for (Coordinate siblingCG : siblingCGs) { for (Coordinate siblingCG : siblingCGs) {
// Compute CG of this + sibling // Compute CG of this + sibling
combinedCG = parentData.cg.average(siblingCG); combinedCG = parentCG.average(siblingCG);
// Add effect of this CG change to parent inertia // Add effect of this CG change to parent inertia
dx2 = pow2(parentData.cg.x - combinedCG.x); dx2 = pow2(parentCG.x - combinedCG.x);
parentData.longitudinalInertia += parentData.cg.weight * dx2; longitudinalInertia += parentCG.weight * dx2;
dr2 = pow2(parentData.cg.y - combinedCG.y) + pow2(parentData.cg.z - combinedCG.z); dr2 = pow2(parentCG.y - combinedCG.y) + pow2(parentCG.z - combinedCG.z);
parentData.rotationalInetria += parentData.cg.weight * dr2; rotationalInertia += parentCG.weight * dr2;
// Add inertia of sibling // Add inertia of sibling
parentData.longitudinalInertia += siblingData.longitudinalInertia; longitudinalInertia += siblingData.getLongitudinalInertia();
parentData.rotationalInetria += siblingData.rotationalInetria; rotationalInertia += siblingData.getRotationalInertia();
// Add effect of sibling CG change // Add effect of sibling CG change
dx2 = pow2(siblingData.cg.x - combinedCG.x); dx2 = pow2(siblingData.getCG().x - combinedCG.x);
parentData.longitudinalInertia += siblingData.cg.weight * dx2; longitudinalInertia += siblingData.getCG().weight * dx2;
dr2 = pow2(siblingData.cg.y - combinedCG.y) + pow2(siblingData.cg.z - combinedCG.z); dr2 = pow2(siblingData.getCG().y - combinedCG.y) + pow2(siblingData.getCG().z - combinedCG.z);
parentData.rotationalInetria += siblingData.cg.weight * dr2; rotationalInertia += siblingData.getCG().weight * dr2;
// Set combined CG // Set combined CG
parentData.cg = combinedCG; parentCG = combinedCG;
} }
} }
// Override total data // Override total data
if (parent.getOverrideSubcomponents()) { if (parent.getOverrideSubcomponents()) {
if (parent.isMassOverridden()) { if (parent.isMassOverridden()) {
double oldMass = parentData.cg.weight; double oldMass = parentCG.weight;
double newMass = MathUtil.max(parent.getOverrideMass(), MIN_MASS); double newMass = MathUtil.max(parent.getOverrideMass(), MIN_MASS);
parentData.longitudinalInertia = parentData.longitudinalInertia * newMass / oldMass; longitudinalInertia = longitudinalInertia * newMass / oldMass;
parentData.rotationalInetria = parentData.rotationalInetria * newMass / oldMass; rotationalInertia = rotationalInertia * newMass / oldMass;
parentData.cg = parentData.cg.setWeight(newMass); parentCG = parentCG.setWeight(newMass);
} }
if (parent.isCGOverridden()) { if (parent.isCGOverridden()) {
double oldx = parentData.cg.x; double oldx = parentCG.x;
double newx = parent.getOverrideCGX(); double newx = parent.getOverrideCGX();
parentData.longitudinalInertia += parentData.cg.weight * pow2(oldx - newx); longitudinalInertia += parentCG.weight * pow2(oldx - newx);
parentData.cg = parentData.cg.setX(newx); parentCG = parentCG.setX(newx);
} }
} }
MassData parentData = new MassData(parentCG, longitudinalInertia, rotationalInertia, 0);
return parentData; return parentData;
} }
/**
private static class MassData { * Check the current cache consistency. This method must be called by all
public Coordinate cg = Coordinate.NUL; * methods that may use any cached data before any other operations are
public double longitudinalInertia = 0; * performed. If the rocket has changed since the previous call to
public double rotationalInetria = 0; * <code>checkCache()</code>, then {@link #voidMassCache()} is called.
* <p>
* This method performs the checking based on the rocket's modification IDs,
* so that these method may be called from listeners of the rocket itself.
*
* @param configuration the configuration of the current call
*/
protected final void checkCache(Configuration configuration) {
if (rocketMassModID != configuration.getRocket().getMassModID() ||
rocketTreeModID != configuration.getRocket().getTreeModID()) {
rocketMassModID = configuration.getRocket().getMassModID();
rocketTreeModID = configuration.getRocket().getTreeModID();
log.debug("Voiding the mass cache");
voidMassCache();
}
} }
/**
@Override * Void cached mass data. This method is called whenever a change occurs in
* the rocket structure that affects the mass of the rocket and when a new
* Rocket is used. This method must be overridden to void any cached data
* necessary. The method must call <code>super.voidMassCache()</code> during
* its execution.
*/
protected void voidMassCache() { protected void voidMassCache() {
super.voidMassCache();
this.cgCache = null; this.cgCache = null;
this.longitudinalInertiaCache = null; this.longitudinalInertiaCache = null;
this.rotationalInertiaCache = null; this.rotationalInertiaCache = null;
@ -370,4 +398,6 @@ public class BasicMassCalculator extends AbstractMassCalculator {
} }