Nike Ajax CAD Model Build

The Rocketry Forum

Help Support The Rocketry Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

vcp

Well-Known Member
Joined
Jan 27, 2009
Messages
1,473
Reaction score
578
Location
Meridian, ID
Yes, I never have finished my Nike Hercule CAD Model Build, but I'm easily sidetracked. Had an urge to look at the Nike Ajax, and I'm pretty happy with how it's going so far...

Nike_Ajax 16.jpg
Nike_Ajax_16.JPG

I'll be able to re-use much of the Nike motor that I had finished for the Hercules.

Really pleased with the way the tunnels came out. The only complex item left to do is the interstage. It was interesting to find out, that according to the Bennett drawing, the tunnels are different sizes.
 
Last edited:
Only the interstage left to do, plus the bolt heads and rivets and whatever other (usually invisible) details I want to add. Ah, and the scale launch lugs.

Nike_Ajax2.JPG
 
This is interesting. What size is it? Is it being designed as a two stage?

-Bob
 
Not many actual dimensions for the interstage, so it's largely photo interpretation, but it looks about right. A little trimming to do, and still those launch lugs.
interstage.JPG
 
This is interesting. What size is it? Is it being designed as a two stage?

-Bob

Right now it's just being done as an exact scale model, with no consideration for internal requirements for flight. I can slice that out later as required. It's being drawn as 1mm = 1in, so that's 1/25.4, but it can easily be scaled to anything. My thoughts at the moment are to print the booster fin unit, use a BT60 for the Nike tube, making it 1/10 scale, and then print the upper stage entirely. The problem of any Nike-Ajax model is the fragility of the interstage, which makes 2-stage even more of a problem. The interstage is rarely done with much fidelity, but for a practical model, it almost certainly needs to be beefed up. I'll eventually get around to printing to see what it's like.
 
BT60 for the booster would make it 1/10th scale which is the scale I am trying to stick to. I'll be following along with your build with great interest. I'd love to get a printed fin can. This is a rocket I am going to model one day. I have a couple of single stage Nike rockets. For two stage rockets my Nike-Tomahawk and Nike-Nike Smoke are being build now. They are on hold while I figure out how I'm going to stage them. I also have the basic parts to build the kit for a Terrier-Nike. The Ajax and Hercules are on my to do list.

-Bob
 
Looking good Gary. This would be a great rocket made with a 3D printer.
 
I still have The Launch Pad Nike-Ajax. I haven't flown it in many years, but it is still flyable. It is only one-stage using a cluster of three D12-3's. I believe it was Chuck Brandt the owner of the The Launch Pad made a non-production two-stage version years ago.
 
I've often mentioned that to my eternal shame, I haven't been using a 'real' CAD system, but rather the freeware OpenSCAD. It's just been something that I've always turned to. For some people, the logic of 'programming' an object in code just seems to click. Maybe it's just me. Perhaps to explain the madness, I thought I'd go through an example of how I create an object in OpenSCAD code. If you want to follow along, you should be able to take the code segments below, and drop them into the OpenSCAD editor window. OpenSCAD is available here, and is trivially simple to install. Pressing F5 (preview) should get a view that looks like the pictures below. (Be sure and get the axes pointed around as I have them, so that x extends to the left.)

Notice that a command line is always terminated by a semicolon. A command line can consist of a series of commands that extend over more than one line on the page. Anything on a line following a '//' is a comment that does not affect the code.

The following dimensions are first defined in the code. All are taken from the section of the Bennett Nike-Ajax drawing below, or from the Alway drawing. I try to identify the source of all the dimensions used. (TLAR = That Looks About Right - sometimes we have to take a best guess.) Note that the basic measurement unit in OpenSCAD is mm, and all of the following dimensions are in inches. I don't bother to convert, but rather just enter the inch dimensions, which gives me a drawing that is actually 1/25.4 scale. It's not a problem, I can easily scale it to whatever I need later.

Body_Diameter = 12; // Bennett
Main_Fin_Span = 18.95; // not including aileron - Bennett 18 61/64
Main_Fin_Root = 70.234; // not including aileron - Bennett 70 15/64
Main_Fin_Edge_Diameter = 0.679; // Bennett
Center_Panel_Thickness = 1.929; // Bennett
Aileron_Width = 1.5; // Alway
Aileron_TE_Diameter = 0.25; // TLAR
Aileron_Body_Standoff = 0.34; // TLAR
Rear_Panel_Root = 15.188; // Bennett 15 3/16
Rear_Mid_Panel_Root = 30.938; // Bennett 30 15/16
Center_Panel_Root = Rear_Mid_Panel_Root - Rear_Panel_Root;
Front_Panel_Root = Main_Fin_Root - Rear_Mid_Panel_Root;

Bennett - Main Fin.JPG


Starting really simple, I'll place a sphere at the origin. It's the diameter of the edge of the fin. The $fn factor just sets the coarseness of the sphere:

sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

Now, I don't want that exactly on the origin, because I want the trailing edge of the fin to just touch the z-axis, so I'll move it (translate) one-half of its diameter to the left - in the x-direction. I'll be building the fin with its root on the x-axis. The translate command takes the form of: translate ([x, y, z]) It translates the object that follows it in the command line.

translate ([Main_Fin_Edge_Diameter/2 , 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

Then I'll do the same thing, placing a sphere at the trailing edge tip of the fin, so that the trailing edge will be on the z-axis

translate ([Main_Fin_Edge_Diameter/2 , 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

Same deal, another sphere at the forward tip of the fin:

translate ([Main_Fin_Root - Main_Fin_Edge_Diameter/2, 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

So with the three spheres placed, it looks like this:

spheres.JPG

And now, the magic of the hull command. I use hull a lot, probably more than I should. Yes, you could define the fin with a polygon, but, at least in OpenSCAD, it's so easy to just translate the points around and then hull them. The hull command just acts upon everything that follows it within curly brackets {...}, and creates a surface connecting all the objects.

hull () {
translate ([Main_Fin_Edge_Diameter/2 , 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([Main_Fin_Edge_Diameter/2 , 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([Main_Fin_Root - Main_Fin_Edge_Diameter/2, 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
} // end hull

...and you get a fin:

flat fin.JPG

But it's a flat fin, just the thickness of the edge. The Ajax fin has a center panel that is thicker. To fix that, we'll add another object, this time a cylinder. A cylinder is just defined by its height and diameter, h and d. The cylinder command alone would give a cylinder standing vertically at the origin. I'll use the rotate command to rotate it 90 degrees left around the y-axis, so that it's laying horizontally on the x-axis. Then use the translate command to move it along the x-axis, to where the center panel is, and move it on the y-axis so that it is at the thickness of the panel.

translate ([Rear_Panel_Root, (Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
rotate (a = [0, 90, 0])
cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);

Which looks like this:

flat center.JPG

I'll add a similar cylinder to the other side, and place them both within the hull command so that now all of the code is:

hull () { // Main Fin
// center root panel
translate ([Rear_Panel_Root, (Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
rotate (a = [0, 90, 0])
cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([Rear_Panel_Root, -(Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
rotate (a = [0, 90, 0])
cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);

// forward tip
translate ([Main_Fin_Root - Main_Fin_Edge_Diameter/2, 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

// trailing edge
translate ([Main_Fin_Edge_Diameter/2 , 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([Main_Fin_Edge_Diameter/2 , 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
} // end hull

And we have a 3-D fin:

3d fin.JPG

In the same manner, I'm going to use four spheres to define the aileron on the trailing edge. It tapers in thickness, so I'm using two different sizes of spheres. The root of the aileron is spaced off the body a bit so the root spheres are translated a small bit upwards.

hull () { // aileron
// leading edge
translate ([-Main_Fin_Edge_Diameter/2 , 0, Aileron_Body_Standoff])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([-Main_Fin_Edge_Diameter/2 , 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2 + 0.1])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

// trailing edge
translate ([-Main_Fin_Edge_Diameter/2 - Aileron_Width, 0, -0.16 + Aileron_Body_Standoff])
sphere (d = Aileron_TE_Diameter, $fn = 20);
translate ([-Main_Fin_Edge_Diameter/2 - Aileron_Width, 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2 + 0.7])
sphere (d = Aileron_TE_Diameter, $fn = 20);
} // end hull

If you look closely at that you'll notice the unexplained numbers: 0.1 , -0.16 , 0.7 . Yes, you caught me. Those are fudge factors. The 0.7 translates one sphere upwards so that the edge of the aileron is in line with the leading edge of the main fin. This is undimensioned on the drawings, so I've placed it by eye, nudging the sphere into place. The other numbers adjust the bottom edge of the aileron.

continued...

 

Attachments

  • subtract tube.JPG
    subtract tube.JPG
    35.2 KB · Views: 68
  • final fin.JPG
    final fin.JPG
    21 KB · Views: 66
...continued from previous post

There's only one major thing left to do. The root edge of the fin is not flat - it extends below the horizontal plane by half the diameter of the spheres and cylinders that were used to define it. We'd like to slice it off flat, or better, make it curved to match the body that it will mate with. Enter the difference command. We want to subract away all of the fin that extends into where the missile body will be.

The difference command takes the first object, in this case, everything within the hull command, and subtracts every object that follows. The object being subtracted is a cylinder that is the diameter of the rocket body, rotated so that it lays along the x-axis, and translated downwards by half its diameter so that the surface of the tube is right along the root edge of the fin.

difference() {
hull () { // Main Fin


//*** all of the stuff above ***

} // end hull

translate ([0, 0, -Body_Diameter/2]) rotate (a = [0, 90, 0])
#cylinder (h = 3*Main_Fin_Root, d = Body_Diameter, $fn = 120);

} // end difference


The '#' in front of the cylinder command makes that object visible - since it's an object being subtracted, i.e., a 'negative object', it would otherwise not be visible.

subtract tube.JPG

So here is the entirety of the code, all together. You'll notice the addition of 'module' in the first line. This makes everything that follows it in curly brackets a single code module, that can be called in later blocks of code. I'll later want to place four of these fins, and move them around as necessary, so I can do that just by calling this module. I've made that module call in the last line of the code below, which was necessary to get the fin to display once, during this development. You can take the code below, drop it into the OpenSCAD editor window, press F5 to get a preview, and it should display the fin. I encourage you do give it a try and play with it a bit - the easiest way to learn.

module Main_Fin () {
Body_Diameter = 12; // Bennett
Main_Fin_Span = 18.95; // not including aileron - Bennett 18 61/64
Main_Fin_Root = 70.234; // not including aileron - Bennett 70 15/64
Main_Fin_Edge_Diameter = 0.679; // Bennett
Center_Panel_Thickness = 1.929; // Bennett
Aileron_Width = 1.5; // Alway
Aileron_TE_Diameter = 0.25; // TLAR
Aileron_Body_Standoff = 0.34; // TLAR
Rear_Panel_Root = 15.188; // Bennett 15 3/16
Rear_Mid_Panel_Root = 30.938; // Bennett 30 15/16
Center_Panel_Root = Rear_Mid_Panel_Root - Rear_Panel_Root;
Front_Panel_Root = Main_Fin_Root - Rear_Mid_Panel_Root;

difference() {
hull () { // Main Fin
// center root panel
translate ([Rear_Panel_Root, (Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
rotate (a = [0, 90, 0])
cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([Rear_Panel_Root, -(Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
rotate (a = [0, 90, 0])
cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);

// forward tip
translate ([Main_Fin_Root - Main_Fin_Edge_Diameter/2, 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

// trailing edge
translate ([Main_Fin_Edge_Diameter/2 , 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([Main_Fin_Edge_Diameter/2 , 0, 0])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
} // hull
#translate ([0, 0, -Body_Diameter/2]) rotate (a = [0, 90, 0])
cylinder (h = 2*Main_Fin_Root, d = Body_Diameter, $fn = 120);
} // difference

hull () { // aileron
// leading edge
translate ([-Main_Fin_Edge_Diameter/2 , 0, Aileron_Body_Standoff])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
translate ([-Main_Fin_Edge_Diameter/2 , 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2 +0.1])
sphere (d = Main_Fin_Edge_Diameter, $fn = 20);

// trailing edge
translate ([-Main_Fin_Edge_Diameter/2 - Aileron_Width, 0, -0.16 + Aileron_Body_Standoff])
sphere (d = Aileron_TE_Diameter, $fn = 20);
translate ([-Main_Fin_Edge_Diameter/2 - Aileron_Width, 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2 + 0.7])
sphere (d = Aileron_TE_Diameter, $fn = 20);
}
} // end module Main Fin

Main_Fin (); // module call


Just delete the '#' in the code above and you will see the final trimmed fin:
final fin.JPG

Any questions? Do you want to know more...?

edit: Dang, TRF posting removed all of the indentations that would have helped make the above code readable, oh well.
 
Last edited:
...<snipped>...
edit: Dang, TRF posting removed all of the indentations that would have helped make the above code readable, oh well.
Wow, great post - tons of great OpenSCAD info here. Just so you know, when I clicked the reply button on your post, all the formatting is still there, it’s just not being displayed (here's a sample);

Code:
difference() {
     hull () { // Main Fin

          //*** all of the stuff above ***

     } // end hull

     translate ([0, 0, -Body_Diameter/2]) rotate (a = [0, 90, 0])
          #cylinder (h = 3*Main_Fin_Root, d = Body_Diameter, $fn = 120);

} // end difference

To keep the formatting in a post, try using the 'insert code' option (the insert button is to the left of camera button). It keeps all the indenting. All I did above is simply copy a sample of your prior post and paste it into the code dialog box. Maybe you can ask a mod for permission to edit your prior posts and you can quickly fix the formatting by just copying and pasting into code boxes.

Thanks for all the great code, keep it coming!


Tony
 
Last edited:
Nice stuff Gary!! I think 3D modeling is the likely future of scale model documentation.
 
Gary,

I happen to live right down the street from a Nike Ajax in the Air and Space museum...…..



.20170826_155757.jpg

Be happy to help.... if you need anything measured or pictures let me know..... Its my favorite missile.
Always have plans to build a model of one day ! Maybe start my "Launch Pad" kit soon....

Paul
 
Gary,

I happen to live right down the street from a Nike Ajax in the Air and Space museum...…..

Be happy to help.... if you need anything measured or pictures let me know..... Its my favorite missile.
Always have plans to build a model of one day ! Maybe start my "Launch Pad" kit soon....

Paul

That's the South Dakota museum right? I was stationed at Ellsworth in the '70's. I was asleep a block and a half away from the total washout of the Rapid City flood.

That's a beautiful example of an Ajax. Might take you up on that offer. I recall that there's an AGM-28 Hound Dog there too that looks really nice. That's always been tempting. BTW I've scraped your picture for my collection.

All of my Nike Ajax data is here, in a dropbox folder. No guarantees that link won't change, I'm still organizing things there. Any additions are welcome.
 
To keep the formatting in a post, try using the 'insert code' option (the insert button is to the left of camera button). It keeps all the indenting. All I did above is simply copy a sample of your prior post and paste it into the code dialog box. Maybe you can ask a mod for permission to edit your prior posts and you can quickly fix the formatting by just copying and pasting into code boxes.

Thanks for all the great code, keep it coming!

Tony

Oh wow, I see that now. I would have never guessed that's what it was. Thanks.
 
Ok, neet. Let's continue with the Ajax sustainer body. I'll leave the nose cone for later. The body consists of three parts: an aft cone, a cylindrical body, and a forward cone. This is easily done with the cylinder and translate commands that I used before.

First, some dimensions:
Code:
Forward_Cone_Forward_Diameter = 5.8;
Body_Diameter = 12;
Tail_Diameter = 9; // Alway

Nose_Cone_Length = 14; // Alway
Forward_Cone_Length = 75.781 - 14.00; // Alway
Main_Body_Length = 232.625 - 75.781;
Tail_Cone_Length = 251.00 - 232.625; // Alway

Bottom_Main_Body = Tail_Cone_Length;
Bottom_Forward_Cone = Bottom_Main_Body + Main_Body_Length;
Bottom_Nose_Cone = Bottom_Forward_Cone + Forward_Cone_Length;

smooth = 120;

Two things about those dimensions. First, they are general dimensions that will be used for things other than just the body, so I want them to be global. That means that these variable names will be available in any code module. In the previous Main_Fin module, all of the variables were within the module, so they were local, and available for use only within that module. The second item is the smooth variable. It will be used globally to dictate the smoothness used for most surfaces (the $fn= factor). The time to generate a model is often related to the smoothness selected (especially on a steam-powered computer like mine). Using a lower value of smoothness can speed things up for development, then changing it to a higher value for the final render to make it pretty.

After those dimensions, we'll make a Main_Body () module, and start with the aft cone:
Code:
module Main_Body () {

    // aft cone
    cylinder (h = Tail_Cone_Length, d1 = Tail_Diameter, d2 = Body_Diameter, $fn = smooth);

} // end module Main Body

Main_Body ();

This is the same cylinder command used before, with two differences. First, we want the end of the body model to be sitting vertically at the axis origin, so it's not going to be translated anywhere. Secondly, you'll note a difference with the diameter variable(s). There are two: d1, and d2. Previously, with only one diameter, the command defined a true cylinder. Here with two, it's actually a cone (or a frustum of a cone, to be pedantic). d1 is the bottom diameter, and d2 is the top diameter. Remember also that the last line [ Main_Body (); ], is necessary to call the module and display it (I always forget that). The above stuff will look like this:

tail cone.JPG

The rest is simple. Just a translated cylinder for the central body, and a translated cylinder (cone) for the forward cone. The translations this time are in the z-axis, to stack the parts on top of one another. So I'll just finish with the full block of code:
Code:
Forward_Cone_Forward_Diameter = 5.8;
Body_Diameter = 12;
Tail_Diameter = 9; // Alway

Nose_Cone_Length = 14; // Alway
Forward_Cone_Length = 75.781 - 14.00; // Alway
Main_Body_Length = 232.625 - 75.781;
Tail_Cone_Length = 251.00 - 232.625; // Alway

Bottom_Main_Body = Tail_Cone_Length;
Bottom_Forward_Cone = Bottom_Main_Body + Main_Body_Length;
Bottom_Nose_Cone = Bottom_Forward_Cone + Forward_Cone_Length;

smooth = 120;

module Main_Body () {

    // tail cone
    cylinder (h = Tail_Cone_Length, d1 = Tail_Diameter, d2 = Body_Diameter, $fn = smooth);

    // main body
    translate ([0, 0, Bottom_Main_Body])
        cylinder (h = Main_Body_Length, d = Body_Diameter, $fn = smooth);

    // forward cone
    translate ([0, 0, Bottom_Forward_Cone])
        cylinder (h = Forward_Cone_Length, d1 = Body_Diameter, d2 = Forward_Cone_Forward_Diameter, $fn = smooth);

} // end module Main Body

Main_Body ();

main body.JPG

Next, we'll place the fins on that body.
 
Simple navigation in the OpenSCAD drawing window:

mouse left button hold and drag to rotate around axes
mouse right button hold and drag to translate
scroll wheel to zoom in and out

If you lose track of something, in the View menu, there are handy commands to view top/bottom/left/right/front/back/diagonal/center/all.
 
Last edited:
Placing the main fins on the Nike-Ajax body.

First I'm going to make a new module, for the entire Nike-Ajax second stage, and in it, I'm going to call the module for the main fin that we made earlier:
Code:
module Nike_Ajax_Sustainer () {
  
    rotate (a = [0, -90, 0]) Main_Fin ();

} // end module Nike Ajax Sustainer

Nike_Ajax_Sustainer ();


This block of code is placed in the OpenSCAD editor window, in addition to the modules Main_Fin () and Main_Body () and the global variables that we created earlier. You'll notice that it adds a rotate () command that operates on the Main_Fin () module. This rotates the fin 90 degrees around the y-axis, so that the fin is in the same orientation as the body. (Yes, I could have created the fin in this orientation, but at the time I was thinking in the same orientation as the drawing.)

fin rotated.JPG

Next, I'll add three things to the module. First is a local variable, Main_Fin_Position, which is the position of the fin measured from the hinge line of the fin to the bottom of the sustainer body. Next is a call to display the Main_Body (). And finally, a translate command to place the rotated fin in its position. Notice that I'm translating in two axes at once; one to move it up, and one to move it out on the x-axis by half the body diameter, so that it's placed on the surface of the body.
Code:
module Nike_Ajax_Sustainer () {
    Main_Fin_Position = 252 - 195; // Alway

    Main_Body ();
   
    translate ([-Body_Diameter/2, 0, Main_Fin_Position])
        rotate (a = [0, -90, 0]) Main_Fin ();

} // end module Nike Ajax Sustainer

Nike_Ajax_Sustainer ();
fin and body.JPG

Almost there, we just need more fins. I'll just call the Main_Fin () module three more times. But I also need to place them radially around the body, so I add another rotate command to do the rotation of each fin around the z-axis. I've rotated all fins an extra 45 degrees so that the zero-degree location can be the upper side of the missile as it sits on the launcher.
Code:
module Nike_Ajax_Sustainer () {
    Main_Fin_Position = 252 - 195; // Alway

    Main_Body ();
   
    rotate (a = [0, 0, 45]) translate ([-Body_Diameter/2, 0, Main_Fin_Position])
        rotate (a = [0, -90, 0]) Main_Fin ();
    rotate (a = [0, 0, 135]) translate ([-Body_Diameter/2, 0, Main_Fin_Position])
        rotate (a = [0, -90, 0]) Main_Fin ();  
    rotate (a = [0, 0, 225]) translate ([-Body_Diameter/2, 0, Main_Fin_Position])
        rotate (a = [0, -90, 0]) Main_Fin ();  
    rotate (a = [0, 0, 315]) translate ([-Body_Diameter/2, 0, Main_Fin_Position])
        rotate (a = [0, -90, 0]) Main_Fin ();  

} // end module Nike Ajax Sustainer

color ("White") Nike_Ajax_Sustainer ();

four fins.JPG

I snuck in one last addition in that final code block. Since the entire Nike-Ajax sustainer is usually white, I added a color command that operates on the whole sustainer module.

Next, a recap and a shortcut.
 
Here is the full code as it now stands, with one change that I'll explain below:
Code:
// Nike-Ajax model

Forward_Cone_Forward_Diameter = 5.8;
Body_Diameter = 12;
Tail_Diameter = 9; // Alway

Nose_Cone_Length = 14; // Alway
Forward_Cone_Length = 75.781 - 14.00; // Alway
Main_Body_Length = 232.625 - 75.781;
Tail_Cone_Length = 251.00 - 232.625; // Alway

Bottom_Main_Body = Tail_Cone_Length;
Bottom_Forward_Cone = Bottom_Main_Body + Main_Body_Length;
Bottom_Nose_Cone = Bottom_Forward_Cone + Forward_Cone_Length;

smooth = 120;

module Main_Body () {

    // tail cone
    cylinder (h = Tail_Cone_Length, d1 = Tail_Diameter, d2 = Body_Diameter, $fn = smooth);

    // main body
    translate ([0, 0, Bottom_Main_Body])
        cylinder (h = Main_Body_Length, d = Body_Diameter, $fn = smooth);

    // forward cone  
    translate ([0, 0, Bottom_Forward_Cone])
        cylinder (h = Forward_Cone_Length, d1 = Body_Diameter, d2 = Forward_Cone_Forward_Diameter, $fn = smooth);

} // end module Main Body

//Main_Body ();


module Main_Fin () {
    Main_Fin_Span = 18.95; // not including aileron - Bennett 18 61/64
    Main_Fin_Root = 70.234; // not including aileron - Bennett 70 15/64
    Main_Fin_Edge_Diameter = 0.679; // Bennett
    Center_Panel_Thickness = 1.929; // Bennett
    Aileron_Width = 1.5; // Alway
    Aileron_TE_Diameter = 0.25;   // TLAR
    Aileron_Body_Standoff = 0.34; // TLAR
    Rear_Panel_Root = 15.188; // Bennett 15 3/16
    Rear_Mid_Panel_Root = 30.938; // Bennett 30 15/16
    Center_Panel_Root = Rear_Mid_Panel_Root - Rear_Panel_Root;
    Front_Panel_Root = Main_Fin_Root - Rear_Mid_Panel_Root;

    difference() {
        hull () { // main fin
            // center root panel
            translate ([Rear_Panel_Root, (Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
                rotate (a = [0, 90, 0])
                cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);
            translate ([Rear_Panel_Root, -(Center_Panel_Thickness - Main_Fin_Edge_Diameter)/2, 0])
                rotate (a = [0, 90, 0])
                cylinder (h = Center_Panel_Root, d = Main_Fin_Edge_Diameter, $fn = 20);
               
            // forward tip  
            translate ([Main_Fin_Root - Main_Fin_Edge_Diameter/2, 0, 0])
                sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
               
            // trailing edge
            translate ([Main_Fin_Edge_Diameter/2 - 0.08, 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2])
                sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
            translate ([Main_Fin_Edge_Diameter/2 - 0.08, 0, 0])
                sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
        }
        translate ([0, 0, -Body_Diameter/2]) rotate (a = [0, 90, 0])
            cylinder (h = 3*Main_Fin_Root, d = Body_Diameter, center = true, $fn = smooth);
    }  
           
    hull () { // aileron
        // leading edge
        translate ([-Main_Fin_Edge_Diameter/2 + 0.08, 0, Aileron_Body_Standoff])
            sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
        translate ([-Main_Fin_Edge_Diameter/2 + 0.08, 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2 +0.1])
            sphere (d = Main_Fin_Edge_Diameter, $fn = 20);
           
        // trailing edge
        translate ([-Main_Fin_Edge_Diameter/2 - Aileron_Width, 0, -0.16 + Aileron_Body_Standoff])
            sphere (d = Aileron_TE_Diameter, $fn = 20);
        translate ([-Main_Fin_Edge_Diameter/2 - Aileron_Width, 0, Main_Fin_Span - Main_Fin_Edge_Diameter/2 + 0.7])
            sphere (d = Aileron_TE_Diameter, $fn = 20);
    }
} // end module main fin  


module Nike_Ajax_Sustainer () {
    Main_Fin_Position = 252 - 195; // Alway

    Main_Body ();
   
    for ( fin_angle = [45, 135, 225, 315]) {  
        rotate (a = [0, 0, fin_angle]) translate ([-Body_Diameter/2, 0, Main_Fin_Position])
            rotate (a = [0, -90, 0]) Main_Fin ();  
    } // end for
   
} // end module Nike Ajax Sustainer

color ("White") Nike_Ajax_Sustainer ();

In the last module, instead of calling Main_Fin () four separate times as I did before, I've condensed that a bit by using a for loop command. There are several ways to use a for, but in this case, it just assigns the variable fin_angle sequentially to the values in brackets [45, 135, 225, 315] and then runs the code in the following curly brackets once for each value. So the fin_angle is changed for each call to Main_Fin ().
 
Let's get back to it with a simple little detail. The main body has a number of body panel splits that are pretty easy to add. At most scales, they would be invisible and probably not noticeable in a small print, but I like to have them there anyway.

First, add the station locatons of the splits to the header of the main file:
Code:
// Main Body Panel Breaks
    Panel_Break_1 = 251 - 108.656;
    Panel_Break_2 = 251 - 149.510;
    Panel_Break_3 = 251 - 152.510;
    Panel_Break_4 = 251 - 167.990;
    Panel_Break_5 = 251 - 171.590;
    Panel_Break_6 = 251 - 187.268;
    Panel_Break_7 = 251 - 198.625;

Panel_Gap_Depth = 0.1; // depth of panel gaps - estimated panel gap.
Panel_Gap_Width = 0.1; // width of panel gaps
This includes a variable for the panel gap width and depth as well.

Now I'm going to change the module for the Main Body, as follows:
Code:
module Main_Body () {
    // forward cone
    translate ([0, 0, Bottom_Forward_Cone])
        cylinder (h = 75.781 - 14, d1 = Body_Diameter, d2 = Forward_Cone_Forward_Diameter, $fn = smooth);  // 6.377 TBD
    // main body
    difference() {
        translate ([0, 0, Bottom_Main_Body])
            cylinder (h = Main_Body_Length, d = Body_Diameter, $fn = smooth);
           
        translate ([0, 0, Panel_Break_1]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);
        translate ([0, 0, Panel_Break_2]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);  
        translate ([0, 0, Panel_Break_3]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);
        translate ([0, 0, Panel_Break_4]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);  
        translate ([0, 0, Panel_Break_5]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);
        translate ([0, 0, Panel_Break_6]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);  
        translate ([0, 0, Panel_Break_7]) cylinder (d = Body_Diameter + 2, h = Panel_Gap_Width, center = true, $fn = 8);
    }  
    translate ([0, 0, Bottom_Main_Body])
        cylinder (h = Main_Body_Length, d = Body_Diameter - 2*Panel_Gap_Depth, $fn = smooth);  

    // tail cone
    cylinder (h = Tail_Cone_Length, d1 = Tail_Diameter, d2 = Body_Diameter, $fn = smooth);
} // module Main Body

I've made the main body cylinder to be the first item of a difference statement, and following that, I've subtracted cylinders the height of the gap_width at each station location where there is a panel seam. So now the body is sliced into eight separate cylinders. But I'll glue them back together by placing a new cylinder in place, same length as the body, but just smaller in diameter by two times the gap depth. So now we have a single body again, but with 'groves' at the appropriate station locations.
 
I'm going to skip to the booster fins, because the other Ajax fins are a bit more complex. The booster fins will ease into things a bit slower.

NA Booster Fins Bennett.JPG NA - Booster Fins Alway.JPG

So I've got two sources for the booster fin dimensions, Bennett and Alway. There's really not much disagreement between the two. The one thing that Bennett adds is the small 'drop' to the forward end of the root. The booster tail shroud is a sheet metal cylinder that fits around the end of the Nike booster, but the fins extend forward of this shroud. So the root is not straight; the forward part of the root extends down a little bit more so that it contacts the Nike body forward of the shroud I finally found a photo that shows this well (note that the shroud itself is missing here):

NA Booster Fin Root.JPG

So first I'm going to do the basic fin, without that root extension. Like before, I'm going to place spheres at each corner, and use the hull command to create a surface between them. I've again corrected the sphere positions by subtracting 1/2 the diameter of the sphere so that the sphere is right on the edge. I haven't yet done this spanwise, however. The booster fin is another module:

Code:
module Booster_Fin () {
    Main_Span = 34.688;     // Bennett
    Root_Chord = 37.125;    //
    Tip_Chord = 10.50;      //
    Edge_Diameter = 0.25;   // Est.
    Root_Thickness = 2.297; //
    Tip_Thickness = 0.706;  //
  
    // unextended root
    hull () {
        // forward root edge
        translate ([Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
        // aft root edge
        translate ([Root_Chord - Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
        // aft tip edge
        translate ([Root_Chord/2 + Tip_Chord/2 - Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
        // forward tip edge
        translate ([Root_Chord/2 - Tip_Chord/2 + Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
        // root center
        translate ([Root_Chord/2, Root_Thickness/2 - Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);
        translate ([Root_Chord/2, -Root_Thickness/2 + Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);   
        // tip center
        translate ([Root_Chord/2, Tip_Thickness/2 - Edge_Diameter/2, Main_Span]) 
            sphere (d = Edge_Diameter, $fn = 20);
        translate ([Root_Chord/2, -Tip_Thickness/2 + Edge_Diameter/2, Main_Span]) 
            sphere (d = Edge_Diameter, $fn = 20);   
    } // end hull
}  // end module Booster_Fin

Booster_Fin ();
Which then looks like this:

Booster Fin 1.JPG

Next, I'll fix that root.
 
Last edited:
Now I want to extend the forward bit of that root downward, but the dimensions are a bit vague. I'm going to do a horrible, horrible hack. With this code:
Code:
module Booster_Fin () {
    Main_Span = 34.688;     // Bennett
    Root_Chord = 37.125;    //
    Tip_Chord = 10.50;      //
    Edge_Diameter = 0.25;   // Est.
    Root_Thickness = 2.297; //
    Tip_Thickness = 0.706;  //
   
    // unextended root
    hull () {
        // forward root edge
        translate ([Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
        // aft root edge
        translate ([Root_Chord - Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
        // aft tip edge
        translate ([Root_Chord/2 + Tip_Chord/2 - Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
        // forward tip edge
        translate ([Root_Chord/2 - Tip_Chord/2 + Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
        // root center
        translate ([Root_Chord/2, Root_Thickness/2 - Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);
        translate ([Root_Chord/2, -Root_Thickness/2 + Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);  
        // tip center
        translate ([Root_Chord/2, Tip_Thickness/2 - Edge_Diameter/2, Main_Span])
            sphere (d = Edge_Diameter, $fn = 20);
        translate ([Root_Chord/2, -Tip_Thickness/2 + Edge_Diameter/2, Main_Span])
            sphere (d = Edge_Diameter, $fn = 20);  
    } // end hull
   
    #hull () {
        // forward root edge
        translate ([Edge_Diameter/2, 0, -0.5]) sphere (d = Edge_Diameter, $fn = 20);
        // aft root edge
        translate ([Root_Chord - Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
        // forward tip edge
        translate ([Root_Chord/2 + Tip_Chord/2 - Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
        // aft tip edge
        translate ([Root_Chord/2 - Tip_Chord/2 + Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
        // root center
        translate ([Root_Chord/2, Root_Thickness/2 - Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);
        translate ([Root_Chord/2, -Root_Thickness/2 + Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);  
        // tip center
        translate ([Root_Chord/2, Tip_Thickness/2 - Edge_Diameter/2, Main_Span])
            sphere (d = Edge_Diameter, $fn = 20);
        translate ([Root_Chord/2, -Tip_Thickness/2 + Edge_Diameter/2, Main_Span])
            sphere (d = Edge_Diameter, $fn = 20);  
    } // end hull  
}  // end module Booster_Fin

Booster_Fin ();
The second hull block is the same as the first except for this line:
Code:
        // forward root edge
        translate ([Edge_Diameter/2, 0, -0.5]) sphere (d = Edge_Diameter, $fn = 20);
The forward root tip sphere has been translated down by 0.5. The second block is also preceded by a '#' which makes it translucent. The tip looks like this:

fin tip.JPG

Now I'm going to move that lower tip forward a small increment at a time, until the leading edge of the translucent fin matches the first, opaque fin.
Code:
        // forward root edge
        translate ([Edge_Diameter/2 - 0.2, 0, -0.5]) sphere (d = Edge_Diameter, $fn = 20);
Moving it forward that 0.2 it becomes this:

fin tip2.JPG

The 'extended' fin leading edge is now in-line with the original fin, but extends below it. So now I'll trim off the root. According to Bennett that drop is 3/32", so start by differencing the fin with a cube that sits 0.94 below the x-y plane. We can also get rid of the non-extended fin, and we can also trim the fin tip. Remember that these things (cubes, in this case) aren't part of the fin - I'm using them to trim off the bits of the fin I don't want.

I don't think I've mentioned using the cube () object yet. It just takes the form cube ({x. y, z]) , where x, y, and z are the dimensions of the cube. Adding the parameter center = true places the center of the cube at the origin, which usually makes it easier to position later. I've created a cube 10 high (z), and 10 wide (y); and four times the root length, so that even though it's x position is centered at the origin it extends past the length of the fin. Moving this cube in z by the fin span, plus half the height of the cube, places the lower surface of that cube at the fin tip, and subtracting it slices the tip off flat. (Remember, the tip wasn't flat, it was made with spheres.) Using the same cube moved downwards in z by 0.94 plus half its height slices off the root at the extended position. Same cube again, but this time only the root length, moved down by half its height, moved aft by half the root length, and moved further aft by the position of the start of the root slant, slices off the main flat area of the root. I also hulled this cube with a smaller cube to create the slanted area between the forward and aft root areas. Clear as mud.

I also added the root cylindrical mounting hub.

root trim.JPG
trimmed root.JPG
final boost fin.JPG
Code:
module Booster_Fin () {
    Main_Span = 34.688;     // Bennett
    Root_Chord = 37.125;    //
    Tip_Chord = 10.50;      //
    Edge_Diameter = 0.25;   // Est.
    Root_Thickness = 2.297; //
    Tip_Thickness = 0.706;  //
    Root_Drop_Extension = 0.094; // 3/32 Bennett
   
    difference() {
        hull () {
            // forward root edge
            translate ([Edge_Diameter/2 - 0.2, 0, -0.5]) sphere (d = Edge_Diameter, $fn = 20);
            // aft root edge
            translate ([Root_Chord - Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
            // forward tip edge
            translate ([Root_Chord/2 + Tip_Chord/2 - Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
            // aft tip edge
            translate ([Root_Chord/2 - Tip_Chord/2 + Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
            // root center
            translate ([Root_Chord/2, Root_Thickness/2 - Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);
            translate ([Root_Chord/2, -Root_Thickness/2 + Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);  
            // tip center
            translate ([Root_Chord/2, Tip_Thickness/2 - Edge_Diameter/2, Main_Span])
                sphere (d = Edge_Diameter, $fn = 20);
            translate ([Root_Chord/2, -Tip_Thickness/2 + Edge_Diameter/2, Main_Span])
                sphere (d = Edge_Diameter, $fn = 20);  
        } // end hull  
        // trim the fin tip with a cube translated by the fin span.
        translate ([0, 0, Main_Span + 10/2]) cube (size = [Root_Chord * 4, 10, 10], center = true);
        // trim the extended fin root
        translate ([0, 0, -Root_Drop_Extension - 10/2]) cube (size = [Root_Chord * 4, 10, 10], center = true);      
        // trim the shroud (non-extended) section of the fin root
        translate ([Root_Chord/2 + 7.875, 0, -10/2]) cube (size = [Root_Chord, 10, 10], center = true);  
        // slanted trim between the two sections
        hull () {
            translate ([Root_Chord/2 + 7.875, 0, -10/2]) cube (size = [Root_Chord, 10, 10], center = true);
            translate ([6, 0, -Root_Drop_Extension]) cube (size = [0.01, 10, 0.01], center = true);
        }
    } // end difference
    // fin mount rod
    translate ([Root_Chord/2, 0, 0]) cylinder (h = 1, d = 2, center = true, $fn = 60);          
}  // end module Booster_Fin

Booster_Fin ();

Well, I said it was a horrible hack. But, it produced exactly what I wanted. The best way to see what's going on would be to run the above code, and comment out sections to see what happens. Eventually, you should be able to pick up on what each section does.
 
Just for grins now we can make a quick booster shroud with fins. I see that I screwed up in that I placed the fin leading edge tip at the origin instead of placing the trailing edge tip there like I did for the main sustainer fin. That causes a few more gyrations in getting it rotated into position. I first have to translate it on the x-axis so that the trailing edge tip is at the origin, then rotate it vertical, then translate it again on the x-axis to the surface of the shroud, and finally rotate three fins radially into position.

I've added a little 'Fin_Spacing' fudge, because I doubt the fin root is actually flush with the shroud.

There will be a bunch of bolts and rivets to be added soon.
Code:
module Booster_Fin_Can () {
    Root_Chord = 37.125;    //
    Boost_Shroud_Diameter = 16.67;  // Bennett
    Boost_Shroud_Length = 28.125;   // Bennett
    Boost_Shroud_Thickness = 0.085; // Alway
    Fin_Spacing = 0.05; // est spacing between fin root and shroud

    difference() {
        cylinder (h = Boost_Shroud_Length, d = Boost_Shroud_Diameter, $fn = smooth);
        cylinder (h = 3 * Boost_Shroud_Length, d = Boost_Shroud_Diameter - 2 * Boost_Shroud_Thickness, center = true, $fn = smooth);
    }
    for ( rot = [0, 120, 240]) {   
        rotate (a = [0, 0, rot]) translate ([Boost_Shroud_Diameter/2 + Fin_Spacing, 0, 0])
            rotate (a = [0, 90, 0]) translate ([-Root_Chord, 0, 0]) Booster_Fin ();
    }
    // TODO bolts
}

Booster_Fin_Can ();

boost fin can.JPG
 
The Nike Ajax booster fin has some fairly prominent rivets on the leading and trailing edge. Probably not enough to be seen at most scales, but I like to have details like that in the CAD model anyway - it's easy enough to turn them off if I don't want them interfering with printing.
booster fin rivets.JPG

I count 37 on each edge. The center and root fasteners are flush phillips-heads that aren't nearly as prominent - I'll add them later. But now, the rivets.

First a new little module:
Code:
module rivet (diameter, prominence) {  //single rivet
// diameter = rivet outer diameter
// prominence = value 0-1 ; 1 = hemisphere, 0.35 = flattened, etc
    scale (v = [1, 1, prominence])  sphere (d = diameter, $fn = 12);
} // module rivets
This module adds a new feature of passed variables. The factors (diameter, prominence) are passed into this module from the line that calls it, and defines the size of the rivet. The diameter is pretty obvious, the prominence is used in the scale command. The scale command simply takes the form scale ([x, y, z]) where x, y, and z are how much the object is scaled on each axis. In this case the head of the rivet isn't going to be a sphere, but will be flattened somewhat. Calling it with a command like rivet (0.35, 0.3); will produce one rivet.


rotate (a = [90, 0, 0]) rivet (0.35, 0.3); This part just calls the rivet module to produce one rivet at the origin and rotates it on edge to match the vertical orientation that I used to develop the fin.
one rivet.JPG
Now I'll add the
for loop that produces 37 rivets. The variable rivet_spaceLE is a first guess at the spacing between the rivets.
Code:
    rivet_spaceLE = 1.0;    

    for ( rivet_number = [ 0: 36]) {
        translate ([rivet_number * rivet_spaceLE, 0, 0])
            rotate (a = [90, 0, 0]) rivet (0.35, 0.3);
    } // end for
This form of the
for command increments the variable rivet_number 37 times between the values of 0 and 36. Each time it's multiplied by the value rivet_spaceLE which makes an x-translation for each rivet in the loop, producing a row. At the moment they're still down the center of the root.

rivet row1.JPG

So now we want to translate them to be in line with the leading edge, using rotate (a = [0, -69, 0]) The angle value -69 was just found by plugging in values until the rivets lined up with the edge - no math required.

rivet row 2.JPG

So now I'm going to just translate the entire row, so that the first rivet is in the right place:
translate ([0.45, -0.18, 0.3]) Once again, these numbers were diddled with until TLAR.
rivet row 3.JPG

The last thing to do is look at the other end of the row:
rivet row 4.JPG

That's a little short - the photos show the last rivet right in the corner. Adjusting the variable
rivet_spaceLE = 1.0; will take care of that. It looks like a value of 1.017 will place it just right.

Now gosh, do we have to go through that again for the trailing edge, and the other side? Not quite. All we have to do is translate the starting point along the root edge x-axis to the trailing edge, and use a mirror of the leading edge angle, adjust the starting point a bit, and it's done. The other side is even easier with the
mirror ([x, y, z]) command. With the mirror command, we'll put a '1' in the 'y' position, which mirrors everything in the following curley brackets around the y-axis. So we just use mirror on the exact same code that the produced the rivets on the front side, and they will be mirrored onto the opposite side. The full booster fin code now looks like this:
Code:
module Booster_Fin () {
    Main_Span = 34.688;     // Bennett
    Root_Chord = 37.125;    //
    Tip_Chord = 10.50;      //
    Edge_Diameter = 0.25;   // Est.
    Root_Thickness = 2.297; //
    Tip_Thickness = 0.706;  //
    Root_Drop_Extension = 0.094; // 3/32 Bennett
  
    difference() {
        hull () {
            // forward root edge
            translate ([Edge_Diameter/2 - 0.2, 0, -0.5]) sphere (d = Edge_Diameter, $fn = 20);
            // aft root edge
            translate ([Root_Chord - Edge_Diameter/2, 0, 0]) sphere (d = Edge_Diameter, $fn = 20);
            // forward tip edge
            translate ([Root_Chord/2 + Tip_Chord/2 - Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
            // aft tip edge
            translate ([Root_Chord/2 - Tip_Chord/2 + Edge_Diameter/2, 0, Main_Span]) sphere (d = Edge_Diameter, $fn = 20);
            // root center
            translate ([Root_Chord/2, Root_Thickness/2 - Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20);
            translate ([Root_Chord/2, -Root_Thickness/2 + Edge_Diameter/2, 0]) sphere (d = Edge_Diameter, $fn = 20); 
            // tip center
            translate ([Root_Chord/2, Tip_Thickness/2 - Edge_Diameter/2, Main_Span])
                sphere (d = Edge_Diameter, $fn = 20);
            translate ([Root_Chord/2, -Tip_Thickness/2 + Edge_Diameter/2, Main_Span])
                sphere (d = Edge_Diameter, $fn = 20); 
        } // end hull 
        // trim the fin tip with a translated by the fin span.
        translate ([0, 0, Main_Span + 10/2]) cube (size = [Root_Chord * 4, 10, 10], center = true);
        // trim the extended fin root
        translate ([0, 0, -Root_Drop_Extension - 10/2]) cube (size = [Root_Chord * 4, 10, 10], center = true);     
        // trim the shroud section of the fin root
        translate ([Root_Chord/2 + 7.875, 0, -10/2]) cube (size = [Root_Chord, 10, 10], center = true); 
        // slanted trim between the two sections
        hull () {
            translate ([Root_Chord/2 + 7.875, 0, -10/2]) cube (size = [Root_Chord, 10, 10], center = true);
            translate ([6, 0, -Root_Drop_Extension]) cube (size = [0.01, 10, 0.01], center = true);
        }
    } // end difference
  
    // fin mount rod
    translate ([Root_Chord/2, 0, 0]) cylinder (h = 1, d = 2, center = true, $fn = 60);     

    rivet_spaceLE = 1.017; // leading edge rivet spacing
    translate ([0.45, -0.18, 0.3])  for ( rivet_number = [ 0: 36]) { // for 37 rivets
        rotate (a = [0, -69, 0]) translate ([rivet_number * rivet_spaceLE, 0, 0])
            rotate (a = [90, 0, 0]) rivet (0.35, 0.3);
    } // end for
    rivet_spaceTE = 1.016; // trailing edge rivet spacing
    translate ([0.3, -0.18, 0.3]) for ( rivet_number = [ 0: 36]) { // for 37 rivets
        translate ([Root_Chord - 0.7, 0, 0]) rotate (a = [0, -111, 0])
            translate ([rivet_number * rivet_spaceTE, 0, 0]) rotate (a = [90, 0, 0]) rivet (0.35, 0.3);
    } // end for
  
    mirror ([0, 1, 0]) { // mirror places the rivets on the opposite side
        translate ([0.45, -0.18, 0.3])  for ( rivet_number = [ 0: 36]) { // for 37 rivets
            rotate (a = [0, -69, 0]) translate ([rivet_number * rivet_spaceLE, 0, 0])
                rotate (a = [90, 0, 0]) rivet (0.35, 0.3);
        } // end for
        translate ([0.3, -0.18, 0.3]) for ( rivet_number = [ 0: 36]) { // for 37 rivets
            translate ([Root_Chord - 0.7, 0, 0]) rotate (a = [0, -111, 0])
                translate ([rivet_number * rivet_spaceTE, 0, 0]) rotate (a = [90, 0, 0]) rivet (0.35, 0.3);
        } // end for
    } // end mirror

}  // end module Booster_Fin

Booster_Fin ();
Remember that this also has to have the little module rivet() from above, in the code as well. The whole fin can now looks like this. Notice that I didn't make any changes to the Booster_Fin_Can code - since it calls the revised Booster_Fin module, the new rivets come in automatically.
fin can rivets.JPG









 
Have I lost everybody? ... Ah well. One more neet little thing anyway. There's an attached file below titled 'Nike_M5_Motor.txt' Download that file and rename it to: 'Nike_M5_Motor.scad' and place it in the same directory with the other Nike Ajax OpenSCAD files.

At the top of the Nike Ajax file we've been working on, add the line:
include <Nike_M5_Motor.scad>;

That other file was my OpenSCAD code for the Nike M5 motor, which I'm not going to try and explain. You might be able to figure it out, but I didn't write it with the intention of other humans reading it, so it might be pretty obscure. The good news is, you don't have to. Using the include statement above, effectively adds that code right into the Nike-Ajax stuff we've been working on. Code re-use. (And re-usable for every other Nike-based rocket - neet.)

Now with the module rivet() from above, the module Booster_Fin_Can () , and the module Booster_Fin () , plus that include line, we can do this:
Code:
//Booster_Fin ();
//Booster_Fin_Can ();

color ("White") Booster_Fin_Can ();
rotate (a = [0, 0, 60]) Nike_M5_motor();
Comment out any earlier calls to display the Booster Fin or Booster Fin Can. The last two lines display the Booster Fin Can in white, and drops in the Nike M5 motor from the other file. It's rotated 60 degrees to get the flange holes lined up right. Wa-la. The entire Nike-Ajax booster: (Whoops - less the interstage, for now.)

Ajax m5.JPG

The fin leading edge detail shows how the root comes off of the shroud and perfectly skips over the Nike weld line so that the front of the root is flush with the Nike body.

fin LE weld.JPG

Ajax M5 2.JPG

There are a few details on the M5 ignitor that will have to be changed for the Ajax.
 

Attachments

  • Nike_M5_Motor.txt
    19.8 KB · Views: 35
Ok, this is getting out of hand. Files get too big and are unwieldy. Time to split things up and organize a bit. This means, however, that the project will be split into perhaps a dozen files, usually one for each component.

The text editor embedded into OpenSCAD has improved a lot recently, but it doesn't handle having multiple tabbed files open simultaneously. (You can just have multiple OpenSCAD windows open, but that gets clumsy.) It's not necessary, but I suggest using an alternate programming editor - my choice is Notepad++. It can be configured for a particular language, so that it has keyword coloring, autocomplete, and help notes. Notepad++ is free and easy to install, but the language configuration takes some work. If you want to try it, there are instructions and language files here: https://www.thingiverse.com/thing:167899 When using Notepad++ with OpenSCAD, you turn off the OpenSCAD editor window, and anytime you save a Notepad++ file that is open in OpenSCAD, it forces OpenSCAD to recompile the project. Works neet. There are some other programming editors that have been configured to work with OpenSCAD, but this is the one I know - 'cause I did the language files.
 
With the files I'll be including here, there really are no programming changes - nothing new - just some rearrangement. I'll only detail a couple here. First the Nike-Ajax common.scad file, which contains some global variables and common modules:
Code:
/*
Nike Ajax - global dimensions and common modules

Use of this file is licensed under the Creative Commons - Attribution - Non-Commercial license.
https://creativecommons.org/licenses/by-nc/3.0/  by Gary A. Crowell Sr.
*/

smooth = 120;

Forward_Cone_Forward_Diameter = 5.8;
Body_Diameter = 12;
Tail_Diameter = 9; // Alway

Nose_Cone_Length = 14; // Alway


// Booster_Fin_Shroud dimensions
    Root_Chord = 37.125;    //
    Boost_Shroud_Diameter = 16.67;  // Bennett
    Boost_Shroud_Length = 28.125;   // Bennett
    Boost_Shroud_Thickness = 0.085; // Alway
    Fin_Spacing = 0.05; // spacing between fin root and shroud


module rivet (diameter, prominence) {  //single rivet
// diameter = rivet outer diameter
// prominence = value 0-1 ; 1 = hemisphere, 0.35 = flattened, etc
    scale (v = [1, 1, prominence])  sphere (d = diameter, $fn = 12);
} // module rivet

Nothing really new there. And then the top-level file Nike-Ajax.scad.
Code:
/*
Nike Ajax

Use of this file is licensed under the Creative Commons - Attribution - Non-Commercial license.
https://creativecommons.org/licenses/by-nc/3.0/  by Gary A. Crowell Sr.

For ease of development, since all data sources were scaled in inches, all dimensions were
entered as inches, but OpenSCAD uses mm.  So the resulting scale is 1 mm = 1 in, or 1/25.4.

For conversion to other scales use the following factors:
 
        1/144   = 0.176
        1/100   = 0.254
        1/87    = 0.292
        1/72    = 0.353
        1/48    = 0.529
        1/35    = 0.726
        1/24    = 1.058
        1/12    = 2.117
        1/10    = 2.540
        1/8     = 3.175
BT5   = 1/30.33 = 0.837
BT20  = 1/22.42 = 1.133
BT50  = 1/16.91 = 1.502
BT55  = 1/12.45 = 2.040
BT60  = 1/10.08 = 2.520
BT70  = 1/7.44  = 3.414
BT80  = 1/6.35  = 4.000
3"LOC = 1/5.32  = 4.744
3.9LOC= 1/4.13  = 6.150
*/

// include files for Nike-Ajax components
    //include <Nike-Ajax common.scad>; // this is included in all other files
    include <Nike_M5_Motor.scad>;
    include <Nike-Ajax body.scad>;
    include <Nike-Ajax main fin.scad>;
    //include <Nike-Ajax guide fin.scad>;
    //include <Nike-Ajax radar fin.scad>;
    include <Nike-Ajax booster fin.scad>;
    include <Nike-Ajax booster fin shroud.scad>;
    //include <Nike-Ajax interstage.scad>;
    //include <Nike-Ajax nose cone.scad>;
    //include <Nike-Ajax launch lugs.scad>;

// main component locations  
    Bottom_Ajax_Tail_Cone_Sta = 251;
    Bottom_Nike_Sta = 392;
    Main_Fin_Sta = 195;

   
module Nike_Ajax_Sustainer () {
    // main body
    color ("White") Main_Body ();

    // fins
    color ("White") for ( rot = [45, 135, 225, 315]) {
        rotate (a = [0, 0, rot])
            translate ([Body_Diameter/2, 0, Bottom_Ajax_Tail_Cone_Sta - Main_Fin_Sta]) Main_Fin ();
        //rotate (a = [0, 0, rot]) translate ([-3.8, 0, 251 - 48.826]) Guide_Fin ();
        //rotate (a = [0, 0, rot]) translate ([-5.48, 0, 251 - 74.675]) Radar_Fin ();  
    } // end for
   
    // TODO tunnels
    // TODO nose cone
   
} // end module Nike Ajax Sustainer
   
   
// booster fins
    for ( rot = [0, 120, 240]) {  
        rotate (a = [0, 0, rot]) translate ([Boost_Shroud_Diameter/2 + Fin_Spacing, 0, Root_Chord/2])
            Booster_Fin ();
    } // end for
 
 
color ("White" ) Booster_Fin_Shroud ();
translate ([0, 0, Bottom_Nike_Sta - Bottom_Ajax_Tail_Cone_Sta]) Nike_Ajax_Sustainer ();
rotate (a = [0, 0, 60]) Nike_M5_motor();
// TODO
    // interstage
    // launch lugs


First thing in that code is that in the header comments I've put in the scale factors that would be used for most model sizes. A scale () command around the final model with the scale factor will produce a model in the indicated scale.

Next, are the include statements for all of the individual component files. Some are commented out because we don't have those components developed yet. And finally, there are some TODO placeholders for some other bits that are yet to be done. All of these .txt files must have their extension changed to .scad for use with OpenSCAD.
 

Attachments

  • Nike-Ajax common.txt
    882 bytes · Views: 39
  • Nike-Ajax main fin.txt
    2.8 KB · Views: 34
  • Nike-Ajax body.txt
    8.8 KB · Views: 33
  • Nike-Ajax booster fin.txt
    3.6 KB · Views: 37
  • Nike-Ajax booster fin shroud.txt
    1,007 bytes · Views: 35
  • Nike_M5_Motor.txt
    19.8 KB · Views: 39
  • Nike-Ajax.txt
    2.4 KB · Views: 32
Back
Top