/** Copyright (C) 2012-2016 by Autodesk, Inc. All rights reserved. Pocket NC post processor configuration. $Revision: 40925 011f5185fa6794bf121f4c46d161206cef5cbcd0 $ $Date: 2016-01-13 17:19:46 $ FORKID {B9F40C50-EBFF-4547-90FF-CAF4C01C8E30} */ description = "Generic Pocket NC"; vendor = "Pocket NC"; vendorUrl = "http://www.pocketnc.com/"; legal = "Copyright (C) 2012-2016 by Autodesk, Inc."; certificationLevel = 2; minimumRevision = 24000; longDescription = "Generic post for Pocket NC. Note that the XYZ axes of the WCS in the Setup should be set such that the axes all align with the machine XYZ axes in the A0/B0 machine orientation (this means that the WCS Z-axis would be horizontal like on a lathe). By default the post will make the tool go to the home position between operations if the A-axis changes by more than the limit specified by the 'maximumAAxisChange' property (20 degrees by default). You can turn off homing between operations if desired by turning off the 'goHomeBetweenOperations' property but you would have to make sure the tool doesn't collide with the part during AB reorientation."; extension = "ngc"; setCodePage("ascii"); capabilities = CAPABILITY_MILLING; tolerance = spatial(0.002, MM); minimumChordLength = spatial(0.001, MM); minimumCircularRadius = spatial(0.001, MM); maximumCircularRadius = spatial(1000, MM); minimumCircularSweep = toRad(0.001); maximumCircularSweep = toRad(180); allowHelicalMoves = true; allowedCircularPlanes = undefined; // allow any circular motion // user-defined properties properties = { writeMachine: true, // write machine writeTools: true, // writes the tools showSequenceNumbers: true, // show sequence numbers sequenceNumberStart: 1, // first sequence number sequenceNumberIncrement: 1, // increment for sequence numbers optionalStop: true, // optional stop separateWordsWithSpace: true, // specifies that the words should be separated with a white space useRadius: true, // specifies that arcs should be output using the radius (R word) instead of the I, J, and K words. useParametricFeed: true, // specifies that feed should be output using Q values showNotes: true, // specifies that operation notes should be output. smoothingTolerance: 0.002, // smoothing tolerance (-1 for disabled). goHomeBetweenOperations: true, // make sure machine goes home between operations if the A axis changes more than the 'maximumAAxisChange' property. If you turn off homing then make sure that the part wont collide with the tool. maximumAAxisChange: 20 // the maximum allowed A change in degrees before machine will be force home between operations. }; var useG28 = false; var permittedCommentChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,=_-"; var mapCoolantTable = new Table( [9, 8, 7], {initial:COOLANT_OFF, force:true}, "Invalid coolant mode" ); var gFormat = createFormat({prefix:"G", decimals:1}); var mFormat = createFormat({prefix:"M", decimals:1}); var hFormat = createFormat({prefix:"H", decimals:1}); var dFormat = createFormat({prefix:"D", decimals:1}); var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var rFormat = xyzFormat; // radius var abcFormat = createFormat({decimals:3, forceDecimal:true, scale:DEG}); var feedFormat = createFormat({decimals:(unit == MM ? 2 : 3), forceDecimal:true}); var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var toolFormat = createFormat({decimals:0}); var rpmFormat = createFormat({decimals:0}); var secFormat = createFormat({decimals:3, forceDecimal:true}); // seconds - range 0.001-99999.999 var taperFormat = createFormat({decimals:1, scale:DEG}); var xOutput = createVariable({prefix:"X"}, xyzFormat); var yOutput = createVariable({prefix:"Y"}, xyzFormat); var zOutput = createVariable({prefix:"Z"}, xyzFormat); var aOutput = createVariable({prefix:"A"}, abcFormat); var bOutput = createVariable({prefix:"B"}, abcFormat); var cOutput = createVariable({prefix:"C"}, abcFormat); var feedOutput = createVariable({prefix:"F"}, feedFormat); var sOutput = createVariable({prefix:"S", force:true}, rpmFormat); var dOutput = createVariable({}, dFormat); // circular output var iOutput = createReferenceVariable({prefix:"I", force:true}, xyzFormat); var jOutput = createReferenceVariable({prefix:"J", force:true}, xyzFormat); var kOutput = createReferenceVariable({prefix:"K", force:true}, xyzFormat); var gMotionModal = createModal({}, gFormat); // modal group 1 // G0-G3, ... var gPlaneModal = createModal({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 var gAbsIncModal = createModal({}, gFormat); // modal group 3 // G90-91 var gFeedModeModal = createModal({}, gFormat); // modal group 5 // G93-94 var gUnitModal = createModal({}, gFormat); // modal group 6 // G20-21 var gCycleModal = createModal({}, gFormat); // modal group 9 // G81, ... var gRetractModal = createModal({}, gFormat); // modal group 10 // G98-99 // fixed settings var firstFeedParameter = 100; var WARNING_WORK_OFFSET = 0; // collected state var sequenceNumber; var currentWorkOffset; var forceSpindleSpeed = false; var activeMovements; // do not use by default var currentFeedId; var previousABC = new Vector(0, 0, 0); /** Writes the specified block. */ function writeBlock() { if (properties.showSequenceNumbers) { writeWords2("N" + sequenceNumber, arguments); sequenceNumber += properties.sequenceNumberIncrement; if (sequenceNumber > 9999999) { sequenceNumber = properties.sequenceNumberStart; } } else { writeWords(arguments); } } /** Writes the specified optional block. */ function writeOptionalBlock() { if (properties.showSequenceNumbers) { var words = formatWords(arguments); if (words) { writeWords("/", "N" + sequenceNumber, words); sequenceNumber += properties.sequenceNumberIncrement; if (sequenceNumber > 9999999) { sequenceNumber = properties.sequenceNumberStart; } } } else { writeWords2("/", arguments); } } function formatComment(text) { return "(" + filterText(String(text).toUpperCase(), permittedCommentChars) + ")"; } /** Output a comment. */ function writeComment(text) { writeln(formatComment(text)); } function onRewindMachine() { } function onOpen() { if (true) { // only one kind of machine // var aAxis = createAxis({coordinate:0, table:true, axis:[-1, 0, 0], range:[-110.000,20.000], preference:1}); // use this later var bAxis = createAxis({coordinate:1, table:true, axis:[0, 1, 0], range:[-100.000,100.000], preference:0}); // postpone some warnings about unsupported orientations until running the NC program var cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], range:[0,360], preference:0, cyclic:true}); machineConfiguration = new MachineConfiguration(bAxis, cAxis); machineConfiguration.setHomePositionX(toPreciseUnit(54, MM)); machineConfiguration.setHomePositionY(toPreciseUnit(49, MM)); setMachineConfiguration(machineConfiguration); optimizeMachineAngles2(1); // TCP mode } if (!machineConfiguration.isMachineCoordinate(0)) { aOutput.disable(); } if (!machineConfiguration.isMachineCoordinate(1)) { bOutput.disable(); } if (!machineConfiguration.isMachineCoordinate(2)) { cOutput.disable(); } if (!properties.separateWordsWithSpace) { setWordSeparator(""); } sequenceNumber = properties.sequenceNumberStart; writeln("%"); //writeln("(AXIS,stop)"); // disable LinuxCNC visualization 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); } } switch (unit) { case IN: writeBlock(gUnitModal.format(20)); break; case MM: writeBlock(gUnitModal.format(21)); break; } // dump tool information if (properties.writeTools) { var zRanges = {}; if (is3D()) { var numberOfSections = getNumberOfSections(); for (var i = 0; i < numberOfSections; ++i) { var section = getSection(i); var zRange = section.getGlobalZRange(); var tool = section.getTool(); if (zRanges[tool.number]) { zRanges[tool.number].expandToRange(zRange); } else { zRanges[tool.number] = zRange; } } } /* var tools = getToolTable(); if (tools.getNumberOfTools() > 0) { for (var i = 0; i < tools.getNumberOfTools(); ++i) { var tool = tools.getTool(i); var comment = "T" + toolFormat.format(tool.number) + " " + "D=" + xyzFormat.format(tool.diameter) + " " + localize("CR") + "=" + xyzFormat.format(tool.cornerRadius); if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) { comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg"); } if (zRanges[tool.number]) { comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum()); } comment += " - " + getToolTypeName(tool.type); writeComment(comment); } } */ } if (false) { // check for duplicate tool number for (var i = 0; i < getNumberOfSections(); ++i) { var sectioni = getSection(i); var tooli = sectioni.getTool(); for (var j = i + 1; j < getNumberOfSections(); ++j) { var sectionj = getSection(j); var toolj = sectionj.getTool(); if (tooli.number == toolj.number) { if (xyzFormat.areDifferent(tooli.diameter, toolj.diameter) || xyzFormat.areDifferent(tooli.cornerRadius, toolj.cornerRadius) || abcFormat.areDifferent(tooli.taperAngle, toolj.taperAngle) || (tooli.numberOfFlutes != toolj.numberOfFlutes)) { error( subst( localize("Using the same tool number for different cutter geometry for operation '%1' and '%2'."), sectioni.hasParameter("operation-comment") ? sectioni.getParameter("operation-comment") : ("#" + (i + 1)), sectionj.hasParameter("operation-comment") ? sectionj.getParameter("operation-comment") : ("#" + (j + 1)) ) ); return; } } } } } // absolute coordinates, feed per min, and incremental arc center mode writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(94), gFormat.format(40), gPlaneModal.format(17), gFormat.format(91.1)); } function onComment(message) { writeComment(message); } /** Force output of X, Y, and Z. */ function forceXYZ() { xOutput.reset(); yOutput.reset(); zOutput.reset(); } /** Force output of A, B, and C. */ function forceABC() { aOutput.reset(); bOutput.reset(); cOutput.reset(); } function forceFeed() { currentFeedId = undefined; feedOutput.reset(); } /** Force output of X, Y, Z, A, B, C, and F on next output. */ function forceAny() { forceXYZ(); forceABC(); forceFeed(); } function FeedContext(id, description, feed) { this.id = id; this.description = description; this.feed = feed; } function getFeed(f) { if (activeMovements) { var feedContext = activeMovements[movement]; if (feedContext != undefined) { if (!feedFormat.areDifferent(feedContext.feed, f)) { if (feedContext.id == currentFeedId) { return ""; // nothing has changed } forceFeed(); currentFeedId = feedContext.id; return "F#" + (firstFeedParameter + feedContext.id); } } currentFeedId = undefined; // force Q feed next time } return feedOutput.format(f); // use feed value } function initializeActiveFeeds() { activeMovements = new Array(); var movements = currentSection.getMovements(); var id = 0; var activeFeeds = new Array(); if (hasParameter("operation:tool_feedCutting")) { if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) { var feedContext = new FeedContext(id, localize("Fraesvorschub"), 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("VORBOHREN"), 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("SCHLICHTVORSCHUB"), 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("SCHLICHTVORSCHUB"), 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("Einfahrvorschub"), 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("Ausfahrvorschub"), 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("Kein-Kontakt-Vorschub"), 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("Reduzierter-Vorschub"), 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("Rampenvorschub"), 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("Tauchvorschub"), getParameter("operation:tool_feedPlunge")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_PLUNGE] = feedContext; } ++id; } if (true) { // high feed if (movements & (1 << MOVEMENT_HIGH_FEED)) { var feedContext = new FeedContext(id, localize("High Feed"), this.highFeedrate); activeFeeds.push(feedContext); activeMovements[MOVEMENT_HIGH_FEED] = feedContext; } ++id; } for (var i = 0; i < activeFeeds.length; ++i) { var feedContext = activeFeeds[i]; writeBlock("#" + (firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed), formatComment(feedContext.description)); } } var currentWorkPlaneABC = undefined; /** Move to safe position before indexing rotaries. */ function moveToSafeIndexPosition() { if (!machineConfiguration.hasHomePositionX() && !machineConfiguration.hasHomePositionY()) { return; } var homeX; if (machineConfiguration.hasHomePositionX()) { homeX = "X" + xyzFormat.format(machineConfiguration.getHomePositionX()); } var homeY; if (machineConfiguration.hasHomePositionY()) { homeY = "Y" + xyzFormat.format(machineConfiguration.getHomePositionY()); } gMotionModal.reset(); writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), homeX, homeY); xOutput.reset(); yOutput.reset(); } 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); var endABC = getABCDir(abc.x, abc.y, abc.z); if (properties.goHomeBetweenOperations && (getCurrentSectionId() >= 0)) { // only if we are between operations var aDelta = Math.abs(abc.x - (currentWorkPlaneABC ? currentWorkPlaneABC.x : 0)); if (aDelta > toRad(properties.maximumAAxisChange)) { moveToSafeIndexPosition(); } } writeBlock( gMotionModal.format(0), conditional(machineConfiguration.isMachineCoordinate(0), formatRotaryAxis(endABC.x, aOutput)), conditional(machineConfiguration.isMachineCoordinate(1), formatRotaryAxis(endABC.y, bOutput)), conditional(machineConfiguration.isMachineCoordinate(2), formatRotaryAxis(endABC.z, cOutput)) ); onCommand(COMMAND_LOCK_MULTI_AXIS); previousABC = endABC; currentWorkPlaneABC = abc; } var closestABC = false; // choose closest machine angles var currentMachineABC; function getWorkPlaneMachineABC(workPlane) { var W = workPlane; // map to global frame var abc = machineConfiguration.getABC(W); if (closestABC) { if (currentMachineABC) { abc = machineConfiguration.remapToABC(abc, currentMachineABC); } else { abc = machineConfiguration.getPreferredABC(abc); } } else { abc = machineConfiguration.getPreferredABC(abc); } try { abc = machineConfiguration.remapABC(abc); currentMachineABC = abc; } catch (e) { error( localize("Machine angles not supported") + ":" + conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x)) + conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y)) + conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z)) ); } var direction = machineConfiguration.getDirection(abc); if (!isSameDirection(direction, W.forward)) { error(localize("Orientation not supported.")); } if (!machineConfiguration.isABCSupported(abc)) { error( localize("Work plane is not supported") + ":" + conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x)) + conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y)) + conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z)) ); } var tcp = false; if (tcp) { setRotation(W); // TCP mode } else { var O = machineConfiguration.getOrientation(abc); var R = machineConfiguration.getRemainingOrientation(abc, W); setRotation(R); } return abc; } function onSection() { var insertToolCall = isFirstSection() || currentSection.getForceToolChange && currentSection.getForceToolChange() || (tool.number != getPreviousSection().getTool().number); var retracted = false; // specifies that the tool has been retracted to the safe plane var newWorkOffset = isFirstSection() || (getPreviousSection().workOffset != currentSection.workOffset); // work offset changes var newWorkPlane = isFirstSection() || !isSameDirection(getPreviousSection().getGlobalFinalToolAxis(), currentSection.getGlobalInitialToolAxis()); if (insertToolCall || newWorkOffset || newWorkPlane) { // stop spindle before retract during tool change if (insertToolCall && !isFirstSection()) { onCommand(COMMAND_STOP_SPINDLE); } // retract to safe plane retracted = true; if (useG28) { writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(88)); // retract writeBlock(gAbsIncModal.format(90)); } else { gMotionModal.reset(); writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), "Z" + "[#<_ini[AXIS_2]MAX_LIMIT>-0.1]"); // retract } zOutput.reset(); } if (hasParameter("operation-comment")) { var comment = getParameter("operation-comment"); if (comment) { writeComment(comment); } } if (properties.showNotes && hasParameter("notes")) { var notes = getParameter("notes"); if (notes) { var lines = String(notes).split("\n"); var r1 = new RegExp("^[\\s]+", "g"); var r2 = new RegExp("[\\s]+$", "g"); for (line in lines) { var comment = lines[line].replace(r1, "").replace(r2, ""); if (comment) { writeComment(comment); } } } } if (insertToolCall) { forceWorkPlane(); retracted = true; onCommand(COMMAND_COOLANT_OFF); if (!isFirstSection() && properties.optionalStop) { onCommand(COMMAND_OPTIONAL_STOP); } if (tool.number > 999) { warning(localize("Tool number exceeds maximum value.")); } writeBlock(gFormat.format(49)); onCommand(COMMAND_STOP_SPINDLE); var homeX; if (machineConfiguration.hasHomePositionX()) { homeX = "X" + xyzFormat.format(machineConfiguration.getHomePositionX()); } var homeY; if (machineConfiguration.hasHomePositionY()) { homeY = "Y" + xyzFormat.format(machineConfiguration.getHomePositionY()); } gMotionModal.reset(); writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), homeX, homeY); forceXYZ(); //writeBlock(mFormat.format(0)); // force stop for manual tool change writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); if (tool.comment) { writeComment(tool.comment); } var showToolZMin = false; if (showToolZMin) { if (is3D()) { var numberOfSections = getNumberOfSections(); var zRange = currentSection.getGlobalZRange(); var number = tool.number; for (var i = currentSection.getId() + 1; i < numberOfSections; ++i) { var section = getSection(i); if (section.getTool().number != number) { break; } zRange.expandToRange(section.getGlobalZRange()); } writeComment(localize("ZMIN") + "=" + zRange.getMinimum()); } } } if (insertToolCall || forceSpindleSpeed || isFirstSection() || (rpmFormat.areDifferent(tool.spindleRPM, sOutput.getCurrent())) || (tool.clockwise != getPreviousSection().getTool().clockwise)) { forceSpindleSpeed = false; var localRPM = tool.spindleRPM; if (tool.spindleRPM < 1) { error(localize("Spindle speed out of range.")); return; } if (tool.spindleRPM > 8000) { error(localize("Spindle speed exceeds maximum value.")); localRPM = 8000; } writeBlock( sOutput.format(localRPM), mFormat.format(tool.clockwise ? 3 : 4) ); } // wcs if (insertToolCall) { // force work offset when changing tool currentWorkOffset = undefined; } var workOffset = currentSection.workOffset; currentWorkOffset = undefined; // force work offset if (workOffset == 0) { warningOnce(localize("Work offset has not been specified. Using G54 as WCS."), WARNING_WORK_OFFSET); workOffset = 1; } if (workOffset > 0) { if (workOffset > 6) { var p = workOffset - 6; // 1->... if (p > 3) { error(localize("Work offset out of range.")); return; } else { if (workOffset != currentWorkOffset) { gMotionModal.reset(); writeBlock(gFormat.format(59.1), "P" + p, gMotionModal.format(0)); // G59.1P currentWorkOffset = workOffset; } } } else { if (workOffset != currentWorkOffset) { gMotionModal.reset(); writeBlock(gFormat.format(53 + workOffset), gMotionModal.format(0)); // G54->G59 currentWorkOffset = workOffset; } } } forceXYZ(); if (machineConfiguration.isMultiAxisConfiguration()) { // use 5-axis indexing for multi-axis mode // set working plane after datum shift var abc = new Vector(0, 0, 0); if (currentSection.isMultiAxis()) { forceWorkPlane(); cancelTransformation(); } else { abc = getWorkPlaneMachineABC(currentSection.workPlane); } setWorkPlane(abc); } else { // pure 3D var remaining = currentSection.workPlane; if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { error(localize("Tool orientation is not supported.")); return; } setRotation(remaining); } // set coolant after we have positioned at Z { var c = mapCoolantTable.lookup(tool.coolant); if (c) { writeBlock(mFormat.format(c)); } else { warning(localize("Coolant not supported.")); } } forceAny(); gMotionModal.reset(); var initialPosition = getFramePosition(currentSection.getInitialPosition()); if (!retracted) { if (getCurrentPosition().z < initialPosition.z) { writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); } } if (insertToolCall || retracted || (!isFirstSection() && getPreviousSection().isMultiAxis())) { var lengthOffset = tool.lengthOffset; if (lengthOffset > 999) { error(localize("Length offset out of range.")); return; } gMotionModal.reset(); writeBlock(gPlaneModal.format(17)); if (!machineConfiguration.isHeadConfiguration()) { writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y) ); writeBlock(gMotionModal.format(0), gFormat.format(43), zOutput.format(initialPosition.z), hFormat.format(lengthOffset)); } else { writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), gFormat.format(43), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y), zOutput.format(initialPosition.z), hFormat.format(lengthOffset) ); } gMotionModal.reset(); } else { writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y) ); } if (properties.useParametricFeed && hasParameter("operation-strategy") && (getParameter("operation-strategy") != "drill")) { if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && (getPreviousSection().getPatternId() == currentSection.getPatternId())) { // use the current feeds } else { initializeActiveFeeds(); } } else { activeMovements = undefined; } if (properties.smoothingTolerance > 0) { if (hasParameter("operation-strategy") && (getParameter("operation-strategy") != "drill")) { writeBlock(gFormat.format(64), "P" + xyzFormat.format(properties.smoothingTolerance)); } } } function onDwell(seconds) { if (seconds > 99999.999) { warning(localize("Dwelling time is out of range.")); } writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + secFormat.format(seconds)); } function onSpindleSpeed(spindleSpeed) { writeBlock(sOutput.format(spindleSpeed)); } function onCycle() { writeBlock(gPlaneModal.format(17)); } function getCommonCycle(x, y, z, r) { forceXYZ(); // force xyz on first drill hole of any cycle return [xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + xyzFormat.format(r)]; } function onCyclePoint(x, y, z) { switch (cycleType) { case "tapping": case "left-tapping": case "right-tapping": cycleExpanded = true; repositionToCycleClearance(cycle, x, y, z); writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), conditional(gPlaneModal.getCurrent() == 17, zOutput.format(cycle.retract)), conditional(gPlaneModal.getCurrent() == 18, yOutput.format(cycle.retract)), conditional(gPlaneModal.getCurrent() == 19, xOutput.format(cycle.retract)) ); writeBlock( gAbsIncModal.format(90), gFormat.format(33.1), conditional(gPlaneModal.getCurrent() == 17, zOutput.format(z)), conditional(gPlaneModal.getCurrent() == 18, yOutput.format(y)), conditional(gPlaneModal.getCurrent() == 19, xOutput.format(x)), "K" + pitchFormat.format(tool.threadPitch) ); gMotionModal.reset(); writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), conditional(gPlaneModal.getCurrent() == 17, zOutput.format(cycle.clearance)), conditional(gPlaneModal.getCurrent() == 18, yOutput.format(cycle.clearance)), conditional(gPlaneModal.getCurrent() == 19, xOutput.format(cycle.clearance)) ); return; /* case "tapping-with-chip-breaking": case "left-tapping-with-chip-breaking": case "right-tapping-with-chip-breaking": */ } if (isFirstCyclePoint()) { repositionToCycleClearance(cycle, x, y, z); // return to initial Z which is clearance plane and set absolute mode var F = cycle.feedrate; var P = (cycle.dwell == 0) ? 0 : clamp(0.001, cycle.dwell, 99999999); // in seconds switch (cycleType) { case "drilling": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(81), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); break; case "counter-boring": if (P > 0) { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(82), getCommonCycle(x, y, z, cycle.retract), "P" + secFormat.format(P), feedOutput.format(F) ); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(81), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); } break; case "chip-breaking": expandCyclePoint(x, y, z); break; case "deep-drilling": if (P > 0) { expandCyclePoint(x, y, z); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(83), getCommonCycle(x, y, z, cycle.retract), "Q" + xyzFormat.format(cycle.incrementalDepth), // conditional(P > 0, "P" + secFormat.format(P)), feedOutput.format(F) ); } break; case "fine-boring": expandCyclePoint(x, y, z); break; /* // not supported case "back-boring": var dx = (gPlaneModal.getCurrent() == 19) ? cycle.backBoreDistance : 0; var dy = (gPlaneModal.getCurrent() == 18) ? cycle.backBoreDistance : 0; var dz = (gPlaneModal.getCurrent() == 17) ? cycle.backBoreDistance : 0; writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(87), getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom), "Q" + xyzFormat.format(cycle.shift), "P" + secFormat.format(P), // not optional feedOutput.format(F) ); break; */ case "reaming": if (P > 0) { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89), getCommonCycle(x, y, z, cycle.retract), "P" + secFormat.format(P), feedOutput.format(F) ); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); } break; case "stop-boring": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(86), getCommonCycle(x, y, z, cycle.retract), conditional(P > 0, "P" + secFormat.format(P)), feedOutput.format(F) ); break; case "manual-boring": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(88), getCommonCycle(x, y, z, cycle.retract), "P" + secFormat.format(P), // not optional feedOutput.format(F) ); break; case "boring": if (P > 0) { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89), getCommonCycle(x, y, z, cycle.retract), "P" + secFormat.format(P), // not optional feedOutput.format(F) ); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); } break; default: expandCyclePoint(x, y, z); } } else { if (cycleExpanded) { expandCyclePoint(x, y, z); } else { var _x = xOutput.format(x); var _y = yOutput.format(y); var _z = zOutput.format(z); if (!_x && !_y && !_z) { switch (gPlaneModal.getCurrent()) { case 17: // XY xOutput.reset(); // at least one axis is required _x = xOutput.format(x); break; case 18: // ZX zOutput.reset(); // at least one axis is required _z = zOutput.format(z); break; case 19: // YZ yOutput.reset(); // at least one axis is required _y = yOutput.format(y); break; } } writeBlock(_x, _y, _z); } } } function onCycleEnd() { if (!cycleExpanded) { writeBlock(gCycleModal.format(80)); gMotionModal.reset(); } } var pendingRadiusCompensation = -1; function onRadiusCompensation() { pendingRadiusCompensation = radiusCompensation; } function onRapid(_x, _y, _z) { var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); if (x || y || z) { if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation mode cannot be changed at rapid traversal.")); return; } writeBlock(gMotionModal.format(0), x, y, z); forceFeed(); } } function onLinear(_x, _y, _z, feed) { var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); var f = getFeed(feed); if (x || y || z) { if (pendingRadiusCompensation >= 0) { pendingRadiusCompensation = -1; var d = tool.diameterOffset; if (d > 999) { warning(localize("The diameter offset exceeds the maximum value.")); } writeBlock(gPlaneModal.format(17)); switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: dOutput.reset(); writeBlock(gMotionModal.format(1), gFormat.format(41), dOutput.format(d), x, y, z, f); break; case RADIUS_COMPENSATION_RIGHT: dOutput.reset(); writeBlock(gMotionModal.format(1), gFormat.format(42), dOutput.format(d), x, y, z, f); break; default: writeBlock(gFormat.format(40)); writeBlock(gMotionModal.format(1), 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 endABC = getABCDir(_a, _b, _c); var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); var a = aOutput.format(endABC.x); var b = bOutput.format(endABC.y); var c = formatRotaryAxis(endABC.z, cOutput); writeBlock(gMotionModal.format(0), x, y, z, a, b, c); previousABC = endABC; forceFeed(); } function onLinear5D(_x, _y, _z, _a, _b, _c, feed) { if (!currentSection.isOptimizedForMachine()) { error(localize("This post configuration has not been customized for 5-axis simultaneous toolpath.")); return; } if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation cannot be activated/deactivated for 5-axis move.")); return; } var endABC = getABCDir(_a, _b, _c); var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); var a = aOutput.format(endABC.x); var b = bOutput.format(endABC.y); var c = formatRotaryAxis(endABC.z, cOutput); 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); } } previousABC = endABC; } function getABCDir(_a, _b, _c) { var endABC = new Array(_a, _b, _c); var startABC = new Array(Math.abs(previousABC.x), Math.abs(previousABC.y), Math.abs(previousABC.z)); var signedABC = new Array(previousABC.x, previousABC.y, previousABC.z); // calculate the rotary axes directions for (var i = 2; i < 3; ++i) { // always work with angles between 0-360 degrees endABC[i] %= (Math.PI*2); if (endABC[i] < 0) { endABC[i] += Math.PI*2; } if (endABC[i] >= Math.PI*2) { endABC[i] = 0; } // angles are the same // apply the correct sign to the new angle so it is not output if (!abcFormat.areDifferent(startABC[i], endABC[i])) { endABC[i] = signedABC[i]; } // calculate the correct direction (sign) for the output angles // A-0 will be converted to A-360 if (((endABC[i]-startABC[i] < 0) && (endABC[i]-startABC[i] > -Math.PI)) || endABC[i]-startABC[i] > Math.PI) { if (endABC[i] == 0) { endABC[i] = -Math.PI*2; } else { endABC[i] = -endABC[i]; } } } // return the signed angles return new Vector(endABC[0], endABC[1], endABC[2]); } function formatRotaryAxis(_axis, _format) { if (abcFormat.getResultingValue(_axis) == -360.0) { var s = _format.format(_axis); if (s) { return s.slice(0, 1) + "-0"; } } else if (abcFormat.getResultingValue(_axis) == 360.0) { return _format.format(0); } else { return _format.format(_axis); } } function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); return; } var start = getCurrentPosition(); if (isFullCircle()) { if (properties.useRadius || isHelical()) { // radius mode does not support full arcs linearize(tolerance); return; } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); break; case PLANE_ZX: writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; case PLANE_YZ: writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; default: linearize(tolerance); } } else if (!properties.useRadius) { switch (getCircularPlane()) { case PLANE_XY: writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); break; case PLANE_ZX: writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; case PLANE_YZ: writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; default: linearize(tolerance); } } else { // use radius mode var r = getCircularRadius(); if (toDeg(getCircularSweep()) > (180 + 1e-9)) { r = -r; // allow up to <360 deg arcs } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; case PLANE_ZX: writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; case PLANE_YZ: writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; default: linearize(tolerance); } } } var mapCommand = { COMMAND_STOP:0, COMMAND_OPTIONAL_STOP:1, COMMAND_END:2, COMMAND_SPINDLE_CLOCKWISE:3, COMMAND_SPINDLE_COUNTERCLOCKWISE:4, COMMAND_STOP_SPINDLE:5, COMMAND_ORIENTATE_SPINDLE:19, COMMAND_LOAD_TOOL:6, COMMAND_COOLANT_ON:8, COMMAND_COOLANT_OFF:9 }; function onCommand(command) { switch (command) { case COMMAND_STOP: writeBlock(mFormat.format(0)); forceSpindleSpeed = true; return; case COMMAND_START_SPINDLE: onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE); return; case COMMAND_LOCK_MULTI_AXIS: return; case COMMAND_UNLOCK_MULTI_AXIS: return; case COMMAND_BREAK_CONTROL: writeln("o call"); return; case COMMAND_TOOL_MEASURE: return; } var stringId = getCommandStringId(command); var mcode = mapCommand[stringId]; if (mcode != undefined) { writeBlock(mFormat.format(mcode)); } else { onUnsupportedCommand(command); } } function onSectionEnd() { if (currentSection.isMultiAxis()) { writeBlock(gMotionModal.format(49)); } writeBlock(gPlaneModal.format(17)); if ((((getCurrentSectionId() + 1) >= getNumberOfSections()) || (tool.number != getNextSection().getTool().number))&& tool.breakControl) { onCommand(COMMAND_BREAK_CONTROL); } forceAny(); } function onClose() { onCommand(COMMAND_COOLANT_OFF); if (useG28) { writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(88)); // retract } else { gMotionModal.reset(); writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), "Z" + "[#<_ini[AXIS_2]MAX_LIMIT>-0.1]"); // retract } zOutput.reset(); writeBlock(gFormat.format(49)); moveToSafeIndexPosition(); // always go home setWorkPlane(new Vector(0, 0, 0)); // reset working plane onImpliedCommand(COMMAND_END); onImpliedCommand(COMMAND_STOP_SPINDLE); writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off writeln("%"); }