Merge pull request #1985 from JoePfeiffer/fix-prev-next-component
Check for gaps and overlaps in airframe
This commit is contained in:
commit
92a1eb067d
@ -1864,6 +1864,10 @@ 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.OPEN_AIRFRAME_FORWARD = Forward end of airframe is open (radius is > 0)
|
||||||
|
Warning.AIRFRAME_GAP = Gap in rocket airframe
|
||||||
|
Warning.AIRFRAME_OVERLAP = Overlap in airframe components
|
||||||
|
Warning.PODSET_FORWARD = In-line podset forward of parent airframe component
|
||||||
|
Warning.PODSET_OVERLAP = In-line podset overlaps parent airframe component
|
||||||
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
|
||||||
|
@ -19,6 +19,8 @@ import net.sf.openrocket.rocketcomponent.FinSet;
|
|||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.InstanceMap;
|
import net.sf.openrocket.rocketcomponent.InstanceMap;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ParallelStage;
|
||||||
|
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||||
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;
|
||||||
@ -279,6 +281,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
@Override
|
@Override
|
||||||
public void checkGeometry(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
|
||||||
if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) {
|
if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) {
|
||||||
@ -288,9 +291,17 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SymmetricComponent prevComp = null;
|
SymmetricComponent prevComp = null;
|
||||||
|
if ((treeRoot instanceof ComponentAssembly) &&
|
||||||
|
(!(treeRoot instanceof Rocket)) &&
|
||||||
|
(treeRoot.getChildCount() > 0)) {
|
||||||
|
prevComp = ((SymmetricComponent) (treeRoot.getChild(0))).getPreviousSymmetricComponent();
|
||||||
|
}
|
||||||
|
|
||||||
while(null != queue.peek()) {
|
while(null != queue.peek()) {
|
||||||
RocketComponent comp = queue.poll();
|
RocketComponent comp = queue.poll();
|
||||||
if( comp instanceof SymmetricComponent ){
|
if(( comp instanceof SymmetricComponent ) ||
|
||||||
|
((comp instanceof AxialStage) &&
|
||||||
|
!(comp instanceof ParallelStage))) {
|
||||||
for (RocketComponent child : comp.getChildren()) {
|
for (RocketComponent child : comp.getChildren()) {
|
||||||
// Ignore inactive stages
|
// Ignore inactive stages
|
||||||
if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) {
|
if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) {
|
||||||
@ -299,42 +310,84 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
queue.add(child);
|
queue.add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymmetricComponent sym = (SymmetricComponent) comp;
|
if (comp instanceof SymmetricComponent) {
|
||||||
prevComp = sym.getPreviousSymmetricComponent();
|
SymmetricComponent sym = (SymmetricComponent) comp;
|
||||||
if (prevComp == null) {
|
if( null == prevComp){
|
||||||
if (sym.getForeRadius() - sym.getThickness() > MathUtil.EPSILON) {
|
if (sym.getForeRadius() - sym.getThickness() > MathUtil.EPSILON) {
|
||||||
warnings.add(Warning.OPEN_AIRFRAME_FORWARD, sym.getName());
|
warnings.add(Warning.OPEN_AIRFRAME_FORWARD, sym.toString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Check for radius discontinuity
|
// Check for radius discontinuity
|
||||||
// We're going to say it's discontinuous if it is presented to the user as having two different
|
// We're going to say it's discontinuous if it is presented to the user as having two different
|
||||||
// string representations. Hopefully there are enough digits in the string that it will
|
// string representations. Hopefully there are enough digits in the string that it will
|
||||||
// present as different if the discontinuity is big enough to matter.
|
// 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 (!UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(2.0*sym.getForeRadius())
|
||||||
// if ( !MathUtil.equals(sym.getForeRadius(), prevComp.getAftRadius())) {
|
.equals(UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(2.0*prevComp.getAftRadius()))) {
|
||||||
warnings.add( Warning.DIAMETER_DISCONTINUITY, sym + ", " + prevComp);
|
warnings.add( Warning.DIAMETER_DISCONTINUITY, prevComp + ", " + sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for phantom tube
|
||||||
|
if ((sym.getLength() < MathUtil.EPSILON) ||
|
||||||
|
(sym.getAftRadius() < MathUtil.EPSILON && sym.getForeRadius() < MathUtil.EPSILON)) {
|
||||||
|
warnings.add(Warning.ZERO_VOLUME_BODY, sym.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for gap or overlap in airframe. We'll use a textual comparison to see if there is a
|
||||||
|
// gap or overlap, then use arithmetic comparison to see which it is. This won't be quite as reliable
|
||||||
|
// as the case for radius, since we never actually display the absolute X position
|
||||||
|
|
||||||
|
double symXfore = sym.toAbsolute(Coordinate.NUL)[0].x;
|
||||||
|
double prevXfore = prevComp.toAbsolute(Coordinate.NUL)[0].x;
|
||||||
|
|
||||||
|
double symXaft = sym.toAbsolute(new Coordinate(comp.getLength(), 0, 0, 0))[0].x;
|
||||||
|
double prevXaft = prevComp.toAbsolute(new Coordinate(prevComp.getLength(), 0, 0, 0))[0].x;
|
||||||
|
|
||||||
|
if (!UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(symXfore)
|
||||||
|
.equals(UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(prevXaft))) {
|
||||||
|
if (symXfore > prevXaft) {
|
||||||
|
warnings.add(Warning.AIRFRAME_GAP, prevComp + ", " + sym);
|
||||||
|
} else {
|
||||||
|
// If we only have the component with a single forward compartment bring up
|
||||||
|
// a body component overlap message
|
||||||
|
if ((symXfore >= prevXfore) &&
|
||||||
|
((symXaft >= prevXaft) || (null == sym.getNextSymmetricComponent()))) {
|
||||||
|
warnings.add(Warning.AIRFRAME_OVERLAP, prevComp + ", " + sym);
|
||||||
|
} else {
|
||||||
|
// We have a PodSet that is either overlapping or completely forward of its parent component.
|
||||||
|
// We'll find the forward-most and aft-most components and figure out which
|
||||||
|
SymmetricComponent firstComp = prevComp;
|
||||||
|
SymmetricComponent scout = prevComp;
|
||||||
|
while (null != scout) {
|
||||||
|
firstComp = scout;
|
||||||
|
scout = scout.getPreviousSymmetricComponent();
|
||||||
|
}
|
||||||
|
double firstCompXfore = firstComp.toAbsolute(Coordinate.NUL)[0].x;
|
||||||
|
|
||||||
|
SymmetricComponent lastComp = sym;
|
||||||
|
scout = sym;
|
||||||
|
while (null != scout) {
|
||||||
|
lastComp = scout;
|
||||||
|
scout = scout.getNextSymmetricComponent();
|
||||||
|
}
|
||||||
|
double lastCompXaft = lastComp.toAbsolute(new Coordinate(lastComp.getLength(), 0, 0, 0))[0].x;
|
||||||
|
|
||||||
|
// completely forward vs. overlap
|
||||||
|
if (lastCompXaft <= firstCompXfore) {
|
||||||
|
warnings.add(Warning.PODSET_FORWARD, comp.getParent().toString());
|
||||||
|
} else {
|
||||||
|
warnings.add(Warning.PODSET_OVERLAP, comp.getParent().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
prevComp = sym;
|
||||||
}
|
}
|
||||||
|
} else if ((comp instanceof PodSet) ||
|
||||||
// Check for phantom tube
|
(comp instanceof ParallelStage)) {
|
||||||
if ((sym.getLength() < MathUtil.EPSILON) ||
|
|
||||||
(sym.getAftRadius() < MathUtil.EPSILON && sym.getForeRadius() < MathUtil.EPSILON)) {
|
|
||||||
warnings.add(Warning.ZERO_VOLUME_BODY, sym.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// double x = component.toAbsolute(Coordinate.NUL)[0].x;
|
|
||||||
// // Check for lengthwise discontinuity
|
|
||||||
// if (x > componentX + 0.0001) {
|
|
||||||
// if (!MathUtil.equals(radius, 0)) {
|
|
||||||
// warnings.add(Warning.DISCONTINUITY);
|
|
||||||
// radius = 0;
|
|
||||||
//}
|
|
||||||
//componentX = component.toAbsolute(new Coordinate(component.getLengthAerodynamic()))[0].x;
|
|
||||||
|
|
||||||
}else if( comp instanceof ComponentAssembly ){
|
|
||||||
checkGeometry(configuration, comp, warnings);
|
checkGeometry(configuration, comp, warnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +362,18 @@ public abstract class Warning {
|
|||||||
/** A <code>Warning</code> that a ComponentAssembly has an open forward end */
|
/** 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"));
|
public static final Warning OPEN_AIRFRAME_FORWARD = new Other(trans.get("Warning.OPEN_AIRFRAME_FORWARD"));
|
||||||
|
|
||||||
|
/** A <code>Warning</code> that there is a gap in the airframe */
|
||||||
|
public static final Warning AIRFRAME_GAP = new Other(trans.get("Warning.AIRFRAME_GAP"));
|
||||||
|
|
||||||
|
/** A <code>Warning</code> that there are overlapping airframe components */
|
||||||
|
public static final Warning AIRFRAME_OVERLAP = new Other(trans.get("Warning.AIRFRAME_OVERLAP"));
|
||||||
|
|
||||||
|
/** A <code>Warning</code> that an inline podset is completely forward of its parent component */
|
||||||
|
public static final Warning PODSET_FORWARD = new Other(trans.get("Warning.PODSET_FORWARD"));
|
||||||
|
|
||||||
|
/** A <code>Warning</code> that an inline podset overlaps its parent component */
|
||||||
|
public static final Warning PODSET_OVERLAP = new Other(trans.get("Warning.PODSET_OVERLAP"));
|
||||||
|
|
||||||
/** 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.
|
||||||
public static final Warning THICK_FIN = new Other(trans.get("Warning.THICK_FIN"));
|
public static final Warning THICK_FIN = new Other(trans.get("Warning.THICK_FIN"));
|
||||||
|
@ -593,6 +593,7 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
|
|||||||
* indicates a preferred radius, a negative value indicates that a
|
* indicates a preferred radius, a negative value indicates that a
|
||||||
* match was not found.
|
* match was not found.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected abstract double getRearAutoRadius();
|
protected abstract double getRearAutoRadius();
|
||||||
|
|
||||||
|
|
||||||
@ -611,8 +612,8 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
|
|||||||
// (b) BodyTube -- for Parallel Stages & PodSets
|
// (b) BodyTube -- for Parallel Stages & PodSets
|
||||||
final RocketComponent grandParent = this.parent.getParent();
|
final RocketComponent grandParent = this.parent.getParent();
|
||||||
|
|
||||||
int searchParentIndex = grandParent.getChildPosition(this.parent); // position of stage w/in parent
|
int searchParentIndex = grandParent.getChildPosition(this.parent); // position of component w/in parent
|
||||||
int searchSiblingIndex = this.parent.getChildPosition(this)-1; // guess at index of previous stage
|
int searchSiblingIndex = this.parent.getChildPosition(this)-1; // guess at index of previous component
|
||||||
|
|
||||||
while( 0 <= searchParentIndex ) {
|
while( 0 <= searchParentIndex ) {
|
||||||
final RocketComponent searchParent = grandParent.getChild(searchParentIndex);
|
final RocketComponent searchParent = grandParent.getChild(searchParentIndex);
|
||||||
@ -620,21 +621,27 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
|
|||||||
if(searchParent instanceof ComponentAssembly){
|
if(searchParent instanceof ComponentAssembly){
|
||||||
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) && inline(searchSibling)) {
|
||||||
SymmetricComponent candidate = (SymmetricComponent) searchSibling;
|
return (SymmetricComponent) searchSibling;
|
||||||
if (inline(candidate)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
--searchSiblingIndex;
|
--searchSiblingIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look forward to the previous stage
|
||||||
--searchParentIndex;
|
--searchParentIndex;
|
||||||
|
|
||||||
if( 0 <= searchParentIndex){
|
if( 0 <= searchParentIndex){
|
||||||
searchSiblingIndex = grandParent.getChild(searchParentIndex).getChildCount() - 1;
|
searchSiblingIndex = grandParent.getChild(searchParentIndex).getChildCount() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// one last thing -- I could be the child of a PodSet, and in line with
|
||||||
|
// the SymmetricComponent that is my grandParent
|
||||||
|
if ((grandParent instanceof SymmetricComponent) && inline(grandParent)) {
|
||||||
|
return (SymmetricComponent) grandParent;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,19 +669,30 @@ 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) && inline(searchSibling)) {
|
||||||
SymmetricComponent candidate = (SymmetricComponent) searchSibling;
|
return (SymmetricComponent) searchSibling;
|
||||||
if (inline(candidate)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
++searchSiblingIndex;
|
++searchSiblingIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look aft to the next stage
|
||||||
++searchParentIndex;
|
++searchParentIndex;
|
||||||
searchSiblingIndex = 0;
|
searchSiblingIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// One last thing -- I could have a child that is a PodSet that is in line
|
||||||
|
// with me
|
||||||
|
for (RocketComponent child : getChildren()) {
|
||||||
|
if (child instanceof PodSet) {
|
||||||
|
for (RocketComponent grandchild : child.getChildren()) {
|
||||||
|
if ((grandchild instanceof SymmetricComponent) && inline(grandchild)) {
|
||||||
|
return (SymmetricComponent) grandchild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,7 +700,7 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
|
|||||||
* Determine whether a candidate symmetric component is in line with us
|
* Determine whether a candidate symmetric component is in line with us
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private boolean inline(final SymmetricComponent candidate) {
|
private boolean inline(final RocketComponent candidate) {
|
||||||
// if we share a parent, we are in line
|
// if we share a parent, we are in line
|
||||||
if (this.parent == candidate.parent)
|
if (this.parent == candidate.parent)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1743,10 +1743,69 @@ public class TestRockets {
|
|||||||
return rocket;
|
return rocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alpha III modified to have an inline pod
|
||||||
|
public static final Rocket makeEstesAlphaIIIwithInlinePod() {
|
||||||
|
|
||||||
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
|
||||||
|
// Find rocket components to manipulate
|
||||||
|
final InstanceMap imap = rocket.getSelectedConfiguration().getActiveInstances();
|
||||||
|
AxialStage stage = null;
|
||||||
|
BodyTube body = null;
|
||||||
|
|
||||||
|
RocketComponent c = null;
|
||||||
|
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||||
|
c = entry.getKey();
|
||||||
|
|
||||||
|
// reference everything to the bottom
|
||||||
|
c.setAxialMethod(AxialMethod.BOTTOM);
|
||||||
|
|
||||||
|
if (c instanceof AxialStage) {
|
||||||
|
stage = (AxialStage) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c instanceof BodyTube) {
|
||||||
|
body = (BodyTube) c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// disconnect the body from the stage
|
||||||
|
stage.removeChild(body);
|
||||||
|
|
||||||
|
// We need to reference the components hooked to the body to its aft end, not forward
|
||||||
|
|
||||||
|
// Make a shorter copy of the body tube and connect it the Stage
|
||||||
|
// Notice -- total lengths of the short tubes must add up to match the original
|
||||||
|
BodyTube frontTube = new BodyTube(body.getLength()/2.0, body.getOuterRadius(), body.getThickness());
|
||||||
|
frontTube.setName("Front Body Tube");
|
||||||
|
stage.addChild(frontTube);
|
||||||
|
|
||||||
|
// Add a PodSet to the front body tube.
|
||||||
|
PodSet pod = new PodSet();
|
||||||
|
pod.setInstanceCount(1);
|
||||||
|
pod.setRadiusMethod(RadiusMethod.COAXIAL);
|
||||||
|
frontTube.addChild(pod);
|
||||||
|
pod.setAxialMethod(AxialMethod.TOP);
|
||||||
|
pod.setAxialOffset(frontTube.getLength());
|
||||||
|
|
||||||
|
// Add another even shorter tube to the pod
|
||||||
|
BodyTube middleTube = new BodyTube(body.getLength()/4.0, body.getOuterRadius(), body.getThickness());
|
||||||
|
middleTube.setName("Middle Body Tube");
|
||||||
|
pod.addChild(middleTube);
|
||||||
|
|
||||||
|
// Shorten the original body tube, rename it, and put it on the pod
|
||||||
|
body.setName("Aft body tube");
|
||||||
|
body.setLength(body.getLength()/4.0);
|
||||||
|
pod.addChild(body);
|
||||||
|
|
||||||
|
return rocket;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dump a test rocket to a file, so we can open it in OR
|
* dump a test rocket to a file, so we can open it in OR
|
||||||
*/
|
*/
|
||||||
static void dumpRocket(Rocket rocket, String filename) {
|
public static void dumpRocket(Rocket rocket, String filename) {
|
||||||
|
|
||||||
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
|
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
|
||||||
OpenRocketSaver saver = new OpenRocketSaver();
|
OpenRocketSaver saver = new OpenRocketSaver();
|
||||||
|
@ -19,6 +19,7 @@ import net.sf.openrocket.rocketcomponent.FinSet;
|
|||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||||
import net.sf.openrocket.rocketcomponent.ParallelStage;
|
import net.sf.openrocket.rocketcomponent.ParallelStage;
|
||||||
|
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
||||||
@ -442,4 +443,53 @@ public class BarrowmanCalculatorTest {
|
|||||||
assertEquals(" Estes Alpha III with multiple empty stages cp y value is incorrect:", cp_calcRef.y, cp_calcMulti.y , EPSILON);
|
assertEquals(" Estes Alpha III with multiple empty stages cp y value is incorrect:", cp_calcRef.y, cp_calcMulti.y , EPSILON);
|
||||||
assertEquals(" Estes Alpha III with multiple empty stages cp z value is incorrect:", cp_calcRef.z, cp_calcMulti.z , EPSILON);
|
assertEquals(" Estes Alpha III with multiple empty stages cp z value is incorrect:", cp_calcRef.z, cp_calcMulti.z , EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests in-line pod aerodynamics and warnings
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testInlinePods() {
|
||||||
|
WarningSet warnings = new WarningSet();
|
||||||
|
|
||||||
|
// reference rocket and results
|
||||||
|
final Rocket refRocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
final FlightConfiguration refConfig = refRocket.getSelectedConfiguration();
|
||||||
|
final FlightConditions refConditions = new FlightConditions(refConfig);
|
||||||
|
|
||||||
|
final BarrowmanCalculator refCalc = new BarrowmanCalculator();
|
||||||
|
double refCP = refCalc.getCP(refConfig, refConditions, warnings).x;
|
||||||
|
final AerodynamicForces refForces = refCalc.getAerodynamicForces(refConfig, refConditions, warnings);
|
||||||
|
assertTrue("reference rocket should have no warnings", warnings.isEmpty());
|
||||||
|
final double refCD = refForces.getCD();
|
||||||
|
|
||||||
|
// test rocket
|
||||||
|
final Rocket testRocket = TestRockets.makeEstesAlphaIIIwithInlinePod();
|
||||||
|
final PodSet pod = (PodSet) testRocket.getChild(0).getChild(1).getChild(0);
|
||||||
|
final FlightConfiguration testConfig = testRocket.getSelectedConfiguration();
|
||||||
|
final FlightConditions testConditions = new FlightConditions(testConfig);
|
||||||
|
|
||||||
|
TestRockets.dumpRocket(testRocket, "/home/joseph/rockets/openrocket/git/openrocket/work/testrocket.ork");
|
||||||
|
final BarrowmanCalculator testCalc = new BarrowmanCalculator();
|
||||||
|
double testCP = testCalc.getCP(testConfig, testConditions, warnings).x;
|
||||||
|
final AerodynamicForces testForces = testCalc.getAerodynamicForces(testConfig, testConditions, warnings);
|
||||||
|
assertTrue("test rocket should have no warnings", warnings.isEmpty());
|
||||||
|
|
||||||
|
assertEquals("ref and test rocket CP should match", refCP, testCP, EPSILON);
|
||||||
|
|
||||||
|
final double testCD = testForces.getCD();
|
||||||
|
assertEquals("ref and test rocket CD should match", refCD, testCD, EPSILON);
|
||||||
|
|
||||||
|
// move the pod back.
|
||||||
|
pod.setAxialOffset(pod.getAxialOffset() + 0.1);
|
||||||
|
testCP = testCalc.getCP(testConfig, testConditions, warnings).x;
|
||||||
|
assertFalse("should be warning from gap in airframe", warnings.isEmpty());
|
||||||
|
|
||||||
|
// move the pod forward.
|
||||||
|
warnings.clear();
|
||||||
|
pod.setAxialOffset(pod.getAxialOffset() - 0.2);
|
||||||
|
testCP = testCalc.getCP(testConfig, testConditions, warnings).x;
|
||||||
|
assertFalse("should be warning from airframe overlap", warnings.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user