move speed calc and compensation into pre vs gcode post processing

This commit is contained in:
Stewart Allen 2017-12-13 16:04:56 -05:00
commit f3c4f647f3
5 changed files with 140 additions and 102 deletions

View file

@ -227,9 +227,8 @@ var gs_base_point = exports;
}; };
/** /**
* return a point along the line this from point to p2 * return a point along the line this from point to p2 offset
* but offset by a distance. positive distances are * by a distance. positive distances are closer to this point.
* closer to this point.
* *
* @param p2 * @param p2
* @param dist * @param dist
@ -244,6 +243,23 @@ var gs_base_point = exports;
return newPoint(p2.x - ox, p2.y - oy, p2.z, KEYS.NONE); return newPoint(p2.x - ox, p2.y - oy, p2.z, KEYS.NONE);
}; };
/**
* return a point along the line this from point to p2 offset
* by a distance. positive distances are farther from this point.
*
* @param p2
* @param dist
*/
PRO.offsetPointTo = function(p2, dist) {
var p1 = this,
dx = p2.x - p1.x,
dy = p2.y - p1.y,
ls = dist / Math.sqrt(dx * dx + dy * dy),
ox = dx * ls,
oy = dy * ls;
return newPoint(p1.x + ox, p1.y + oy, p2.z, KEYS.NONE);
};
/** /**
* @param {Point} p2 * @param {Point} p2
* @param {number} offset * @param {number} offset
@ -263,7 +279,6 @@ var gs_base_point = exports;
return BASE.newLine(np1, np2, KEYS.NONE); return BASE.newLine(np1, np2, KEYS.NONE);
}; };
/** /**
* checks if a point is inside of a polygon * checks if a point is inside of a polygon
* does not check children/holes * does not check children/holes

View file

@ -218,7 +218,9 @@ var gs_kiri_fdm = exports;
}); });
printPoint = print.poly2polyEmit(polys, printPoint, function(poly, index, count, startPoint) { printPoint = print.poly2polyEmit(polys, printPoint, function(poly, index, count, startPoint) {
return print.polyPrintPath(poly, startPoint, preout); return print.polyPrintPath(poly, startPoint, preout, {
rate: process.firstLayerSpeed * process.outputFeedrate
});
}); });
print.addPrintPoints(preout, layerout, startPoint); print.addPrintPoints(preout, layerout, startPoint);
@ -260,7 +262,6 @@ var gs_kiri_fdm = exports;
process = settings.process, process = settings.process,
fan_power = device.gcodeFan, fan_power = device.gcodeFan,
trackProgress = device.gcodeTrack, trackProgress = device.gcodeTrack,
layer1speed = process.firstLayerSpeed,
time = 0, time = 0,
layer = 0, layer = 0,
output = [], output = [],
@ -291,12 +292,7 @@ var gs_kiri_fdm = exports;
bottom: offset ? 0 : -device.bedDepth/2, bottom: offset ? 0 : -device.bedDepth/2,
z_max: device.maxHeight z_max: device.maxHeight
}, },
shortDist = process.outputShortDistance,
shortFact = process.outputShortFactor,
glideBridgeDist = device.nozzleSize * 2,
maxPrintMMM = process.outputFeedrate * 60,
seekMMM = process.outputSeekrate * 60, seekMMM = process.outputSeekrate * 60,
retOver = process.outputRetractOver,
retDist = process.outputRetractDist, retDist = process.outputRetractDist,
retSpeed = process.outputRetractSpeed * 60, retSpeed = process.outputRetractSpeed * 60,
// ratio of nozzle area to filament area times // ratio of nozzle area to filament area times
@ -304,7 +300,7 @@ var gs_kiri_fdm = exports;
emitPerMM = print.extrudePerMM(device.nozzleSize, device.filamentSize, process.sliceHeight), emitPerMM = print.extrudePerMM(device.nozzleSize, device.filamentSize, process.sliceHeight),
emitPerMMLayer1 = print.extrudePerMM(device.nozzleSize, device.filamentSize, process.sliceHeight * process.firstLayerHeight), emitPerMMLayer1 = print.extrudePerMM(device.nozzleSize, device.filamentSize, process.sliceHeight * process.firstLayerHeight),
constReplace = print.constReplace, constReplace = print.constReplace,
pidx, path, out, lastp, laste, dist, printMMM, shortMMM, pidx, path, out, speedMMM, emitMM, lastp, laste, dist,
appendAll = function(arr) { appendAll = function(arr) {
arr.forEach(function(line) { append(line) }); arr.forEach(function(line) { append(line) });
}, },
@ -402,21 +398,24 @@ var gs_kiri_fdm = exports;
}, 1); }, 1);
while (layer < layers.length) { while (layer < layers.length) {
append("; --- layer "+layer+" ---");
// second layer fan on
if (layer === 1 && fan_power) append(constReplace(fan_power,consts));
shortMMM = shortFact * maxPrintMMM;
printMMM = maxPrintMMM;
// first layer 50% underspeed
if (layer === 0) {
printMMM *= layer1speed;
shortMMM *= layer1speed;
}
path = layers[layer]; path = layers[layer];
moveTo({z:zpos}, seekMMM);
append("; --- layer "+layer+" ---");
// second layer fan on
if (layer === 1 && fan_power) {
append(constReplace(fan_power,consts));
}
// move up to next layer
if (layer > 0) moveTo({z:zpos}, seekMMM);
zpos += zinc; zpos += zinc;
// iterate through layer outputs
for (pidx=0; pidx<path.length; pidx++) { for (pidx=0; pidx<path.length; pidx++) {
out = path[pidx]; out = path[pidx];
speedMMM = (out.speed || process.outputFeedrate) * 60;
// if no point in output, it's a dwell command // if no point in output, it's a dwell command
if (!out.point) { if (!out.point) {
dwell(out.speed); dwell(out.speed);
@ -425,6 +424,7 @@ var gs_kiri_fdm = exports;
var x = out.point.x, var x = out.point.x,
y = out.point.y; y = out.point.y;
// adjust for inversions and offsets
if (process.outputInvertX) x = -x; if (process.outputInvertX) x = -x;
if (process.outputInvertY) y = -y; if (process.outputInvertY) y = -y;
if (offset) { if (offset) {
@ -433,60 +433,41 @@ var gs_kiri_fdm = exports;
} }
dist = lastp ? lastp.distTo2D(out.point) : 0; dist = lastp ? lastp.distTo2D(out.point) : 0;
distance += dist;
progress = Math.round((distance / totaldistance) * 100);
if (out.emit && retracted) { if (out.emit && retracted) {
moveTo({e:retracted}, retSpeed, "engage (ooze control)"); moveTo({e:retracted}, retSpeed, "engage (ooze control)");
retracted = 0; retracted = 0;
time += (retDist / retSpeed) * 60 * 2; // retraction time
} }
if (lastp && out.emit) { if (lastp && out.emit) {
var outMMM = printMMM, emitMM = (layer === 0 ? emitPerMMLayer1 : emitPerMM) * out.emit * dist;
emitMM = emitPerMM * out.emit * dist; moveTo({x:x, y:y, e:emitMM}, speedMMM);
if (layer === 0) {
emitMM = emitPerMMLayer1 * out.emit * dist;
} else if (out.speed && out.speed < process.outputFeedrate) {
// usually outer shell (finish speed) override
outMMM = out.speed * 60;
}
if (layer > 0 && dist < shortDist) {
outMMM = shortMMM + ((outMMM - shortMMM) * (dist / shortDist));
} else {
// approximate compensation for acceleration & deceleration
time += (shortDist * 2) / outMMM / 10 * 60;
}
// print time
time += (dist / outMMM) * 60;
moveTo({x:x, y:y, e:emitMM}, outMMM);
emitted += emitMM; emitted += emitMM;
} else { } else {
var moveMMM = seekMMM;
// usually wipe speed override
if (out.speed) {
moveMMM = out.speed * 60;
}
if (!retracted && out.retract) { if (!retracted && out.retract) {
retracted = retDist; retracted = retDist;
moveTo({e:-retracted}, retSpeed, "retract (ooze control)"); moveTo({e:-retracted}, retSpeed, "retract (ooze control)");
moveTo({x:x, y:y}, moveMMM); moveTo({x:x, y:y}, speedMMM);
} else if (lastp && dist <= glideBridgeDist) {
// connect ends of infill
var e = (layer === 0 ? emitPerMMLayer1 : emitPerMM) * dist;
moveTo({x:x, y:y, e:e}, outMMM);
} else {
moveTo({x:x, y:y}, moveMMM);
}
time += (dist / moveMMM) * 60; // seek distance
time += (retDist / retSpeed) * 60 * 2; // retraction time time += (retDist / retSpeed) * 60 * 2; // retraction time
// approximate compensation for acceleration & deceleration } else {
time += (shortDist * 2) / moveMMM / 10 * 60; moveTo({x:x, y:y}, speedMMM);
} }
lastp = out.point; }
laste = out.emit;
// update time and distance
time += (dist / speedMMM) * 60;
distance += dist;
progress = Math.round((distance / totaldistance) * 100);
// emit tracked progress // emit tracked progress
if (trackProgress && progress != lastProgress) { if (trackProgress && progress != lastProgress) {
append(constReplace(trackProgress, {progress:progress})); append(constReplace(trackProgress, {progress:progress}));
lastProgress = progress; lastProgress = progress;
} }
lastp = out.point;
laste = out.emit;
} }
layer++; layer++;
} }

View file

@ -56,7 +56,7 @@ var gs_kiri_laser = exports;
laserOut(pi, object); laserOut(pi, object);
}); });
} else { } else {
print.polyPrintPath(poly, start, object, 1); print.polyPrintPath(poly, start, object, {extrude: 1});
} }
} }

View file

@ -222,7 +222,7 @@ var gs_kiri_print = exports;
// data to speed up worker -> browser transfer // data to speed up worker -> browser transfer
newlayer.push({ newlayer.push({
emit: out.emit, emit: out.emit,
speed: out.speed, speed: out.speed * 60,
// retract: out.retract, // retract: out.retract,
point: {x: out.point.x, y: out.point.y, z: out.point.z} point: {x: out.point.x, y: out.point.y, z: out.point.z}
}); });
@ -366,7 +366,7 @@ var gs_kiri_print = exports;
* @param {Point} point * @param {Point} point
* @param {number} emit (0=move, !0=filament emit/laser on/cut mode) * @param {number} emit (0=move, !0=filament emit/laser on/cut mode)
* @param {number} [speed] speed * @param {number} [speed] speed
* @param {number} [tool] tool * @param {number} [tool] tool # or nozzle #
*/ */
function addOutput(array, point, emit, speed, tool) { function addOutput(array, point, emit, speed, tool) {
// drop duplicates (usually intruced by FDM bisections) // drop duplicates (usually intruced by FDM bisections)
@ -381,6 +381,18 @@ var gs_kiri_print = exports;
array.push(new Output(point, emit, speed, tool)); array.push(new Output(point, emit, speed, tool));
} }
function segmentOutput(output, p1, p2, s1, s2, steps, mult) {
var sd = (s2 - s1) / (steps + 1);
var dd = p1.distTo2D(p2) / steps;
var dist = dd;
var spd = s1;
while (steps-- > 0) {
spd += sd;
p1 = p1.offsetPointTo(p2, dd);
addOutput(output, p1, mult, spd);
}
}
/** /**
* FDM only. add points in polygon to an output array (print path) * FDM only. add points in polygon to an output array (print path)
* *
@ -391,27 +403,50 @@ var gs_kiri_print = exports;
* @param {Function} [onfirst] optional fn to call on first point * @param {Function} [onfirst] optional fn to call on first point
* @return {Point} last output point * @return {Point} last output point
*/ */
PRO.polyPrintPath = function(poly, startPoint, output, extrude, onfirst) { PRO.polyPrintPath = function(poly, startPoint, output, options) {
poly.setClockwise(); poly.setClockwise();
var closest = poly.findClosestPointTo(startPoint), var options = options || {},
process = this.settings.process,
shortDist = process.outputShortDistance,
shortFact = process.outputShortFactor,
shellMult = options.extrude || process.outputShellMult,
printSpeed = options.rate || process.outputFeedrate,
shortSpeed = printSpeed * shortFact,
moveSpeed = process.outputSeekrate,
closest = poly.findClosestPointTo(startPoint),
first = true, first = true,
settings = this.settings, last = startPoint;
shellMult = extrude || settings.process.outputShellMult,
shellSpeed = settings.process.outputFinishrate || 0;
poly.forEachPoint(function(point) { poly.forEachPoint(function(point, pos, points, count) {
if (first) { if (first) {
if (onfirst) onfirst(point); if (options.onfirst) options.onfirst(point);
// move from startPoint to point // move from startPoint to point
addOutput(output, point, 0, 0); addOutput(output, point, 0, moveSpeed);
first = false; first = false;
} else { } else {
addOutput(output, point, shellMult, poly.depth == 0 ? shellSpeed : 0); var dist = last.distTo2D(point);
if (options.shorten && dist > options.shorten && count === points.length) {
point = last.offsetPointFrom(point, options.shorten);
} }
if (options.accel && dist >= options.accel) {
var p2 = last.offsetPointTo(point, shortDist),
p3 = last.offsetPointFrom(point, shortDist);
segmentOutput(output, last, p2, shortSpeed, printSpeed, 5, shellMult);
addOutput(output, p3, shellMult, printSpeed);
segmentOutput(output, p3, point, printSpeed, shortSpeed, 5, shellMult);
} else
if (shortDist && dist < shortDist) {
var shortRate = shortSpeed + (printSpeed - shortSpeed) * (dist / shortDist);
addOutput(output, point, shellMult, shortRate);
} else {
addOutput(output, point, shellMult, printSpeed);
}
}
last = point;
}, true, closest.index); }, true, closest.index);
return output[output.length - 1].point; return output.last().point;
}; };
/** /**
@ -439,6 +474,9 @@ var gs_kiri_print = exports;
sparseMult = process.outputSparseMult, sparseMult = process.outputSparseMult,
wipeDistance = process.outputWipeDistance, wipeDistance = process.outputWipeDistance,
wipeSpeed = process.outputWipeSpeed || 20, wipeSpeed = process.outputWipeSpeed || 20,
firstSpeed = process.firstLayerSpeed * process.outputFeedrate,
printSpeed = slice.index === 0 ? firstSpeed : process.outputFeedrate,
moveSpeed = process.outputSeekrate,
origin = startPoint.add(offset), origin = startPoint.add(offset),
z = slice.z; z = slice.z;
@ -447,15 +485,14 @@ var gs_kiri_print = exports;
} }
function outputWipe(poly) { function outputWipe(poly) {
if (!poly) return; if (!poly || !wipeDistance) return;
var closest = poly.findClosestPointTo(startPoint), var closest = poly.findClosestPointTo(startPoint),
distance = wipeDistance, distance = wipeDistance,
last = startPoint, last = startPoint,
steps = 0; steps = 0;
if (!distance) return; retract();
while (distance > 0) poly.forEachPoint(function(point) { while (distance > 0) poly.forEachPoint(function(point) {
if (distance > 0) { if (distance > 0) {
var len = last.distTo2D(point); var len = last.distTo2D(point);
@ -467,7 +504,7 @@ var gs_kiri_print = exports;
distance -= last.distTo2D(point); distance -= last.distTo2D(point);
} }
last = point; last = point;
if (steps++ === 0) retract(); // if (steps++ === 0) retract();
} }
}, true, closest.index); }, true, closest.index);
@ -483,15 +520,22 @@ var gs_kiri_print = exports;
lastPoly = next; lastPoly = next;
}); });
} else { } else {
startPoint = scope.polyPrintPath(poly, startPoint, preout, shellMult, function(point) { var finishShell = poly.depth === 0 && slice.index > 0;
if (startPoint.distTo2D(point) > fillSkip) { startPoint = scope.polyPrintPath(poly, startPoint, preout, {
if (last) { rate: finishShell ? process.outputFinishrate : printSpeed,
outputWipe(last) accel: finishShell ? process.outputShortDistance * 2 : 0,
} else { shorten: finishShell ? nozzle / 2 : 0,
retract(); extrude: shellMult,
onfirst: function(firstPoint) {
// if (startPoint.distTo2D(firstPoint) > fillSkip) {
// if (last) {
// outputWipe(last)
// } else {
// retract();
// }
// }
checkBisect(startPoint, firstPoint, bounds);
} }
}
checkBisect(startPoint, point, bounds);
}); });
} }
} }
@ -523,7 +567,7 @@ var gs_kiri_print = exports;
// output non-printing bisecting paths // output non-printing bisecting paths
routes.forEach(function(path) { routes.forEach(function(path) {
path.forEachPoint(function(p) { path.forEachPoint(function(p) {
addOutput(preout, p, 0); addOutput(preout, p, 0, moveSpeed);
}); });
}); });
} }
@ -542,14 +586,14 @@ var gs_kiri_print = exports;
if (poly.last() === point) poly.reverse(); if (poly.last() === point) poly.reverse();
poly.forEachPoint(function(p, i) { poly.forEachPoint(function(p, i) {
if (i === 0 && lp) checkBisect(lp, p, bounds); if (i === 0 && lp) checkBisect(lp, p, bounds);
addOutput(preout, p, i === 0 ? 0 : sparseMult); addOutput(preout, p, i === 0 ? 0 : sparseMult, printSpeed);
lp = p; lp = p;
}); });
}); });
} }
function outputFills(lines, bounds) { function outputFills(lines, bounds) {
var mindist, p1, p2, dist, point, find, find2, list, len, lastout, pass = 0; var mindist, p1, p2, dist, point, find, list, len, lastout, pass = 0;
while (lines) { while (lines) {
list = []; list = [];
mindist = Infinity; mindist = Infinity;
@ -563,12 +607,6 @@ var gs_kiri_print = exports;
if (list.length > 0) { if (list.length > 0) {
list.sort(function(a,b) { return a.d - b.d }); list.sort(function(a,b) { return a.d - b.d });
find = list[0]; find = list[0];
find2 = list[4] || list[3] || list [2] || list[1];
// do 2nd closest fill lines within bigger fill areas
// if (layer === 0 && pass > 0 && find2 && lastout === 2 && len > thinWall) {//} && find2.d <= fillSkip) {
// find = find2;
// }
// order segment by closest to farthest point // order segment by closest to farthest point
if (find.i % 2 === 0) { if (find.i % 2 === 0) {
@ -591,7 +629,7 @@ var gs_kiri_print = exports;
// to avoid shaking printer to death. // to avoid shaking printer to death.
if (find.d <= thinWall && len <= thinWall) { if (find.d <= thinWall && len <= thinWall) {
p2 = p1.midPointTo(p2); p2 = p1.midPointTo(p2);
addOutput(preout, p2, fillMult * (find.d / thinWall)); addOutput(preout, p2, fillMult * (find.d / thinWall), printSpeed);
lastout = 1; lastout = 1;
} else { } else {
// check for intersection with bounds and if found // check for intersection with bounds and if found
@ -600,8 +638,14 @@ var gs_kiri_print = exports;
checkBisect(startPoint, p1, bounds); checkBisect(startPoint, p1, bounds);
} }
addOutput(preout, p1, 0); // bridge ends of fill if they're close together
addOutput(preout, p2, fillMult); if (dist < thinWall) {
addOutput(preout, p1, fillMult, printSpeed);
} else {
addOutput(preout, p1, 0, moveSpeed);
}
addOutput(preout, p2, fillMult, printSpeed);
lastout = 2; lastout = 2;
} }
@ -655,8 +699,8 @@ var gs_kiri_print = exports;
next.fills.forEach(function(p) { p.z = z }); next.fills.forEach(function(p) { p.z = z });
outputFills(next.fills, next.inner); outputFills(next.fills, next.inner);
} }
// lastTop = null;
} else { } else {
// when skipping between tops, first perform a wipe
if (lastTop && lastTop !== next && wipe) { if (lastTop && lastTop !== next && wipe) {
outputWipe(wipe); outputWipe(wipe);
wipe = null; wipe = null;
@ -668,12 +712,8 @@ var gs_kiri_print = exports;
outputSparse(next.fill_sparse, bounds); outputSparse(next.fill_sparse, bounds);
if (next.inner) { if (next.inner) {
wipe = next.inner.last(); wipe = next.inner.last();
// best to use inner offset for wipe
// outputWipe(next.inner.last());
} else { } else {
wipe = next.traces.last(); wipe = next.traces.last();
// otherwise fall back to innermost trace
// outputWipe(next.traces.last());
} }
lastTop = next; lastTop = next;
} }
@ -681,6 +721,9 @@ var gs_kiri_print = exports;
return obj instanceof Polygon ? obj : obj.poly; return obj instanceof Polygon ? obj : obj.poly;
}); });
// final wipe before lowering bed
if (wipe) outputWipe(wipe);
// offset print points // offset print points
for (i=0; i<preout.length; i++) { for (i=0; i<preout.length; i++) {
preout[i].point = preout[i].point.add(offset); preout[i].point = preout[i].point.add(offset);
@ -708,7 +751,6 @@ var gs_kiri_print = exports;
/** /**
* emit each element in an array based on * emit each element in an array based on
* the next closest endpoint. * the next closest endpoint.
* todo replace outputFills() with this
*/ */
function tip2tipEmit(array, startPoint, emitter) { function tip2tipEmit(array, startPoint, emitter) {
var mindist, dist, found, count = 0; var mindist, dist, found, count = 0;

View file

@ -1,7 +1,7 @@
var exports = { var exports = {
COPYRIGHT:"Copyright (C) 2014-2017 Stewart Allen <stewart@neuron.com> - All Rights Reserved", COPYRIGHT:"Copyright (C) 2014-2017 Stewart Allen <stewart@neuron.com> - All Rights Reserved",
LICENSE:"Unauthorized copying, modification and re-distribution are strictly prohibited without prior written consent.", LICENSE:"Unauthorized copying, modification and re-distribution are strictly prohibited without prior written consent.",
VERSION:"1.0.71" VERSION:"1.0.72"
}; };
if (!module) var module = {}; if (!module) var module = {};
module.exports = exports; module.exports = exports;