Add unit test "testPhantomTubes" comparing a simple 3FNC rocket against the same rocket, implemented by replacing the fins by three pods, putting a 0-diameter body tube on each pod, and putting one fin on each pod.

This commit is contained in:
JoePfeiffer 2020-03-25 14:52:52 -06:00
parent 9845decb20
commit 00abce96ff
2 changed files with 131 additions and 1 deletions

View File

@ -1,13 +1,16 @@
package net.sf.openrocket.util;
import java.util.ArrayList;
import java.io.FileOutputStream;
import java.util.Map;
import java.util.Random;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.OpenRocketDocumentFactory;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.material.Material.Type;
import net.sf.openrocket.motor.Manufacturer;
@ -34,6 +37,8 @@ import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.InstanceContext;
import net.sf.openrocket.rocketcomponent.InstanceMap;
import net.sf.openrocket.rocketcomponent.InternalComponent;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.MassComponent;
@ -1629,5 +1634,84 @@ public class TestRockets {
rocket.enableEvents();
return rocketDoc;
}
// the following two models are used in testing
// otherwise-identical rockets, one created in the obvious way
// using a single finset and the other creating three pods, each
// with a single fin.
public static final Rocket make3FNCNoPods() {
Rocket rocket = new Rocket();
rocket.enableEvents();
AxialStage stage = new AxialStage();
stage.setName("Sustainer");
rocket.addChild(stage);
// shape, length, radius
NoseCone nosecone = new NoseCone(Transition.Shape.OGIVE, 0.102, 0.0125);
stage.addChild(nosecone);
// length, outer radius, thickness
BodyTube bodytube = new BodyTube(0.305, 0.0125, 0.001);
bodytube.setName("Main Body");
stage.addChild(bodytube);
// number of fins, root chord, tip chord, sweep, height
TrapezoidFinSet trapezoidfinset = new TrapezoidFinSet(3, 0.051, 0.025, 0.038, 0.044);
bodytube.addChild(trapezoidfinset);
// This is how we can dump a test rocket so we can look at it in OR to better
// visualize it
//
// OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
// OpenRocketSaver saver = new OpenRocketSaver();
// try {
// FileOutputStream str = new FileOutputStream("3fnc.ork");
// saver.save(str, doc, null);
// }
// catch (Exception e) {
// System.err.println("exception " + e);
// }
return rocket;
}
// second model used to test with/without pods. In order to
// maintain consistency between the models, we'll create the
// no-pods first, and then modify it to make the with-pods version
public static final Rocket make3FNCWithPods() {
Rocket rocket = TestRockets.make3FNCNoPods();
// find the body and fins
final InstanceMap imap = rocket.getSelectedConfiguration().getActiveInstances();
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
RocketComponent c = entry.getKey();
if (c instanceof TrapezoidFinSet) {
final TrapezoidFinSet fins = (TrapezoidFinSet) c;
final BodyTube body = (BodyTube) fins.getParent();
body.removeChild(fins);
// create a PodSet to hook the fins to
PodSet podset = new PodSet();
podset.setInstanceCount(fins.getFinCount());
body.addChild(podset);
// put a phantom body tube on the pods
BodyTube podBody = new BodyTube(fins.getRootChord(), 0);
podBody.setName("Pod Body");
podset.addChild(podBody);
// change the number of fins to 1 and put the revised
// finset on the podbody
fins.setFinCount(1);
podBody.addChild(fins);
}
}
return rocket;
}
}

View File

@ -231,4 +231,50 @@ public class BarrowmanCalculatorTest {
assertFalse(" Missed discontinuity in Falcon 9 Heavy:", calc.isContinuous( rocket));
}
@Test
public void testPhantomTubes() {
Rocket rocketNoPods = TestRockets.make3FNCNoPods();
FlightConfiguration configNoPods = rocketNoPods.getSelectedConfiguration();
FlightConditions conditionsNoPods = new FlightConditions(configNoPods);
WarningSet warningsNoPods = new WarningSet();
Rocket rocketWithPods = TestRockets.make3FNCWithPods();
FlightConfiguration configPods = rocketWithPods.getSelectedConfiguration();
FlightConditions conditionsPods = new FlightConditions(configPods);
WarningSet warningsPods = new WarningSet();
AerodynamicCalculator calcPods = new BarrowmanCalculator();
AerodynamicCalculator calcNoPods = new BarrowmanCalculator();
final AerodynamicForces forcesNoPods = calcPods.getAerodynamicForces(configNoPods, conditionsNoPods, warningsNoPods);
final AerodynamicForces forcesPods = calcPods.getAerodynamicForces(configPods, conditionsPods, warningsPods);
assertEquals(" 3FNC With Pods rocket CD value is incorrect:", forcesPods.getCD(), forcesNoPods.getCD(), EPSILON);
// The "with pods" version has no way of seeing the fins are
// on the actual body tube rather than the phantom tubes,
// so CD won't take fin-body interference into consideration.
// So we'll adjust our CD in these tests. The magic numbers
// in x and w come from temporarily disabling the
// interference calculation in FinSetCalc and comparing
// results with and without it
// cpNoPods (0.34125,0.00000,0.00000,w=16.20502) -- interference disabled
// cpNoPods (0.34797,0.00000,0.00000,w=19.34773) -- interference enabled
// another note: the fact that this is seen as three one-fin
// FinSets instead of a single three-fin FinSet means the CP
// will be off-axis (one of the fins is taken as having an
// angle of 0 to the airstream, so it has no contribution).
// This doesn't turn out to cause a problem in an actual
// simulation, so we are just not testing for it. Test with
// correction if we want some time is here but commented out
final Coordinate cpNoPods = calcNoPods.getCP(configNoPods, conditionsNoPods, warningsNoPods);
final Coordinate cpPods = calcPods.getCP(configPods, conditionsPods, warningsPods);
assertEquals(" 3FNC With Pods rocket cp x value is incorrect:", cpPods.x, cpNoPods.x - 0.00672, EPSILON);
// assertEquals(" 3FNC With Pods rocket cp y value is incorrect:", cpPods.y, cpNoPods.y - 0.00548, EPSILON);
// assertEquals(" 3FNC With Pods rocket cp z value is incorrect:", cpPods.z, cpNoPods.z, EPSILON);
assertEquals(" 3FNC With Pods rocket CNa value is incorrect:", cpPods.weight, cpNoPods.weight - 3.14271, EPSILON);
}
}