From 958c4b8d7f5e9da6e3c83a645b3994ddf3efb97c Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Thu, 11 Jun 2020 22:11:19 -0400 Subject: [PATCH] add max z feedrate. fix first point x,y and z moves split --- src/kiri/conf.js | 1 + src/kiri/init.js | 39 ++++++---- src/kiri/main.js | 53 +++++++------ src/mode/cam/driver.js | 165 +++++++++++++++++++++++------------------ src/mode/sla/driver.js | 11 +++ src/moto/space.js | 12 --- web/kiri/lang/en.js | 10 ++- 7 files changed, 161 insertions(+), 130 deletions(-) diff --git a/src/kiri/conf.js b/src/kiri/conf.js index 43f7385f..e65ba093 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -347,6 +347,7 @@ p:{ processName: "default", camFastFeed: 6000, + camFastFeedZ: 300, roughingTool: 1000, roughingSpindle: 1000, roughingDown: 2, diff --git a/src/kiri/init.js b/src/kiri/init.js index dae241d6..0b10630c 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -1292,9 +1292,6 @@ sliceSupportNozzle: UC.newSelect(LANG.sp_nozl_s, {title:LANG.sp_nozl_l, modes:FDM, expert:true}, "extruders"), sliceSupportEnable: UC.newBoolean(LANG.enable, onBooleanClick, {modes:FDM}), - camCommon: UC.newGroup(LANG.cc_menu, null, {modes:CAM}), - camFastFeed: UC.newInput(LANG.cc_rapd_s, {title:LANG.cc_rapd_l, convert:UC.toInt, modes:CAM}), - roughing: UC.newGroup(LANG.cr_menu, null, {modes:CAM}), roughingTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), roughingSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM}), @@ -1330,13 +1327,6 @@ drillLift: UC.newInput(LANG.cd_lift_s, {title:LANG.cd_lift_l, convert:UC.toFloat, modes:CAM}), drillingOn: UC.newBoolean(LANG.enable, onBooleanClick, {modes:CAM}), - camTabs: UC.newGroup(LANG.ct_menu, null, {modes:CAM}), - camTabsAngle: UC.newInput(LANG.ct_angl_s, {title:LANG.ct_angl_l, convert:UC.toInt, bound:UC.bound(0,360), modes:CAM}), - camTabsCount: UC.newInput(LANG.ct_numb_s, {title:LANG.ct_numb_l, convert:UC.toInt, bound:UC.bound(1,20), modes:CAM}), - camTabsWidth: UC.newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:UC.toFloat, bound:UC.bound(0.1,100), modes:CAM}), - camTabsHeight: UC.newInput(LANG.ct_hght_s, {title:LANG.ct_hght_l, convert:UC.toFloat, bound:UC.bound(0.1,100), modes:CAM}), - camTabsOn: UC.newBoolean(LANG.enable, onBooleanClick, {title:LANG.ct_nabl_l, modes:CAM}), - output: UC.newGroup(LANG.fr_menu, null, {modes:FDM}), outputRaftSpacing: UC.newInput(LANG.fr_spac_s, {title:LANG.fr_spac_l, convert:UC.toFloat, bound:UC.bound(0.0,3.0), modes:FDM}), outputRaft: UC.newBoolean(LANG.enable, onBooleanClick, {title:LANG.fr_nabl_l, modes:FDM}), @@ -1357,13 +1347,20 @@ outputFillMult: UC.newInput(LANG.ou_flml_s, {title:LANG.ou_exml_l, convert:UC.toFloat, bound:UC.bound(0.0,2.0), modes:FDM}), outputSparseMult: UC.newInput(LANG.ou_spml_s, {title:LANG.ou_exml_l, convert:UC.toFloat, bound:UC.bound(0.0,2.0), modes:FDM}), outputFanLayer: UC.newInput(LANG.ou_fanl_s, {title:LANG.ou_fanl_l, convert:UC.toInt, bound:UC.bound(0,100), modes:FDM, expert:true}), - camTolerance: UC.newInput(LANG.ou_toll_s, {title:LANG.ou_toll_l, convert:UC.toFloat, bound:UC.bound(0.001,1.0), modes:CAM}), - camZTopOffset: UC.newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:UC.toFloat, modes:CAM}), - camZBottom: UC.newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:UC.toFloat, modes:CAM}), - camZClearance: UC.newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:UC.toFloat, bound:UC.bound(0.01,100), modes:CAM}), + outputClockwise: UC.newBoolean(LANG.ou_conv_s, onBooleanClick, {title:LANG.ou_conv_l, modes:CAM}), camEaseDown: UC.newBoolean(LANG.cr_ease_s, onBooleanClick, {title:LANG.cr_ease_l, modes:CAM}), camDepthFirst: UC.newBoolean(LANG.ou_depf_s, onBooleanClick, {title:LANG.ou_depf_l, modes:CAM}), + camZTopOffset: UC.newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:UC.toFloat, modes:CAM}), + camZBottom: UC.newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:UC.toFloat, modes:CAM}), + camZClearance: UC.newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:UC.toFloat, bound:UC.bound(0.01,100), modes:CAM}), + + camTabs: UC.newGroup(LANG.ct_menu, null, {modes:CAM}), + camTabsAngle: UC.newInput(LANG.ct_angl_s, {title:LANG.ct_angl_l, convert:UC.toInt, bound:UC.bound(0,360), modes:CAM}), + camTabsCount: UC.newInput(LANG.ct_numb_s, {title:LANG.ct_numb_l, convert:UC.toInt, bound:UC.bound(1,20), modes:CAM}), + camTabsWidth: UC.newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:UC.toFloat, bound:UC.bound(0.1,100), modes:CAM}), + camTabsHeight: UC.newInput(LANG.ct_hght_s, {title:LANG.ct_hght_l, convert:UC.toFloat, bound:UC.bound(0.1,100), modes:CAM}), + camTabsOn: UC.newBoolean(LANG.enable, onBooleanClick, {title:LANG.ct_nabl_l, modes:CAM}), camStock: UC.newGroup(LANG.cs_menu, null, {modes:CAM}), camStockX: UC.newInput(LANG.cs_wdth_s, {title:LANG.cs_wdth_l, convert:UC.toFloat, bound:UC.bound(0,9999), modes:CAM}), @@ -1371,6 +1368,11 @@ camStockZ: UC.newInput(LANG.cs_hght_s, {title:LANG.cs_hght_l, convert:UC.toFloat, bound:UC.bound(0,9999), modes:CAM}), camStockOffset: UC.newBoolean(LANG.cs_offs_s, onBooleanClick, {title:LANG.cs_offs_l, modes:CAM}), + camCommon: UC.newGroup(LANG.cc_menu, null, {modes:CAM}), + camFastFeedZ: UC.newInput(LANG.cc_rzpd_s, {title:LANG.cc_rzpd_l, convert:UC.toInt, modes:CAM}), + camFastFeed: UC.newInput(LANG.cc_rapd_s, {title:LANG.cc_rapd_l, convert:UC.toInt, modes:CAM}), + camTolerance: UC.newInput(LANG.ou_toll_s, {title:LANG.ou_toll_l, convert:UC.toFloat, bound:UC.bound(0.001,1.0), modes:CAM}), + outputOriginBounds: UC.newBoolean(LANG.or_bnds_s, onBooleanClick, {title:LANG.or_bnds_l, modes:LASER}), outputOriginCenter: UC.newBoolean(LANG.or_cntr_s, onBooleanClick, {title:LANG.or_cntr_l, modes:CAM_LASER}), camOriginTop: UC.newBoolean(LANG.or_topp_s, onBooleanClick, {title:LANG.or_topp_l, modes:CAM}), @@ -1732,6 +1734,15 @@ function init_two() { API.event.emit('init.two'); + // call driver initializations, if present + Object.values(KIRI.driver).forEach(driver => { + if (driver.init) try { + driver.init(KIRI, API); + } catch (error) { + console.log({driver_init_fail: driver, error}) + } + }); + let current = settings(), control = current.controller; diff --git a/src/kiri/main.js b/src/kiri/main.js index 0b9aceea..1da6e39a 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -41,6 +41,7 @@ UI = {}, UC = KIRI.ui.prefix('kiri').inputAction(updateSettings).hideAction(updateDialogLeft), MODE = MODES.FDM, + DRIVER = undefined, onEvent = {}, currentPrint = null, selectedMeshes = [], @@ -797,7 +798,7 @@ widget.slice(settings, function(sliced, error) { let mark = UTIL.time(); // on done - widget.render(renderMode, MODE === MODES.CAM); + widget.render(); // clear wireframe widget.setWireframe(false, color.wireframe, color.wireframe_opacity); widget.setOpacity(settings.mode === 'CAM' ? color.cam_sliced_opacity : color.sliced_opacity); @@ -1922,32 +1923,13 @@ DBUG.log("invalid mode: "+mode); mode = 'FDM'; } - $('app-mode-name').innerHTML = mode; - $('set-tools').style.display = mode === 'CAM' ? '' : 'none'; + // change mode constants settings.mode = mode; MODE = MODES[mode]; - // restore cached device profile for this mode - if (settings.cdev[mode]) { - settings.device = clone(settings.cdev[mode]); - API.event.emit('device.set', currentDeviceName()); - } - if (MODE === MODES.CAM) { - SPACE.platform.setColor(0xeeeeee); - } else { - SPACE.platform.setColor(0xcccccc); - } - if (MODE === MODES.SLA) { - UI.act.preview.classList.add('hide'); - } else { - UI.act.preview.classList.remove('hide'); - } - // updates right-hand menu by enabling/disabling fields - setViewMode(VIEWS.ARRANGE); - UC.setMode(MODE); - API.conf.load(); - API.conf.save(); - clearWidgetCache(); - SPACE.update(); + DRIVER = KIRI.driver[mode]; + // update mode display + $('app-mode-name').innerHTML = mode; + // highlight relevant device mode button ["fdm","sla","cam","laser"].forEach(dev => { let cl = $(`mode-${dev}`).classList; if (dev === mode.toLowerCase()) { @@ -1956,18 +1938,35 @@ cl.remove("dev-sel"); } }); + // restore cached device profile for this mode + if (settings.cdev[mode]) { + settings.device = clone(settings.cdev[mode]); + API.event.emit('device.set', currentDeviceName()); + } + // really belongs in CAM driver (lots of work / abstraction needed) if (camStock) { camStock.material.visible = settings.mode === 'CAM'; } - API.space.restore(null, true); - if (then) then(); + // updates right-hand menu by enabling/disabling fields + setViewMode(VIEWS.ARRANGE); + UC.setMode(MODE); + // sanitize and persist settings + API.conf.load(); + API.conf.save(); + // other housekeeping + clearWidgetCache(); triggerSettingsEvent(); platformUpdateSelected(); updateFields(); + // because device dialog, if showing, needs to be updated if (modalShowing()) { API.show.devices(); } + API.space.restore(null, true); API.event.emit("mode.set", mode); + if (then) { + then(); + } } function currentDeviceName() { diff --git a/src/mode/cam/driver.js b/src/mode/cam/driver.js index b430a84a..830f5436 100644 --- a/src/mode/cam/driver.js +++ b/src/mode/cam/driver.js @@ -12,6 +12,7 @@ UTIL = BASE.util, POLY = BASE.polygons, CAM = KIRI.driver.CAM = { + init, slice, sliceRender, printSetup, @@ -47,6 +48,14 @@ newPolygon = BASE.newPolygon, time = UTIL.time; + function init(kiri, api) { + api.event.on("mode.set", (mode) => { + let isCAM = mode === 'CAM'; + $('set-tools').style.display = isCAM ? '' : 'none'; + kiri.space.platform.setColor(isCAM ? 0xeeeeee : 0xcccccc); + }); + } + function getToolById(settings, id) { for (let i=0, t=settings.tools; i toolDiam || (deltaZ > toolDiam && deltaXY > tolerance)) && (isMove || absDeltaZ >= tolerance)) { - let maxz = toolProfile ? MAX( - getTopoZPathMax( - widget, - toolProfile, - lastPoint.x - wmx, - lastPoint.y - wmy, - point.x - wmx, - point.y - wmy) + zadd, - point.z, - lastPoint.z) : zmax, - mustGoUp = MAX(maxz - point.z, maxz - lastPoint.z) >= tolerance, - clearz = maxz; - // up if any point between higher than start/finish - if (mustGoUp) { - clearz = maxz + zclear; - layerPush(lastPoint.clone().setZ(clearz), 0, 0, tool.number); - } - // over to point above where we descend to - if (mustGoUp || point.z < maxz) { - layerPush(point.clone().setZ(clearz), 0, 0, tool.number); - // new pos for plunge calc - deltaXY = 0; - } - } - // synth new plunge rate - if (deltaZ <= -tolerance) { - let threshold = MIN(deltaXY / 2, absDeltaZ), - modifier = threshold / absDeltaZ; - if (threshold && modifier && deltaXY > tolerance) { - // use modifier to speed up long XY move plunge rates - rate = Math.round(plungeRate + ((feedRate - plungeRate) * modifier)); - } else { - rate = plungeRate; - } - // console.log({deltaZ: deltaZ, deltaXY: deltaXY, threshold:threshold, modifier:modifier, rate:rate, plungeRate:plungeRate}); - } - } else { - // before first point, move cutting head to point above it - layerPush(point.clone().setZ(zmax), 0, 0, tool.number); + let deltaXY = lastPoint.distTo2D(point), + deltaZ = point.z - lastPoint.z, + absDeltaZ = Math.abs(deltaZ), + isMove = !cut; + // drop points too close together + if (deltaXY < 0.001 && point.z === lastPoint.z) { + console.trace(["drop dup",lastPoint,point]); + return; } + if (isMove && deltaXY <= toolDiamMove) { + // convert short planar moves to cuts + if (absDeltaZ <= tolerance) { + cut = 1; + isMove = false; + } else if (deltaZ <= -tolerance) { + // move over before descending + layerPush(point.clone().setZ(lastPoint.z), 0, 0, tool.number); + // new pos for plunge calc + deltaXY = 0; + } + } //else (TODO verify no else here b/c above could change isMove) + // move over things + if ((deltaXY > toolDiam || (deltaZ > toolDiam && deltaXY > tolerance)) && (isMove || absDeltaZ >= tolerance)) { + let maxz = toolProfile ? MAX( + getTopoZPathMax( + widget, + toolProfile, + lastPoint.x - wmx, + lastPoint.y - wmy, + point.x - wmx, + point.y - wmy) + zadd, + point.z, + lastPoint.z) : zmax, + mustGoUp = MAX(maxz - point.z, maxz - lastPoint.z) >= tolerance, + clearz = maxz; + // up if any point between higher than start/finish + if (mustGoUp) { + clearz = maxz + zclear; + layerPush(lastPoint.clone().setZ(clearz), 0, 0, tool.number); + } + // over to point above where we descend to + if (mustGoUp || point.z < maxz) { + layerPush(point.clone().setZ(clearz), 0, 0, tool.number); + // new pos for plunge calc + deltaXY = 0; + } + } + // synth new plunge rate + if (deltaZ <= -tolerance) { + let threshold = MIN(deltaXY / 2, absDeltaZ), + modifier = threshold / absDeltaZ; + if (threshold && modifier && deltaXY > tolerance) { + // use modifier to speed up long XY move plunge rates + rate = Math.round(plungeRate + ((feedRate - plungeRate) * modifier)); + } else { + rate = plungeRate; + } + // console.log({deltaZ: deltaZ, deltaXY: deltaXY, threshold:threshold, modifier:modifier, rate:rate, plungeRate:plungeRate}); + } + // todo synthesize move speed from feed / plunge accordingly layerPush( point, @@ -1779,12 +1785,6 @@ function moveTo(out) { let newpos = out.point; - // first point out sets the current position (but not Z) - if (points === 0) { - pos.x = newpos.x; - pos.y = newpos.y; - } - // no point == dwell // out.speed = time to dwell in ms if (!newpos) { @@ -1808,13 +1808,32 @@ filterEmit(cmdToolChange, consts); } + // first point out sets the current position (but not Z) + // hacky AF way to split initial x,y,z into z then x,y + if (points === 0) { + pos.x = pos.y = pos.z = 0; + points++; + moveTo({ + tool: out.tool, + point: { x: 0, y: 0, z: newpos.z }, + speed: spro.camFastFeedZ + }); + moveTo({ + tool: out.tool, + point: { x: newpos.x, y: newpos.y, z: newpos.z }, + speed: spro.camFastFeed + }); + points--; + return; + } + let speed = out.speed, - feed = speed || spro.camFastFeed, nl = [speed ? 'G1' : 'G0'], dx = newpos.x - pos.x, dy = newpos.y - pos.y, dz = newpos.z - pos.z, - dist = Math.sqrt(dx * dx + dy * dy + dz * dz); + dist = Math.sqrt(dx * dx + dy * dy + dz * dz), + feed = Math.min(speed || spro.camFastFeed, dz ? spro.camFastFeedZ : spro.camFastFeed); // drop dup points (all deltas are 0) if (!(dx || dy || dz)) { diff --git a/src/mode/sla/driver.js b/src/mode/sla/driver.js index 3b14c0f1..c06ef9a1 100644 --- a/src/mode/sla/driver.js +++ b/src/mode/sla/driver.js @@ -14,6 +14,7 @@ CONF = BASE.config, POLY = BASE.polygons, SLA = KIRI.driver.SLA = { + init, slice, sliceRender, printSetup, @@ -35,6 +36,16 @@ if (legacy) console.log("SLA Driver in Legacy Mode"); + function init(kiri, api) { + api.event.on("mode.set", (mode) => { + if (mode === 'SLA') { + api.ui.act.preview.classList.add('hide'); + } else { + api.ui.act.preview.classList.remove('hide'); + } + }); + } + /** * DRIVER SLICE CONTRACT - runs in worker * diff --git a/src/moto/space.js b/src/moto/space.js index f9529156..f6de9a90 100644 --- a/src/moto/space.js +++ b/src/moto/space.js @@ -391,18 +391,6 @@ case cca('t'): Space.view.top(); break; - // case cca('f'): - // Space.view.front(); - // break; - // case cca('l'): - // Space.view.left(); - // break; - // case cca('r'): - // Space.view.right(); - // break; - // case cca('b'): - // Space.view.back(); - // break; default: handled = false; break; diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index 126d5185..2b1376b6 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -243,9 +243,11 @@ kiri.lang['en-us'] = { cc_pock_l: "constrain cuts to\npart boundaries", // CNC COMMON - cc_menu: "common", - cc_rapd_s: "rapid feed", - cc_rapd_l: "rapid moves feedrate\nin workspace units / minute", + cc_menu: "limits", + cc_rapd_s: "xy feed", + cc_rapd_l: "max xy moves feedrate\nin workspace units / minute", + cc_rzpd_s: "z feed", + cc_rzpd_l: "max z moves feedrate\nin workspace units / minute", // CNC ROUGHING cr_menu: "roughing", @@ -333,7 +335,7 @@ kiri.lang['en-us'] = { // OUTPUT CAM ou_toll_s: "tolerance", - ou_toll_l: "surface precision\nin workspace units", + ou_toll_l: "surface precision\nin workspace units\nlower is slower and\nuses more memory", ou_ztof_s: "z top offset", ou_ztof_l: "offset from stock surface\nto top face of part\nin workspace units", ou_zbot_s: "z bottom",