aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <franklin@rockbox.org>2020-01-31 00:28:40 -0500
committerFranklin Wei <franklin@rockbox.org>2020-01-31 00:28:40 -0500
commit2e0c87e565e5491e3a8a001e52acd553ca1948e1 (patch)
treec6d07a3bbfb0bda40a1178d81d1581f962ff024e
parent51d193e7d58e1419360a0b6ff59af9bd0e06ec00 (diff)
downloadrastercarve-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-xrastercarve/__main__.py61
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)