summaryrefslogtreecommitdiff
path: root/gcode/rocket_gcode.py
diff options
context:
space:
mode:
authorMike Beattie <mike@ethernal.org>2013-08-30 03:36:35 +1200
committerMike Beattie <mike@ethernal.org>2013-08-30 03:36:35 +1200
commit4d8d3ce82a05316912088ceec144c5b557a4b5cb (patch)
tree3dc8a09fe1fa6495bcd4f47087c39e8f518d8e37 /gcode/rocket_gcode.py
parentd7f66ca9c6e643d4fcad1602681fa13bb7bc2028 (diff)
Add gcode generation script
For generating gcode to cut rings and bulkheads with a cnc router Signed-off-by: Mike Beattie <mike@ethernal.org>
Diffstat (limited to 'gcode/rocket_gcode.py')
-rw-r--r--gcode/rocket_gcode.py193
1 files changed, 193 insertions, 0 deletions
diff --git a/gcode/rocket_gcode.py b/gcode/rocket_gcode.py
new file mode 100644
index 0000000..21da27e
--- /dev/null
+++ b/gcode/rocket_gcode.py
@@ -0,0 +1,193 @@
+#! /usr/bin/python
+# Copyright 2008 by Bdale Garbee <bdale@gag.com>. GPLv2
+# Copyright 2011 by Anthony Towns <aj@erisian.com.au>. GPLv2
+
+# This is a Python library to emit g-code to cut motor mount centering
+# rings or bulkheads for a model rocket.
+#
+# Z reference plane is top surface of stock, X/Y origin is center of ring
+
+import math
+import sys
+
+def mm2inch(mm):
+ return mm/25.4
+
+def polar2xy(radius, degrees = None, radians = None):
+ if degrees is not None:
+ radians = degrees / 180.0 * math.pi
+ x = radius * math.cos(radians)
+ y = radius * math.sin(radians)
+ return x,y
+
+class Gcode(object):
+ def __init__(self,
+ free, cutter, speed = 8,
+ output = sys.stdout):
+ self.Zfree = free
+ self.Zdepth = 0.0
+ self.Speed = speed
+ self.CutterOD = cutter
+ self.output = output
+
+ self.write("%")
+ self.write("G17 G20 G90")
+ self.write("M3 S5000")
+
+ self.origin()
+
+ def comment(self, comment):
+ self.output.write("\n(%s)\n" % (comment))
+
+ def close(self):
+ self.write("M5 M2")
+ self.write("%")
+ self.output.close()
+
+ def write(self, gcode):
+ self.output.write(gcode + "\n")
+
+ def plunge(self):
+ self.write("(plunge)")
+ self.write("G01 Z %.4f F%d" % (-self.Zdepth, int(self.Speed/2)))
+
+ def retract(self):
+ self.write("(retract)")
+ self.write("G00 Z %.4f" % (self.Zfree))
+
+ def origin(self):
+ self.retract()
+ self.write("(origin)")
+ self.write("G00 X0 Y0")
+
+ def hole(self, x, y, depth, increment, speed):
+ self.write("G00 X %6.4f Y %6.4f" % (x, y))
+ self.write("G83 Z %6.4f R %.4f Q %6.4f F %d" % (-depth, self.Zfree, increment, speed))
+
+ def circle(self, diameter, x=0, y=0):
+ radius = diameter/2.0
+ self.write("G00 X %6.4f Y %6.4f" % (x, y + radius))
+ self.plunge()
+ self.write("G02 X %6.4f Y %6.4f I %6.4f J %6.4f F%d" % (
+ x, y - radius, 0, -radius, self.Speed))
+ self.write("G02 X %6.4f Y %6.4f I %6.4f J %6.4f F%d" % (
+ x, y + radius, 0, +radius, self.Speed))
+ self.retract()
+
+ def slot(self, startX, startY, stopX, stopY, width, depth, increment):
+ deltaX = stopX - startX
+ deltaY = stopY - startY
+ length = (deltaX**2 + deltaY**2)**0.5
+ offX = -deltaY / length # unit vector, 90 degrees to slot
+ offY = deltaX / length
+
+ width += 0.0
+ if increment > depth:
+ self.Zdepth = depth
+ else:
+ self.Zdepth = increment
+
+ while self.Zdepth <= depth:
+ if width < self.CutterOD:
+ self.comment("***desired slot width smaller than cutter***")
+ runs = 1
+ step = 0
+ elif width == self.CutterOD:
+ runs = 1
+ step = 0
+ else:
+ runs = int(math.ceil((width)/self.CutterOD))
+ beginX = startX + offX * (width-self.CutterOD)/2
+ beginY = startY + offY * (width-self.CutterOD)/2
+ endX = stopX + offX * (width-self.CutterOD)/2
+ endY = stopY + offY * (width-self.CutterOD)/2
+ step = (width-self.CutterOD)/(runs-1)
+
+ self.write("G00 X%6.4f Y%6.4f" % (beginX, beginY))
+
+ self.plunge()
+ for n in range(runs-1):
+ self.write("G01 X%6.4f Y%6.4f F%d" % (endX, endY, self.Speed))
+ beginX, endX = endX - offX * step, beginX - offX * step
+ beginY, endY = endY - offY * step, beginY - offY * step
+ self.write("G01 X%6.4f Y%6.4f F%d" % (beginX, beginY, self.Speed))
+
+ self.write("G01 X%6.4f Y%6.4f F%d" % (endX, endY, self.Speed))
+
+ self.retract()
+
+ if self.Zdepth == depth:
+ break
+ self.Zdepth += increment
+ if self.Zdepth > depth:
+ self.Zdepth = depth
+
+
+ def fin_slots(self, FinCount, innerD, outerD, width, depth, increment = 0.1, rotate = 0):
+ for fin in range(FinCount):
+ self.comment("fin slot %d" % (fin))
+
+ FinDegrees = 90 + rotate + 360.0 / FinCount * fin
+ while FinDegrees > 360: FinDegrees -= 360
+ # angle from origin (on y-axis)
+
+ FinSlotInX, FinSlotInY = polar2xy((innerD/2.0)-self.CutterOD,
+ degrees=FinDegrees)
+ FinSlotOutX, FinSlotOutY = polar2xy((outerD/2.0)+self.CutterOD,
+ degrees=FinDegrees)
+
+ self.slot(FinSlotInX, FinSlotInY, FinSlotOutX, FinSlotOutY, width, depth, increment)
+
+ def ring_cluster(self, count, diam, sep = 1.0, rotation = 0, dist = None):
+ base_dist = diam/2.0 / math.sin(math.pi/count)
+ if (dist is not None):
+ sep = dist / base_dist
+
+ for cluster in range(count):
+ self.comment("cluster MMT hole %d" % (cluster))
+
+ degrees = rotation + cluster*360.0/count
+ while degrees > 360: degrees -= 360
+
+ ClusX, ClusY = polar2xy(base_dist * sep, degrees=degrees)
+ self.circle(diam - self.CutterOD, x=ClusX, y=ClusY)
+
+ def aeropack(self, count, hole_radius, rotation, depth, increment, speed):
+ for h in range(count):
+ self.comment("Aeropack screw hole %d" % (h))
+
+ degrees = rotation + h*360.0/count
+ while degrees > 360: degrees -= 360
+
+ HoleX, HoleY = polar2xy(hole_radius, degrees=degrees)
+ self.hole(x=HoleX, y=HoleY, depth=depth, increment=increment, speed=speed)
+
+ def aeropack_54mm(self, rotation = 15, depth = 0.125, increment = 0.125, speed = 25):
+ self.aeropack(12, mm2inch(46), rotation, depth, increment, speed)
+
+ def aeropack_75mm(self, rotation = 15, depth = 0.125, increment = 0.125, speed = 25):
+ self.aeropack(12, mm2inch(46), rotation, depth, increment, speed)
+
+ def aeropack_98mm(self, rotation = 15, depth = 0.125, increment = 0.125, speed = 25):
+ self.aeropack(12, mm2inch(46), rotation, depth, increment, speed)
+
+
+ def dsub(self, x, y, rotation = 0):
+ # 9pin dsub female
+ # 1mm deep frame, 30mm long by 12mm wide
+
+ old_depth = self.Zdepth
+ self.Zdepth = mm2inch(1)
+ dX, dY = polar2xy(mm2inch(15), degrees = rotation)
+ self.slot(x-dX, y-dY, x+dX, y+dY, mm2inch(12))
+
+ # need approx 1cm of depth for connector + room for wires
+ # so that's basically all the way through...
+ # connector is barely 1mm (maybe 0.5mm?) on sides
+ # connector is 6mm from either edge on longer side
+ # connector is 8mm from either edge on shorter side
+
+ self.Zdepth = old_depth
+ dX, dY = polar2xy(mm2inch(9), degrees = rotation)
+ self.slot(x-dX, y-dY, x+dX, y+dY, mm2inch(10))
+