more performant gcode visualization for raster-gcode. disabled gcode analysis of octoprint. direct call of gcode generation scripts

This commit is contained in:
Teja 2015-08-15 16:57:49 +02:00
parent 9980030a51
commit 517ea1a007
5 changed files with 231 additions and 94 deletions

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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);
}
};

View file

@ -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();