1 package net.sf.openrocket.util;
4 import java.util.Random;
6 import net.sf.openrocket.database.Databases;
7 import net.sf.openrocket.material.Material;
8 import net.sf.openrocket.material.Material.Type;
9 import net.sf.openrocket.motor.Motor;
10 import net.sf.openrocket.rocketcomponent.BodyTube;
11 import net.sf.openrocket.rocketcomponent.Bulkhead;
12 import net.sf.openrocket.rocketcomponent.CenteringRing;
13 import net.sf.openrocket.rocketcomponent.ExternalComponent;
14 import net.sf.openrocket.rocketcomponent.FreeformFinSet;
15 import net.sf.openrocket.rocketcomponent.IllegalFinPointException;
16 import net.sf.openrocket.rocketcomponent.InnerTube;
17 import net.sf.openrocket.rocketcomponent.InternalComponent;
18 import net.sf.openrocket.rocketcomponent.LaunchLug;
19 import net.sf.openrocket.rocketcomponent.MassComponent;
20 import net.sf.openrocket.rocketcomponent.NoseCone;
21 import net.sf.openrocket.rocketcomponent.ReferenceType;
22 import net.sf.openrocket.rocketcomponent.Rocket;
23 import net.sf.openrocket.rocketcomponent.RocketComponent;
24 import net.sf.openrocket.rocketcomponent.Stage;
25 import net.sf.openrocket.rocketcomponent.Transition;
26 import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
27 import net.sf.openrocket.rocketcomponent.TubeCoupler;
28 import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
29 import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
30 import net.sf.openrocket.rocketcomponent.MotorMount.IgnitionEvent;
31 import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
32 import net.sf.openrocket.rocketcomponent.Transition.Shape;
34 public class TestRockets {
36 private final String key;
37 private final Random rnd;
40 public TestRockets(String key) {
43 Random rnd = new Random();
44 StringBuilder sb = new StringBuilder();
45 for (int i=0; i<6; i++) {
46 int n = rnd.nextInt(62);
48 sb.append((char)('0'+n));
50 sb.append((char)('A'+n-10));
52 sb.append((char)('a'+n-36));
59 this.rnd = new Random(key.hashCode());
65 * Create a new test rocket based on the value 'key'. The rocket utilizes most of the
66 * properties and features available. The same key always returns the same rocket,
67 * but different key values produce slightly different rockets. A key value of
68 * <code>null</code> generates a rocket using a random key.
70 * The rocket created by this method is not fly-worthy. It is also NOT guaranteed
71 * that later versions would produce exactly the same rocket!
73 * @return a rocket design.
75 public Rocket makeTestRocket() {
77 Rocket rocket = new Rocket();
79 rocket.setCustomReferenceLength(rnd(0.05));
80 rocket.setDesigner("Designer " + key);
81 rocket.setReferenceType((ReferenceType) randomEnum(ReferenceType.class));
82 rocket.setRevision("Rocket revision " + key);
86 Stage stage = new Stage();
88 rocket.addChild(stage);
91 NoseCone nose = new NoseCone();
93 nose.setAftRadius(rnd(0.03));
94 nose.setAftRadiusAutomatic(rnd.nextBoolean());
95 nose.setAftShoulderCapped(rnd.nextBoolean());
96 nose.setAftShoulderLength(rnd(0.02));
97 nose.setAftShoulderRadius(rnd(0.02));
98 nose.setAftShoulderThickness(rnd(0.002));
99 nose.setClipped(rnd.nextBoolean());
100 nose.setThickness(rnd(0.002));
101 nose.setFilled(rnd.nextBoolean());
102 nose.setForeRadius(rnd(0.1)); // Unset
103 nose.setLength(rnd(0.15));
104 nose.setShapeParameter(rnd(0.5));
105 nose.setType((Shape) randomEnum(Shape.class));
106 stage.addChild(nose);
109 Transition shoulder = new Transition();
111 shoulder.setAftRadius(rnd(0.06));
112 shoulder.setAftRadiusAutomatic(rnd.nextBoolean());
113 shoulder.setAftShoulderCapped(rnd.nextBoolean());
114 shoulder.setAftShoulderLength(rnd(0.02));
115 shoulder.setAftShoulderRadius(rnd(0.05));
116 shoulder.setAftShoulderThickness(rnd(0.002));
117 shoulder.setClipped(rnd.nextBoolean());
118 shoulder.setThickness(rnd(0.002));
119 shoulder.setFilled(rnd.nextBoolean());
120 shoulder.setForeRadius(rnd(0.03));
121 shoulder.setForeRadiusAutomatic(rnd.nextBoolean());
122 shoulder.setForeShoulderCapped(rnd.nextBoolean());
123 shoulder.setForeShoulderLength(rnd(0.02));
124 shoulder.setForeShoulderRadius(rnd(0.02));
125 shoulder.setForeShoulderThickness(rnd(0.002));
126 shoulder.setLength(rnd(0.15));
127 shoulder.setShapeParameter(rnd(0.5));
128 shoulder.setThickness(rnd(0.003));
129 shoulder.setType((Shape) randomEnum(Shape.class));
130 stage.addChild(shoulder);
133 BodyTube body = new BodyTube();
135 body.setThickness(rnd(0.002));
136 body.setFilled(rnd.nextBoolean());
137 body.setIgnitionDelay(rnd.nextDouble()*3);
138 body.setIgnitionEvent((IgnitionEvent) randomEnum(IgnitionEvent.class));
139 body.setLength(rnd(0.3));
140 body.setMotorMount(rnd.nextBoolean());
141 body.setMotorOverhang(rnd.nextGaussian()*0.03);
142 body.setRadius(rnd(0.06));
143 body.setRadiusAutomatic(rnd.nextBoolean());
144 stage.addChild(body);
147 Transition boattail = new Transition();
149 boattail.setAftRadius(rnd(0.03));
150 boattail.setAftRadiusAutomatic(rnd.nextBoolean());
151 boattail.setAftShoulderCapped(rnd.nextBoolean());
152 boattail.setAftShoulderLength(rnd(0.02));
153 boattail.setAftShoulderRadius(rnd(0.02));
154 boattail.setAftShoulderThickness(rnd(0.002));
155 boattail.setClipped(rnd.nextBoolean());
156 boattail.setThickness(rnd(0.002));
157 boattail.setFilled(rnd.nextBoolean());
158 boattail.setForeRadius(rnd(0.06));
159 boattail.setForeRadiusAutomatic(rnd.nextBoolean());
160 boattail.setForeShoulderCapped(rnd.nextBoolean());
161 boattail.setForeShoulderLength(rnd(0.02));
162 boattail.setForeShoulderRadius(rnd(0.05));
163 boattail.setForeShoulderThickness(rnd(0.002));
164 boattail.setLength(rnd(0.15));
165 boattail.setShapeParameter(rnd(0.5));
166 boattail.setThickness(rnd(0.003));
167 boattail.setType((Shape) randomEnum(Shape.class));
168 stage.addChild(boattail);
171 MassComponent mass = new MassComponent();
173 mass.setComponentMass(rnd(0.05));
174 mass.setLength(rnd(0.05));
175 mass.setRadialDirection(rnd(100));
176 mass.setRadialPosition(rnd(0.02));
177 mass.setRadius(rnd(0.05));
187 private void setBasics(RocketComponent c) {
188 c.setComment(c.getComponentName() + " comment " + key);
189 c.setName(c.getComponentName() + " name " + key);
191 c.setCGOverridden(rnd.nextBoolean());
192 c.setMassOverridden(rnd.nextBoolean());
193 c.setOverrideCGX(rnd(0.2));
194 c.setOverrideMass(rnd(0.05));
195 c.setOverrideSubcomponents(rnd.nextBoolean());
198 // Only massive components are drawn
199 c.setColor(randomColor());
200 c.setLineStyle((LineStyle) randomEnum(LineStyle.class));
203 if (c instanceof ExternalComponent) {
204 ExternalComponent e = (ExternalComponent)c;
205 e.setFinish((Finish) randomEnum(Finish.class));
207 e.setMaterial(Material.newMaterial(Type.BULK, "Testmat "+d, d, rnd.nextBoolean()));
210 if (c instanceof InternalComponent) {
211 InternalComponent i = (InternalComponent)c;
212 i.setRelativePosition((Position) randomEnum(Position.class));
213 i.setPositionValue(rnd(0.3));
219 private double rnd(double scale) {
220 return (rnd.nextDouble()*0.2+0.9) * scale;
223 private Color randomColor() {
224 return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
227 private <T extends Enum<T>> Enum<T> randomEnum(Class<T> c) {
228 Enum<T>[] values = c.getEnumConstants();
229 if (values.length == 0)
232 return values[rnd.nextInt(values.length)];
240 public Rocket makeSmallFlyable() {
241 double noseconeLength=0.10,noseconeRadius=0.01;
242 double bodytubeLength=0.20,bodytubeRadius=0.01,bodytubeThickness=0.001;
245 double finRootChord=0.04,finTipChord=0.05,finSweep=0.01,finThickness=0.003, finHeight=0.03;
252 TrapezoidFinSet finset;
254 rocket = new Rocket();
256 stage.setName("Stage1");
258 nosecone = new NoseCone(Transition.Shape.ELLIPSOID,noseconeLength,noseconeRadius);
259 bodytube = new BodyTube(bodytubeLength,bodytubeRadius,bodytubeThickness);
261 finset = new TrapezoidFinSet(finCount,finRootChord,finTipChord,finSweep,finHeight);
264 // Stage construction
265 rocket.addChild(stage);
268 // Component construction
269 stage.addChild(nosecone);
270 stage.addChild(bodytube);
272 bodytube.addChild(finset);
274 Material material = Prefs.getDefaultComponentMaterial(null, Material.Type.BULK);
275 nosecone.setMaterial(material);
276 bodytube.setMaterial(material);
277 finset.setMaterial(material);
279 String id = rocket.newMotorConfigurationID();
280 bodytube.setMotorMount(true);
282 for (Motor m: Databases.MOTOR) {
283 if (m.getDesignation().equals("B4")) {
284 bodytube.setMotor(id, m);
288 bodytube.setMotorOverhang(0.005);
289 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
291 rocket.getDefaultConfiguration().setAllStages();
298 public static Rocket makeBigBlue() {
303 FreeformFinSet finset;
306 rocket = new Rocket();
308 stage.setName("Stage1");
310 nosecone = new NoseCone(Transition.Shape.ELLIPSOID,0.105,0.033);
311 nosecone.setThickness(0.001);
312 bodytube = new BodyTube(0.69,0.033,0.001);
314 finset = new FreeformFinSet();
316 finset.setPoints(new Coordinate[] {
317 new Coordinate(0, 0),
318 new Coordinate(0.115, 0.072),
319 new Coordinate(0.255, 0.072),
320 new Coordinate(0.255, 0.037),
321 new Coordinate(0.150, 0)
323 } catch (IllegalFinPointException e) {
326 finset.setThickness(0.003);
327 finset.setFinCount(4);
329 finset.setCantAngle(0*Math.PI/180);
330 System.err.println("Fin cant angle: "+(finset.getCantAngle() * 180/Math.PI));
332 mcomp = new MassComponent(0.2,0.03,0.045 + 0.060);
333 mcomp.setRelativePosition(Position.TOP);
334 mcomp.setPositionValue(0);
336 // Stage construction
337 rocket.addChild(stage);
338 rocket.setPerfectFinish(false);
341 // Component construction
342 stage.addChild(nosecone);
343 stage.addChild(bodytube);
345 bodytube.addChild(finset);
347 bodytube.addChild(mcomp);
349 // Material material = new Material("Test material", 500);
350 // nosecone.setMaterial(material);
351 // bodytube.setMaterial(material);
352 // finset.setMaterial(material);
354 String id = rocket.newMotorConfigurationID();
355 bodytube.setMotorMount(true);
357 for (Motor m: Databases.MOTOR) {
358 if (m.getDesignation().equals("F12J")) {
359 bodytube.setMotor(id, m);
363 bodytube.setMotorOverhang(0.005);
364 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
366 rocket.getDefaultConfiguration().setAllStages();
374 public static Rocket makeIsoHaisu() {
378 BodyTube tube1, tube2, tube3;
379 TrapezoidFinSet finset;
380 TrapezoidFinSet auxfinset;
383 final double R = 0.07;
385 rocket = new Rocket();
387 stage.setName("Stage1");
389 nosecone = new NoseCone(Transition.Shape.OGIVE,0.53,R);
390 nosecone.setThickness(0.005);
391 nosecone.setMassOverridden(true);
392 nosecone.setOverrideMass(0.588);
393 stage.addChild(nosecone);
395 tube1 = new BodyTube(0.505,R,0.005);
396 tube1.setMassOverridden(true);
397 tube1.setOverrideMass(0.366);
398 stage.addChild(tube1);
400 tube2 = new BodyTube(0.605,R,0.005);
401 tube2.setMassOverridden(true);
402 tube2.setOverrideMass(0.427);
403 stage.addChild(tube2);
405 tube3 = new BodyTube(1.065,R,0.005);
406 tube3.setMassOverridden(true);
407 tube3.setOverrideMass(0.730);
408 stage.addChild(tube3);
411 LaunchLug lug = new LaunchLug();
414 TubeCoupler coupler = new TubeCoupler();
415 coupler.setOuterRadiusAutomatic(true);
416 coupler.setThickness(0.005);
417 coupler.setLength(0.28);
418 coupler.setMassOverridden(true);
419 coupler.setOverrideMass(0.360);
420 coupler.setRelativePosition(Position.BOTTOM);
421 coupler.setPositionValue(-0.14);
422 tube1.addChild(coupler);
426 MassComponent mass = new MassComponent(0.05, 0.05, 0.280);
427 mass.setRelativePosition(Position.TOP);
428 mass.setPositionValue(0.2);
429 tube1.addChild(mass);
432 mass = new MassComponent(0.05, 0.05, 0.125);
433 mass.setRelativePosition(Position.TOP);
434 mass.setPositionValue(0.2);
435 tube1.addChild(mass);
438 mass = new MassComponent(0.40, R, 1.500);
439 mass.setRelativePosition(Position.TOP);
440 mass.setPositionValue(0.25);
441 tube1.addChild(mass);
444 auxfinset = new TrapezoidFinSet();
445 auxfinset.setName("CONTROL");
446 auxfinset.setFinCount(2);
447 auxfinset.setRootChord(0.05);
448 auxfinset.setTipChord(0.05);
449 auxfinset.setHeight(0.10);
450 auxfinset.setSweep(0);
451 auxfinset.setThickness(0.008);
452 auxfinset.setCrossSection(CrossSection.AIRFOIL);
453 auxfinset.setRelativePosition(Position.TOP);
454 auxfinset.setPositionValue(0.28);
455 auxfinset.setBaseRotation(Math.PI/2);
456 tube1.addChild(auxfinset);
461 coupler = new TubeCoupler();
462 coupler.setOuterRadiusAutomatic(true);
463 coupler.setLength(0.28);
464 coupler.setRelativePosition(Position.TOP);
465 coupler.setPositionValue(0.47);
466 coupler.setMassOverridden(true);
467 coupler.setOverrideMass(0.360);
468 tube2.addChild(coupler);
473 mass = new MassComponent(0.1, 0.05, 0.028);
474 mass.setRelativePosition(Position.TOP);
475 mass.setPositionValue(0.14);
476 tube2.addChild(mass);
478 Bulkhead bulk = new Bulkhead();
479 bulk.setOuterRadiusAutomatic(true);
480 bulk.setMassOverridden(true);
481 bulk.setOverrideMass(0.050);
482 bulk.setRelativePosition(Position.TOP);
483 bulk.setPositionValue(0.27);
484 tube2.addChild(bulk);
487 mass = new MassComponent(0.1, 0.05, 0.125);
488 mass.setRelativePosition(Position.TOP);
489 mass.setPositionValue(0.19);
490 tube2.addChild(mass);
494 InnerTube inner = new InnerTube();
495 inner.setOuterRadius(0.08/2);
496 inner.setInnerRadius(0.0762/2);
497 inner.setLength(0.86);
498 inner.setMassOverridden(true);
499 inner.setOverrideMass(0.388);
500 tube3.addChild(inner);
503 CenteringRing center = new CenteringRing();
504 center.setInnerRadiusAutomatic(true);
505 center.setOuterRadiusAutomatic(true);
506 center.setLength(0.005);
507 center.setMassOverridden(true);
508 center.setOverrideMass(0.038);
509 center.setRelativePosition(Position.BOTTOM);
510 center.setPositionValue(0);
511 tube3.addChild(center);
514 center = new CenteringRing();
515 center.setInnerRadiusAutomatic(true);
516 center.setOuterRadiusAutomatic(true);
517 center.setLength(0.005);
518 center.setMassOverridden(true);
519 center.setOverrideMass(0.038);
520 center.setRelativePosition(Position.TOP);
521 center.setPositionValue(0.28);
522 tube3.addChild(center);
525 center = new CenteringRing();
526 center.setInnerRadiusAutomatic(true);
527 center.setOuterRadiusAutomatic(true);
528 center.setLength(0.005);
529 center.setMassOverridden(true);
530 center.setOverrideMass(0.038);
531 center.setRelativePosition(Position.TOP);
532 center.setPositionValue(0.83);
533 tube3.addChild(center);
539 finset = new TrapezoidFinSet();
540 finset.setRootChord(0.495);
541 finset.setTipChord(0.1);
542 finset.setHeight(0.185);
543 finset.setThickness(0.005);
544 finset.setSweep(0.3);
545 finset.setRelativePosition(Position.BOTTOM);
546 finset.setPositionValue(-0.03);
547 finset.setBaseRotation(Math.PI/2);
548 tube3.addChild(finset);
551 finset.setCantAngle(0*Math.PI/180);
552 System.err.println("Fin cant angle: "+(finset.getCantAngle() * 180/Math.PI));
555 // Stage construction
556 rocket.addChild(stage);
557 rocket.setPerfectFinish(false);
561 String id = rocket.newMotorConfigurationID();
562 tube3.setMotorMount(true);
564 for (Motor m: Databases.MOTOR) {
565 if (m.getDesignation().equals("L540")) {
566 tube3.setMotor(id, m);
570 tube3.setMotorOverhang(0.02);
571 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
573 // tube3.setIgnitionEvent(MotorMount.IgnitionEvent.NEVER);
575 rocket.getDefaultConfiguration().setAllStages();