diff options
| author | Franklin Wei <franklin@rockbox.org> | 2020-01-31 00:28:40 -0500 |
|---|---|---|
| committer | Franklin Wei <franklin@rockbox.org> | 2020-01-31 00:28:40 -0500 |
| commit | 2e0c87e565e5491e3a8a001e52acd553ca1948e1 (patch) | |
| tree | c6d07a3bbfb0bda40a1178d81d1581f962ff024e | |
| parent | 51d193e7d58e1419360a0b6ff59af9bd0e06ec00 (diff) | |
| download | rastercarve-2e0c87e565e5491e3a8a001e52acd553ca1948e1.zip rastercarve-2e0c87e565e5491e3a8a001e52acd553ca1948e1.tar.gz rastercarve-2e0c87e565e5491e3a8a001e52acd553ca1948e1.tar.bz2 rastercarve-2e0c87e565e5491e3a8a001e52acd553ca1948e1.tar.xz | |
Add custom preamble/epilogue support.
Allows reading custom preamble and/or epilogue from file or command line.
Opens the road for metric support.
| -rwxr-xr-x | rastercarve/__main__.py | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/rastercarve/__main__.py b/rastercarve/__main__.py index 8d38e31..b5149a8 100755 --- a/rastercarve/__main__.py +++ b/rastercarve/__main__.py @@ -20,6 +20,7 @@ from rastercarve import __version__ import argparse import cv2 # image scaling +import io # stringIO for parsing lines import json import numpy as np # a little vector stuff from tqdm import tqdm # progress bar @@ -41,6 +42,10 @@ DEF_STEPOVER = 110 DEF_LINE_ANGLE = 22.5 # angle of lines across image, [0-90) degrees DEF_LINEAR_RESOLUTION = .01 # spacing between image samples along a line (inches) +#### G-code parameters +DEF_PREAMBLE = "G00 G90 G80 G28 G17 G20 G40 G49\nM03" +DEF_EPILOGUE = "M05" + #### Image interpolation SUPERSAMPLE = 2 # scale heightmap by this factor before cutting @@ -78,12 +83,17 @@ def debug(str): eprint(str) debug_msgs += 1 -line = 1 -gcodebuf = "" +line_no = 1 def gcode(s): - global line - print((s if hasattr(glob_args, 'suppress_linenos') else "N%d %s" % (line, s)) ) - line += 1 + global line_no + print((s if hasattr(glob_args, 'suppress_linenos') else "N%d %s" % (line_no, s)) ) + line_no += 1 + +def gcode_multiline(s): + f = io.StringIO(s) + for l in f: + gcode(l.rstrip()) + pathlen = 0 # in rapidlen = 0 # in @@ -233,9 +243,9 @@ def dump_stats(orig_size, img_size, line_width, line_spacing, eprint("Output resolution: %.1f PPI" % (output_ppi)) eprint("Scaled image by f=%.2f (%.1f PPI)" % (scale_factor, interp_ppi)) eprint("Total toolpath length: %.1f in" % (pathlen)) - eprint(" - Rapids: %.1f in (%.1f s)" % (rapidlen, rapidlen / (glob_args.rapid_rate / 60))) - eprint(" - Plunges: %.1f in (%.1f s)" % (plungelen, plungelen / (glob_args.plunge_rate / 60))) - eprint(" - Moves: %.1f in (%.1f s)" % (movelen, movelen / (glob_args.feed_rate / 60))) + eprint(" - Rapids: %.1f in (%.1f sec)" % (rapidlen, rapidlen / (glob_args.rapid_rate / 60))) + eprint(" - Plunges: %.1f in (%.1f sec)" % (plungelen, plungelen / (glob_args.plunge_rate / 60))) + eprint(" - Moves: %.1f in (%.1f sec)" % (movelen, movelen / (glob_args.feed_rate / 60))) eprint("Feed rate: %.1f in/min" % (glob_args.feed_rate)) eprint("Plunge rate: %.1f in/min" % (glob_args.plunge_rate)) eprint("Estimated machining time: %.1f sec" % (pathtime)) @@ -260,6 +270,23 @@ def dump_stats(orig_size, img_size, line_width, line_spacing, json.dump(stats, f) +def getPreambleEpilogue(): + global glob_args + pre, epi = DEF_PREAMBLE, DEF_EPILOGUE + if hasattr(glob_args, 'preamble'): + pre = glob_args.preamble + elif hasattr(glob_args, 'preamble_file'): + with open(glob_args.preamble_file) as f: + pre = f.read() + + if hasattr(glob_args, 'epilogue'): + epi = glob_args.epilogue + elif hasattr(glob_args, 'epilogue_file'): + with open(glob_args.epilogue_file) as f: + epi = f.read() + + return pre, epi + def doEngrave(): # check parameter sanity for c in CONSTRAINTS: @@ -267,6 +294,8 @@ def doEngrave(): eprint("Refusing to generate G-code.") return + preamble, epilogue = getPreambleEpilogue() + # invert and convert to grayscale img = ~cv2.cvtColor(cv2.imread(glob_args.filename), cv2.COLOR_BGR2GRAY) @@ -287,11 +316,10 @@ def doEngrave(): img_interp = cv2.resize(img, None, fx = scale_factor, fy = scale_factor) interp_ppi = img_ppi * scale_factor - # preamble: https://www.instructables.com/id/How-to-write-G-code-basics/ print("( Generated by rastercarve: github.com/built1n/rastercarve )") print("( Image name: %s )" % (glob_args.filename)) - gcode("G00 G90 G80 G28 G17 G20 G40 G49\n") - gcode("M03") # start spindle + + gcode_multiline(preamble) d = np.array([math.cos(glob_args.line_angle * DEG2RAD), -math.sin(glob_args.line_angle * DEG2RAD)]) @@ -344,7 +372,7 @@ def doEngrave(): moveSlow(end[0], end[1], glob_args.traverse_z) moveRapid(0, 0, glob_args.traverse_z) - gcode("M05") # stop spindle + gcode_multiline(epilogue) dump_stats(orig_size, img_size, line_width, line_spacing, nlines, img_ppi, output_ppi, scale_factor, interp_ppi, pathlen, @@ -391,8 +419,17 @@ flag with caution on other machines.""") gcode_group = parser.add_argument_group('G-code parameters') + gcode_group.add_argument('--no-line-numbers', help='suppress G-code line numbers (dangerous on ShopBot!)', action='store_true', dest='suppress_linenos', default=argparse.SUPPRESS) + preamble_group = gcode_group.add_mutually_exclusive_group(required=False) + preamble_group.add_argument('--preamble', help='override the default G-code preamble; to specify multiple lines on the command line, use $\'\' strings with \\n; each line of the preamble will be prepended with a line number, except when used with --no-line-numbers', action='store', dest='preamble', default=argparse.SUPPRESS) + preamble_group.add_argument('--preamble-file', help='like --preamble, but read from a file', action='store', dest='preamble_file', default=argparse.SUPPRESS) + + epilogue_group = gcode_group.add_mutually_exclusive_group(required=False) + epilogue_group.add_argument('--epilogue', help='override the default G-code epilogue; see above notes for --preamble', action='store', dest='epilogue', default=argparse.SUPPRESS) + epilogue_group.add_argument('--epilogue-file', help='like --epilogue, but read from a file', action='store', dest='epilogue_file', default=argparse.SUPPRESS) + parser.add_argument('--json', help='dump statistics in JSON format', action='store', dest='json_dest', default=argparse.SUPPRESS) parser.add_argument('--debug', help='print debug messages', action='store_true', dest='debug', default=argparse.SUPPRESS) parser.add_argument('-q', help='disable progress and statistics', action='store_true', dest='quiet', default=argparse.SUPPRESS) |