6d3c7e59045b3cb82ad60b3af2897a5270338b92
[debian/openrocket] / core / src / net / sf / openrocket / util / TestRockets.java
1 package net.sf.openrocket.util;
2
3 import java.util.Random;
4
5 import net.sf.openrocket.material.Material;
6 import net.sf.openrocket.material.Material.Type;
7 import net.sf.openrocket.motor.Motor;
8 import net.sf.openrocket.rocketcomponent.BodyTube;
9 import net.sf.openrocket.rocketcomponent.Bulkhead;
10 import net.sf.openrocket.rocketcomponent.CenteringRing;
11 import net.sf.openrocket.rocketcomponent.ExternalComponent;
12 import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
13 import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
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.MotorMount.IgnitionEvent;
21 import net.sf.openrocket.rocketcomponent.NoseCone;
22 import net.sf.openrocket.rocketcomponent.ReferenceType;
23 import net.sf.openrocket.rocketcomponent.Rocket;
24 import net.sf.openrocket.rocketcomponent.RocketComponent;
25 import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
26 import net.sf.openrocket.rocketcomponent.Stage;
27 import net.sf.openrocket.rocketcomponent.Transition;
28 import net.sf.openrocket.rocketcomponent.Transition.Shape;
29 import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
30 import net.sf.openrocket.rocketcomponent.TubeCoupler;
31 import net.sf.openrocket.startup.Application;
32
33 public class TestRockets {
34         
35         private final String key;
36         private final Random rnd;
37         
38         
39         public TestRockets(String key) {
40                 
41                 if (key == null) {
42                         Random rnd = new Random();
43                         StringBuilder sb = new StringBuilder();
44                         for (int i = 0; i < 6; i++) {
45                                 int n = rnd.nextInt(62);
46                                 if (n < 10) {
47                                         sb.append((char) ('0' + n));
48                                 } else if (n < 36) {
49                                         sb.append((char) ('A' + n - 10));
50                                 } else {
51                                         sb.append((char) ('a' + n - 36));
52                                 }
53                         }
54                         key = sb.toString();
55                 }
56                 
57                 this.key = key;
58                 this.rnd = new Random(key.hashCode());
59                 
60         }
61         
62         
63         /**
64          * Create a new test rocket based on the value 'key'.  The rocket utilizes most of the 
65          * properties and features available.  The same key always returns the same rocket,
66          * but different key values produce slightly different rockets.  A key value of
67          * <code>null</code> generates a rocket using a random key.
68          * <p>
69          * The rocket created by this method is not fly-worthy.  It is also NOT guaranteed
70          * that later versions would produce exactly the same rocket!
71          * 
72          * @return              a rocket design.
73          */
74         public Rocket makeTestRocket() {
75                 
76                 Rocket rocket = new Rocket();
77                 setBasics(rocket);
78                 rocket.setCustomReferenceLength(rnd(0.05));
79                 rocket.setDesigner("Designer " + key);
80                 rocket.setReferenceType((ReferenceType) randomEnum(ReferenceType.class));
81                 rocket.setRevision("Rocket revision " + key);
82                 rocket.setName(key);
83                 
84
85                 Stage stage = new Stage();
86                 setBasics(stage);
87                 rocket.addChild(stage);
88                 
89
90                 NoseCone nose = new NoseCone();
91                 setBasics(stage);
92                 nose.setAftRadius(rnd(0.03));
93                 nose.setAftRadiusAutomatic(rnd.nextBoolean());
94                 nose.setAftShoulderCapped(rnd.nextBoolean());
95                 nose.setAftShoulderLength(rnd(0.02));
96                 nose.setAftShoulderRadius(rnd(0.02));
97                 nose.setAftShoulderThickness(rnd(0.002));
98                 nose.setClipped(rnd.nextBoolean());
99                 nose.setThickness(rnd(0.002));
100                 nose.setFilled(rnd.nextBoolean());
101                 nose.setForeRadius(rnd(0.1)); // Unset
102                 nose.setLength(rnd(0.15));
103                 nose.setShapeParameter(rnd(0.5));
104                 nose.setType((Shape) randomEnum(Shape.class));
105                 stage.addChild(nose);
106                 
107
108                 Transition shoulder = new Transition();
109                 setBasics(shoulder);
110                 shoulder.setAftRadius(rnd(0.06));
111                 shoulder.setAftRadiusAutomatic(rnd.nextBoolean());
112                 shoulder.setAftShoulderCapped(rnd.nextBoolean());
113                 shoulder.setAftShoulderLength(rnd(0.02));
114                 shoulder.setAftShoulderRadius(rnd(0.05));
115                 shoulder.setAftShoulderThickness(rnd(0.002));
116                 shoulder.setClipped(rnd.nextBoolean());
117                 shoulder.setThickness(rnd(0.002));
118                 shoulder.setFilled(rnd.nextBoolean());
119                 shoulder.setForeRadius(rnd(0.03));
120                 shoulder.setForeRadiusAutomatic(rnd.nextBoolean());
121                 shoulder.setForeShoulderCapped(rnd.nextBoolean());
122                 shoulder.setForeShoulderLength(rnd(0.02));
123                 shoulder.setForeShoulderRadius(rnd(0.02));
124                 shoulder.setForeShoulderThickness(rnd(0.002));
125                 shoulder.setLength(rnd(0.15));
126                 shoulder.setShapeParameter(rnd(0.5));
127                 shoulder.setThickness(rnd(0.003));
128                 shoulder.setType((Shape) randomEnum(Shape.class));
129                 stage.addChild(shoulder);
130                 
131
132                 BodyTube body = new BodyTube();
133                 setBasics(body);
134                 body.setThickness(rnd(0.002));
135                 body.setFilled(rnd.nextBoolean());
136                 body.setIgnitionDelay(rnd.nextDouble() * 3);
137                 body.setIgnitionEvent((IgnitionEvent) randomEnum(IgnitionEvent.class));
138                 body.setLength(rnd(0.3));
139                 body.setMotorMount(rnd.nextBoolean());
140                 body.setMotorOverhang(rnd.nextGaussian() * 0.03);
141                 body.setOuterRadius(rnd(0.06));
142                 body.setOuterRadiusAutomatic(rnd.nextBoolean());
143                 stage.addChild(body);
144                 
145
146                 Transition boattail = new Transition();
147                 setBasics(boattail);
148                 boattail.setAftRadius(rnd(0.03));
149                 boattail.setAftRadiusAutomatic(rnd.nextBoolean());
150                 boattail.setAftShoulderCapped(rnd.nextBoolean());
151                 boattail.setAftShoulderLength(rnd(0.02));
152                 boattail.setAftShoulderRadius(rnd(0.02));
153                 boattail.setAftShoulderThickness(rnd(0.002));
154                 boattail.setClipped(rnd.nextBoolean());
155                 boattail.setThickness(rnd(0.002));
156                 boattail.setFilled(rnd.nextBoolean());
157                 boattail.setForeRadius(rnd(0.06));
158                 boattail.setForeRadiusAutomatic(rnd.nextBoolean());
159                 boattail.setForeShoulderCapped(rnd.nextBoolean());
160                 boattail.setForeShoulderLength(rnd(0.02));
161                 boattail.setForeShoulderRadius(rnd(0.05));
162                 boattail.setForeShoulderThickness(rnd(0.002));
163                 boattail.setLength(rnd(0.15));
164                 boattail.setShapeParameter(rnd(0.5));
165                 boattail.setThickness(rnd(0.003));
166                 boattail.setType((Shape) randomEnum(Shape.class));
167                 stage.addChild(boattail);
168                 
169
170                 MassComponent mass = new MassComponent();
171                 setBasics(mass);
172                 mass.setComponentMass(rnd(0.05));
173                 mass.setLength(rnd(0.05));
174                 mass.setRadialDirection(rnd(100));
175                 mass.setRadialPosition(rnd(0.02));
176                 mass.setRadius(rnd(0.05));
177                 nose.addChild(mass);
178                 
179
180
181
182                 return rocket;
183         }
184         
185         
186         private void setBasics(RocketComponent c) {
187                 c.setComment(c.getComponentName() + " comment " + key);
188                 c.setName(c.getComponentName() + " name " + key);
189                 
190                 c.setCGOverridden(rnd.nextBoolean());
191                 c.setMassOverridden(rnd.nextBoolean());
192                 c.setOverrideCGX(rnd(0.2));
193                 c.setOverrideMass(rnd(0.05));
194                 c.setOverrideSubcomponents(rnd.nextBoolean());
195                 
196                 if (c.isMassive()) {
197                         // Only massive components are drawn
198                         c.setColor(randomColor());
199                         c.setLineStyle((LineStyle) randomEnum(LineStyle.class));
200                 }
201                 
202                 if (c instanceof ExternalComponent) {
203                         ExternalComponent e = (ExternalComponent) c;
204                         e.setFinish((Finish) randomEnum(Finish.class));
205                         double d = rnd(100);
206                         e.setMaterial(Material.newUserMaterial(Type.BULK, "Testmat " + d, d));
207                 }
208                 
209                 if (c instanceof InternalComponent) {
210                         InternalComponent i = (InternalComponent) c;
211                         i.setRelativePosition((Position) randomEnum(Position.class));
212                         i.setPositionValue(rnd(0.3));
213                 }
214         }
215         
216         
217
218         private double rnd(double scale) {
219                 return (rnd.nextDouble() * 0.2 + 0.9) * scale;
220         }
221         
222         private Color randomColor() {
223                 return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
224         }
225         
226         private <T extends Enum<T>> Enum<T> randomEnum(Class<T> c) {
227                 Enum<T>[] values = c.getEnumConstants();
228                 if (values.length == 0)
229                         return null;
230                 
231                 return values[rnd.nextInt(values.length)];
232         }
233         
234         
235
236
237
238         public Rocket makeSmallFlyable() {
239                 double noseconeLength = 0.10, noseconeRadius = 0.01;
240                 double bodytubeLength = 0.20, bodytubeRadius = 0.01, bodytubeThickness = 0.001;
241                 
242                 int finCount = 3;
243                 double finRootChord = 0.04, finTipChord = 0.05, finSweep = 0.01, finThickness = 0.003, finHeight = 0.03;
244                 
245
246                 Rocket rocket;
247                 Stage stage;
248                 NoseCone nosecone;
249                 BodyTube bodytube;
250                 TrapezoidFinSet finset;
251                 
252                 rocket = new Rocket();
253                 stage = new Stage();
254                 stage.setName("Stage1");
255                 
256                 nosecone = new NoseCone(Transition.Shape.ELLIPSOID, noseconeLength, noseconeRadius);
257                 bodytube = new BodyTube(bodytubeLength, bodytubeRadius, bodytubeThickness);
258                 
259                 finset = new TrapezoidFinSet(finCount, finRootChord, finTipChord, finSweep, finHeight);
260                 
261
262                 // Stage construction
263                 rocket.addChild(stage);
264                 
265
266                 // Component construction
267                 stage.addChild(nosecone);
268                 stage.addChild(bodytube);
269                 
270                 bodytube.addChild(finset);
271                 
272                 Material material = Application.getPreferences().getDefaultComponentMaterial(null, Material.Type.BULK);
273                 nosecone.setMaterial(material);
274                 bodytube.setMaterial(material);
275                 finset.setMaterial(material);
276                 
277                 String id = rocket.newMotorConfigurationID();
278                 bodytube.setMotorMount(true);
279                 
280                 Motor m = Application.getMotorSetDatabase().findMotors(null, null, "B4", Double.NaN, Double.NaN).get(0);
281                 bodytube.setMotor(id, m);
282                 bodytube.setMotorOverhang(0.005);
283                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
284                 
285                 rocket.getDefaultConfiguration().setAllStages();
286                 
287
288                 return rocket;
289         }
290         
291         
292         public static Rocket makeBigBlue() {
293                 Rocket rocket;
294                 Stage stage;
295                 NoseCone nosecone;
296                 BodyTube bodytube;
297                 FreeformFinSet finset;
298                 MassComponent mcomp;
299                 
300                 rocket = new Rocket();
301                 stage = new Stage();
302                 stage.setName("Stage1");
303                 
304                 nosecone = new NoseCone(Transition.Shape.ELLIPSOID, 0.105, 0.033);
305                 nosecone.setThickness(0.001);
306                 bodytube = new BodyTube(0.69, 0.033, 0.001);
307                 
308                 finset = new FreeformFinSet();
309                 try {
310                         finset.setPoints(new Coordinate[] {
311                                         new Coordinate(0, 0),
312                                         new Coordinate(0.115, 0.072),
313                                         new Coordinate(0.255, 0.072),
314                                         new Coordinate(0.255, 0.037),
315                                         new Coordinate(0.150, 0)
316                         });
317                 } catch (IllegalFinPointException e) {
318                         e.printStackTrace();
319                 }
320                 finset.setThickness(0.003);
321                 finset.setFinCount(4);
322                 
323                 finset.setCantAngle(0 * Math.PI / 180);
324                 System.err.println("Fin cant angle: " + (finset.getCantAngle() * 180 / Math.PI));
325                 
326                 mcomp = new MassComponent(0.2, 0.03, 0.045 + 0.060);
327                 mcomp.setRelativePosition(Position.TOP);
328                 mcomp.setPositionValue(0);
329                 
330                 // Stage construction
331                 rocket.addChild(stage);
332                 rocket.setPerfectFinish(false);
333                 
334
335                 // Component construction
336                 stage.addChild(nosecone);
337                 stage.addChild(bodytube);
338                 
339                 bodytube.addChild(finset);
340                 
341                 bodytube.addChild(mcomp);
342                 
343                 //              Material material = new Material("Test material", 500);
344                 //              nosecone.setMaterial(material);
345                 //              bodytube.setMaterial(material);
346                 //              finset.setMaterial(material);
347                 
348                 String id = rocket.newMotorConfigurationID();
349                 bodytube.setMotorMount(true);
350                 
351                 //              Motor m = Application.getMotorSetDatabase().findMotors(null, null, "F12J", Double.NaN, Double.NaN).get(0);
352                 //              bodytube.setMotor(id, m);
353                 //              bodytube.setMotorOverhang(0.005);
354                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
355                 
356                 rocket.getDefaultConfiguration().setAllStages();
357                 
358
359                 return rocket;
360         }
361         
362         
363
364         public static Rocket makeIsoHaisu() {
365                 Rocket rocket;
366                 Stage stage;
367                 NoseCone nosecone;
368                 BodyTube tube1, tube2, tube3;
369                 TrapezoidFinSet finset;
370                 TrapezoidFinSet auxfinset;
371                 MassComponent mcomp;
372                 
373                 final double R = 0.07;
374                 
375                 rocket = new Rocket();
376                 stage = new Stage();
377                 stage.setName("Stage1");
378                 
379                 nosecone = new NoseCone(Transition.Shape.OGIVE, 0.53, R);
380                 nosecone.setThickness(0.005);
381                 nosecone.setMassOverridden(true);
382                 nosecone.setOverrideMass(0.588);
383                 stage.addChild(nosecone);
384                 
385                 tube1 = new BodyTube(0.505, R, 0.005);
386                 tube1.setMassOverridden(true);
387                 tube1.setOverrideMass(0.366);
388                 stage.addChild(tube1);
389                 
390                 tube2 = new BodyTube(0.605, R, 0.005);
391                 tube2.setMassOverridden(true);
392                 tube2.setOverrideMass(0.427);
393                 stage.addChild(tube2);
394                 
395                 tube3 = new BodyTube(1.065, R, 0.005);
396                 tube3.setMassOverridden(true);
397                 tube3.setOverrideMass(0.730);
398                 stage.addChild(tube3);
399                 
400
401                 LaunchLug lug = new LaunchLug();
402                 tube1.addChild(lug);
403                 
404                 TubeCoupler coupler = new TubeCoupler();
405                 coupler.setOuterRadiusAutomatic(true);
406                 coupler.setThickness(0.005);
407                 coupler.setLength(0.28);
408                 coupler.setMassOverridden(true);
409                 coupler.setOverrideMass(0.360);
410                 coupler.setRelativePosition(Position.BOTTOM);
411                 coupler.setPositionValue(-0.14);
412                 tube1.addChild(coupler);
413                 
414
415                 // Parachute
416                 MassComponent mass = new MassComponent(0.05, 0.05, 0.280);
417                 mass.setRelativePosition(Position.TOP);
418                 mass.setPositionValue(0.2);
419                 tube1.addChild(mass);
420                 
421                 // Cord
422                 mass = new MassComponent(0.05, 0.05, 0.125);
423                 mass.setRelativePosition(Position.TOP);
424                 mass.setPositionValue(0.2);
425                 tube1.addChild(mass);
426                 
427                 // Payload
428                 mass = new MassComponent(0.40, R, 1.500);
429                 mass.setRelativePosition(Position.TOP);
430                 mass.setPositionValue(0.25);
431                 tube1.addChild(mass);
432                 
433
434                 auxfinset = new TrapezoidFinSet();
435                 auxfinset.setName("CONTROL");
436                 auxfinset.setFinCount(2);
437                 auxfinset.setRootChord(0.05);
438                 auxfinset.setTipChord(0.05);
439                 auxfinset.setHeight(0.10);
440                 auxfinset.setSweep(0);
441                 auxfinset.setThickness(0.008);
442                 auxfinset.setCrossSection(CrossSection.AIRFOIL);
443                 auxfinset.setRelativePosition(Position.TOP);
444                 auxfinset.setPositionValue(0.28);
445                 auxfinset.setBaseRotation(Math.PI / 2);
446                 tube1.addChild(auxfinset);
447                 
448
449
450
451                 coupler = new TubeCoupler();
452                 coupler.setOuterRadiusAutomatic(true);
453                 coupler.setLength(0.28);
454                 coupler.setRelativePosition(Position.TOP);
455                 coupler.setPositionValue(0.47);
456                 coupler.setMassOverridden(true);
457                 coupler.setOverrideMass(0.360);
458                 tube2.addChild(coupler);
459                 
460
461
462                 // Parachute
463                 mass = new MassComponent(0.1, 0.05, 0.028);
464                 mass.setRelativePosition(Position.TOP);
465                 mass.setPositionValue(0.14);
466                 tube2.addChild(mass);
467                 
468                 Bulkhead bulk = new Bulkhead();
469                 bulk.setOuterRadiusAutomatic(true);
470                 bulk.setMassOverridden(true);
471                 bulk.setOverrideMass(0.050);
472                 bulk.setRelativePosition(Position.TOP);
473                 bulk.setPositionValue(0.27);
474                 tube2.addChild(bulk);
475                 
476                 // Chord
477                 mass = new MassComponent(0.1, 0.05, 0.125);
478                 mass.setRelativePosition(Position.TOP);
479                 mass.setPositionValue(0.19);
480                 tube2.addChild(mass);
481                 
482
483
484                 InnerTube inner = new InnerTube();
485                 inner.setOuterRadius(0.08 / 2);
486                 inner.setInnerRadius(0.0762 / 2);
487                 inner.setLength(0.86);
488                 inner.setMassOverridden(true);
489                 inner.setOverrideMass(0.388);
490                 tube3.addChild(inner);
491                 
492
493                 CenteringRing center = new CenteringRing();
494                 center.setInnerRadiusAutomatic(true);
495                 center.setOuterRadiusAutomatic(true);
496                 center.setLength(0.005);
497                 center.setMassOverridden(true);
498                 center.setOverrideMass(0.038);
499                 center.setRelativePosition(Position.BOTTOM);
500                 center.setPositionValue(0);
501                 tube3.addChild(center);
502                 
503
504                 center = new CenteringRing();
505                 center.setInnerRadiusAutomatic(true);
506                 center.setOuterRadiusAutomatic(true);
507                 center.setLength(0.005);
508                 center.setMassOverridden(true);
509                 center.setOverrideMass(0.038);
510                 center.setRelativePosition(Position.TOP);
511                 center.setPositionValue(0.28);
512                 tube3.addChild(center);
513                 
514
515                 center = new CenteringRing();
516                 center.setInnerRadiusAutomatic(true);
517                 center.setOuterRadiusAutomatic(true);
518                 center.setLength(0.005);
519                 center.setMassOverridden(true);
520                 center.setOverrideMass(0.038);
521                 center.setRelativePosition(Position.TOP);
522                 center.setPositionValue(0.83);
523                 tube3.addChild(center);
524                 
525
526
527
528
529                 finset = new TrapezoidFinSet();
530                 finset.setRootChord(0.495);
531                 finset.setTipChord(0.1);
532                 finset.setHeight(0.185);
533                 finset.setThickness(0.005);
534                 finset.setSweep(0.3);
535                 finset.setRelativePosition(Position.BOTTOM);
536                 finset.setPositionValue(-0.03);
537                 finset.setBaseRotation(Math.PI / 2);
538                 tube3.addChild(finset);
539                 
540
541                 finset.setCantAngle(0 * Math.PI / 180);
542                 System.err.println("Fin cant angle: " + (finset.getCantAngle() * 180 / Math.PI));
543                 
544
545                 // Stage construction
546                 rocket.addChild(stage);
547                 rocket.setPerfectFinish(false);
548                 
549
550
551                 String id = rocket.newMotorConfigurationID();
552                 tube3.setMotorMount(true);
553                 
554                 //              Motor m = Application.getMotorSetDatabase().findMotors(null, null, "L540", Double.NaN, Double.NaN).get(0);
555                 //              tube3.setMotor(id, m);
556                 //              tube3.setMotorOverhang(0.02);
557                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
558                 
559                 //              tube3.setIgnitionEvent(MotorMount.IgnitionEvent.NEVER);
560                 
561                 rocket.getDefaultConfiguration().setAllStages();
562                 
563
564                 return rocket;
565         }
566         
567
568
569 }