--- /dev/null
+
+// The Estes A8-3 and C6-7 motors have diameter of 17.7 mm,
+// length 69.5 mm. The Estes Alpha launch pad has rod diameter 3.4 mm.
+
+motor_diam = 17.7 + 0.5; // add some tolerance
+motor_len = 69.5 + 0.5;
+motor_wall = 2;
+
+segment_overlap = 15;
+
+thin_wall = 1.0; // depends on the print width
+thick_wall = 2.5*thin_wall;
+
+clip_spring_angle = 45;
+clip_spring_depth = 20;
+
+rod_diam = 4;
+
+eps = 0.01;
+infty = 1000;
+
+//----------------- MOTOR MODULE -----------------------------
+
+module fin() {
+ assign(h1 = 2*motor_len/3, // near end height
+ h2 = 20, // far end height
+ h_off = motor_len, // height offset of the far height
+ w = 30, // distance of the far height
+ fin_w = thin_wall)
+ translate([0, -fin_w/2, -h1])
+ hull() {
+ cube([eps, fin_w, h1]); // near end
+ translate([w, 0, h_off]) // far end
+ cube([eps, fin_w, h2]);
+ };
+};
+
+// alternative fin layout
+module fin2() {
+ assign(h1 = motor_len/2, // near end height
+ w2 = 18, // bottom/far end width
+ h_off = 50, // height offset of the far height
+ w = 30, // distance of the far height
+ fin_w = thin_wall)
+ translate([0, -fin_w/2, -h1])
+ hull() {
+ cube([eps, fin_w, h1]); // near end
+ translate([w-w2, 0, h_off]) // far end
+ cube([w2, fin_w, eps]);
+ };
+};
+
+rod_hole_height = 15;
+rod_hole_side = 1.5*(rod_diam + thin_wall);
+
+module motor_module_solid()
+{
+ // the lowest part is for joining the segments
+ cylinder(r = motor_diam/2 + thin_wall, h = segment_overlap + eps);
+
+ // conical joint between the two cylinders
+ translate([0, 0, segment_overlap - thick_wall + thin_wall])
+ cylinder(r1 = motor_diam/2 + thin_wall,
+ r2 = motor_diam/2 + thick_wall,
+ h = thick_wall - thin_wall + eps);
+
+ // protrusions to hold the main tube in place
+ for (a = [60, 180, 300]) {
+ rotate([0, 0, a]) {
+ translate([motor_diam/2 - thin_wall, 0, 0])
+ cylinder(r1 = thick_wall-thin_wall/2, r2 = thick_wall, h = segment_overlap/3 + eps);
+ translate([motor_diam/2 - thin_wall, 0, segment_overlap/3])
+ cylinder(r = thick_wall, h = 2*segment_overlap/3 + eps);
+ };
+ };
+
+ // the thick cylinder above it
+ translate([0, 0, segment_overlap])
+ cylinder(r = motor_diam/2 + thick_wall,
+ h = motor_len + motor_wall - segment_overlap);
+
+ // clip spring
+ translate([0, 0, motor_len + motor_wall])
+ intersection() {
+ translate([motor_diam/2+6, infty/2, 4])
+ rotate([90, 0, 0])
+ cylinder(r = 8, h = infty);
+ cylinder(r = motor_diam/2 + thick_wall, h = infty);
+ rotate([0, 0, -clip_spring_angle/2+eps])
+ cube(infty);
+ rotate([0, 0, clip_spring_angle/2-eps])
+ scale([1, -1, 1])
+ cube([infty, infty, 8]);
+ };
+
+ // fins
+ for (a = [60, 180, 300]) {
+ rotate([0, 0, a])
+ translate([motor_diam/2 + thick_wall-thin_wall, 0, motor_wall + motor_len])
+ // fin();
+ fin2();
+ };
+
+ // rod hole holder
+ hull() {
+ translate([motor_diam/2 + thick_wall - rod_diam/2 - thin_wall,
+ 0, segment_overlap])
+ scale([1, 1.4, 1])
+ cylinder(r = rod_diam/2 + thin_wall, h = eps);
+ translate([motor_diam/2 + thick_wall + rod_diam/2, 0, segment_overlap + rod_hole_side])
+ scale([1, 1.1, 1])
+ cylinder(r = rod_diam/2 + thin_wall, h = rod_hole_height);
+ translate([motor_diam/2 + thick_wall - rod_diam/2 - thin_wall,
+ 0, segment_overlap + 2*rod_hole_side + rod_hole_height])
+ scale([1, 1.4, 1])
+ cylinder(r = rod_diam/2 + thin_wall, h = eps);
+ };
+
+};
+
+module motor_module() {
+ difference() {
+ motor_module_solid();
+
+ // top ring to hold the motor inside
+ translate([0, 0, -eps])
+ cylinder(r = motor_diam/2 - motor_wall,
+ h = motor_wall + 2*eps);
+
+ // motor hole
+ translate([0, 0, motor_wall - eps])
+ cylinder(r = motor_diam/2, h = motor_len + 2*eps);
+
+ // three rails inside the motor hole
+ translate([0, 0, segment_overlap + thick_wall]) difference() {
+ union() {
+ cylinder(r = motor_diam/2 + thin_wall,
+ h = motor_len - segment_overlap - 2*thick_wall + eps);
+ translate([0, 0, motor_len - segment_overlap - 2*thick_wall])
+ cylinder(r1 = motor_diam/2 + thin_wall, r2 = motor_diam/2, h = thick_wall + eps);
+ };
+ for (a = [60, 180, 300]) rotate([0, 0, a])
+ translate([motor_diam/2 + 2.5, 0, -eps])
+ cylinder(r = 3, h = infty);
+ };
+
+ // clip spring
+ for (r = [-clip_spring_angle/2, clip_spring_angle/2]) {
+ rotate([0, 0, r])
+ translate([-thin_wall/2, 0, motor_len + motor_wall - clip_spring_depth])
+ cube([infty, thin_wall, infty]);
+ };
+ translate([0, 0, motor_len - eps])
+ intersection() {
+ cylinder(r = motor_diam/2 + thin_wall,
+ h = thick_wall + 2*eps);
+ rotate([0, 0, -clip_spring_angle/2+eps])
+ cube(infty);
+ rotate([0, 0, clip_spring_angle/2-eps])
+ scale([1, -1, 1])
+ cube([infty, infty, 8]);
+ };
+
+
+ // rod hole
+ translate([motor_diam/2 + thick_wall + eps + rod_diam/2, 0, 0])
+ cylinder(r = rod_diam/2, h = infty);
+ };
+};
+
+// -------------------- CENTRAL TUBE ---------------------
+
+central_tube_h = 80;
+
+module central_tube_solid() {
+ cylinder(r = motor_diam/2 + thick_wall, h = central_tube_h);
+};
+
+module central_tube() {
+ difference() {
+ central_tube_solid();
+ translate([0, 0, -eps])
+ cylinder(r = motor_diam/2 + thick_wall - thin_wall,
+ h = infty);
+ };
+};
+
+//------------------------- FRONT CONE -----------------------
+cone_h = 45;
+cone_resolution = 40;
+
+function bez_i4(t, ctls) =
+ (pow(1-t, 3) * ctls[0])
+ + (3 * t * pow(1-t, 2) * ctls[1])
+ + (3 * pow(t, 2) * (1-t) * ctls[2])
+ + (pow(t, 3) * ctls[3]);
+
+module bezier_cone(cps, res)
+{
+ for (t = [0:1:res])
+ translate([0, 0, (bez_i4(t/res, cps))[0]])
+ cylinder(r1 = (bez_i4(t/res, cps))[1],
+ r2 = (bez_i4((t + 1)/res, cps))[1],
+ h = (bez_i4((t + 1)/res, cps))[0]
+ - (bez_i4(t/res, cps))[0] + eps);
+};
+
+module front_cone_body() {
+ translate([0, 0, segment_overlap])
+ bezier_cone([
+ [ 0, motor_diam/2 + thick_wall ], // start
+ [ cone_h/2, motor_diam/2 + thick_wall ], // cp 1
+ [ cone_h - motor_diam/2 - thick_wall, motor_diam/2 + thick_wall ], // cp 2
+ [ cone_h, 0 ],
+ ], 40);
+
+ translate([0, 0, segment_overlap-thick_wall+thin_wall])
+ cylinder(r1 = motor_diam/2+thin_wall,
+ r2 = motor_diam/2 + thick_wall,
+ h = thick_wall - thin_wall + eps);
+
+ cylinder(r = motor_diam/2+thin_wall, h = segment_overlap + eps);
+};
+
+module front_cone() {
+ difference() {
+ front_cone_body();
+ translate([0, 0, segment_overlap])
+ bezier_cone([
+ [ 0.7*thin_wall, motor_diam/2 + thick_wall - thin_wall ], // start
+ [ cone_h/2-0.7*thin_wall, motor_diam/2 + thick_wall - thin_wall], // cp 1
+ [ cone_h - motor_diam/2 - thick_wall + thin_wall - 1.4*thin_wall, motor_diam/2 + thick_wall - thin_wall ], // cp 2
+ [ cone_h - 1.4*thin_wall, 0 ],
+ ], 40);
+
+ translate([0, 0, segment_overlap-thick_wall+1.7*thin_wall])
+ cylinder(r1 = motor_diam/2,
+ r2 = motor_diam/2 + thick_wall-thin_wall,
+ h = thick_wall-thin_wall + eps);
+
+ translate([0, 0, -eps])
+ cylinder(r = motor_diam/2, h = segment_overlap + 2*eps);
+
+ // debug
+ // translate([0, 0, -eps]) cube(infty);
+ };
+};
+
+module thread_holder() {
+ rotate([0, 90, 0]) {
+ translate([0, 0, -1.5]) difference() {
+ cylinder(r = 10, h = 3);
+ translate([0, 0, -eps])
+ cylinder(r = 8, h = 3 + 2*eps);
+ };
+ };
+}
+
+// thread_holder();
+
+$fn = 128;
+
+translate([motor_diam + thick_wall, 0, 0])
+ motor_module();
+
+rotate([0, 0, 120])
+translate([motor_diam + thick_wall, 0, 0])
+ central_tube();
+
+rotate([0, 0, 240])
+translate([motor_diam + thick_wall, 0, 0])
+ front_cone();
+