/** Copyright (C) 2012-2024 by Autodesk, Inc. All rights reserved. MaslowCNC post processor configuration. $Revision: 44155 c7484e5d16072dec47fddad89ef85ab59f07423c $ $Date: 2024-12-13 16:41:18 $ FORKID {695FCA46-F545-4E34-8856-D8F81BBD96A8} */ description = "MaslowCNC"; vendor = "MaslowCNC"; vendorUrl = "http://www.maslowcnc.com/"; legal = "Copyright (C) 2012-2024 by Autodesk, Inc."; certificationLevel = 2; minimumRevision = 45917; longDescription = "Generic post for MaslowCNC."; extension = "nc"; setCodePage("ascii"); capabilities = CAPABILITY_MILLING | CAPABILITY_MACHINE_SIMULATION; 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 = false; allowedCircularPlanes = 1 << PLANE_XY; highFeedrate = (unit == MM) ? 5000 : 200; // user-defined properties properties = { useM06: { title : "Use M6", description: "Disable to avoid outputting M6. If disabled Preload is also disabled", group : "preferences", type : "boolean", value : true, scope : "post" }, showSequenceNumbers: { title : "Use sequence numbers", description: "'Yes' outputs sequence numbers on each block, 'Only on tool change' outputs sequence numbers on tool change blocks only, and 'No' disables the output of sequence numbers.", group : "formats", type : "enum", values : [ {title:"Yes", id:"true"}, {title:"No", id:"false"}, {title:"Only on tool change", id:"toolChange"} ], value: "false", scope: "post" }, sequenceNumberStart: { title : "Start sequence number", description: "The number at which to start the sequence numbers.", group : "formats", type : "integer", value : 10, scope : "post" }, sequenceNumberIncrement: { title : "Sequence number increment", description: "The amount by which the sequence number is incremented by in each block.", group : "formats", type : "integer", value : 5, scope : "post" }, optionalStop: { title : "Optional stop", description: "Outputs optional stop code during when necessary in the code.", group : "preferences", type : "boolean", value : false, scope : "post" }, separateWordsWithSpace: { title : "Separate words with space", description: "Adds spaces between words if 'yes' is selected.", group : "formats", type : "boolean", value : true, scope : "post" }, useActiveSpindle: { title : "Use active spindle", description: "Enable to use spindle commands (S, M3, M4, ...).", group : "preferences", type : "boolean", value : true, scope : "post" }, useRadius: { title : "Radius arcs", description: "If yes is selected, arcs are outputted using radius values rather than IJK.", group : "preferences", type : "boolean", value : false, scope : "post" }, safePositionMethod: { title : "Safe Retracts", description: "Select your desired retract option. 'Clearance Height' retracts to the operation clearance height.", group : "homePositions", type : "enum", values : [ {title:"G28", id:"G28"}, {title:"G53", id:"G53"}, {title:"Clearance Height", id:"clearanceHeight"} ], value: "clearanceHeight", scope: "post" }, useCoolant: { title : "Use coolant", description: "Specifies that coolant commands should be output", group : "preferences", type : "boolean", value : false, scope : "post" }, useWorkOffsets: { title : "Use work offsets", description: "Specifies to output work offset code (eg. G54).", group : "preferences", type : "boolean", value : false, scope : "post" }, useCircularInterpolation: { title : "Circular interpolation", description: "Output arcs as linear moves when set to No.", group : "preferences", type : "boolean", value : true, scope : "post" } }; // wcs definiton wcsDefinitions = { useZeroOffset: false, wcs : [ {name:"Standard", format:"G", range:[54, 59]} ] }; var gFormat = createFormat({prefix:"G", decimals:0}); var mFormat = createFormat({prefix:"M", decimals:0}); var hFormat = createFormat({prefix:"H", decimals:0}); // not supported at the moment var diameterOffsetFormat = createFormat({prefix:"D", decimals:0}); // not supported at the moment var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4)}); var rFormat = xyzFormat; // radius var abcFormat = createFormat({decimals:3, type:FORMAT_REAL, scale:DEG}); var feedFormat = createFormat({decimals:(unit == MM ? 0 : 1), type:FORMAT_REAL}); var toolFormat = createFormat({decimals:0}); var rpmFormat = createFormat({decimals:0}); var secFormat = createFormat({decimals:3, type:FORMAT_REAL}); // seconds - range 0.001-99999.999 var milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999 var taperFormat = createFormat({decimals:1, scale:DEG}); var xOutput = createOutputVariable({onchange:function() {state.retractedX = false;}, prefix:"X"}, xyzFormat); var yOutput = createOutputVariable({onchange:function() {state.retractedY = false;}, prefix:"Y"}, xyzFormat); var zOutput = createOutputVariable({onchange:function() {state.retractedZ = false;}, prefix:"Z"}, xyzFormat); var feedOutput = createOutputVariable({prefix:"F"}, feedFormat); var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat); // circular output var iOutput = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, xyzFormat); var jOutput = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, xyzFormat); var kOutput = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, xyzFormat); var gMotionModal = createOutputVariable({control:CONTROL_FORCE}, gFormat); // modal group 1 // G0-G3, ... var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 var gAbsIncModal = createOutputVariable({}, gFormat); // modal group 3 // G90-91 var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G93-94 var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G20-21 var gRetractModal = createOutputVariable({}, gFormat); // modal group 10 // G98-99 // collected State var wait; var settings = { coolant: { // samples: // {id: COOLANT_THROUGH_TOOL, on: 88, off: 89} // {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]} // {id: COOLANT_THROUGH_TOOL, on: "M88 P3 (myComment)", off: "M89"} coolants: [ {id:COOLANT_FLOOD, on:8}, {id:COOLANT_MIST}, {id:COOLANT_THROUGH_TOOL}, {id:COOLANT_AIR}, {id:COOLANT_AIR_THROUGH_TOOL}, {id:COOLANT_SUCTION}, {id:COOLANT_FLOOD_MIST}, {id:COOLANT_FLOOD_THROUGH_TOOL}, {id:COOLANT_OFF, off:9} ], singleLineCoolant: false, // specifies to output multiple coolant codes in one line rather than in separate lines }, retract: { cancelRotationOnRetracting: false, // specifies that rotations (G68) need to be canceled prior to retracting methodXY : undefined, // special condition, overwrite retract behavior per axis methodZ : undefined, // special condition, overwrite retract behavior per axis useZeroValues : ["G28", "G30"], // enter property value id(s) for using "0" value instead of machineConfiguration axes home position values (ie G30 Z0) homeXY : {onIndexing:false, onToolChange:false, onProgramEnd:false} // Specifies when the machine should be homed in X/Y. Sample: onIndexing:{axes:[X, Y], singleLine:false} }, comments: { permittedCommentChars: " abcdefghijklmnopqrstuvwxyz0123456789.,=_-:", // letters are not case sensitive, use option 'outputFormat' below. Set to 'undefined' to allow any character prefix : "(", // specifies the prefix for the comment suffix : ")", // specifies the suffix for the comment outputFormat : "upperCase", // can be set to "upperCase", "lowerCase" and "ignoreCase". Set to "ignoreCase" to write comments without upper/lower case formatting maximumLineLength : 80 // the maximum number of characters allowed in a line, set to 0 to disable comment output }, maximumSequenceNumber : 99999, // the maximum sequence number (Nxxx), use 'undefined' for unlimited supportsOptionalBlocks : false, // specifies if optional block output is supported outputToolLengthCompensation: false, // specifies if tool length compensation code should be output (G43) outputToolLengthOffset : false, // specifies if tool length offset code should be output (Hxx) // fixed settings below, do not modify supportsTCP : false // this postprocessor does not support TCP }; function onOpen() { if (machineConfiguration.isMultiAxisConfiguration()) { error(localize("This postprocessor does not support multi axis machine configurations.")); } if (getProperty("useRadius")) { maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC } if (!getProperty("useCircularInterpolation")) { allowedCircularPlanes = 0; } if (!getProperty("separateWordsWithSpace")) { setWordSeparator(""); } writeComment(programName); writeComment(programComment); writeProgramHeader(); // absolute coordinates and feed per min writeBlock(gFormat.format(0), gFormat.format(40), gAbsIncModal.format(90), gPlaneModal.format(17)); writeBlock(gUnitModal.format(unit == MM ? 21 : 20)); validateCommonParameters(); } function onSection() { var forceSectionRestart = optionalSection && !currentSection.isOptional(); optionalSection = currentSection.isOptional(); var insertToolCall = isToolChangeNeeded("number") || forceSectionRestart; var newWorkOffset = isNewWorkOffset() || forceSectionRestart; var newWorkPlane = isNewWorkPlane() || forceSectionRestart; if (insertToolCall || newWorkOffset || newWorkPlane) { if (insertToolCall && !isFirstSection()) { onCommand(COMMAND_STOP_SPINDLE); // stop spindle before retract during tool change } if (getProperty("safePositionMethod") == "G28" && isFirstSection()) { // avoid initial retract at program start since no tool is loaded at this point state.retractedZ = true; } else { writeRetract(Z); // retract } } writeln(""); writeComment(getParameter("operation-comment", "")); // tool change writeToolCall(tool, insertToolCall); if (insertToolCall && !getProperty("useActiveSpindle")) { wait = true; } startSpindle(tool, insertToolCall); if (wait) { onCommand(COMMAND_STOP); forceSpindleSpeed = false; } // wcs if (insertToolCall) { // force work offset when changing tool currentWorkOffset = undefined; } if (getProperty("useWorkOffsets")) { writeWCS(currentSection, true); } { // 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); } setCoolant(tool.coolant); // writes the required coolant codes forceXYZ(); forceFeed(); // prepositioning var initialPosition = getFramePosition(currentSection.getInitialPosition()); var isRequired = insertToolCall || state.retractedZ || !state.lengthCompensationActive || (!isFirstSection() && getPreviousSection().isMultiAxis()); writeInitialPositioning(initialPosition, isRequired); state.retractedZ = false; } function onDwell(seconds) { var maxValue = 99999.999; if (seconds > maxValue) { warning(subst(localize("Dwelling time of '%1' exceeds the maximum value of '%2' in operation '%3'"), seconds, maxValue, getParameter("operation-comment", ""))); } writeBlock(gFormat.format(4), "P" + secFormat.format(seconds)); } function onSpindleSpeed(spindleSpeed) { if (getProperty("useActiveSpindle")) { writeBlock(sOutput.format(spindleSpeed)); } else { writeComment(sOutput.format(spindleSpeed)); onCommand(COMMAND_STOP); } } var mapCommand = { COMMAND_END : 2, COMMAND_STOP_SPINDLE: 5 }; function onCommand(command) { switch (command) { case COMMAND_COOLANT_OFF: setCoolant(COOLANT_OFF); return; case COMMAND_COOLANT_ON: setCoolant(tool.coolant); // writes the required coolant codes return; case COMMAND_STOP: writeBlock(mFormat.format(0)); forceSpindleSpeed = true; forceCoolant = true; return; case COMMAND_OPTIONAL_STOP: writeBlock(mFormat.format(1)); forceSpindleSpeed = true; forceCoolant = true; return; case COMMAND_STOP_SPINDLE: if (!getProperty("useActiveSpindle")) { return; } break; case COMMAND_START_SPINDLE: if (getProperty("useActiveSpindle")) { forceSpindleSpeed = false; writeToolBlock(mFormat.format(tool.clockwise ? 3 : 4), sOutput.format(spindleSpeed)); } else { writeComment(mFormat.format(tool.clockwise ? 3 : 4) + " " + sOutput.format(spindleSpeed)); wait = true; } return; case COMMAND_LOAD_TOOL: writeToolBlock("T" + toolFormat.format(tool.number), getProperty("useM06") ? mFormat.format(6) : ""); writeComment(tool.comment); 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() { writeBlock(gPlaneModal.format(17)); if (!isLastSection()) { if (getNextSection().getTool().coolant != tool.coolant) { setCoolant(COOLANT_OFF); } if (tool.breakControl && isToolChangeNeeded(getNextSection(), getProperty("toolAsName") ? "description" : "number")) { onCommand(COMMAND_BREAK_CONTROL); } } forceXYZ(); forceFeed(); wait = false; // reset } function onClose() { optionalSection = false; writeln(""); setCoolant(COOLANT_OFF); writeRetract(Z); onCommand(COMMAND_STOP_SPINDLE); if (getSetting("retract.homeXY.onProgramEnd", false)) { writeRetract(settings.retract.homeXY.onProgramEnd); } writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off } // >>>>> INCLUDED FROM include_files/commonFunctions.cpi // internal variables, do not change var receivedMachineConfiguration; var tcp = {isSupportedByControl:getSetting("supportsTCP", true), isSupportedByMachine:false, isSupportedByOperation:false}; var state = { retractedX : false, // specifies that the machine has been retracted in X retractedY : false, // specifies that the machine has been retracted in Y retractedZ : false, // specifies that the machine has been retracted in Z tcpIsActive : false, // specifies that TCP is currently active twpIsActive : false, // specifies that TWP is currently active lengthCompensationActive: !getSetting("outputToolLengthCompensation", true), // specifies that tool length compensation is active mainState : true // specifies the current context of the state (true = main, false = optional) }; var validateLengthCompensation = getSetting("outputToolLengthCompensation", true); // disable validation when outputToolLengthCompensation is disabled var multiAxisFeedrate; var sequenceNumber; var optionalSection = false; var currentWorkOffset; var forceSpindleSpeed = false; var operationNeedsSafeStart = false; // used to convert blocks to optional for safeStartAllOperations function activateMachine() { // disable unsupported rotary axes output if (!machineConfiguration.isMachineCoordinate(0) && (typeof aOutput != "undefined")) { aOutput.disable(); } if (!machineConfiguration.isMachineCoordinate(1) && (typeof bOutput != "undefined")) { bOutput.disable(); } if (!machineConfiguration.isMachineCoordinate(2) && (typeof cOutput != "undefined")) { cOutput.disable(); } // setup usage of useTiltedWorkplane settings.workPlaneMethod.useTiltedWorkplane = getProperty("useTiltedWorkplane") != undefined ? getProperty("useTiltedWorkplane") : getSetting("workPlaneMethod.useTiltedWorkplane", false); settings.workPlaneMethod.useABCPrepositioning = getProperty("useABCPrepositioning") != undefined ? getProperty("useABCPrepositioning") : getSetting("workPlaneMethod.useABCPrepositioning", false); if (!machineConfiguration.isMultiAxisConfiguration()) { return; // don't need to modify any settings for 3-axis machines } // identify if any of the rotary axes has TCP enabled var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; tcp.isSupportedByMachine = axes.some(function(axis) {return axis.isEnabled() && axis.isTCPEnabled();}); // true if TCP is enabled on any rotary axis // save multi-axis feedrate settings from machine configuration var mode = machineConfiguration.getMultiAxisFeedrateMode(); var type = mode == FEED_INVERSE_TIME ? machineConfiguration.getMultiAxisFeedrateInverseTimeUnits() : (mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateDPMType() : DPM_STANDARD); multiAxisFeedrate = { mode : mode, maximum : machineConfiguration.getMultiAxisFeedrateMaximum(), type : type, tolerance: mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateOutputTolerance() : 0, bpwRatio : mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateBpwRatio() : 1 }; // setup of retract/reconfigure TAG: Only needed until post kernel supports these machine config settings if (receivedMachineConfiguration && machineConfiguration.performRewinds()) { safeRetractDistance = machineConfiguration.getSafeRetractDistance(); safePlungeFeed = machineConfiguration.getSafePlungeFeedrate(); safeRetractFeed = machineConfiguration.getSafeRetractFeedrate(); } if (typeof safeRetractDistance == "number" && getProperty("safeRetractDistance") != undefined && getProperty("safeRetractDistance") != 0) { safeRetractDistance = getProperty("safeRetractDistance"); } if (machineConfiguration.isHeadConfiguration()) { compensateToolLength = typeof compensateToolLength == "undefined" ? false : compensateToolLength; } if (machineConfiguration.isHeadConfiguration() && compensateToolLength) { for (var i = 0; i < getNumberOfSections(); ++i) { var section = getSection(i); if (section.isMultiAxis()) { machineConfiguration.setToolLength(getBodyLength(section.getTool())); // define the tool length for head adjustments section.optimizeMachineAnglesByMachine(machineConfiguration, OPTIMIZE_AXIS); } } } else { optimizeMachineAngles2(OPTIMIZE_AXIS); } } function getBodyLength(tool) { for (var i = 0; i < getNumberOfSections(); ++i) { var section = getSection(i); if (tool.number == section.getTool().number) { return section.getParameter("operation:tool_overallLength", tool.bodyLength + tool.holderLength); } } return tool.bodyLength + tool.holderLength; } function getFeed(f) { if (getProperty("useG95")) { return feedOutput.format(f / spindleSpeed); // use feed value } if (typeof activeMovements != "undefined" && 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 settings.parametricFeeds.feedOutputVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id); } } currentFeedId = undefined; // force parametric feed next time } return feedOutput.format(f); // use feed value } function validateCommonParameters() { validateToolData(); for (var i = 0; i < getNumberOfSections(); ++i) { var section = getSection(i); if (getSection(0).workOffset == 0 && section.workOffset > 0) { if (!(typeof wcsDefinitions != "undefined" && wcsDefinitions.useZeroOffset)) { error(localize("Using multiple work offsets is not possible if the initial work offset is 0.")); } } if (section.isMultiAxis()) { if (!section.isOptimizedForMachine() && (!getSetting("workPlaneMethod.useTiltedWorkplane", false) || !getSetting("supportsToolVectorOutput", false))) { error(localize("This postprocessor requires a machine configuration for 5-axis simultaneous toolpath.")); } if (machineConfiguration.getMultiAxisFeedrateMode() == FEED_INVERSE_TIME && !getSetting("supportsInverseTimeFeed", true)) { error(localize("This postprocessor does not support inverse time feedrates.")); } if (getSetting("supportsToolVectorOutput", false) && !tcp.isSupportedByControl) { error(localize("Incompatible postprocessor settings detected." + EOL + "Setting 'supportsToolVectorOutput' requires setting 'supportsTCP' to be enabled as well.")); } } } if (!tcp.isSupportedByControl && tcp.isSupportedByMachine) { error(localize("The machine configuration has TCP enabled which is not supported by this postprocessor.")); } if (getProperty("safePositionMethod") == "clearanceHeight") { var msg = "-Attention- Property 'Safe Retracts' is set to 'Clearance Height'." + EOL + "Ensure the clearance height will clear the part and or fixtures." + EOL + "Raise the Z-axis to a safe height before starting the program."; warning(msg); writeComment(msg); } } function validateToolData() { var _default = 99999; var _maximumSpindleRPM = machineConfiguration.getMaximumSpindleSpeed() > 0 ? machineConfiguration.getMaximumSpindleSpeed() : settings.maximumSpindleRPM == undefined ? _default : settings.maximumSpindleRPM; var _maximumToolNumber = machineConfiguration.isReceived() && machineConfiguration.getNumberOfTools() > 0 ? machineConfiguration.getNumberOfTools() : settings.maximumToolNumber == undefined ? _default : settings.maximumToolNumber; var _maximumToolLengthOffset = settings.maximumToolLengthOffset == undefined ? _default : settings.maximumToolLengthOffset; var _maximumToolDiameterOffset = settings.maximumToolDiameterOffset == undefined ? _default : settings.maximumToolDiameterOffset; var header = ["Detected maximum values are out of range.", "Maximum values:"]; var warnings = { toolNumber : {msg:"Tool number value exceeds the maximum value for tool: " + EOL, max:" Tool number: " + _maximumToolNumber, values:[]}, lengthOffset : {msg:"Tool length offset value exceeds the maximum value for tool: " + EOL, max:" Tool length offset: " + _maximumToolLengthOffset, values:[]}, diameterOffset: {msg:"Tool diameter offset value exceeds the maximum value for tool: " + EOL, max:" Tool diameter offset: " + _maximumToolDiameterOffset, values:[]}, spindleSpeed : {msg:"Spindle speed exceeds the maximum value for operation: " + EOL, max:" Spindle speed: " + _maximumSpindleRPM, values:[]} }; var toolIds = []; for (var i = 0; i < getNumberOfSections(); ++i) { var section = getSection(i); if (toolIds.indexOf(section.getTool().getToolId()) === -1) { // loops only through sections which have a different tool ID var toolNumber = section.getTool().number; var lengthOffset = section.getTool().lengthOffset; var diameterOffset = section.getTool().diameterOffset; var comment = section.getParameter("operation-comment", ""); if (toolNumber > _maximumToolNumber && !getProperty("toolAsName")) { warnings.toolNumber.values.push(SP + toolNumber + EOL); } if (lengthOffset > _maximumToolLengthOffset) { warnings.lengthOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Length offset: " + lengthOffset + ")" + EOL); } if (diameterOffset > _maximumToolDiameterOffset) { warnings.diameterOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Diameter offset: " + diameterOffset + ")" + EOL); } toolIds.push(section.getTool().getToolId()); } // loop through all sections regardless of tool id for idenitfying spindle speeds // identify if movement ramp is used in current toolpath, use ramp spindle speed for comparisons var ramp = section.getMovements() & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_ZIG_ZAG) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_HELIX)); var _sectionSpindleSpeed = Math.max(section.getTool().spindleRPM, ramp ? section.getTool().rampingSpindleRPM : 0, 0); if (_sectionSpindleSpeed > _maximumSpindleRPM) { warnings.spindleSpeed.values.push(SP + section.getParameter("operation-comment", "") + " (" + _sectionSpindleSpeed + " RPM" + ")" + EOL); } } // sort lists by tool number warnings.toolNumber.values.sort(function(a, b) {return a - b;}); warnings.lengthOffset.values.sort(function(a, b) {return a.localeCompare(b);}); warnings.diameterOffset.values.sort(function(a, b) {return a.localeCompare(b);}); var warningMessages = []; for (var key in warnings) { if (warnings[key].values != "") { header.push(warnings[key].max); // add affected max values to the header warningMessages.push(warnings[key].msg + warnings[key].values.join("")); } } if (warningMessages.length != 0) { warningMessages.unshift(header.join(EOL) + EOL); warning(warningMessages.join(EOL)); } } function forceFeed() { currentFeedId = undefined; feedOutput.reset(); } /** 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(); } /** Writes the specified block. */ function writeBlock() { var text = formatWords(arguments); if (!text) { return; } var prefix = getSetting("sequenceNumberPrefix", "N"); var suffix = getSetting("writeBlockSuffix", ""); if ((optionalSection || skipBlocks) && !getSetting("supportsOptionalBlocks", true)) { error(localize("Optional blocks are not supported by this post.")); } if (getProperty("showSequenceNumbers") == "true") { if (sequenceNumber == undefined || sequenceNumber >= settings.maximumSequenceNumber) { sequenceNumber = getProperty("sequenceNumberStart"); } if (optionalSection || skipBlocks) { writeWords2("/", prefix + sequenceNumber, text + suffix); } else { writeWords2(prefix + sequenceNumber, text + suffix); } sequenceNumber += getProperty("sequenceNumberIncrement"); } else { if (optionalSection || skipBlocks) { writeWords2("/", text + suffix); } else { writeWords(text + suffix); } } } validate(settings.comments, "Setting 'comments' is required but not defined."); function formatComment(text) { var prefix = settings.comments.prefix; var suffix = settings.comments.suffix; var _permittedCommentChars = settings.comments.permittedCommentChars == undefined ? "" : settings.comments.permittedCommentChars; switch (settings.comments.outputFormat) { case "upperCase": text = text.toUpperCase(); _permittedCommentChars = _permittedCommentChars.toUpperCase(); break; case "lowerCase": text = text.toLowerCase(); _permittedCommentChars = _permittedCommentChars.toLowerCase(); break; case "ignoreCase": _permittedCommentChars = _permittedCommentChars.toUpperCase() + _permittedCommentChars.toLowerCase(); break; default: error(localize("Unsupported option specified for setting 'comments.outputFormat'.")); } if (_permittedCommentChars != "") { text = filterText(String(text), _permittedCommentChars); } text = String(text).substring(0, settings.comments.maximumLineLength - prefix.length - suffix.length); return text != "" ? prefix + text + suffix : ""; } /** Output a comment. */ function writeComment(text) { if (!text) { return; } var comments = String(text).split(EOL); for (comment in comments) { var _comment = formatComment(comments[comment]); if (_comment) { if (getSetting("comments.showSequenceNumbers", false)) { writeBlock(_comment); } else { writeln(_comment); } } } } function onComment(text) { writeComment(text); } /** Writes the specified block - used for tool changes only. */ function writeToolBlock() { var show = getProperty("showSequenceNumbers"); setProperty("showSequenceNumbers", (show == "true" || show == "toolChange") ? "true" : "false"); writeBlock(arguments); setProperty("showSequenceNumbers", show); machineSimulation({/*x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE,*/ mode:TOOLCHANGE}); // move machineSimulation to a tool change position } var skipBlocks = false; var initialState = JSON.parse(JSON.stringify(state)); // save initial state var optionalState = JSON.parse(JSON.stringify(state)); var saveCurrentSectionId = undefined; function writeStartBlocks(isRequired, code) { var saveSkipBlocks = skipBlocks; var saveMainState = state; // save main state if (!isRequired) { if (!getProperty("safeStartAllOperations", false)) { return; // when safeStartAllOperations is disabled, dont output code and return } if (saveCurrentSectionId != getCurrentSectionId()) { saveCurrentSectionId = getCurrentSectionId(); forceModals(); // force all modal variables when entering a new section optionalState = Object.create(initialState); // reset optionalState to initialState when entering a new section } skipBlocks = true; // if values are not required, but safeStartAllOperations is enabled - write following blocks as optional state = optionalState; // set state to optionalState if skipBlocks is true state.mainState = false; } code(); // writes out the code which is passed to this function as an argument state = saveMainState; // restore main state skipBlocks = saveSkipBlocks; // restore skipBlocks value } var pendingRadiusCompensation = -1; function onRadiusCompensation() { pendingRadiusCompensation = radiusCompensation; if (pendingRadiusCompensation >= 0 && !getSetting("supportsRadiusCompensation", true)) { error(localize("Radius compensation mode is not supported.")); return; } } function onPassThrough(text) { var commands = String(text).split(","); for (text in commands) { writeBlock(commands[text]); } } function forceModals() { if (arguments.length == 0) { // reset all modal variables listed below if (typeof gMotionModal != "undefined") { gMotionModal.reset(); } if (typeof gPlaneModal != "undefined") { gPlaneModal.reset(); } if (typeof gAbsIncModal != "undefined") { gAbsIncModal.reset(); } if (typeof gFeedModeModal != "undefined") { gFeedModeModal.reset(); } } else { for (var i in arguments) { arguments[i].reset(); // only reset the modal variable passed to this function } } } /** Helper function to be able to use a default value for settings which do not exist. */ function getSetting(setting, defaultValue) { var result = defaultValue; var keys = setting.split("."); var obj = settings; for (var i in keys) { if (obj[keys[i]] != undefined) { // setting does exist result = obj[keys[i]]; if (typeof [keys[i]] === "object") { obj = obj[keys[i]]; continue; } } else { // setting does not exist, use default value if (defaultValue != undefined) { result = defaultValue; } else { error("Setting '" + keys[i] + "' has no default value and/or does not exist."); return undefined; } } } return result; } function getForwardDirection(_section) { var forward = undefined; var _optimizeType = settings.workPlaneMethod && settings.workPlaneMethod.optimizeType; if (_section.isMultiAxis()) { forward = _section.workPlane.forward; } else if (!getSetting("workPlaneMethod.useTiltedWorkplane", false) && machineConfiguration.isMultiAxisConfiguration()) { if (_optimizeType == undefined) { var saveRotation = getRotation(); getWorkPlaneMachineABC(_section, true); forward = getRotation().forward; setRotation(saveRotation); // reset rotation } else { var abc = getWorkPlaneMachineABC(_section, false); var forceAdjustment = settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH; forward = machineConfiguration.getOptimizedDirection(_section.workPlane.forward, abc, false, forceAdjustment); } } else { forward = getRotation().forward; } return forward; } function getRetractParameters() { var _arguments = typeof arguments[0] === "object" ? arguments[0].axes : arguments; var singleLine = arguments[0].singleLine == undefined ? true : arguments[0].singleLine; var words = []; // store all retracted axes in an array var retractAxes = new Array(false, false, false); var method = getProperty("safePositionMethod", "undefined"); if (method == "clearanceHeight") { if (!is3D()) { error(localize("Safe retract option 'Clearance Height' is only supported when all operations are along the setup Z-axis.")); } return undefined; } validate(settings.retract, "Setting 'retract' is required but not defined."); validate(_arguments.length != 0, "No axis specified for getRetractParameters()."); for (i in _arguments) { retractAxes[_arguments[i]] = true; } if ((retractAxes[0] || retractAxes[1]) && !state.retractedZ) { // retract Z first before moving to X/Y home error(localize("Retracting in X/Y is not possible without being retracted in Z.")); return undefined; } // special conditions if (retractAxes[0] || retractAxes[1]) { method = getSetting("retract.methodXY", method); } if (retractAxes[2]) { method = getSetting("retract.methodZ", method); } // define home positions var useZeroValues = (settings.retract.useZeroValues && settings.retract.useZeroValues.indexOf(method) != -1); var _xHome = machineConfiguration.hasHomePositionX() && !useZeroValues ? machineConfiguration.getHomePositionX() : toPreciseUnit(0, MM); var _yHome = machineConfiguration.hasHomePositionY() && !useZeroValues ? machineConfiguration.getHomePositionY() : toPreciseUnit(0, MM); var _zHome = machineConfiguration.getRetractPlane() != 0 && !useZeroValues ? machineConfiguration.getRetractPlane() : toPreciseUnit(0, MM); for (var i = 0; i < _arguments.length; ++i) { switch (_arguments[i]) { case X: if (!state.retractedX) { words.push("X" + xyzFormat.format(_xHome)); xOutput.reset(); state.retractedX = true; } break; case Y: if (!state.retractedY) { words.push("Y" + xyzFormat.format(_yHome)); yOutput.reset(); state.retractedY = true; } break; case Z: if (!state.retractedZ) { words.push("Z" + xyzFormat.format(_zHome)); zOutput.reset(); state.retractedZ = true; } break; default: error(localize("Unsupported axis specified for getRetractParameters().")); return undefined; } } return { method : method, retractAxes: retractAxes, words : words, positions : { x: retractAxes[0] ? _xHome : undefined, y: retractAxes[1] ? _yHome : undefined, z: retractAxes[2] ? _zHome : undefined}, singleLine: singleLine}; } /** Returns true when subprogram logic does exist into the post. */ function subprogramsAreSupported() { return typeof subprogramState != "undefined"; } // Start of machine simulation connection move support var debugSimulation = false; // enable to output debug information for connection move support in the NC program var TCPON = "TCP ON"; var TCPOFF = "TCP OFF"; var TWPON = "TWP ON"; var TWPOFF = "TWP OFF"; var TOOLCHANGE = "TOOL CHANGE"; var WORK = "WORK CS"; var MACHINE = "MACHINE CS"; var MIN = "MIN"; var MAX = "MAX"; var WARNING_NON_RANGE = [0, 1, 2]; var isTwpOn; // only used for debugging var isTcpOn; // only used for debugging if (typeof groupDefinitions != "object") { groupDefinitions = {}; } groupDefinitions.machineSimulation = {title:"Machine Simulation", collapsed:true, order:99}; properties.simulateConnectionMovesEnabled = { title : "Simulate Connection Moves (Preview feature)", description: "Specifies that connection moves like prepositioning, tool changes, retracts and other non-cutting moves should be shown in the machine simulation." + EOL + "Note, this property does not affect the NC output, it only affects the machine simulation.", group: "machineSimulation", type : "boolean", value: true, scope: "machine" }; /** * Helper function for connection moves in machine simulation. * @param {Object} parameters An object containing the desired options for machine simulation. * @note Available properties are: * @param {Number} x X axis position, alternatively use MIN or MAX to move to the axis limit * @param {Number} y Y axis position, alternatively use MIN or MAX to move to the axis limit * @param {Number} z Z axis position, alternatively use MIN or MAX to move to the axis limit * @param {Number} a A axis position (in radians) * @param {Number} b B axis position (in radians) * @param {Number} c C axis position (in radians) * @param {Number} feed desired feedrate, automatically set to high/current feedrate if not specified * @param {String} mode mode TCPON | TCPOFF | TWPON | TWPOFF | TOOLCHANGE * @param {String} coordinates WORK | MACHINE - if undefined, work coordinates will be used by default * @param {Number} eulerAngles the calculated Euler angles for the workplane * @example machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); machineSimulation({x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE, mode:TOOLCHANGE}); */ function machineSimulation(parameters) { if (revision < 50075 || skipBlocks || !getProperty("simulateConnectionMovesEnabled")) { return; // return when post kernel revision is lower than 50075 or when skipBlocks is enabled } getAxisLimit = function(axis, limit) { validate(limit == MIN || limit == MAX, subst(localize("Invalid argument \"%1\" passed to the machineSimulation function."), limit)); var range = axis.getRange(); if (range.isNonRange()) { var axisLetters = ["X", "Y", "Z"]; var warningMessage = subst(localize("An attempt was made to move the \"%1\" axis to its MIN/MAX limits during machine simulation, but its range is set to \"unlimited\"." + EOL + "A limited range must be set for the \"%1\" axis in the machine definition, or these motions will not be shown in machine simulation."), axisLetters[axis.getCoordinate()]); warningOnce(warningMessage, WARNING_NON_RANGE[axis.getCoordinate()]); return undefined; } return limit == MIN ? range.minimum : range.maximum; }; var x = (isNaN(parameters.x) && parameters.x) ? getAxisLimit(machineConfiguration.getAxisX(), parameters.x) : parameters.x; var y = (isNaN(parameters.y) && parameters.y) ? getAxisLimit(machineConfiguration.getAxisY(), parameters.y) : parameters.y; var z = (isNaN(parameters.z) && parameters.z) ? getAxisLimit(machineConfiguration.getAxisZ(), parameters.z) : parameters.z; var rotaryAxesErrorMessage = localize("Invalid argument for rotary axes passed to the machineSimulation function. Only numerical values are supported."); var a = (isNaN(parameters.a) && parameters.a) ? error(rotaryAxesErrorMessage) : parameters.a; var b = (isNaN(parameters.b) && parameters.b) ? error(rotaryAxesErrorMessage) : parameters.b; var c = (isNaN(parameters.c) && parameters.c) ? error(rotaryAxesErrorMessage) : parameters.c; var coordinates = parameters.coordinates; var eulerAngles = parameters.eulerAngles; var feed = parameters.feed; if (feed === undefined && typeof gMotionModal !== "undefined") { feed = gMotionModal.getCurrent() !== 0; } var mode = parameters.mode; var performToolChange = mode == TOOLCHANGE; if (mode !== undefined && ![TCPON, TCPOFF, TWPON, TWPOFF, TOOLCHANGE].includes(mode)) { error(subst("Mode '%1' is not supported.", mode)); } // mode takes precedence over active state var enableTCP = mode != undefined ? mode == TCPON : typeof state !== "undefined" && state.tcpIsActive; var enableTWP = mode != undefined ? mode == TWPON : typeof state !== "undefined" && state.twpIsActive; var disableTCP = mode != undefined ? mode == TCPOFF : typeof state !== "undefined" && !state.tcpIsActive; var disableTWP = mode != undefined ? mode == TWPOFF : typeof state !== "undefined" && !state.twpIsActive; if (enableTCP) { // update TCP mode simulation.setTWPModeOff(); simulation.setTCPModeOn(); isTcpOn = true; } else if (disableTCP) { simulation.setTCPModeOff(); isTcpOn = false; } if (enableTWP) { // update TWP mode simulation.setTCPModeOff(); if (settings.workPlaneMethod.eulerConvention == undefined) { simulation.setTWPModeAlignToCurrentPose(); } else if (eulerAngles) { simulation.setTWPModeByEulerAngles(settings.workPlaneMethod.eulerConvention, eulerAngles.x, eulerAngles.y, eulerAngles.z); } isTwpOn = true; } else if (disableTWP) { simulation.setTWPModeOff(); isTwpOn = false; } if (debugSimulation) { writeln(" DEBUG" + JSON.stringify(parameters)); writeln(" DEBUG" + JSON.stringify({isTwpOn:isTwpOn, isTcpOn:isTcpOn, feed:feed})); } if (x !== undefined || y !== undefined || z !== undefined || a !== undefined || b !== undefined || c !== undefined) { if (x !== undefined) {simulation.setTargetX(x);} if (y !== undefined) {simulation.setTargetY(y);} if (z !== undefined) {simulation.setTargetZ(z);} if (a !== undefined) {simulation.setTargetA(a);} if (b !== undefined) {simulation.setTargetB(b);} if (c !== undefined) {simulation.setTargetC(c);} if (feed != undefined && feed) { simulation.setMotionToLinear(); simulation.setFeedrate(typeof feed == "number" ? feed : feedOutput.getCurrent() == 0 ? highFeedrate : feedOutput.getCurrent()); } else { simulation.setMotionToRapid(); } if (coordinates != undefined && coordinates == MACHINE) { simulation.moveToTargetInMachineCoords(); } else { simulation.moveToTargetInWorkCoords(); } } if (performToolChange) { simulation.performToolChangeCycle(); simulation.moveToTargetInMachineCoords(); } } // <<<<< INCLUDED FROM include_files/commonFunctions.cpi // >>>>> INCLUDED FROM include_files/writeWCS.cpi function writeWCS(section, wcsIsRequired) { if (section.workOffset != currentWorkOffset) { if (getSetting("workPlaneMethod.cancelTiltFirst", false) && wcsIsRequired) { cancelWorkPlane(); } if (typeof forceWorkPlane == "function" && wcsIsRequired) { forceWorkPlane(); } writeStartBlocks(wcsIsRequired, function () { writeBlock(section.wcs); }); currentWorkOffset = section.workOffset; } } // <<<<< INCLUDED FROM include_files/writeWCS.cpi // >>>>> INCLUDED FROM include_files/writeToolCall.cpi function writeToolCall(tool, insertToolCall) { if (!isFirstSection()) { writeStartBlocks(!getProperty("safeStartAllOperations") && insertToolCall, function () { writeRetract(Z); // write optional Z retract before tool change if safeStartAllOperations is enabled }); } writeStartBlocks(insertToolCall, function () { writeRetract(Z); if (getSetting("retract.homeXY.onToolChange", false)) { writeRetract(settings.retract.homeXY.onToolChange); } if (!isFirstSection() && insertToolCall) { if (typeof forceWorkPlane == "function") { forceWorkPlane(); } onCommand(COMMAND_COOLANT_OFF); // turn off coolant on tool change if (typeof disableLengthCompensation == "function") { disableLengthCompensation(false); } } if (tool.manualToolChange) { onCommand(COMMAND_STOP); writeComment("MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number)); } else { if (!isFirstSection() && getProperty("optionalStop") && insertToolCall) { onCommand(COMMAND_OPTIONAL_STOP); } onCommand(COMMAND_LOAD_TOOL); } }); if (typeof forceModals == "function" && (insertToolCall || getProperty("safeStartAllOperations"))) { forceModals(); } } // <<<<< INCLUDED FROM include_files/writeToolCall.cpi // >>>>> INCLUDED FROM include_files/startSpindle.cpi function startSpindle(tool, insertToolCall) { if (tool.type != TOOL_PROBE) { var spindleSpeedIsRequired = insertToolCall || forceSpindleSpeed || isFirstSection() || rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent()) || (tool.clockwise != getPreviousSection().getTool().clockwise); writeStartBlocks(spindleSpeedIsRequired, function () { if (spindleSpeedIsRequired || operationNeedsSafeStart) { onCommand(COMMAND_START_SPINDLE); } }); } } // <<<<< INCLUDED FROM include_files/startSpindle.cpi // >>>>> INCLUDED FROM include_files/coolant.cpi var currentCoolantMode = COOLANT_OFF; var coolantOff = undefined; var isOptionalCoolant = false; var forceCoolant = false; function setCoolant(coolant) { var coolantCodes = getCoolantCodes(coolant); if (Array.isArray(coolantCodes)) { writeStartBlocks(!isOptionalCoolant, function () { if (settings.coolant.singleLineCoolant) { writeBlock(coolantCodes.join(getWordSeparator())); } else { for (var c in coolantCodes) { writeBlock(coolantCodes[c]); } } }); return undefined; } return coolantCodes; } function getCoolantCodes(coolant, format) { if (!getProperty("useCoolant", true)) { return undefined; // coolant output is disabled by property if it exists } isOptionalCoolant = false; if (typeof operationNeedsSafeStart == "undefined") { operationNeedsSafeStart = false; } var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line var coolants = settings.coolant.coolants; if (!coolants) { error(localize("Coolants have not been defined.")); } if (tool.type && tool.type == TOOL_PROBE) { // avoid coolant output for probing coolant = COOLANT_OFF; } if (coolant == currentCoolantMode) { if (operationNeedsSafeStart && coolant != COOLANT_OFF) { isOptionalCoolant = true; } else if (!forceCoolant || coolant == COOLANT_OFF) { return undefined; // coolant is already active } } if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined) && !forceCoolant && !isOptionalCoolant) { if (Array.isArray(coolantOff)) { for (var i in coolantOff) { multipleCoolantBlocks.push(coolantOff[i]); } } else { multipleCoolantBlocks.push(coolantOff); } } forceCoolant = false; var m; var coolantCodes = {}; for (var c in coolants) { // find required coolant codes into the coolants array if (coolants[c].id == coolant) { coolantCodes.on = coolants[c].on; if (coolants[c].off != undefined) { coolantCodes.off = coolants[c].off; break; } else { for (var i in coolants) { if (coolants[i].id == COOLANT_OFF) { coolantCodes.off = coolants[i].off; break; } } } } } if (coolant == COOLANT_OFF) { m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified } else { coolantOff = coolantCodes.off; m = coolantCodes.on; } if (!m) { onUnsupportedCoolant(coolant); m = 9; } else { if (Array.isArray(m)) { for (var i in m) { multipleCoolantBlocks.push(m[i]); } } else { multipleCoolantBlocks.push(m); } currentCoolantMode = coolant; for (var i in multipleCoolantBlocks) { if (typeof multipleCoolantBlocks[i] == "number") { multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]); } } if (format == undefined || format) { return multipleCoolantBlocks; // return the single formatted coolant value } else { return m; // return unformatted coolant value } } return undefined; } // <<<<< INCLUDED FROM include_files/coolant.cpi // >>>>> INCLUDED FROM include_files/writeProgramHeader.cpi properties.writeMachine = { title : "Write machine", description: "Output the machine settings in the header of the program.", group : "formats", type : "boolean", value : true, scope : "post" }; properties.writeTools = { title : "Write tool list", description: "Output a tool list in the header of the program.", group : "formats", type : "boolean", value : true, scope : "post" }; function writeProgramHeader() { // dump machine configuration var vendor = machineConfiguration.getVendor(); var model = machineConfiguration.getModel(); var mDescription = machineConfiguration.getDescription(); if (getProperty("writeMachine") && (vendor || model || mDescription)) { writeComment(localize("Machine")); if (vendor) { writeComment(" " + localize("vendor") + ": " + vendor); } if (model) { writeComment(" " + localize("model") + ": " + model); } if (mDescription) { writeComment(" " + localize("description") + ": " + mDescription); } } // dump tool information if (getProperty("writeTools")) { if (false) { // set to true to use the post kernel version of the tool list writeToolTable(TOOL_NUMBER_COL); } else { 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 = (getProperty("toolAsName") ? "\"" + tool.description.toUpperCase() + "\"" : "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); } } } } } // <<<<< INCLUDED FROM include_files/writeProgramHeader.cpi // >>>>> INCLUDED FROM include_files/onRapid_fanuc.cpi 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(); } } // <<<<< INCLUDED FROM include_files/onRapid_fanuc.cpi // >>>>> INCLUDED FROM include_files/onLinear_fanuc.cpi function onLinear(_x, _y, _z, feed) { if (pendingRadiusCompensation >= 0) { 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 = getSetting("outputToolDiameterOffset", true) ? diameterOffsetFormat.format(tool.diameterOffset) : ""; writeBlock(gPlaneModal.format(17)); switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, d, f); break; case RADIUS_COMPENSATION_RIGHT: writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, 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); } } } // <<<<< INCLUDED FROM include_files/onLinear_fanuc.cpi // >>>>> INCLUDED FROM include_files/onCircular_fanuc.cpi 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 (getProperty("useRadius") || isHelical()) { // radius mode does not support full arcs linearize(tolerance); return; } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); break; case PLANE_ZX: writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); break; case PLANE_YZ: writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); break; default: linearize(tolerance); } } else if (!getProperty("useRadius")) { switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); break; case PLANE_ZX: writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); break; case PLANE_YZ: writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); break; default: if (getProperty("allow3DArcs")) { // make sure maximumCircularSweep is well below 360deg // we could use G02.4 or G03.4 - direction is calculated var ip = getPositionU(0.5); writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); } else { 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: if (getProperty("allow3DArcs")) { // make sure maximumCircularSweep is well below 360deg // we could use G02.4 or G03.4 - direction is calculated var ip = getPositionU(0.5); writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); } else { linearize(tolerance); } } } } // <<<<< INCLUDED FROM include_files/onCircular_fanuc.cpi // >>>>> INCLUDED FROM include_files/writeRetract_fanuc.cpi function writeRetract() { var retract = getRetractParameters.apply(this, arguments); if (retract && retract.words.length > 0) { if (typeof cancelWCSRotation == "function" && getSetting("retract.cancelRotationOnRetracting", false)) { // cancel rotation before retracting cancelWCSRotation(); } if (typeof disableLengthCompensation == "function" && getSetting("allowCancelTCPBeforeRetracting", false) && state.tcpIsActive) { disableLengthCompensation(); // cancel TCP before retracting } for (var i in retract.words) { var words = retract.singleLine ? retract.words : retract.words[i]; switch (retract.method) { case "G28": forceModals(gMotionModal, gAbsIncModal); writeBlock(gFormat.format(28), gAbsIncModal.format(91), words); writeBlock(gAbsIncModal.format(90)); break; case "G30": forceModals(gMotionModal, gAbsIncModal); writeBlock(gFormat.format(30), gAbsIncModal.format(91), words); writeBlock(gAbsIncModal.format(90)); break; case "G53": forceModals(gMotionModal); writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), words); break; default: if (typeof writeRetractCustom == "function") { writeRetractCustom(retract); return; } else { error(subst(localize("Unsupported safe position method '%1'"), retract.method)); } } machineSimulation({ x : retract.singleLine || words.indexOf("X") != -1 ? retract.positions.x : undefined, y : retract.singleLine || words.indexOf("Y") != -1 ? retract.positions.y : undefined, z : retract.singleLine || words.indexOf("Z") != -1 ? retract.positions.z : undefined, coordinates: MACHINE }); if (retract.singleLine) { break; } } } } // <<<<< INCLUDED FROM include_files/writeRetract_fanuc.cpi // >>>>> INCLUDED FROM include_files/initialPositioning_fanuc.cpi /** * Writes the initial positioning procedure for a section to get to the start position of the toolpath. * @param {Vector} position The initial position to move to * @param {boolean} isRequired true: Output full positioning, false: Output full positioning in optional state or output simple positioning only * @param {String} codes1 Allows to add additional code to the first positioning line * @param {String} codes2 Allows to add additional code to the second positioning line (if applicable) * @example var myVar1 = formatWords("T" + tool.number, currentSection.wcs); var myVar2 = getCoolantCodes(tool.coolant); writeInitialPositioning(initialPosition, isRequired, myVar1, myVar2); */ function writeInitialPositioning(position, isRequired, codes1, codes2) { var motionCode = {single:0, multi:0}; switch (highFeedMapping) { case HIGH_FEED_MAP_ANY: motionCode = {single:1, multi:1}; // map all rapid traversals to high feed break; case HIGH_FEED_MAP_MULTI: motionCode = {single:0, multi:1}; // map rapid traversal along more than one axis to high feed break; } var feed = (highFeedMapping != HIGH_FEED_NO_MAPPING) ? getFeed(highFeedrate) : ""; var hOffset = getSetting("outputToolLengthOffset", true) ? hFormat.format(tool.lengthOffset) : ""; var additionalCodes = [formatWords(codes1), formatWords(codes2)]; forceModals(gMotionModal); writeStartBlocks(isRequired, function() { var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); if (typeof disableLengthCompensation == "function") { disableLengthCompensation(!isRequired); // cancel tool length compensation prior to enabling it, required when switching G43/G43.4 modes } // multi axis prepositioning with TWP if (currentSection.isMultiAxis() && getSetting("workPlaneMethod.prepositionWithTWP", true) && getSetting("workPlaneMethod.useTiltedWorkplane", false) && tcp.isSupportedByOperation && getCurrentDirection().isNonZero()) { var W = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : Matrix.getOrientationFromDirection(getCurrentDirection()); var prePosition = W.getTransposed().multiply(position); var angles = W.getEuler2(settings.workPlaneMethod.eulerConvention); setWorkPlane(angles); writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(prePosition.x), yOutput.format(prePosition.y), feed, additionalCodes[0]); machineSimulation({x:prePosition.x, y:prePosition.y}); cancelWorkPlane(); writeBlock(getOffsetCode(), hOffset, additionalCodes[1]); // omit Z-axis output is desired forceAny(); // required to output XYZ coordinates in the following line } else { if (machineConfiguration.isHeadConfiguration()) { writeBlock(modalCodes, gMotionModal.format(motionCode.multi), getOffsetCode(), xOutput.format(position.x), yOutput.format(position.y), zOutput.format(position.z), hOffset, feed, additionalCodes ); machineSimulation({x:position.x, y:position.y, z:position.z}); } else { writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes[0]); machineSimulation({x:position.x, y:position.y}); writeBlock(gMotionModal.format(motionCode.single), getOffsetCode(), zOutput.format(position.z), hOffset, additionalCodes[1]); machineSimulation(tcp.isSupportedByOperation ? {x:position.x, y:position.y, z:position.z} : {z:position.z}); } } forceModals(gMotionModal); if (isRequired) { additionalCodes = []; // clear additionalCodes buffer } }); validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that lenght compensation is enabled if (!isRequired) { // simple positioning var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); if (!state.retractedZ && xyzFormat.getResultingValue(getCurrentPosition().z) < xyzFormat.getResultingValue(position.z)) { writeBlock(modalCodes, gMotionModal.format(motionCode.single), zOutput.format(position.z), feed); machineSimulation({z:position.z}); } forceXYZ(); writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes); machineSimulation({x:position.x, y:position.y}); } } Matrix.getOrientationFromDirection = function (ijk) { var forward = ijk; var unitZ = new Vector(0, 0, 1); var W; if (Math.abs(Vector.dot(forward, unitZ)) < 0.5) { var imX = Vector.cross(forward, unitZ).getNormalized(); W = new Matrix(imX, Vector.cross(forward, imX), forward); } else { var imX = Vector.cross(new Vector(0, 1, 0), forward).getNormalized(); W = new Matrix(imX, Vector.cross(forward, imX), forward); } return W; }; // <<<<< INCLUDED FROM include_files/initialPositioning_fanuc.cpi // >>>>> INCLUDED FROM include_files/getOffsetCode_fanuc.cpi var toolLengthCompOutput = createOutputVariable({control : CONTROL_FORCE, onchange: function() { state.tcpIsActive = toolLengthCompOutput.getCurrent() == 43.4 || toolLengthCompOutput.getCurrent() == 43.5; state.lengthCompensationActive = toolLengthCompOutput.getCurrent() != 49; } }, gFormat); function getOffsetCode() { if (!getSetting("outputToolLengthCompensation", true) && toolLengthCompOutput.isEnabled()) { state.lengthCompensationActive = true; // always assume that length compensation is active toolLengthCompOutput.disable(); } var offsetCode = 43; if (tcp.isSupportedByOperation) { offsetCode = machineConfiguration.isMultiAxisConfiguration() ? 43.4 : 43.5; } return toolLengthCompOutput.format(offsetCode); } // <<<<< INCLUDED FROM include_files/getOffsetCode_fanuc.cpi