updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / util / TestRockets.java
1 package net.sf.openrocket.util;
2
3 import java.awt.Color;
4 import java.util.Random;
5
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;
33
34 public class TestRockets {
35         
36         private final String key;
37         private final Random rnd;
38         
39         
40         public TestRockets(String key) {
41
42                 if (key == null) {
43                         Random rnd = new Random();
44                         StringBuilder sb = new StringBuilder();
45                         for (int i=0; i<6; i++) {
46                                 int n = rnd.nextInt(62);
47                                 if (n < 10) {
48                                         sb.append((char)('0'+n));
49                                 } else if (n < 36) {
50                                         sb.append((char)('A'+n-10));
51                                 } else {
52                                         sb.append((char)('a'+n-36));
53                                 }
54                         }
55                         key = sb.toString();
56                 }
57                 
58                 this.key = key;
59                 this.rnd = new Random(key.hashCode());
60
61         }
62
63
64         /**
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.
69          * <p>
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!
72          * 
73          * @return              a rocket design.
74          */
75         public Rocket makeTestRocket() {
76                 
77                 Rocket rocket = new Rocket();
78                 setBasics(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);
83                 rocket.setName(key);
84                 
85                 
86                 Stage stage = new Stage();
87                 setBasics(stage);
88                 rocket.addChild(stage);
89                 
90                 
91                 NoseCone nose = new NoseCone();
92                 setBasics(stage);
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);
107                 
108                 
109                 Transition shoulder = new Transition();
110                 setBasics(shoulder);
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);
131                 
132                 
133                 BodyTube body = new BodyTube();
134                 setBasics(body);
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);
145
146                 
147                 Transition boattail = new Transition();
148                 setBasics(boattail);
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);
169                 
170
171                 MassComponent mass = new MassComponent();
172                 setBasics(mass);
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));
178                 nose.addChild(mass);
179                 
180                 
181                 
182                 
183                 return rocket;
184         }
185         
186         
187         private void setBasics(RocketComponent c) {
188                 c.setComment(c.getComponentName() + " comment " + key);
189                 c.setName(c.getComponentName() + " name " + key);
190
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());
196
197                 if (c.isMassive()) {
198                         // Only massive components are drawn
199                         c.setColor(randomColor());
200                         c.setLineStyle((LineStyle) randomEnum(LineStyle.class));
201                 }
202                 
203                 if (c instanceof ExternalComponent) {
204                         ExternalComponent e = (ExternalComponent)c;
205                         e.setFinish((Finish) randomEnum(Finish.class));
206                         double d = rnd(100);
207                         e.setMaterial(Material.newMaterial(Type.BULK, "Testmat "+d, d, rnd.nextBoolean()));
208                 }
209                 
210                 if (c instanceof InternalComponent) {
211                         InternalComponent i = (InternalComponent)c;
212                         i.setRelativePosition((Position) randomEnum(Position.class));
213                         i.setPositionValue(rnd(0.3));
214                 }
215         }
216         
217         
218         
219         private double rnd(double scale) {
220                 return (rnd.nextDouble()*0.2+0.9) * scale;
221         }
222         
223         private Color randomColor() {
224                 return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
225         }
226         
227         private <T extends Enum<T>> Enum<T> randomEnum(Class<T> c) {
228                 Enum<T>[] values = c.getEnumConstants();
229                 if (values.length == 0)
230                         return null;
231                 
232                 return values[rnd.nextInt(values.length)];
233         }
234
235         
236         
237         
238         
239         
240         public Rocket makeSmallFlyable() {
241                 double noseconeLength=0.10,noseconeRadius=0.01;
242                 double bodytubeLength=0.20,bodytubeRadius=0.01,bodytubeThickness=0.001;
243                 
244                 int finCount=3;
245                 double finRootChord=0.04,finTipChord=0.05,finSweep=0.01,finThickness=0.003, finHeight=0.03;
246                 
247                 
248                 Rocket rocket;
249                 Stage stage;
250                 NoseCone nosecone;
251                 BodyTube bodytube;
252                 TrapezoidFinSet finset;
253                 
254                 rocket = new Rocket();
255                 stage = new Stage();
256                 stage.setName("Stage1");
257
258                 nosecone = new NoseCone(Transition.Shape.ELLIPSOID,noseconeLength,noseconeRadius);
259                 bodytube = new BodyTube(bodytubeLength,bodytubeRadius,bodytubeThickness);
260
261                 finset = new TrapezoidFinSet(finCount,finRootChord,finTipChord,finSweep,finHeight);
262                 
263                 
264                 // Stage construction
265                 rocket.addChild(stage);
266
267                 
268                 // Component construction
269                 stage.addChild(nosecone);
270                 stage.addChild(bodytube);
271
272                 bodytube.addChild(finset);
273                 
274                 Material material = Prefs.getDefaultComponentMaterial(null, Material.Type.BULK);
275                 nosecone.setMaterial(material);
276                 bodytube.setMaterial(material);
277                 finset.setMaterial(material);
278                 
279                 String id = rocket.newMotorConfigurationID();
280                 bodytube.setMotorMount(true);
281                 
282                 for (Motor m: Databases.MOTOR) {
283                         if (m.getDesignation().equals("B4")) {
284                                 bodytube.setMotor(id, m);
285                                 break;
286                         }
287                 }
288                 bodytube.setMotorOverhang(0.005);
289                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
290                 
291                 rocket.getDefaultConfiguration().setAllStages();
292                 
293                 
294                 return rocket;
295         }
296
297
298         public static Rocket makeBigBlue() {
299                 Rocket rocket;
300                 Stage stage;
301                 NoseCone nosecone;
302                 BodyTube bodytube;
303                 FreeformFinSet finset;
304                 MassComponent mcomp;
305                 
306                 rocket = new Rocket();
307                 stage = new Stage();
308                 stage.setName("Stage1");
309
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);
313
314                 finset = new FreeformFinSet();
315                 try {
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)
322                         });
323                 } catch (IllegalFinPointException e) {
324                         e.printStackTrace();
325                 }
326                 finset.setThickness(0.003);
327                 finset.setFinCount(4);
328                 
329                 finset.setCantAngle(0*Math.PI/180);
330                 System.err.println("Fin cant angle: "+(finset.getCantAngle() * 180/Math.PI));
331                 
332                 mcomp = new MassComponent(0.2,0.03,0.045 + 0.060);
333                 mcomp.setRelativePosition(Position.TOP);
334                 mcomp.setPositionValue(0);
335                 
336                 // Stage construction
337                 rocket.addChild(stage);
338                 rocket.setPerfectFinish(false);
339
340                 
341                 // Component construction
342                 stage.addChild(nosecone);
343                 stage.addChild(bodytube);
344
345                 bodytube.addChild(finset);
346                 
347                 bodytube.addChild(mcomp);
348                 
349 //              Material material = new Material("Test material", 500);
350 //              nosecone.setMaterial(material);
351 //              bodytube.setMaterial(material);
352 //              finset.setMaterial(material);
353                 
354                 String id = rocket.newMotorConfigurationID();
355                 bodytube.setMotorMount(true);
356                 
357                 for (Motor m: Databases.MOTOR) {
358                         if (m.getDesignation().equals("F12J")) {
359                                 bodytube.setMotor(id, m);
360                                 break;
361                         }
362                 }
363                 bodytube.setMotorOverhang(0.005);
364                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
365                 
366                 rocket.getDefaultConfiguration().setAllStages();
367                 
368                 
369                 return rocket;
370         }
371         
372         
373
374         public static Rocket makeIsoHaisu() {
375                 Rocket rocket;
376                 Stage stage;
377                 NoseCone nosecone;
378                 BodyTube tube1, tube2, tube3;
379                 TrapezoidFinSet finset;
380                 TrapezoidFinSet auxfinset;
381                 MassComponent mcomp;
382                 
383                 final double R = 0.07;
384                 
385                 rocket = new Rocket();
386                 stage = new Stage();
387                 stage.setName("Stage1");
388
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);
394                 
395                 tube1 = new BodyTube(0.505,R,0.005);
396                 tube1.setMassOverridden(true);
397                 tube1.setOverrideMass(0.366);
398                 stage.addChild(tube1);
399                 
400                 tube2 = new BodyTube(0.605,R,0.005);
401                 tube2.setMassOverridden(true);
402                 tube2.setOverrideMass(0.427);
403                 stage.addChild(tube2);
404                 
405                 tube3 = new BodyTube(1.065,R,0.005);
406                 tube3.setMassOverridden(true);
407                 tube3.setOverrideMass(0.730);
408                 stage.addChild(tube3);
409                 
410                 
411                 LaunchLug lug = new LaunchLug();
412                 tube1.addChild(lug);
413                 
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);
423                 
424                 
425                 // Parachute
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);
430                 
431                 // Cord
432                 mass = new MassComponent(0.05, 0.05, 0.125);
433                 mass.setRelativePosition(Position.TOP);
434                 mass.setPositionValue(0.2);
435                 tube1.addChild(mass);
436                 
437                 // Payload
438                 mass = new MassComponent(0.40, R, 1.500);
439                 mass.setRelativePosition(Position.TOP);
440                 mass.setPositionValue(0.25);
441                 tube1.addChild(mass);
442                 
443                 
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);
457                 
458                 
459                 
460                 
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);
469                 
470                 
471                 
472                 // Parachute
473                 mass = new MassComponent(0.1, 0.05, 0.028);
474                 mass.setRelativePosition(Position.TOP);
475                 mass.setPositionValue(0.14);
476                 tube2.addChild(mass);
477                 
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);
485                 
486                 // Chord
487                 mass = new MassComponent(0.1, 0.05, 0.125);
488                 mass.setRelativePosition(Position.TOP);
489                 mass.setPositionValue(0.19);
490                 tube2.addChild(mass);
491                 
492                 
493                 
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);
501                 
502                 
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);
512                 
513                 
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);
523                 
524                 
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);
534                 
535                 
536                 
537                 
538                 
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);
549                 
550                 
551                 finset.setCantAngle(0*Math.PI/180);
552                 System.err.println("Fin cant angle: "+(finset.getCantAngle() * 180/Math.PI));
553                 
554                 
555                 // Stage construction
556                 rocket.addChild(stage);
557                 rocket.setPerfectFinish(false);
558
559                 
560                 
561                 String id = rocket.newMotorConfigurationID();
562                 tube3.setMotorMount(true);
563                 
564                 for (Motor m: Databases.MOTOR) {
565                         if (m.getDesignation().equals("L540")) {
566                                 tube3.setMotor(id, m);
567                                 break;
568                         }
569                 }
570                 tube3.setMotorOverhang(0.02);
571                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
572
573 //              tube3.setIgnitionEvent(MotorMount.IgnitionEvent.NEVER);
574                 
575                 rocket.getDefaultConfiguration().setAllStages();
576                 
577                 
578                 return rocket;
579         }
580         
581         
582         
583 }