/** Copyright (C) 2012-2018 by Autodesk, Inc. All rights reserved. UCCNC post processor configuration. $Revision: 42145 3ef6ef136f68132df4d932bf16f29ac1ec1b893b $ $Date: 2018-09-28 16:13:20 $ FORKID {9076F4FE-2652-48D2-9DAD-1A22C240A8B8} */ description = "STEPCRAFT UCCNC"; vendor = "UCCNC"; vendorUrl = "http://www.cncdrive.com/"; legal = "Copyright (C) 2012-2018 by Autodesk, Inc."; certificationLevel = 2; minimumRevision = 40783; longDescription = "Generic post for STEPCRAFT machines using UCCNC control software. If you are using a fourth axis, make sure to select which axis it is mounted along. If you have an automatic tool changer, enable the property 'useToolChanger'. For laser cutting, set your desired power setting by using property 'laserPowerPrecentage'."; extension = "nc"; setCodePage("ascii"); capabilities = CAPABILITY_MILLING | CAPABILITY_JET; tolerance = spatial(0.002, MM); minimumChordLength = spatial(0.25, MM); minimumCircularRadius = spatial(0.01, MM); maximumCircularRadius = spatial(1000, MM); minimumCircularSweep = toRad(0.01); maximumCircularSweep = toRad(90); allowHelicalMoves = true; allowedCircularPlanes = 1 << PLANE_XY; // allow only XY circular motion // user-defined properties properties = { writeMachine: true, // write machine writeTools: true, // writes the tools showSequenceNumbers: false, // show sequence numbers sequenceNumberStart: 10, // first sequence number sequenceNumberIncrement: 1, // increment for sequence numbers separateWordsWithSpace: true, // specifies that the words should be separated with a white space useToolChanger: false, // specifies that a tool changer is available toolChangePositionX: 0, // specifies the tool change position for X toolChangePositionY: 0, // specifies the tool change position for Y fourthAxisAround: "none", // specifies the fourth axis if mounted useSmoothing: true, // specifies to use constant velocity mode useParametricFeed: false, // specifies that feed should be output using parameters laserPowerPrecentage: 25 // set the laser power in % /*referenceRun: true*/ // move to reference point first at the beginning of the program }; // user-defined property definitions propertyDefinitions = { writeMachine: {title:"Write machine", description:"Output the machine settings in the header of the code.", group:0, type:"boolean"}, writeTools: {title:"Write tool list", description:"Output a tool list in the header of the code.", group:0, type:"boolean"}, showSequenceNumbers: {title:"Use sequence numbers", description:"Use sequence numbers for each block of outputted code.", group:1, type:"boolean"}, sequenceNumberStart: {title:"Start sequence number", description:"The number at which to start the sequence numbers.", group:1, type:"integer"}, sequenceNumberIncrement: {title:"Sequence number increment", description:"The amount by which the sequence number is incremented by in each block.", group:1, type:"integer"}, separateWordsWithSpace: {title:"Separate words with space", description:"Adds spaces between words if 'yes' is selected.", type:"boolean"}, useToolChanger: {title:"Use tool changer", description:"Specifies that a tool changer is available.", type:"boolean"}, toolChangePositionX: {title:"Tool change position X", description:"X-axis tool change position.", type:"number"}, toolChangePositionY: {title:"Tool change position Y", description:"Y-axis tool change position.", type:"number"}, fourthAxisAround: {title:"Fourth axis mounted along", description:"Specifies which axis the fourth axis is mounted on.", type:"enum", values:[{id:"none", title:"None"}, {id:"x", title:"Along X"}, {id:"y", title:"Along Y"}]}, useSmoothing: {title:"Use smoothing", description:"Specifies if smoothing should be used or not.", type:"boolean"}, useParametricFeed: {title:"Parametric feed", description:"Specifies the feed value that should be output using a Q value.", type:"boolean"}, laserPowerPrecentage: {title:"Laser power percentage", description:"Sets the laser power in percentage.", type:"number"} }; // samples: // throughTool: {on: 88, off: 89} // throughTool: {on: [8, 88], off: [9, 89]} var coolants = { flood: {on: 8}, mist: {on: 7}, throughTool: {}, air: {}, airThroughTool: {}, suction: {}, floodMist: {}, floodThroughTool: {}, off: 9 }; var gFormat = createFormat({prefix:"G", decimals:1}); var mFormat = createFormat({prefix:"M", decimals:0}); var hFormat = createFormat({prefix:"H", decimals:0}); var qFormat = createFormat({prefix:"Q", decimals:0}); var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var abcFormat = createFormat({decimals:3, forceDecimal:true, scale:DEG}); var feedFormat = createFormat({decimals:(unit == MM ? 1 : 2)}); var toolFormat = createFormat({decimals:0}); var rpmFormat = createFormat({decimals:0}); var secFormat = createFormat({decimals:3, forceDecimal:true}); // seconds - range 0.001-1000 var milliFormat = createFormat({decimals:0}); // milliseconds - range 1-? var taperFormat = createFormat({decimals:1, scale:DEG}); var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var xOutput = createVariable({prefix:"X"}, xyzFormat); var yOutput = createVariable({prefix:"Y"}, xyzFormat); var zOutput = createVariable({onchange:function () {retracted = false;}, 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 pitchOutput = createVariable({prefix:"K", force:true}, pitchFormat); // 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-22 var gCycleModal = createModal({}, gFormat); // modal group 9 // G81, ... var gRetractModal = createModal({}, gFormat); // modal group 10 // G98-99 var WARNING_WORK_OFFSET = 0; // fixed settings var firstFeedParameter = 1; // collected state var sequenceNumber; var currentWorkOffset; var retracted = false; // specifies that the tool has been retracted to the safe plane /** Writes the specified block. */ function writeBlock() { if (!formatWords(arguments)) { return; } if (properties.showSequenceNumbers) { writeWords2("N" + sequenceNumber, arguments); sequenceNumber += properties.sequenceNumberIncrement; } else { writeWords(arguments); } } function formatComment(text) { return "(" + String(text).replace(/[[\]]/g, "") + ")"; } /** Output a comment. */ function writeComment(text) { writeln(formatComment(text)); } function onOpen() { if (properties.fourthAxisAround != "none") { var aAxis = createAxis({coordinate:0, table:true, axis:[(properties.fourthAxisAround == "x" ? 1 : 0), (properties.fourthAxisAround == "y" ? 1 : 0), 0], cyclic:true, preference:0}); machineConfiguration = new MachineConfiguration(aAxis); setMachineConfiguration(machineConfiguration); optimizeMachineAngles2(1); // map tip 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; 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); if (!tool.jetTool) { 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 ((getNumberOfSections() > 0) && (getSection(0).workOffset == 0)) { for (var i = 0; i < getNumberOfSections(); ++i) { if (getSection(i).workOffset > 0) { error(localize("Using multiple work offsets is not possible if the initial work offset is 0.")); return; } } } if ((properties.fourthAxisAround != "none") && !is3D()) { warning(localize("4th axis operations detected. Make sure that your WCS origin is placed on the rotary axis.")); } // absolute coordinates and feed per min writeBlock(gAbsIncModal.format(90)); /* if (properties.referenceRun) { writeBlock(gFormat.format(28.1)); } */ /* not supported on UCCNC switch (unit) { case IN: writeBlock(gUnitModal.format(20)); break; case MM: writeBlock(gUnitModal.format(22)); // G21 is cm break; } */ } 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(); } /** Force output of X, Y, Z, A, B, C, and F on next output. */ function forceAny() { forceXYZ(); forceABC(); forceFeed(); } function forceFeed() { currentFeedId = undefined; feedOutput.reset(); } function onParameter(name, value) { } 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 gMotionModal.reset(); 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.")); return new Vector(); } 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 = false; if (tcp) { setRotation(W); // TCP mode } else { var O = machineConfiguration.getOrientation(abc); var R = machineConfiguration.getRemainingOrientation(abc, W); setRotation(R); } return abc; } 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)); } } function isProbeOperation() { return (hasParameter("operation-strategy") && getParameter("operation-strategy") == "probe"); } var jetMode = false; function onSection() { var insertToolCall = isFirstSection() || currentSection.getForceToolChange && currentSection.getForceToolChange() || (tool.number != getPreviousSection().getTool().number); 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()) || (currentSection.isOptimizedForMachine() && getPreviousSection().isOptimizedForMachine() && Vector.diff(getPreviousSection().getFinalToolAxisABC(), currentSection.getInitialToolAxisABC()).length > 1e-4) || (!machineConfiguration.isMultiAxisConfiguration() && currentSection.isMultiAxis()) || (!getPreviousSection().isMultiAxis() && currentSection.isMultiAxis() || getPreviousSection().isMultiAxis() && !currentSection.isMultiAxis()); // force newWorkPlane between indexing and simultaneous operations jetMode = currentSection.getType() == TYPE_JET; if (!isFirstSection() && (currentSection.getType() != getPreviousSection().getType())) { writeBlock(mFormat.format(0), formatComment(localize("Pause program for changing milling/laser aggregate."))); } if (jetMode) { zOutput.disable(); sOutput.disable(); } else { zOutput.enable(); sOutput.enable(); } if (insertToolCall || newWorkOffset || newWorkPlane) { if (!jetMode) { // retract to safe plane writeRetract(Z); } } writeln(""); if (hasParameter("operation-comment")) { var comment = getParameter("operation-comment"); if (comment) { writeComment(comment); } } if (insertToolCall && !jetMode) { forceWorkPlane(); if (!isFirstSection()) { setCoolant(COOLANT_OFF); } if (properties.useToolChanger) { writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); } else { if (!isFirstSection()) { onCommand(COMMAND_STOP_SPINDLE); writeComment(localize("Move to tool change position")); writeBlock(gMotionModal.format(0), gFormat.format(53), "X" + xyzFormat.format(properties.toolChangePositionX), "Y" + xyzFormat.format(properties.toolChangePositionY)); writeBlock(mFormat.format(0), formatComment(localize("Pause program for tool change"))); } writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6) + " (" + getToolTypeName(tool.type) + " D=" + xyzFormat.format(tool.diameter) + (tool.description ? " " + tool.description : "") + ")"); } 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 (insertToolCall || isFirstSection() || (rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent())) || (tool.clockwise != getPreviousSection().getTool().clockwise)) { if (!jetMode) { if (spindleSpeed < 1) { error(localize("Spindle speed out of range.")); return; } if (spindleSpeed > 99999) { warning(localize("Spindle speed exceeds maximum value.")); } writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } else { writeBlock(mFormat.format(3)); // signal active for uccnc } } if (properties.useParametricFeed && hasParameter("operation-strategy") && (getParameter("operation-strategy") != "drill") && // legacy !(currentSection.hasAnyCycle && currentSection.hasAnyCycle())) { if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && ((getPreviousSection().getPatternId() == currentSection.getPatternId()) && (currentSection.getPatternId() != 0))) { // use the current feeds } else { initializeActiveFeeds(); } } else { activeMovements = undefined; } if (properties.useSmoothing && !jetMode) { if (hasParameter("operation-strategy") && (getParameter("operation-strategy") == "drill")) { writeBlock(gFormat.format(61)); } else { writeBlock(gFormat.format(64)); } } // 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) { error(localize("Work offset out of range.")); return; } 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(); abc = currentSection.getInitialToolAxisABC(); } 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 setCoolant(tool.coolant); forceAny(); var initialPosition = getFramePosition(currentSection.getInitialPosition()); if (!retracted && !insertToolCall) { if (getCurrentPosition().z < initialPosition.z) { writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); } } if (insertToolCall || retracted) { var lengthOffset = tool.lengthOffset; if (lengthOffset > 99) { error(localize("Length offset out of range.")); return; } gMotionModal.reset(); if (!machineConfiguration.isHeadConfiguration()) { if (!jetMode) { writeBlock(gFormat.format(43), hFormat.format(lengthOffset)); } writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y) ); writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); } else { if (!jetMode) { writeBlock(gFormat.format(43), hFormat.format(lengthOffset)); } writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y), zOutput.format(initialPosition.z) ); } } else { writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y) ); } } function onPower(power) { var cuttingPower = 255 * (properties.laserPowerPrecentage / 100); if ((qFormat.getResultingValue(cuttingPower) > 255) || (qFormat.getResultingValue(cuttingPower) < 64)) { error(localize("Property 'laserPowerPrecentage' is out of range. Only 25% to 100% is allowed.")); return; } writeBlock(mFormat.format(power ? 10 : 11), conditional(power, qFormat.format(cuttingPower))); } var currentCoolantMode = COOLANT_OFF; var coolantOff = undefined; function setCoolant(coolant) { var coolantCodes = getCoolantCodes(coolant); if (Array.isArray(coolantCodes)) { for (var c in coolantCodes) { writeBlock(coolantCodes[c]); } return undefined; } return coolantCodes; } function getCoolantCodes(coolant) { if (!coolants) { error(localize("Coolants have not been defined.")); } if (!coolantOff) { // use the default coolant off command when an 'off' value is not specified for the previous coolant mode coolantOff = coolants.off; } if (isProbeOperation()) { // avoid coolant output for probing coolant = COOLANT_OFF; } if (coolant == currentCoolantMode) { return undefined; // coolant is already active } var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF)) { multipleCoolantBlocks.push(mFormat.format(coolantOff)); } var m; if (coolant == COOLANT_OFF) { m = coolantOff; coolantOff = coolants.off; } switch (coolant) { case COOLANT_FLOOD: if (!coolants.flood) { break; } m = coolants.flood.on; coolantOff = coolants.flood.off; break; case COOLANT_THROUGH_TOOL: if (!coolants.throughTool) { break; } m = coolants.throughTool.on; coolantOff = coolants.throughTool.off; break; case COOLANT_AIR: if (!coolants.air) { break; } m = coolants.air.on; coolantOff = coolants.air.off; break; case COOLANT_AIR_THROUGH_TOOL: if (!coolants.airThroughTool) { break; } m = coolants.airThroughTool.on; coolantOff = coolants.airThroughTool.off; break; case COOLANT_FLOOD_MIST: if (!coolants.floodMist) { break; } m = coolants.floodMist.on; coolantOff = coolants.floodMist.off; break; case COOLANT_MIST: if (!coolants.mist) { break; } m = coolants.mist.on; coolantOff = coolants.mist.off; break; case COOLANT_SUCTION: if (!coolants.suction) { break; } m = coolants.suction.on; coolantOff = coolants.suction.off; break; case COOLANT_FLOOD_THROUGH_TOOL: if (!coolants.floodThroughTool) { break; } m = coolants.floodThroughTool.on; coolantOff = coolants.floodThroughTool.off; break; } if (!m) { onUnsupportedCoolant(coolant); m = 9; } if (m) { if (Array.isArray(m)) { for (var i in m) { multipleCoolantBlocks.push(mFormat.format(m[i])); } } else { multipleCoolantBlocks.push(mFormat.format(m)); } currentCoolantMode = coolant; return multipleCoolantBlocks; // return the single formatted coolant value } return undefined; } function onDwell(seconds) { if (seconds > 99999.999) { warning(localize("Dwelling time is out of range.")); } seconds = clamp(0.001, seconds, 99999.999); writeBlock(gFormat.format(4), "P" + milliFormat.format(seconds * 1000)); } function onSpindleSpeed(spindleSpeed) { writeBlock(sOutput.format(spindleSpeed)); } function onCycle() { if (jetMode) { error(localize("Drilling is not supported for laser cutting.")); return; } } function getCommonCycle(x, y, z, r) { forceXYZ(); return [xOutput.format(x), yOutput.format(y), zOutput.format(z), (r !== undefined) ? "R" + xyzFormat.format(r) : ""]; } function onCyclePoint(x, y, z) { if (!isSameDirection(getRotation().forward, new Vector(0, 0, 1))) { expandCyclePoint(x, y, z); return; } var forceCycle = false; switch (cycleType) { case "tapping": case "left-tapping": case "right-tapping": case "tapping-with-chip-breaking": case "left-tapping-with-chip-breaking": case "right-tapping-with-chip-breaking": if (!isFirstCyclePoint()) { onCommand(COMMAND_STOP_SPINDLE); } forceCycle = true; } if (forceCycle || 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 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds writeBlock(gAbsIncModal.format(90)); switch (cycleType) { case "drilling": writeBlock( gRetractModal.format(98), gCycleModal.format(81), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); break; case "counter-boring": if (P > 0) { writeBlock( gRetractModal.format(98), gCycleModal.format(82), getCommonCycle(x, y, z, cycle.retract), "P" + milliFormat.format(P), feedOutput.format(F) ); } else { writeBlock( gRetractModal.format(98), gCycleModal.format(81), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); } break; case "chip-breaking": if (P > 0) { expandCyclePoint(x, y, z); } else { writeBlock( gRetractModal.format(98), gCycleModal.format(73), getCommonCycle(x, y, z, cycle.retract), "Q" + xyzFormat.format(cycle.incrementalDepth), feedOutput.format(F) ); } break; case "deep-drilling": if (P > 0) { expandCyclePoint(x, y, z); } else { writeBlock( gRetractModal.format(98), gCycleModal.format(83), getCommonCycle(x, y, z, cycle.retract), "Q" + xyzFormat.format(cycle.incrementalDepth), feedOutput.format(F) ); } break; case "tapping": if (P > 0) { expandCyclePoint(x, y, z); } else { if (!isFirstCyclePoint()) { writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } writeBlock( gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 33.2 : 33.1), zOutput.format(z), pitchOutput.format(tool.threadPitch) ); gCycleModal.reset(); } break; case "left-tapping": if (P > 0) { expandCyclePoint(x, y, z); } else { if (!isFirstCyclePoint()) { writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } writeBlock( gRetractModal.format(98), gCycleModal.format(33.2), zOutput.format(z), pitchOutput.format(tool.threadPitch) ); gCycleModal.reset(); } break; case "right-tapping": if (P > 0) { expandCyclePoint(x, y, z); } else { if (!isFirstCyclePoint()) { writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } writeBlock( gRetractModal.format(98), gCycleModal.format(33.1), zOutput.format(z), pitchOutput.format(tool.threadPitch) ); gCycleModal.reset(); } break; case "tapping-with-chip-breaking": if (P > 0) { expandCyclePoint(x, y, z); } else { if (!isFirstCyclePoint()) { writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } writeBlock( gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 33.2 : 33.1), zOutput.format(z), pitchOutput.format(tool.threadPitch), "Q" + xyzFormat.format(cycle.incrementalDepth) ); gCycleModal.reset(); } break; case "right-tapping-with-chip-breaking": if (P > 0) { expandCyclePoint(x, y, z); } else { if (!isFirstCyclePoint()) { writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } writeBlock( gRetractModal.format(98), gCycleModal.format(33.1), zOutput.format(z), pitchOutput.format(tool.threadPitch), "Q" + xyzFormat.format(cycle.incrementalDepth) ); gCycleModal.reset(); } break; case "left-tapping-with-chip-breaking": if (P > 0) { expandCyclePoint(x, y, z); } else { if (!isFirstCyclePoint()) { writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); } writeBlock( gRetractModal.format(98), gCycleModal.format(33.2), zOutput.format(z), pitchOutput.format(tool.threadPitch), "Q" + xyzFormat.format(cycle.incrementalDepth) ); gCycleModal.reset(); } break; default: expandCyclePoint(x, y, z); } } else { if (cycleExpanded) { expandCyclePoint(x, y, z); } else { var _x = xOutput.format(x); var _y = yOutput.format(y); if (!_x && !_y) { xOutput.reset(); // at least one axis is required _x = xOutput.format(x); } writeBlock(_x, _y); } } if (forceCycle) { sOutput.reset(); } } function onCycleEnd() { if (!cycleExpanded) { writeBlock(gCycleModal.format(80)); zOutput.reset(); } } var pendingRadiusCompensation = -1; function onRadiusCompensation() { pendingRadiusCompensation = radiusCompensation; error(localize("Radius compensation is not supported for UCCNC. Please change the compensation type to 'in computer' for the toolpath.")); return; } 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) { // at least one axis is required if (pendingRadiusCompensation >= 0) { // ensure that we end at desired position when compensation is turned off xOutput.reset(); yOutput.reset(); } 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; switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: writeBlock( gMotionModal.format(1), gFormat.format(41), x, y, z, conditional(properties.useToolChanger, "O" + xyzFormat.format(tool.diameter/2)), f ); break; case RADIUS_COMPENSATION_RIGHT: writeBlock( gMotionModal.format(1), gFormat.format(42), x, y, z, conditional(properties.useToolChanger, "O" + xyzFormat.format(tool.diameter/2)), 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; } // at least one axis is required 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 (isHelical()) { linearize(tolerance); return; } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); break; default: linearize(tolerance); } } else { switch (getCircularPlane()) { case PLANE_XY: writeBlock(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; default: linearize(tolerance); } } } var mapCommand = { }; function onCommand(command) { switch (command) { case COMMAND_POWER_ON: return; case COMMAND_POWER_OFF: return; case COMMAND_STOP: writeBlock(mFormat.format(2)); return; case COMMAND_OPTIONAL_STOP: writeBlock(mFormat.format(1)); return; case COMMAND_COOLANT_OFF: setCoolant(COOLANT_OFF); return; case COMMAND_START_SPINDLE: onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE); return; case COMMAND_SPINDLE_CLOCKWISE: writeBlock(mFormat.format(3)); return; case COMMAND_SPINDLE_COUNTERCLOCKWISE: writeBlock(mFormat.format(4)); return; case COMMAND_STOP_SPINDLE: writeBlock(mFormat.format(5)); return; case COMMAND_ORIENTATE_SPINDLE: 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() { forceAny(); } /** Output block to do safe retract and/or move to home position. */ function writeRetract() { if (arguments.length == 0) { error(localize("No axis specified for writeRetract().")); return; } var words = []; // store all retracted axes in an array for (var i = 0; i < arguments.length; ++i) { let instances = 0; // checks for duplicate retract calls for (var j = 0; j < arguments.length; ++j) { if (arguments[i] == arguments[j]) { ++instances; } } if (instances > 1) { // error if there are multiple retract calls for the same axis error(localize("Cannot retract the same axis twice in one line")); return; } switch (arguments[i]) { case X: words.push("X" + xyzFormat.format(machineConfiguration.hasHomePositionX() ? machineConfiguration.getHomePositionX() : 0)); break; case Y: words.push("Y" + xyzFormat.format(machineConfiguration.hasHomePositionY() ? machineConfiguration.getHomePositionY() : 0)); break; case Z: words.push("Z" + xyzFormat.format(machineConfiguration.getRetractPlane())); retracted = true; // specifies that the tool has been retracted to the safe plane break; default: error(localize("Bad axis specified for writeRetract().")); return; } } if (words.length > 0) { writeBlock(gMotionModal.format(0), gFormat.format(53), words); // retract } zOutput.reset(); } function onClose() { onCommand(COMMAND_COOLANT_OFF); onCommand(COMMAND_STOP_SPINDLE); if (!jetMode) { writeRetract(Z); } setWorkPlane(new Vector(0, 0, 0)); // reset working plane // writeBlock(gFormat.format(28)); // retract writeBlock(mFormat.format(30)); zOutput.reset(); }