more performant gcode visualization for raster-gcode. disabled gcode analysis of octoprint. direct call of gcode generation scripts
This commit is contained in:
parent
9980030a51
commit
517ea1a007
5 changed files with 231 additions and 94 deletions
|
|
@ -186,6 +186,10 @@ class AbstractAnalysisQueue(object):
|
|||
time.sleep(1.0)
|
||||
|
||||
def _analyze(self, entry, high_priority=False):
|
||||
if(True):
|
||||
self._logger.warn("Avoiding analysis of {entry}".format(**locals()))
|
||||
return
|
||||
|
||||
path = entry.absolute_path
|
||||
if path is None or not os.path.exists(path):
|
||||
return
|
||||
|
|
|
|||
|
|
@ -345,99 +345,162 @@ class SvgToGcodePlugin(octoprint.plugin.SlicerPlugin,
|
|||
path, _ = os.path.splitext(model_path)
|
||||
machinecode_path = path + ".gco"
|
||||
|
||||
if on_progress:
|
||||
if not on_progress_args:
|
||||
if on_progress is not None:
|
||||
if on_progress_args is None:
|
||||
on_progress_args = ()
|
||||
if not on_progress_kwargs:
|
||||
if on_progress_kwargs is None:
|
||||
on_progress_kwargs = dict()
|
||||
|
||||
#on_progress_kwargs["_progress"] = your_plugins_slicing_progress
|
||||
#on_progress(*on_progress_args, **on_progress_kwargs)
|
||||
self._svgtogcode_logger.info("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path))
|
||||
|
||||
engine_settings = self._convert_to_engine(profile_path)
|
||||
direct_call = True
|
||||
if(direct_call):
|
||||
## direct call
|
||||
from os.path import expanduser
|
||||
homedir = expanduser("~")
|
||||
converter_path = homedir+"/mrbeam-inkscape-ext"
|
||||
|
||||
hostname = socket.gethostname()
|
||||
if("Bucanero" in hostname):
|
||||
converter_path = '/home/teja/workspace/mrbeam-inkscape-ext'
|
||||
|
||||
from os.path import expanduser
|
||||
homedir = expanduser("~")
|
||||
executable = homedir + "/mrbeam-inkscape-ext/mrbeam.py"
|
||||
log_path = homedir + "/.octoprint/logs/svgtogcode.log"
|
||||
log_enabled = s.get(["debug_logging"])
|
||||
|
||||
# debugging stuff. TODO remove
|
||||
hostname = socket.gethostname()
|
||||
if("Bucanero" in hostname):
|
||||
executable = homedir + "/workspace/mrbeam-inkscape-ext/mrbeam.py"
|
||||
|
||||
# executable = s.get(["svgtogcode_engine"])
|
||||
|
||||
if not executable:
|
||||
return False, "Path to SVG converter is not configured "
|
||||
|
||||
dest_dir, dest_file = os.path.split(machinecode_path)
|
||||
working_dir, _ = os.path.split(executable)
|
||||
args = ['python "%s"' % executable, '-f "%s"' % dest_file, '-d "%s"' % dest_dir]
|
||||
args += ['--no-header=True']
|
||||
for k, v in engine_settings.items():
|
||||
args += ['"%s=%s"' % (k, str(v))]
|
||||
fill_enabled = False # disabled as highly experimental
|
||||
args += ['--fill-areas=%s' % fill_enabled]
|
||||
args += ['--create-log=%s' % log_enabled, '"--log-filename=%s"' % log_path,'"%s"' % model_path]
|
||||
|
||||
#python ~/mrbeam-inkscape-ext/standalone.py -f output.gcode -d output/path --engraving-laser-speed=300
|
||||
# --laser-intensity=1000 --create-log=false path/to/input.svg
|
||||
|
||||
import sarge
|
||||
command = " ".join(args)
|
||||
self._logger.info("Running %r in %s" % (command, working_dir))
|
||||
try:
|
||||
p = sarge.run(command, cwd=working_dir, async=True, stdout=sarge.Capture(), stderr=sarge.Capture())
|
||||
p.wait_events()
|
||||
try:
|
||||
with self._slicing_commands_mutex:
|
||||
self._slicing_commands[machinecode_path] = p.commands[0]
|
||||
|
||||
line_seen = False
|
||||
while p.returncode is None:
|
||||
line = p.stdout.readline(timeout=0.5)
|
||||
if not line:
|
||||
if line_seen:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
line_seen = True
|
||||
self._svgtogcode_logger.debug(line.strip())
|
||||
|
||||
if on_progress is not None:
|
||||
pass
|
||||
finally:
|
||||
p.close()
|
||||
|
||||
with self._cancelled_jobs_mutex:
|
||||
if machinecode_path in self._cancelled_jobs:
|
||||
self._svgtogcode_logger.info("### Cancelled")
|
||||
raise octoprint.slicing.SlicingCancelled()
|
||||
|
||||
self._svgtogcode_logger.info("### Finished, returncode %d" % p.returncode)
|
||||
if p.returncode == 0:
|
||||
return True, None
|
||||
import sys
|
||||
sys.path.append(converter_path)
|
||||
from mrbeam import Laserengraver
|
||||
|
||||
profile = Profile(self._load_profile(profile_path))
|
||||
params = profile.convert_to_engine2()
|
||||
|
||||
dest_dir, dest_file = os.path.split(machinecode_path)
|
||||
params['directory'] = dest_dir
|
||||
params['file'] = dest_file
|
||||
params['noheaders'] = "true" # TODO... booleanify
|
||||
|
||||
params['fill_areas'] = False # disabled as highly experimental
|
||||
if(s.get(["debug_logging"])):
|
||||
log_path = homedir + "/.octoprint/logs/svgtogcode.log"
|
||||
params['log_filename'] = log_path
|
||||
else:
|
||||
self._logger.warn("Could not slice, got return code %r" % p.returncode)
|
||||
return False, "Got returncode %r" % p.returncode
|
||||
params['log_filename'] = ''
|
||||
|
||||
except octoprint.slicing.SlicingCancelled as e:
|
||||
raise e
|
||||
except:
|
||||
self._logger.exception("Could not slice, got an unknown error")
|
||||
return False, "Unknown error, please consult the log file"
|
||||
|
||||
print("### params ", params)
|
||||
try:
|
||||
engine = Laserengraver(params, model_path)
|
||||
engine.affect()
|
||||
|
||||
self._svgtogcode_logger.info("### Conversion finished")
|
||||
return True, None # TODO add analysis about out of working area, ignored elements, invisible elements, text elements
|
||||
except octoprint.slicing.SlicingCancelled as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
print e.__doc__
|
||||
print e.message
|
||||
self._logger.exception("Conversion error ({0}): {1}".format(e.__doc__, e.message))
|
||||
return False, "Unknown error, please consult the log file"
|
||||
|
||||
finally:
|
||||
with self._cancelled_jobs_mutex:
|
||||
if machinecode_path in self._cancelled_jobs:
|
||||
self._cancelled_jobs.remove(machinecode_path)
|
||||
with self._slicing_commands_mutex:
|
||||
if machinecode_path in self._slicing_commands:
|
||||
del self._slicing_commands[machinecode_path]
|
||||
|
||||
finally:
|
||||
with self._cancelled_jobs_mutex:
|
||||
if machinecode_path in self._cancelled_jobs:
|
||||
self._cancelled_jobs.remove(machinecode_path)
|
||||
with self._slicing_commands_mutex:
|
||||
if machinecode_path in self._slicing_commands:
|
||||
del self._slicing_commands[machinecode_path]
|
||||
self._svgtogcode_logger.info("-" * 40)
|
||||
|
||||
self._svgtogcode_logger.info("-" * 40)
|
||||
else:
|
||||
## shell call
|
||||
engine_settings = self._convert_to_engine(profile_path)
|
||||
|
||||
from os.path import expanduser
|
||||
homedir = expanduser("~")
|
||||
executable = homedir + "/mrbeam-inkscape-ext/mrbeam.py"
|
||||
log_path = homedir + "/.octoprint/logs/svgtogcode.log"
|
||||
log_enabled = s.get(["debug_logging"])
|
||||
|
||||
# debugging stuff. TODO remove
|
||||
hostname = socket.gethostname()
|
||||
if("Bucanero" in hostname):
|
||||
executable = homedir + "/workspace/mrbeam-inkscape-ext/mrbeam.py"
|
||||
|
||||
# executable = s.get(["svgtogcode_engine"])
|
||||
|
||||
if not executable:
|
||||
return False, "Path to SVG converter is not configured "
|
||||
|
||||
dest_dir, dest_file = os.path.split(machinecode_path)
|
||||
working_dir, _ = os.path.split(executable)
|
||||
args = ['python "%s"' % executable, '-f "%s"' % dest_file, '-d "%s"' % dest_dir]
|
||||
args += ['--no-header=True']
|
||||
for k, v in engine_settings.items():
|
||||
args += ['"%s=%s"' % (k, str(v))]
|
||||
fill_enabled = False # disabled as highly experimental
|
||||
if(fill_enabled):
|
||||
args += ['--fill-areas']
|
||||
if(log_enabled):
|
||||
args += ['"--log-filename=%s"' % log_path]
|
||||
args += ['"%s"' % model_path]
|
||||
|
||||
|
||||
import sarge
|
||||
command = " ".join(args)
|
||||
self._logger.info("Running %r" % (command))
|
||||
try:
|
||||
p = sarge.run(command, cwd=working_dir, async=True, stdout=sarge.Capture(), stderr=sarge.Capture())
|
||||
p.wait_events()
|
||||
try:
|
||||
with self._slicing_commands_mutex:
|
||||
self._slicing_commands[machinecode_path] = p.commands[0]
|
||||
|
||||
line_seen = False
|
||||
while p.returncode is None:
|
||||
line = p.stdout.readline(timeout=0.5)
|
||||
if not line:
|
||||
if line_seen:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
line_seen = True
|
||||
self._svgtogcode_logger.debug(line.strip())
|
||||
|
||||
if on_progress is not None:
|
||||
pass
|
||||
finally:
|
||||
p.close()
|
||||
|
||||
with self._cancelled_jobs_mutex:
|
||||
if machinecode_path in self._cancelled_jobs:
|
||||
self._svgtogcode_logger.info("### Cancelled")
|
||||
raise octoprint.slicing.SlicingCancelled()
|
||||
|
||||
|
||||
self._svgtogcode_logger.info("### Finished, returncode %d" % p.returncode)
|
||||
if p.returncode == 0:
|
||||
return True, None
|
||||
else:
|
||||
self._logger.warn("Could not slice, got return code %r" % p.returncode)
|
||||
return False, "Got returncode %r" % p.returncode
|
||||
|
||||
except octoprint.slicing.SlicingCancelled as e:
|
||||
raise e
|
||||
except:
|
||||
self._logger.exception("Could not slice, got an unknown error")
|
||||
return False, "Unknown error, please consult the log file"
|
||||
|
||||
finally:
|
||||
with self._cancelled_jobs_mutex:
|
||||
if machinecode_path in self._cancelled_jobs:
|
||||
self._cancelled_jobs.remove(machinecode_path)
|
||||
with self._slicing_commands_mutex:
|
||||
if machinecode_path in self._slicing_commands:
|
||||
del self._slicing_commands[machinecode_path]
|
||||
|
||||
self._svgtogcode_logger.info("-" * 40)
|
||||
# end if False
|
||||
|
||||
def cancel_slicing(self, machinecode_path):
|
||||
with self._slicing_commands_mutex:
|
||||
|
|
|
|||
|
|
@ -13,14 +13,24 @@ import re
|
|||
|
||||
|
||||
defaults = dict(
|
||||
# general settings
|
||||
svgDPI = 90,
|
||||
pierce_time = 0,
|
||||
|
||||
# vector settings
|
||||
speed = 300,
|
||||
intensity = 500,
|
||||
fill_areas = False,
|
||||
cross_fill = False,
|
||||
fill_angle = 0,
|
||||
fill_spacing = 0.25,
|
||||
|
||||
# pixel settings
|
||||
beam_diameter = 0.25,
|
||||
intensity_white = 0,
|
||||
intensity_black = 500,
|
||||
feedrate_white = 1500,
|
||||
feedrate_black = 250,
|
||||
pierce_time = 0,
|
||||
img_contrast = 1.0,
|
||||
img_sharpening = 1.0,
|
||||
img_dithering = False
|
||||
|
|
@ -241,3 +251,27 @@ class Profile(object):
|
|||
}
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def convert_to_engine2(self):
|
||||
|
||||
settings = {
|
||||
"engraving_laser_speed": self.get_int("speed"),
|
||||
"laser_intensity": self.get_int("intensity"),
|
||||
"beam_diameter" : self.get_float("beam_diameter"),
|
||||
"intensity_white" : self.get_int("intensity_white"),
|
||||
"intensity_black" : self.get_int("intensity_black"),
|
||||
"speed_white" : self.get_int("feedrate_white"),
|
||||
"speed_black" : self.get_int("feedrate_black"),
|
||||
"pierce_time" : self.get_float("pierce_time"),
|
||||
"contrast": self.get_float("img_contrast"),
|
||||
"sharpening": self.get_float("img_sharpening"),
|
||||
"dithering": self.get_boolean("img_dithering"),
|
||||
"fill_areas": self.get_boolean("fill_areas"),
|
||||
"cross_fill": self.get_boolean("cross_fill"),
|
||||
"fill_angle": self.get_float("fill_angle"),
|
||||
"fill_spacing": self.get_float("fill_spacing"),
|
||||
"svgDPI": self.get_float("svgDPI")
|
||||
}
|
||||
|
||||
return settings
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ $(function() {
|
|||
|
||||
self.toolOffsets = [{x: 0, y: 0}];
|
||||
|
||||
self.parse = function(gcode, blockDelimiter, blockCallback ) {
|
||||
self.parse = function(gcode, pathDelimiter, pathCallback, imgCallback ) {
|
||||
var argChar, numSlice;
|
||||
|
||||
var x, y, z, pi, pj, pp = 0;
|
||||
|
|
@ -14,6 +14,7 @@ $(function() {
|
|||
var f, lastF = 4000;
|
||||
var extrude = false, extrudeRelative = false, retract = 0;
|
||||
var positionRelative = false;
|
||||
var withinPixelCode = false;
|
||||
|
||||
var dcExtrude = false;
|
||||
var assumeNonDC = false;
|
||||
|
|
@ -27,6 +28,29 @@ $(function() {
|
|||
|
||||
var model = [];
|
||||
for (var i = 0; i < gcode_lines.length; i++) {
|
||||
var l = gcode_lines[i];
|
||||
if(l.startsWith(';Image')) {
|
||||
withinPixelCode = true;
|
||||
// ;Image: 24.71x18.58 @ 2.59,1.70
|
||||
var re = /;Image: ([-+]?[0-9]*\.?[0-9]+)x([-+]?[0-9]*\.?[0-9]+) @ ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)/;
|
||||
var match = l.match(re);
|
||||
if(match){
|
||||
var w = parseFloat(match[1]);
|
||||
var h = parseFloat(match[2]);
|
||||
var x = parseFloat(match[3]);
|
||||
var y = parseFloat(match[4]);
|
||||
if(typeof imgCallback === 'function'){
|
||||
imgCallback(x,y,w,h);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(l.startsWith(';EndImage')) withinPixelCode = false;
|
||||
|
||||
if(withinPixelCode){
|
||||
continue;
|
||||
}
|
||||
var line = l.split(/[\(;]/)[0];
|
||||
|
||||
x = undefined;
|
||||
y = undefined;
|
||||
z = undefined;
|
||||
|
|
@ -37,7 +61,6 @@ $(function() {
|
|||
retract = 0;
|
||||
|
||||
extrude = false;
|
||||
var line = gcode_lines[i].split(/[\(;]/)[0];
|
||||
|
||||
var addToModel = false;
|
||||
var convertAndAddToModel = false;
|
||||
|
|
@ -402,15 +425,15 @@ $(function() {
|
|||
prevY = y;
|
||||
}
|
||||
|
||||
if (typeof (blockCallback) === 'function' && typeof (blockDelimiter) !== 'undefined' && blockDelimiter.test(line)) {
|
||||
blockCallback(model);
|
||||
if (typeof (pathCallback) === 'function' && typeof (pathDelimiter) !== 'undefined' && pathDelimiter.test(line)) {
|
||||
pathCallback(model);
|
||||
model = model.slice(-1); // keep the last element as start of the next block
|
||||
}
|
||||
}
|
||||
|
||||
prevZ = z;
|
||||
if (typeof (blockCallback) === 'function' && model.length > 0) {
|
||||
blockCallback(model);
|
||||
if (typeof (pathCallback) === 'function' && model.length > 0) {
|
||||
pathCallback(model);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -165,18 +165,22 @@ $(function(){
|
|||
}
|
||||
|
||||
self.loadGcode(file, function(gcode){
|
||||
self.parser.parse(gcode, /(m0?3)|(m0?5)/i, function(block){
|
||||
var pathCallback = function(path){
|
||||
var points = [];
|
||||
var intensity = -1;
|
||||
for (var idx = 0; idx < block.length; idx++) {
|
||||
var item = block[idx];
|
||||
for (var idx = 0; idx < path.length; idx++) {
|
||||
var item = path[idx];
|
||||
points.push( [ item.x, item.y ] );
|
||||
intensity = item.laser;
|
||||
}
|
||||
if(points.length > 0)
|
||||
self.draw_gcode(points, intensity, '#'+previewId);
|
||||
|
||||
});
|
||||
};
|
||||
var imgCallback = function(x,y,w,h){
|
||||
self.draw_gcode_img_placeholder(x,y,w,h, '#'+previewId)
|
||||
};
|
||||
self.parser.parse(gcode, /(m0?3)|(m0?5)/i, pathCallback, imgCallback);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -668,6 +672,15 @@ $(function(){
|
|||
});
|
||||
snap.select(target).append(p);
|
||||
};
|
||||
|
||||
self.draw_gcode_img_placeholder = function(x,y,w,h, target){
|
||||
var i = snap.rect(x,y,w,h).attr({
|
||||
fill: '#AAAAFF',
|
||||
stroke: 'none'
|
||||
});
|
||||
snap.select(target).append(i);
|
||||
};
|
||||
|
||||
self.clear_gcode = function(){
|
||||
// console.log("gcodeprev clear");
|
||||
snap.select('#gCodePreview').clear();
|
||||
|
|
|
|||
Loading…
Reference in a new issue