Created
September 27, 2016 16:51
-
-
Save cho45/977213c3102473f2f4506d4a41ba3ab6 to your computer and use it in GitHub Desktop.
Fusion 360 Custom Post Process Script supporting G64 P (tolerance option) for Machinekit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Modifled by cho45 for tolerance support | |
* | |
* | |
Original Copyright: | |
Copyright (C) 2012-2015 by Autodesk, Inc. | |
All rights reserved. | |
LinuxCNC (EMC2) post processor configuration. | |
$Revision: 40905 28dacbe71fc245b31883a3943cf68035f5817953 $ | |
$Date: 2015-12-15 11:50:07 $ | |
FORKID {52A5C3D6-1533-413E-B493-7B93D9E48B30} | |
*/ | |
description = "Machinekit"; | |
vendor = "http://www.machinekit.io/"; | |
vendorUrl = "http://www.machinekit.io/"; | |
legal = "Copyright (C) 2012-2015 by Autodesk, Inc."; | |
certificationLevel = 2; | |
minimumRevision = 24000; | |
extension = "ngc"; | |
setCodePage("ascii"); | |
capabilities = CAPABILITY_MILLING; | |
tolerance = spatial(0.002, MM); | |
minimumChordLength = spatial(0.01, MM); | |
minimumCircularRadius = spatial(0.01, MM); | |
maximumCircularRadius = spatial(1000, MM); | |
minimumCircularSweep = toRad(0.01); | |
maximumCircularSweep = toRad(180); | |
allowHelicalMoves = true; | |
allowedCircularPlanes = undefined; // allow any circular motion | |
// user-defined properties | |
properties = { | |
writeMachine: true, // write machine | |
writeTools: true, // writes the tools | |
preloadTool: true, // preloads next tool on tool change if any | |
showSequenceNumbers: false, // show sequence numbers | |
sequenceNumberStart: 10, // first sequence number | |
sequenceNumberIncrement: 5, // increment for sequence numbers | |
optionalStop: true, // optional stop | |
separateWordsWithSpace: true, // specifies that the words should be separated with a white space | |
useRadius: false, // specifies that arcs should be output using the radius (R word) instead of the I, J, and K words | |
useParametricFeed: false, // specifies that feed should be output using Q values | |
showNotes: false, // specifies that operation notes should be output | |
useG28: false // turn on to use G28 instead of G53 for machine retracts | |
}; | |
var permittedCommentChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,=_-"; | |
var mapCoolantTable = new Table( | |
[9, 8, 7], | |
{initial:COOLANT_OFF, force:true}, | |
"Invalid coolant mode" | |
); | |
var gFormat = createFormat({prefix:"G", decimals:1}); | |
var mFormat = createFormat({prefix:"M", decimals:1}); | |
var hFormat = createFormat({prefix:"H", decimals:1}); | |
var dFormat = createFormat({prefix:"D", decimals:1}); | |
var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); | |
var rFormat = xyzFormat; // radius | |
var abcFormat = createFormat({decimals:3, forceDecimal:true, scale:DEG}); | |
var feedFormat = createFormat({decimals:(unit == MM ? 2 : 3), forceDecimal:true}); | |
var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); | |
var toolFormat = createFormat({decimals:0}); | |
var rpmFormat = createFormat({decimals:0}); | |
var secFormat = createFormat({decimals:3, forceDecimal:true}); // seconds - range 0.001-99999.999 | |
var taperFormat = createFormat({decimals:1, scale:DEG}); | |
var xOutput = createVariable({prefix:"X"}, xyzFormat); | |
var yOutput = createVariable({prefix:"Y"}, xyzFormat); | |
var zOutput = createVariable({prefix:"Z"}, xyzFormat); | |
var aOutput = createVariable({prefix:"A"}, abcFormat); | |
var bOutput = createVariable({prefix:"B"}, abcFormat); | |
var cOutput = createVariable({prefix:"C"}, abcFormat); | |
var feedOutput = createVariable({prefix:"F"}, feedFormat); | |
var sOutput = createVariable({prefix:"S", force:true}, rpmFormat); | |
var dOutput = createVariable({}, dFormat); | |
// circular output | |
var iOutput = createReferenceVariable({prefix:"I", force:true}, xyzFormat); | |
var jOutput = createReferenceVariable({prefix:"J", force:true}, xyzFormat); | |
var kOutput = createReferenceVariable({prefix:"K", force:true}, xyzFormat); | |
var gMotionModal = createModal({}, gFormat); // modal group 1 // G0-G3, ... | |
var gPlaneModal = createModal({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 | |
var gAbsIncModal = createModal({}, gFormat); // modal group 3 // G90-91 | |
var gFeedModeModal = createModal({}, gFormat); // modal group 5 // G93-94 | |
var gUnitModal = createModal({}, gFormat); // modal group 6 // G20-21 | |
var gCycleModal = createModal({}, gFormat); // modal group 9 // G81, ... | |
var gRetractModal = createModal({}, gFormat); // modal group 10 // G98-99 | |
// fixed settings | |
var firstFeedParameter = 100; | |
var WARNING_WORK_OFFSET = 0; | |
// collected state | |
var sequenceNumber; | |
var currentWorkOffset; | |
var forceSpindleSpeed = false; | |
var activeMovements; // do not use by default | |
var currentFeedId; | |
/** | |
Writes the specified block. | |
*/ | |
function writeBlock() { | |
if (properties.showSequenceNumbers) { | |
writeWords2("N" + sequenceNumber, arguments); | |
sequenceNumber += properties.sequenceNumberIncrement; | |
if (sequenceNumber > 99999) { | |
sequenceNumber = properties.sequenceNumberStart; | |
} | |
} else { | |
writeWords(arguments); | |
} | |
} | |
/** | |
Writes the specified optional block. | |
*/ | |
function writeOptionalBlock() { | |
if (properties.showSequenceNumbers) { | |
var words = formatWords(arguments); | |
if (words) { | |
writeWords("/", "N" + sequenceNumber, words); | |
sequenceNumber += properties.sequenceNumberIncrement; | |
if (sequenceNumber > 99999) { | |
sequenceNumber = properties.sequenceNumberStart; | |
} | |
} | |
} else { | |
writeWords2("/", arguments); | |
} | |
} | |
function formatComment(text) { | |
return "(" + filterText(String(text).toUpperCase(), permittedCommentChars) + ")"; | |
} | |
/** | |
Output a comment. | |
*/ | |
function writeComment(text) { | |
writeln(formatComment(text)); | |
} | |
function onOpen() { | |
if (false) { // note: setup your machine here | |
var aAxis = createAxis({coordinate:0, table:false, axis:[1, 0, 0], range:[-360,360], preference:1}); | |
var cAxis = createAxis({coordinate:2, table:false, axis:[0, 0, 1], range:[-360,360], preference:1}); | |
machineConfiguration = new MachineConfiguration(aAxis, cAxis); | |
setMachineConfiguration(machineConfiguration); | |
optimizeMachineAngles2(0); // TCP mode | |
} | |
if (!machineConfiguration.isMachineCoordinate(0)) { | |
aOutput.disable(); | |
} | |
if (!machineConfiguration.isMachineCoordinate(1)) { | |
bOutput.disable(); | |
} | |
if (!machineConfiguration.isMachineCoordinate(2)) { | |
cOutput.disable(); | |
} | |
if (!properties.separateWordsWithSpace) { | |
setWordSeparator(""); | |
} | |
sequenceNumber = properties.sequenceNumberStart; | |
writeln("%"); | |
if (programName) { | |
writeComment(programName); | |
} | |
if (programComment) { | |
writeComment(programComment); | |
} | |
// dump machine configuration | |
var vendor = machineConfiguration.getVendor(); | |
var model = machineConfiguration.getModel(); | |
var description = machineConfiguration.getDescription(); | |
if (properties.writeMachine && (vendor || model || description)) { | |
writeComment(localize("Machine")); | |
if (vendor) { | |
writeComment(" " + localize("vendor") + ": " + vendor); | |
} | |
if (model) { | |
writeComment(" " + localize("model") + ": " + model); | |
} | |
if (description) { | |
writeComment(" " + localize("description") + ": " + description); | |
} | |
} | |
// dump tool information | |
if (properties.writeTools) { | |
var zRanges = {}; | |
if (is3D()) { | |
var numberOfSections = getNumberOfSections(); | |
for (var i = 0; i < numberOfSections; ++i) { | |
var section = getSection(i); | |
var zRange = section.getGlobalZRange(); | |
var tool = section.getTool(); | |
if (zRanges[tool.number]) { | |
zRanges[tool.number].expandToRange(zRange); | |
} else { | |
zRanges[tool.number] = zRange; | |
} | |
} | |
} | |
var tools = getToolTable(); | |
if (tools.getNumberOfTools() > 0) { | |
for (var i = 0; i < tools.getNumberOfTools(); ++i) { | |
var tool = tools.getTool(i); | |
var comment = "T" + toolFormat.format(tool.number) + " " + | |
"D=" + xyzFormat.format(tool.diameter) + " " + | |
localize("CR") + "=" + xyzFormat.format(tool.cornerRadius); | |
if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) { | |
comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg"); | |
} | |
if (zRanges[tool.number]) { | |
comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum()); | |
} | |
comment += " - " + getToolTypeName(tool.type); | |
writeComment(comment); | |
} | |
} | |
} | |
if (false) { | |
// check for duplicate tool number | |
for (var i = 0; i < getNumberOfSections(); ++i) { | |
var sectioni = getSection(i); | |
var tooli = sectioni.getTool(); | |
for (var j = i + 1; j < getNumberOfSections(); ++j) { | |
var sectionj = getSection(j); | |
var toolj = sectionj.getTool(); | |
if (tooli.number == toolj.number) { | |
if (xyzFormat.areDifferent(tooli.diameter, toolj.diameter) || | |
xyzFormat.areDifferent(tooli.cornerRadius, toolj.cornerRadius) || | |
abcFormat.areDifferent(tooli.taperAngle, toolj.taperAngle) || | |
(tooli.numberOfFlutes != toolj.numberOfFlutes)) { | |
error( | |
subst( | |
localize("Using the same tool number for different cutter geometry for operation '%1' and '%2'."), | |
sectioni.hasParameter("operation-comment") ? sectioni.getParameter("operation-comment") : ("#" + (i + 1)), | |
sectionj.hasParameter("operation-comment") ? sectionj.getParameter("operation-comment") : ("#" + (j + 1)) | |
) | |
); | |
return; | |
} | |
} | |
} | |
} | |
} | |
// absolute coordinates, feed per min, and incremental arc center mode | |
writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(94), gPlaneModal.format(17), gFormat.format(91.1)); | |
switch (unit) { | |
case IN: | |
writeBlock(gUnitModal.format(20)); | |
break; | |
case MM: | |
writeBlock(gUnitModal.format(21)); | |
break; | |
} | |
if (tolerance) { | |
writeBlock('G64 P' + tolerance); | |
} | |
} | |
function onComment(message) { | |
writeComment(message); | |
} | |
/** Force output of X, Y, and Z. */ | |
function forceXYZ() { | |
xOutput.reset(); | |
yOutput.reset(); | |
zOutput.reset(); | |
} | |
/** Force output of A, B, and C. */ | |
function forceABC() { | |
aOutput.reset(); | |
bOutput.reset(); | |
cOutput.reset(); | |
} | |
function forceFeed() { | |
currentFeedId = undefined; | |
feedOutput.reset(); | |
} | |
/** Force output of X, Y, Z, A, B, C, and F on next output. */ | |
function forceAny() { | |
forceXYZ(); | |
forceABC(); | |
forceFeed(); | |
} | |
function FeedContext(id, description, feed) { | |
this.id = id; | |
this.description = description; | |
this.feed = feed; | |
} | |
function getFeed(f) { | |
if (activeMovements) { | |
var feedContext = activeMovements[movement]; | |
if (feedContext != undefined) { | |
if (!feedFormat.areDifferent(feedContext.feed, f)) { | |
if (feedContext.id == currentFeedId) { | |
return ""; // nothing has changed | |
} | |
forceFeed(); | |
currentFeedId = feedContext.id; | |
return "F#" + (firstFeedParameter + feedContext.id); | |
} | |
} | |
currentFeedId = undefined; // force Q feed next time | |
} | |
return feedOutput.format(f); // use feed value | |
} | |
function initializeActiveFeeds() { | |
activeMovements = new Array(); | |
var movements = currentSection.getMovements(); | |
var id = 0; | |
var activeFeeds = new Array(); | |
if (hasParameter("operation:tool_feedCutting")) { | |
if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) { | |
var feedContext = new FeedContext(id, localize("Cutting"), getParameter("operation:tool_feedCutting")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_CUTTING] = feedContext; | |
activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; | |
activeMovements[MOVEMENT_EXTENDED] = feedContext; | |
} | |
++id; | |
if (movements & (1 << MOVEMENT_PREDRILL)) { | |
feedContext = new FeedContext(id, localize("Predrilling"), getParameter("operation:tool_feedCutting")); | |
activeMovements[MOVEMENT_PREDRILL] = feedContext; | |
activeFeeds.push(feedContext); | |
} | |
++id; | |
} | |
if (hasParameter("operation:finishFeedrate")) { | |
if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { | |
var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:finishFeedrate")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; | |
} | |
++id; | |
} else if (hasParameter("operation:tool_feedCutting")) { | |
if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { | |
var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:tool_feedCutting")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; | |
} | |
++id; | |
} | |
if (hasParameter("operation:tool_feedEntry")) { | |
if (movements & (1 << MOVEMENT_LEAD_IN)) { | |
var feedContext = new FeedContext(id, localize("Entry"), getParameter("operation:tool_feedEntry")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_LEAD_IN] = feedContext; | |
} | |
++id; | |
} | |
if (hasParameter("operation:tool_feedExit")) { | |
if (movements & (1 << MOVEMENT_LEAD_OUT)) { | |
var feedContext = new FeedContext(id, localize("Exit"), getParameter("operation:tool_feedExit")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_LEAD_OUT] = feedContext; | |
} | |
++id; | |
} | |
if (hasParameter("operation:noEngagementFeedrate")) { | |
if (movements & (1 << MOVEMENT_LINK_DIRECT)) { | |
var feedContext = new FeedContext(id, localize("Direct"), getParameter("operation:noEngagementFeedrate")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; | |
} | |
++id; | |
} else if (hasParameter("operation:tool_feedCutting") && | |
hasParameter("operation:tool_feedEntry") && | |
hasParameter("operation:tool_feedExit")) { | |
if (movements & (1 << MOVEMENT_LINK_DIRECT)) { | |
var feedContext = new FeedContext(id, localize("Direct"), Math.max(getParameter("operation:tool_feedCutting"), getParameter("operation:tool_feedEntry"), getParameter("operation:tool_feedExit"))); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; | |
} | |
++id; | |
} | |
if (hasParameter("operation:reducedFeedrate")) { | |
if (movements & (1 << MOVEMENT_REDUCED)) { | |
var feedContext = new FeedContext(id, localize("Reduced"), getParameter("operation:reducedFeedrate")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_REDUCED] = feedContext; | |
} | |
++id; | |
} | |
if (hasParameter("operation:tool_feedRamp")) { | |
if (movements & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_HELIX) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_ZIG_ZAG))) { | |
var feedContext = new FeedContext(id, localize("Ramping"), getParameter("operation:tool_feedRamp")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_RAMP] = feedContext; | |
activeMovements[MOVEMENT_RAMP_HELIX] = feedContext; | |
activeMovements[MOVEMENT_RAMP_PROFILE] = feedContext; | |
activeMovements[MOVEMENT_RAMP_ZIG_ZAG] = feedContext; | |
} | |
++id; | |
} | |
if (hasParameter("operation:tool_feedPlunge")) { | |
if (movements & (1 << MOVEMENT_PLUNGE)) { | |
var feedContext = new FeedContext(id, localize("Plunge"), getParameter("operation:tool_feedPlunge")); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_PLUNGE] = feedContext; | |
} | |
++id; | |
} | |
if (true) { // high feed | |
if (movements & (1 << MOVEMENT_HIGH_FEED)) { | |
var feedContext = new FeedContext(id, localize("High Feed"), this.highFeedrate); | |
activeFeeds.push(feedContext); | |
activeMovements[MOVEMENT_HIGH_FEED] = feedContext; | |
} | |
++id; | |
} | |
for (var i = 0; i < activeFeeds.length; ++i) { | |
var feedContext = activeFeeds[i]; | |
writeBlock("#" + (firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed), formatComment(feedContext.description)); | |
} | |
} | |
var currentWorkPlaneABC = undefined; | |
function forceWorkPlane() { | |
currentWorkPlaneABC = undefined; | |
} | |
function setWorkPlane(abc) { | |
if (!machineConfiguration.isMultiAxisConfiguration()) { | |
return; // ignore | |
} | |
if (!((currentWorkPlaneABC == undefined) || | |
abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) || | |
abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) || | |
abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z))) { | |
return; // no change | |
} | |
onCommand(COMMAND_UNLOCK_MULTI_AXIS); | |
// NOTE: add retract here | |
writeBlock( | |
gMotionModal.format(0), | |
conditional(machineConfiguration.isMachineCoordinate(0), "A" + abcFormat.format(abc.x)), | |
conditional(machineConfiguration.isMachineCoordinate(1), "B" + abcFormat.format(abc.y)), | |
conditional(machineConfiguration.isMachineCoordinate(2), "C" + abcFormat.format(abc.z)) | |
); | |
onCommand(COMMAND_LOCK_MULTI_AXIS); | |
currentWorkPlaneABC = abc; | |
} | |
var closestABC = false; // choose closest machine angles | |
var currentMachineABC; | |
function getWorkPlaneMachineABC(workPlane) { | |
var W = workPlane; // map to global frame | |
var abc = machineConfiguration.getABC(W); | |
if (closestABC) { | |
if (currentMachineABC) { | |
abc = machineConfiguration.remapToABC(abc, currentMachineABC); | |
} else { | |
abc = machineConfiguration.getPreferredABC(abc); | |
} | |
} else { | |
abc = machineConfiguration.getPreferredABC(abc); | |
} | |
try { | |
abc = machineConfiguration.remapABC(abc); | |
currentMachineABC = abc; | |
} catch (e) { | |
error( | |
localize("Machine angles not supported") + ":" | |
+ conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x)) | |
+ conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y)) | |
+ conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z)) | |
); | |
} | |
var direction = machineConfiguration.getDirection(abc); | |
if (!isSameDirection(direction, W.forward)) { | |
error(localize("Orientation not supported.")); | |
} | |
if (!machineConfiguration.isABCSupported(abc)) { | |
error( | |
localize("Work plane is not supported") + ":" | |
+ conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x)) | |
+ conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y)) | |
+ conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z)) | |
); | |
} | |
var tcp = true; | |
if (tcp) { | |
setRotation(W); // TCP mode | |
} else { | |
var O = machineConfiguration.getOrientation(abc); | |
var R = machineConfiguration.getRemainingOrientation(abc, W); | |
setRotation(R); | |
} | |
return abc; | |
} | |
function onSection() { | |
var insertToolCall = isFirstSection() || | |
currentSection.getForceToolChange && currentSection.getForceToolChange() || | |
(tool.number != getPreviousSection().getTool().number); | |
var retracted = false; // specifies that the tool has been retracted to the safe plane | |
var newWorkOffset = isFirstSection() || | |
(getPreviousSection().workOffset != currentSection.workOffset); // work offset changes | |
var newWorkPlane = isFirstSection() || | |
!isSameDirection(getPreviousSection().getGlobalFinalToolAxis(), currentSection.getGlobalInitialToolAxis()); | |
if (insertToolCall || newWorkOffset || newWorkPlane) { | |
// stop spindle before retract during tool change | |
if (insertToolCall && !isFirstSection()) { | |
onCommand(COMMAND_STOP_SPINDLE); | |
} | |
// retract to safe plane | |
retracted = true; | |
if (properties.useG28) { | |
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract | |
writeBlock(gAbsIncModal.format(90)); | |
} else { | |
writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), "Z" + xyzFormat.format(0)); // retract | |
} | |
zOutput.reset(); | |
} | |
if (hasParameter("operation-comment")) { | |
var comment = getParameter("operation-comment"); | |
if (comment) { | |
writeComment(comment); | |
} | |
} | |
if (properties.showNotes && hasParameter("notes")) { | |
var notes = getParameter("notes"); | |
if (notes) { | |
var lines = String(notes).split("\n"); | |
var r1 = new RegExp("^[\\s]+", "g"); | |
var r2 = new RegExp("[\\s]+$", "g"); | |
for (line in lines) { | |
var comment = lines[line].replace(r1, "").replace(r2, ""); | |
if (comment) { | |
writeComment(comment); | |
} | |
} | |
} | |
} | |
if (insertToolCall) { | |
forceWorkPlane(); | |
retracted = true; | |
onCommand(COMMAND_COOLANT_OFF); | |
if (!isFirstSection() && properties.optionalStop) { | |
onCommand(COMMAND_OPTIONAL_STOP); | |
} | |
if (tool.number > 99) { | |
warning(localize("Tool number exceeds maximum value.")); | |
} | |
writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); | |
if (tool.comment) { | |
writeComment(tool.comment); | |
} | |
var showToolZMin = false; | |
if (showToolZMin) { | |
if (is3D()) { | |
var numberOfSections = getNumberOfSections(); | |
var zRange = currentSection.getGlobalZRange(); | |
var number = tool.number; | |
for (var i = currentSection.getId() + 1; i < numberOfSections; ++i) { | |
var section = getSection(i); | |
if (section.getTool().number != number) { | |
break; | |
} | |
zRange.expandToRange(section.getGlobalZRange()); | |
} | |
writeComment(localize("ZMIN") + "=" + zRange.getMinimum()); | |
} | |
} | |
if (properties.preloadTool) { | |
var nextTool = getNextTool(tool.number); | |
if (nextTool) { | |
writeBlock("T" + toolFormat.format(nextTool.number)); | |
} else { | |
// preload first tool | |
var section = getSection(0); | |
var firstToolNumber = section.getTool().number; | |
if (tool.number != firstToolNumber) { | |
writeBlock("T" + toolFormat.format(firstToolNumber)); | |
} | |
} | |
} | |
} | |
if (insertToolCall || | |
forceSpindleSpeed || | |
isFirstSection() || | |
(rpmFormat.areDifferent(tool.spindleRPM, sOutput.getCurrent())) || | |
(tool.clockwise != getPreviousSection().getTool().clockwise)) { | |
forceSpindleSpeed = false; | |
if (tool.spindleRPM < 1) { | |
error(localize("Spindle speed out of range.")); | |
return; | |
} | |
if (tool.spindleRPM > 99999) { | |
warning(localize("Spindle speed exceeds maximum value.")); | |
} | |
writeBlock( | |
sOutput.format(tool.spindleRPM), mFormat.format(tool.clockwise ? 3 : 4) | |
); | |
} | |
// wcs | |
if (insertToolCall) { // force work offset when changing tool | |
currentWorkOffset = undefined; | |
} | |
var workOffset = currentSection.workOffset; | |
if (workOffset == 0) { | |
warningOnce(localize("Work offset has not been specified. Using G54 as WCS."), WARNING_WORK_OFFSET); | |
workOffset = 1; | |
} | |
if (workOffset > 0) { | |
if (workOffset > 6) { | |
var p = workOffset - 6; // 1->... | |
if (p > 3) { | |
error(localize("Work offset out of range.")); | |
return; | |
} else { | |
if (workOffset != currentWorkOffset) { | |
writeBlock(gFormat.format(59.1), "P" + p); // G59.1P | |
currentWorkOffset = workOffset; | |
} | |
} | |
} else { | |
if (workOffset != currentWorkOffset) { | |
writeBlock(gFormat.format(53 + workOffset)); // G54->G59 | |
currentWorkOffset = workOffset; | |
} | |
} | |
} | |
forceXYZ(); | |
if (machineConfiguration.isMultiAxisConfiguration()) { // use 5-axis indexing for multi-axis mode | |
// set working plane after datum shift | |
var abc = new Vector(0, 0, 0); | |
if (currentSection.isMultiAxis()) { | |
forceWorkPlane(); | |
cancelTransformation(); | |
} else { | |
abc = getWorkPlaneMachineABC(currentSection.workPlane); | |
} | |
setWorkPlane(abc); | |
} else { // pure 3D | |
var remaining = currentSection.workPlane; | |
if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { | |
error(localize("Tool orientation is not supported.")); | |
return; | |
} | |
setRotation(remaining); | |
} | |
// set coolant after we have positioned at Z | |
{ | |
var c = mapCoolantTable.lookup(tool.coolant); | |
if (c) { | |
writeBlock(mFormat.format(c)); | |
} else { | |
warning(localize("Coolant not supported.")); | |
} | |
} | |
forceAny(); | |
gMotionModal.reset(); | |
var initialPosition = getFramePosition(currentSection.getInitialPosition()); | |
if (!retracted) { | |
if (getCurrentPosition().z < initialPosition.z) { | |
writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); | |
} | |
} | |
if (insertToolCall || retracted || (!isFirstSection() && getPreviousSection().isMultiAxis())) { | |
var lengthOffset = tool.lengthOffset; | |
if (lengthOffset > 99) { | |
error(localize("Length offset out of range.")); | |
return; | |
} | |
gMotionModal.reset(); | |
writeBlock(gPlaneModal.format(17)); | |
if (!machineConfiguration.isHeadConfiguration()) { | |
writeBlock( | |
gAbsIncModal.format(90), | |
gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y) | |
); | |
writeBlock(gMotionModal.format(0), gFormat.format(43), zOutput.format(initialPosition.z), hFormat.format(lengthOffset)); | |
} else { | |
writeBlock( | |
gAbsIncModal.format(90), | |
gMotionModal.format(0), | |
gFormat.format(43), xOutput.format(initialPosition.x), | |
yOutput.format(initialPosition.y), | |
zOutput.format(initialPosition.z), hFormat.format(lengthOffset) | |
); | |
} | |
gMotionModal.reset(); | |
} else { | |
writeBlock( | |
gAbsIncModal.format(90), | |
gMotionModal.format(0), | |
xOutput.format(initialPosition.x), | |
yOutput.format(initialPosition.y) | |
); | |
} | |
if (properties.useParametricFeed && | |
hasParameter("operation-strategy") && | |
(getParameter("operation-strategy") != "drill")) { | |
if (!insertToolCall && | |
activeMovements && | |
(getCurrentSectionId() > 0) && | |
(getPreviousSection().getPatternId() == currentSection.getPatternId())) { | |
// use the current feeds | |
} else { | |
initializeActiveFeeds(); | |
} | |
} else { | |
activeMovements = undefined; | |
} | |
} | |
function onDwell(seconds) { | |
if (seconds > 99999.999) { | |
warning(localize("Dwelling time is out of range.")); | |
} | |
writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + secFormat.format(seconds)); | |
} | |
function onSpindleSpeed(spindleSpeed) { | |
writeBlock(sOutput.format(spindleSpeed)); | |
} | |
function onCycle() { | |
writeBlock(gPlaneModal.format(17)); | |
} | |
function getCommonCycle(x, y, z, r) { | |
forceXYZ(); // force xyz on first drill hole of any cycle | |
return [xOutput.format(x), yOutput.format(y), | |
zOutput.format(z), | |
"R" + xyzFormat.format(r)]; | |
} | |
function onCyclePoint(x, y, z) { | |
switch (cycleType) { | |
case "tapping": | |
case "left-tapping": | |
case "right-tapping": | |
cycleExpanded = true; | |
repositionToCycleClearance(cycle, x, y, z); | |
writeBlock( | |
gAbsIncModal.format(90), gMotionModal.format(0), | |
conditional(gPlaneModal.getCurrent() == 17, zOutput.format(cycle.retract)), | |
conditional(gPlaneModal.getCurrent() == 18, yOutput.format(cycle.retract)), | |
conditional(gPlaneModal.getCurrent() == 19, xOutput.format(cycle.retract)) | |
); | |
writeBlock( | |
gAbsIncModal.format(90), gFormat.format(33.1), | |
conditional(gPlaneModal.getCurrent() == 17, zOutput.format(z)), | |
conditional(gPlaneModal.getCurrent() == 18, yOutput.format(y)), | |
conditional(gPlaneModal.getCurrent() == 19, xOutput.format(x)), | |
"K" + pitchFormat.format(tool.threadPitch) | |
); | |
gMotionModal.reset(); | |
writeBlock( | |
gAbsIncModal.format(90), gMotionModal.format(0), | |
conditional(gPlaneModal.getCurrent() == 17, zOutput.format(cycle.clearance)), | |
conditional(gPlaneModal.getCurrent() == 18, yOutput.format(cycle.clearance)), | |
conditional(gPlaneModal.getCurrent() == 19, xOutput.format(cycle.clearance)) | |
); | |
return; | |
/* | |
case "tapping-with-chip-breaking": | |
case "left-tapping-with-chip-breaking": | |
case "right-tapping-with-chip-breaking": | |
*/ | |
} | |
if (isFirstCyclePoint()) { | |
repositionToCycleClearance(cycle, x, y, z); | |
// return to initial Z which is clearance plane and set absolute mode | |
var F = cycle.feedrate; | |
var P = (cycle.dwell == 0) ? 0 : clamp(0.001, cycle.dwell, 99999999); // in seconds | |
switch (cycleType) { | |
case "drilling": | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(81), | |
getCommonCycle(x, y, z, cycle.retract), | |
feedOutput.format(F) | |
); | |
break; | |
case "counter-boring": | |
if (P > 0) { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(82), | |
getCommonCycle(x, y, z, cycle.retract), | |
"P" + secFormat.format(P), | |
feedOutput.format(F) | |
); | |
} else { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(81), | |
getCommonCycle(x, y, z, cycle.retract), | |
feedOutput.format(F) | |
); | |
} | |
break; | |
case "chip-breaking": | |
expandCyclePoint(x, y, z); | |
break; | |
case "deep-drilling": | |
if (P > 0) { | |
expandCyclePoint(x, y, z); | |
} else { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(83), | |
getCommonCycle(x, y, z, cycle.retract), | |
"Q" + xyzFormat.format(cycle.incrementalDepth), | |
// conditional(P > 0, "P" + secFormat.format(P)), | |
feedOutput.format(F) | |
); | |
} | |
break; | |
case "fine-boring": | |
expandCyclePoint(x, y, z); | |
break; | |
/* // not supported | |
case "back-boring": | |
var dx = (gPlaneModal.getCurrent() == 19) ? cycle.backBoreDistance : 0; | |
var dy = (gPlaneModal.getCurrent() == 18) ? cycle.backBoreDistance : 0; | |
var dz = (gPlaneModal.getCurrent() == 17) ? cycle.backBoreDistance : 0; | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(87), | |
getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom), | |
"Q" + xyzFormat.format(cycle.shift), | |
"P" + secFormat.format(P), // not optional | |
feedOutput.format(F) | |
); | |
break; | |
*/ | |
case "reaming": | |
if (P > 0) { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89), | |
getCommonCycle(x, y, z, cycle.retract), | |
"P" + secFormat.format(P), | |
feedOutput.format(F) | |
); | |
} else { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85), | |
getCommonCycle(x, y, z, cycle.retract), | |
feedOutput.format(F) | |
); | |
} | |
break; | |
case "stop-boring": | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(86), | |
getCommonCycle(x, y, z, cycle.retract), | |
conditional(P > 0, "P" + secFormat.format(P)), | |
feedOutput.format(F) | |
); | |
break; | |
case "manual-boring": | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(88), | |
getCommonCycle(x, y, z, cycle.retract), | |
"P" + secFormat.format(P), // not optional | |
feedOutput.format(F) | |
); | |
break; | |
case "boring": | |
if (P > 0) { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89), | |
getCommonCycle(x, y, z, cycle.retract), | |
"P" + secFormat.format(P), // not optional | |
feedOutput.format(F) | |
); | |
} else { | |
writeBlock( | |
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85), | |
getCommonCycle(x, y, z, cycle.retract), | |
feedOutput.format(F) | |
); | |
} | |
break; | |
default: | |
expandCyclePoint(x, y, z); | |
} | |
} else { | |
if (cycleExpanded) { | |
expandCyclePoint(x, y, z); | |
} else { | |
var _x = xOutput.format(x); | |
var _y = yOutput.format(y); | |
var _z = zOutput.format(z); | |
if (!_x && !_y && !_z) { | |
switch (gPlaneModal.getCurrent()) { | |
case 17: // XY | |
xOutput.reset(); // at least one axis is required | |
_x = xOutput.format(x); | |
break; | |
case 18: // ZX | |
zOutput.reset(); // at least one axis is required | |
_z = zOutput.format(z); | |
break; | |
case 19: // YZ | |
yOutput.reset(); // at least one axis is required | |
_y = yOutput.format(y); | |
break; | |
} | |
} | |
writeBlock(_x, _y, _z); | |
} | |
} | |
} | |
function onCycleEnd() { | |
if (!cycleExpanded) { | |
writeBlock(gCycleModal.format(80)); | |
gMotionModal.reset(); | |
} | |
} | |
var pendingRadiusCompensation = -1; | |
function onRadiusCompensation() { | |
pendingRadiusCompensation = radiusCompensation; | |
} | |
function onRapid(_x, _y, _z) { | |
var x = xOutput.format(_x); | |
var y = yOutput.format(_y); | |
var z = zOutput.format(_z); | |
if (x || y || z) { | |
if (pendingRadiusCompensation >= 0) { | |
error(localize("Radius compensation mode cannot be changed at rapid traversal.")); | |
return; | |
} | |
writeBlock(gMotionModal.format(0), x, y, z); | |
forceFeed(); | |
} | |
} | |
function onLinear(_x, _y, _z, feed) { | |
var x = xOutput.format(_x); | |
var y = yOutput.format(_y); | |
var z = zOutput.format(_z); | |
var f = getFeed(feed); | |
if (x || y || z) { | |
if (pendingRadiusCompensation >= 0) { | |
pendingRadiusCompensation = -1; | |
var d = tool.diameterOffset; | |
if (d > 99) { | |
warning(localize("The diameter offset exceeds the maximum value.")); | |
} | |
writeBlock(gPlaneModal.format(17)); | |
switch (radiusCompensation) { | |
case RADIUS_COMPENSATION_LEFT: | |
dOutput.reset(); | |
writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, dOutput.format(d), f); | |
break; | |
case RADIUS_COMPENSATION_RIGHT: | |
dOutput.reset(); | |
writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, dOutput.format(d), f); | |
break; | |
default: | |
writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f); | |
} | |
} else { | |
writeBlock(gMotionModal.format(1), x, y, z, f); | |
} | |
} else if (f) { | |
if (getNextRecord().isMotion()) { // try not to output feed without motion | |
forceFeed(); // force feed on next line | |
} else { | |
writeBlock(gMotionModal.format(1), f); | |
} | |
} | |
} | |
function onRapid5D(_x, _y, _z, _a, _b, _c) { | |
if (!currentSection.isOptimizedForMachine()) { | |
error(localize("This post configuration has not been customized for 5-axis simultaneous toolpath.")); | |
return; | |
} | |
if (pendingRadiusCompensation >= 0) { | |
error(localize("Radius compensation mode cannot be changed at rapid traversal.")); | |
return; | |
} | |
var x = xOutput.format(_x); | |
var y = yOutput.format(_y); | |
var z = zOutput.format(_z); | |
var a = aOutput.format(_a); | |
var b = bOutput.format(_b); | |
var c = cOutput.format(_c); | |
writeBlock(gMotionModal.format(0), x, y, z, a, b, c); | |
forceFeed(); | |
} | |
function onLinear5D(_x, _y, _z, _a, _b, _c, feed) { | |
if (!currentSection.isOptimizedForMachine()) { | |
error(localize("This post configuration has not been customized for 5-axis simultaneous toolpath.")); | |
return; | |
} | |
if (pendingRadiusCompensation >= 0) { | |
error(localize("Radius compensation cannot be activated/deactivated for 5-axis move.")); | |
return; | |
} | |
var x = xOutput.format(_x); | |
var y = yOutput.format(_y); | |
var z = zOutput.format(_z); | |
var a = aOutput.format(_a); | |
var b = bOutput.format(_b); | |
var c = cOutput.format(_c); | |
var f = getFeed(feed); | |
if (x || y || z || a || b || c) { | |
writeBlock(gMotionModal.format(1), x, y, z, a, b, c, f); | |
} else if (f) { | |
if (getNextRecord().isMotion()) { // try not to output feed without motion | |
forceFeed(); // force feed on next line | |
} else { | |
writeBlock(gMotionModal.format(1), f); | |
} | |
} | |
} | |
function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { | |
if (pendingRadiusCompensation >= 0) { | |
error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); | |
return; | |
} | |
var start = getCurrentPosition(); | |
if (isFullCircle()) { | |
if (properties.useRadius || isHelical()) { // radius mode does not support full arcs | |
linearize(tolerance); | |
return; | |
} | |
switch (getCircularPlane()) { | |
case PLANE_XY: | |
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); | |
break; | |
case PLANE_ZX: | |
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); | |
break; | |
case PLANE_YZ: | |
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); | |
break; | |
default: | |
linearize(tolerance); | |
} | |
} else if (!properties.useRadius) { | |
switch (getCircularPlane()) { | |
case PLANE_XY: | |
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); | |
break; | |
case PLANE_ZX: | |
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); | |
break; | |
case PLANE_YZ: | |
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); | |
break; | |
default: | |
linearize(tolerance); | |
} | |
} else { // use radius mode | |
var r = getCircularRadius(); | |
if (toDeg(getCircularSweep()) > (180 + 1e-9)) { | |
r = -r; // allow up to <360 deg arcs | |
} | |
switch (getCircularPlane()) { | |
case PLANE_XY: | |
writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); | |
break; | |
case PLANE_ZX: | |
writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); | |
break; | |
case PLANE_YZ: | |
writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); | |
break; | |
default: | |
linearize(tolerance); | |
} | |
} | |
} | |
var mapCommand = { | |
COMMAND_STOP:0, | |
COMMAND_OPTIONAL_STOP:1, | |
COMMAND_END:2, | |
COMMAND_SPINDLE_CLOCKWISE:3, | |
COMMAND_SPINDLE_COUNTERCLOCKWISE:4, | |
COMMAND_STOP_SPINDLE:5, | |
COMMAND_ORIENTATE_SPINDLE:19, | |
COMMAND_LOAD_TOOL:6, | |
COMMAND_COOLANT_ON:8, | |
COMMAND_COOLANT_OFF:9 | |
}; | |
function onCommand(command) { | |
switch (command) { | |
case COMMAND_STOP: | |
writeBlock(mFormat.format(0)); | |
forceSpindleSpeed = true; | |
return; | |
case COMMAND_START_SPINDLE: | |
onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE); | |
return; | |
case COMMAND_LOCK_MULTI_AXIS: | |
return; | |
case COMMAND_UNLOCK_MULTI_AXIS: | |
return; | |
case COMMAND_BREAK_CONTROL: | |
return; | |
case COMMAND_TOOL_MEASURE: | |
return; | |
} | |
var stringId = getCommandStringId(command); | |
var mcode = mapCommand[stringId]; | |
if (mcode != undefined) { | |
writeBlock(mFormat.format(mcode)); | |
} else { | |
onUnsupportedCommand(command); | |
} | |
} | |
function onSectionEnd() { | |
if (currentSection.isMultiAxis()) { | |
writeBlock(gMotionModal.format(49)); | |
} | |
writeBlock(gPlaneModal.format(17)); | |
if (((getCurrentSectionId() + 1) >= getNumberOfSections()) || | |
(tool.number != getNextSection().getTool().number)) { | |
onCommand(COMMAND_BREAK_CONTROL); | |
} | |
forceAny(); | |
} | |
function onClose() { | |
onCommand(COMMAND_COOLANT_OFF); | |
if (properties.useG28) { | |
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract | |
} else { | |
writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), "Z" + xyzFormat.format(0)); // retract | |
} | |
zOutput.reset(); | |
setWorkPlane(new Vector(0, 0, 0)); // reset working plane | |
if (!machineConfiguration.hasHomePositionX() && !machineConfiguration.hasHomePositionY()) { | |
if (properties.useG28) { | |
// 90/91 mode is don't care | |
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "X" + xyzFormat.format(0), "Y" + xyzFormat.format(0)); // return to home | |
} | |
} else { | |
var homeX; | |
if (machineConfiguration.hasHomePositionX()) { | |
homeX = "X" + xyzFormat.format(machineConfiguration.getHomePositionX()); | |
} | |
var homeY; | |
if (machineConfiguration.hasHomePositionY()) { | |
homeY = "Y" + xyzFormat.format(machineConfiguration.getHomePositionY()); | |
} | |
writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), homeX, homeY); | |
} | |
onImpliedCommand(COMMAND_END); | |
onImpliedCommand(COMMAND_STOP_SPINDLE); | |
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off | |
writeln("%"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment