Merge pull request #1931 from JoePfeiffer/add-open-airframe-warning

Add open airframe warning and use text compare to find airframe discontinuities
This commit is contained in:
Joe Pfeiffer 2023-01-05 10:49:01 -07:00 committed by GitHub
commit 9c46f85425
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 22 deletions

View File

@ -1856,6 +1856,7 @@ PlotConfiguration.Groundtrack = Ground track
Warning.LargeAOA.str1 = Large angle of attack encountered. Warning.LargeAOA.str1 = Large angle of attack encountered.
Warning.LargeAOA.str2 = Large angle of attack encountered ( Warning.LargeAOA.str2 = Large angle of attack encountered (
Warning.DISCONTINUITY = Discontinuity in rocket body diameter Warning.DISCONTINUITY = Discontinuity in rocket body diameter
Warning.OPEN_AIRFRAME_FORWARD = Forward end of airframe is open (radius is > 0)
Warning.THICK_FIN = Thick fins may not simulate accurately. Warning.THICK_FIN = Thick fins may not simulate accurately.
Warning.JAGGED_EDGED_FIN = Jagged-edged fin predictions may be inaccurate. Warning.JAGGED_EDGED_FIN = Jagged-edged fin predictions may be inaccurate.
Warning.LISTENERS_AFFECTED = Listeners modified the flight simulation Warning.LISTENERS_AFFECTED = Listeners modified the flight simulation

View File

@ -69,7 +69,7 @@ public interface AerodynamicCalculator extends Monitorable {
public AerodynamicCalculator newInstance(); public AerodynamicCalculator newInstance();
/** /**
* Test component assembly for continuity (esp. diameter), and post any needed warnings * Check component assembly for geometric problems and post any needed warnings
*/ */
public void testIsContinuous(FlightConfiguration configuration, final RocketComponent component, WarningSet warnings); public void checkGeometry(FlightConfiguration configuration, final RocketComponent component, WarningSet warnings);
} }

View File

@ -21,6 +21,7 @@ import net.sf.openrocket.rocketcomponent.InstanceMap;
import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.unit.UnitGroup;
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.PolyInterpolator; import net.sf.openrocket.util.PolyInterpolator;
@ -44,7 +45,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
private double cacheDiameter = -1; private double cacheDiameter = -1;
private double cacheLength = -1; private double cacheLength = -1;
public BarrowmanCalculator() { public BarrowmanCalculator() {
} }
@ -252,7 +252,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
if (calcMap == null) if (calcMap == null)
buildCalcMap(configuration); buildCalcMap(configuration);
testIsContinuous(configuration, configuration.getRocket(), warnings); checkGeometry(configuration, configuration.getRocket(), warnings);
final InstanceMap imap = configuration.getActiveInstances(); final InstanceMap imap = configuration.getActiveInstances();
@ -276,7 +276,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
} }
@Override @Override
public void testIsContinuous(FlightConfiguration configuration, final RocketComponent treeRoot, WarningSet warnings ){ public void checkGeometry(FlightConfiguration configuration, final RocketComponent treeRoot, WarningSet warnings ){
Queue<RocketComponent> queue = new LinkedList<>(); Queue<RocketComponent> queue = new LinkedList<>();
for (RocketComponent child : treeRoot.getChildren()) { for (RocketComponent child : treeRoot.getChildren()) {
// Ignore inactive stages // Ignore inactive stages
@ -299,14 +299,20 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
} }
SymmetricComponent sym = (SymmetricComponent) comp; SymmetricComponent sym = (SymmetricComponent) comp;
prevComp = sym.getPreviousSymmetricComponent();
if( null == prevComp){ if( null == prevComp){
prevComp = sym; if (sym.getForeRadius() - sym.getThickness() > MathUtil.EPSILON) {
continue; warnings.add(Warning.OPEN_AIRFRAME_FORWARD, sym.toString());
} }
} else {
// Check for radius discontinuity // Check for radius discontinuity
if ( !MathUtil.equals(sym.getForeRadius(), prevComp.getAftRadius())) { // We're going to say it's discontinuous if it is presented to the user as having two different
warnings.add( Warning.DIAMETER_DISCONTINUITY, sym + ", " + prevComp); // string representations. Hopefully there are enough digits in the string that it will
// present as different if the discontinuity is big enough to matter.
if (!UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(2.0*sym.getForeRadius()).equals(UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(2.0*prevComp.getAftRadius()))) {
// if ( !MathUtil.equals(sym.getForeRadius(), prevComp.getAftRadius())) {
warnings.add( Warning.DIAMETER_DISCONTINUITY, sym + ", " + prevComp);
}
} }
// double x = component.toAbsolute(Coordinate.NUL)[0].x; // double x = component.toAbsolute(Coordinate.NUL)[0].x;
@ -318,9 +324,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
//} //}
//componentX = component.toAbsolute(new Coordinate(component.getLengthAerodynamic()))[0].x; //componentX = component.toAbsolute(new Coordinate(component.getLengthAerodynamic()))[0].x;
prevComp = sym;
}else if( comp instanceof ComponentAssembly ){ }else if( comp instanceof ComponentAssembly ){
testIsContinuous(configuration, comp, warnings); checkGeometry(configuration, comp, warnings);
} }
} }

View File

@ -358,6 +358,9 @@ public abstract class Warning {
/** A <code>Warning</code> that the body diameter is discontinuous. */ /** A <code>Warning</code> that the body diameter is discontinuous. */
////Discontinuity in rocket body diameter. ////Discontinuity in rocket body diameter.
public static final Warning DIAMETER_DISCONTINUITY = new Other(trans.get("Warning.DISCONTINUITY")); public static final Warning DIAMETER_DISCONTINUITY = new Other(trans.get("Warning.DISCONTINUITY"));
/** A <code>Warning</code> that a ComponentAssembly has an open forward end */
public static final Warning OPEN_AIRFRAME_FORWARD = new Other(trans.get("Warning.OPEN_AIRFRAME_FORWARD"));
/** A <code>Warning</code> that the fins are thick compared to the rocket body. */ /** A <code>Warning</code> that the fins are thick compared to the rocket body. */
////Thick fins may not be modeled accurately. ////Thick fins may not be modeled accurately.

View File

@ -10,7 +10,7 @@ import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.BoundingBox;
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.rocketcomponent.position.RadiusMethod;
/** /**
* Class for an axially symmetric rocket component generated by rotating * Class for an axially symmetric rocket component generated by rotating
@ -621,7 +621,11 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
while (0 <= searchSiblingIndex) { while (0 <= searchSiblingIndex) {
final RocketComponent searchSibling = searchParent.getChild(searchSiblingIndex); final RocketComponent searchSibling = searchParent.getChild(searchSiblingIndex);
if (searchSibling instanceof SymmetricComponent) { if (searchSibling instanceof SymmetricComponent) {
return (SymmetricComponent) searchSibling; SymmetricComponent candidate = (SymmetricComponent) searchSibling;
if (inline(candidate)) {
return candidate;
}
return null;
} }
--searchSiblingIndex; --searchSiblingIndex;
} }
@ -658,9 +662,12 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
if(searchParent instanceof ComponentAssembly){ if(searchParent instanceof ComponentAssembly){
while (searchSiblingIndex < searchParent.getChildCount()) { while (searchSiblingIndex < searchParent.getChildCount()) {
final RocketComponent searchSibling = searchParent.getChild(searchSiblingIndex); final RocketComponent searchSibling = searchParent.getChild(searchSiblingIndex);
if (searchSibling instanceof SymmetricComponent) { if (searchSibling instanceof SymmetricComponent) {
return (SymmetricComponent) searchSibling; SymmetricComponent candidate = (SymmetricComponent) searchSibling;
if (inline(candidate)) {
return candidate;
}
return null;
} }
++searchSiblingIndex; ++searchSiblingIndex;
} }
@ -671,6 +678,29 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
return null; return null;
} }
/***
* Determine whether a candidate symmetric component is in line with us
*
*/
private boolean inline(final SymmetricComponent candidate) {
// if we share a parent, we are in line
if (this.parent == candidate.parent)
return true;
// if both of our parents are either not ring instanceable, or
// have a radial offset of 0 from their centerline, we are in line.
if ((this.parent instanceof RingInstanceable) &&
(!MathUtil.equals(this.parent.getRadiusMethod().getRadius(this.parent.parent, this, this.parent.getRadiusOffset()), 0)))
return false;
if ((candidate.parent instanceof RingInstanceable) &&
(!MathUtil.equals(candidate.parent.getRadiusMethod().getRadius(candidate.parent.parent, candidate, candidate.parent.getRadiusOffset()), 0)))
return false;
return true;
}
/** /**
* Checks whether the component uses the previous symmetric component for its auto diameter. * Checks whether the component uses the previous symmetric component for its auto diameter.
*/ */

View File

@ -290,7 +290,7 @@ public class BarrowmanCalculatorTest {
FlightConfiguration configuration = rocket.getSelectedConfiguration(); FlightConfiguration configuration = rocket.getSelectedConfiguration();
WarningSet warnings = new WarningSet(); WarningSet warnings = new WarningSet();
calc.testIsContinuous(configuration, rocket, warnings); calc.checkGeometry(configuration, rocket, warnings);
assertTrue("Estes Alpha III should be continuous: ", warnings.isEmpty()); assertTrue("Estes Alpha III should be continuous: ", warnings.isEmpty());
} }
@ -301,7 +301,7 @@ public class BarrowmanCalculatorTest {
FlightConfiguration configuration = rocket.getSelectedConfiguration(); FlightConfiguration configuration = rocket.getSelectedConfiguration();
WarningSet warnings = new WarningSet(); WarningSet warnings = new WarningSet();
calc.testIsContinuous(configuration, rocket, warnings); calc.checkGeometry(configuration, rocket, warnings);
assertTrue("F9H should be continuous: ", warnings.isEmpty()); assertTrue("F9H should be continuous: ", warnings.isEmpty());
} }
@ -319,7 +319,7 @@ public class BarrowmanCalculatorTest {
body.setOuterRadius( 0.012 ); body.setOuterRadius( 0.012 );
body.setName( body.getName()+" << discontinuous"); body.setName( body.getName()+" << discontinuous");
calc.testIsContinuous(configuration, rocket, warnings); calc.checkGeometry(configuration, rocket, warnings);
assertFalse(" Estes Alpha III has an undetected discontinuity:", warnings.isEmpty()); assertFalse(" Estes Alpha III has an undetected discontinuity:", warnings.isEmpty());
} }
@ -340,7 +340,7 @@ public class BarrowmanCalculatorTest {
body.setOuterRadius( 0.012 ); body.setOuterRadius( 0.012 );
body.setName( body.getName()+" << discontinuous"); body.setName( body.getName()+" << discontinuous");
calc.testIsContinuous(configuration, rocket, warnings); calc.checkGeometry(configuration, rocket, warnings);
assertFalse(" Missed discontinuity in Falcon 9 Heavy:" , warnings.isEmpty()); assertFalse(" Missed discontinuity in Falcon 9 Heavy:" , warnings.isEmpty());
} }