Change to incremental in post processor?

Change to incremental in post processor?

Anonymous
Not applicable
3,161 Views
4 Replies
Message 1 of 5

Change to incremental in post processor?

Anonymous
Not applicable

I'm looking to change this post processor from absolute to incremental i'm using it to do some engraving on the z-c axis anyone have some ideas or are able to help would be great

0 Likes
3,162 Views
4 Replies
Replies (4)
Message 2 of 5

bob.schultz
Alumni
Alumni

We have a sample Fanuc post processor that outputs in incremental mode.  You can search for 'useIncremental' throughout the post for an example on how incremental programming can be implemented.



Bob Schultz
Sr. Post Processor Developer

0 Likes
Message 3 of 5

juliocesromero
Explorer
Explorer
Hello! I need some help with a post for Fanuc! is it possible to add the 4axis to the generic Fanuc incremental post available? I've went in to the Post and searched thru it "useIncremental" and found where it reads "set if using multi-axis machine" but I'm not sure what I'm suppose to do in there.

 

or is it possible to use the 4axis post and have it post in incremental rather than absolute?

 

 

 

0 Likes
Message 4 of 5

bob.schultz
Alumni
Alumni

If you are using 4-axis simultaneous operations, then I'd say it would be easier to copy the incremental code from the fanuc incremental post to the fanuc with a-axis post.  This is because there are a lot of support functions in the 4-axis post dealing with feedrates.

 

Look for all references to useIncremental in the incremental post and copy this logic to the a-axis post.  For the // TAG: set if using multi-axis machine comment, change this line to look like the following.

 

var abc = new Vector(0, 0, 0); // TAG: set if using multi-axis machine


Bob Schultz
Sr. Post Processor Developer

0 Likes
Message 5 of 5

juliocesromero
Explorer
Explorer
/**
Copyright (C) 2012-2017 by Autodesk, Inc.
All rights reserved.

FANUC post processor configuration.

$Revision: 41602 8a235290846bfe71ead6a010711f4fc730f48827 $
$Date: 2017-09-14 12:16:32 $

FORKID {04622D27-72F0-45d4-85FB-DB346FD1AE22}
*/

description = "FANUC - Inverse Time and A-axis";
vendor = "Fanuc";
vendorUrl = "http://www.fanuc.com";
legal = "Copyright (C) 2012-2017 by Autodesk, Inc.";
certificationLevel = 2;
minimumRevision = 24000;

longDescription = "Fanuc post illustrating inverse time feed with an A-axis.";

extension = "nc";
programNameIsInteger = true;
setCodePage("ascii");

capabilities = CAPABILITY_MILLING;
tolerance = spatial(0.002, MM);

minimumChordLength = spatial(0.01, MM);
minimumCircularRadius = spatial(0.01, MM);
maximumCircularRadius = spatial(1000, MM);
minimumCircularSweep = toRad(0.01);
maximumCircularSweep = toRad(180);
allowHelicalMoves = true;
allowedCircularPlanes = undefined; // allow any circular motion



// user-defined properties
properties = {
writeMachine: true, // write machine
writeTools: true, // writes the tools
preloadTool: true, // preloads next tool on tool change if any
showSequenceNumbers: true, // show sequence numbers
sequenceNumberStart: 10, // first sequence number
sequenceNumberIncrement: 5, // increment for sequence numbers
optionalStop: true, // optional stop
o8: false, // specifies 8-digit program number
useIncremental: true, // specifies that incremental XYZABC should be output.
separateWordsWithSpace: true, // specifies that the words should be separated with a white space
allow3DArcs: false, // specifies that 3D circular arcs are allowed
useRadius: false, // specifies that arcs should be output using the radius (R word) instead of the I, J, and K words
forceIJK: false, // force output of IJK for G2/G3 when not using R word
showNotes: false, // specifies that operation notes should be output
useSmoothing: false, // specifies if smoothing should be used or not
usePitchForTapping: false, // enable to use pitch instead of feed for the F-word for canned tapping cycles - note that your CNC control must be setup for pitch mode!
useG95: false, // use IPR/MPR instead of IPM/MPM
useG54x4: false, // Fanuc 30i supports G54.4 for Workpiece Error Compensation
makeAAxisOtherWay: false // make the A-axis rotate the opposite way
};

// user-defined property definitions
propertyDefinitions = {
writeMachine: {title:"Write machine", description:"Output the machine settings in the header of the code.", group:0, type:"boolean"},
writeTools: {title:"Write tool list", description:"Output a tool list in the header of the code.", group:0, type:"boolean"},
preloadTool: {title:"Preload tool", description:"Preloads the next tool at a tool change (if any).", group:1, type:"boolean"},
showSequenceNumbers: {title:"Use sequence numbers", description:"Use sequence numbers for each block of outputted code.", group:1, type:"boolean"},
sequenceNumberStart: {title:"Start sequence number", description:"The number at which to start the sequence numbers.", group:1, type:"integer"},
sequenceNumberIncrement: {title:"Sequence number increment", description:"The amount by which the sequence number is incremented by in each block.", group:1, type:"integer"},
optionalStop: {title:"Optional stop", description:"Outputs optional stop code during when necessary in the code.", type:"boolean"},
o8: {title:"8 Digit program number", description:"Specifies that an 8 digit program number is needed.", type:"boolean"},
separateWordsWithSpace: {title:"Separate words with space", description:"Adds spaces between words if 'yes' is selected.", type:"boolean"},
allow3DArcs: {title:"Allow 3D arcs", description:"Specifies whether 3D circular arcs are allowed.", type:"boolean"},
useIncremental: {title:"Use Incremental", description:"Specifies whether incremental XYZABC should be output.", type:"boolean"},
useRadius: {title:"Radius arcs", description:"If yes is selected, arcs are outputted using radius values rather than IJK.", type:"boolean"},
forceIJK: {title:"Force IJK", description:"Force the output of IJK for G2/G3 when not using R mode.", type:"boolean"},
showNotes: {title:"Show notes", description:"Writes operation notes as comments in the outputted code.", type:"boolean"},
useSmoothing: {title:"Use smoothing", description:"Specifies if smoothing should be used or not.", type:"boolean"},
usePitchForTapping: {title:"Force IJK", description:"Enables the use of pitch instead of feed for the F-word in canned tapping cycles. Your CNC control must be setup for pitch mode!", type:"boolean"},
useG95: {title:"Use G95", description:"Use IPR/MPR instead of IPM/MPM.", type:"boolean"},
useG54x4: {title:"Use G54.4", description:"Fanuc 30i supports G54.4 for workpiece error compensation.", type:"boolean"},
makeAAxisOtherWay: {title:"Reverse A-axis", description:"Makes the A-axis rotate the opposite way.", type:"boolean"}
};

var permittedCommentChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,=_-";

var gFormat = createFormat({prefix:"G", width:2, zeropad:true, decimals:1});
var mFormat = createFormat({prefix:"M", width:2, zeropad:true, decimals:1});
var hFormat = createFormat({prefix:"H", width:2, zeropad:true, decimals:1});
var dFormat = createFormat({prefix:"D", width:2, zeropad:true, decimals:1});
var probe100Format = createFormat({decimals:3, zeropad:true, width:3, forceDecimal:true});

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 ? 1 : 2), 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 milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999
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 pitchOutput = createVariable({prefix:"F", force:true}, pitchFormat);
var inverseTimeOutput = createVariable({prefix:"F", force:true}, feedFormat);
var sOutput = createVariable({prefix:"S", force:true}, rpmFormat);
var dOutput = createVariable({}, dFormat);

// circular output
var iOutput = createReferenceVariable({prefix:"I"}, xyzFormat);
var jOutput = createReferenceVariable({prefix:"J"}, xyzFormat);
var kOutput = createReferenceVariable({prefix:"K"}, 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 // G94-95
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
var gRotationModal = createModal({force:true}, gFormat); // modal group 16 // G68-G69

// fixed settings
var useMultiAxisFeatures = false;
var forceMultiAxisIndexing = false; // force multi-axis indexing for 3D programs

var WARNING_WORK_OFFSET = 0;

var ANGLE_PROBE_NOT_SUPPORTED = 0;
var ANGLE_PROBE_USE_ROTATION = 1;
var ANGLE_PROBE_USE_CAXIS = 2;

// collected state
var sequenceNumber;
var currentWorkOffset;
var optionalSection = false;
var useIncremental = false;
var forceSpindleSpeed = false;
var g68RotationMode = 0;
var angularProbingMode;

/**
Writes the specified block.
*/
function writeBlock() {
if (properties.showSequenceNumbers) {
if (optionalSection) {
var text = formatWords(arguments);
if (text) {
writeWords("/", "N" + sequenceNumber, text);
}
} else {
writeWords2("N" + sequenceNumber, arguments);
}
sequenceNumber += properties.sequenceNumberIncrement;
} else {
if (optionalSection) {
writeWords2("/", arguments);
} 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;
}
} else {
writeWords2("/", arguments);
}
}

function formatComment(text) {
return "(" + filterText(String(text).toUpperCase(), permittedCommentChars).replace(/[\(\)]/g, "") + ")";
}

/**
Output a comment.
*/
function writeComment(text) {
writeln(formatComment(text));
}

function onOpen() {
if (properties.useRadius) {
maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC
}

if (true) {
var aAxis = createAxis({coordinate:0, table:true, axis:[(properties.makeAAxisOtherWay ? -1 : 1) * -1, 0, 0], cyclic:true, preference:1});
machineConfiguration = new MachineConfiguration(aAxis);

setMachineConfiguration(machineConfiguration);
optimizeMachineAngles2(1); // map tip mode
}

if (!machineConfiguration.isMachineCoordinate(0)) {
aOutput.disable();
}
if (!machineConfiguration.isMachineCoordinate(1)) {
bOutput.disable();
}
if (!machineConfiguration.isMachineCoordinate(2)) {
cOutput.disable();
}

if (!properties.separateWordsWithSpace) {
setWordSeparator("");
}

if (properties.forceIJK) {
iOutput = createReferenceVariable({prefix:"I", force:true}, xyzFormat);
jOutput = createReferenceVariable({prefix:"J", force:true}, xyzFormat);
kOutput = createReferenceVariable({prefix:"K", force:true}, xyzFormat);
}

sequenceNumber = properties.sequenceNumberStart;
writeln("%");

if (programName) {
var programId;
try {
programId = getAsInt(programName);
} catch(e) {
error(localize("Program name must be a number."));
return;
}
if (properties.o8) {
if (!((programId >= 1) && (programId <= 99999999))) {
error(localize("Program number is out of range."));
return;
}
} else {
if (!((programId >= 1) && (programId <= 9999))) {
error(localize("Program number is out of range."));
return;
}
}
if ((programId >= 8000) && (programId <= 9999)) {
warning(localize("Program number is reserved by tool builder."));
}
var oFormat = createFormat({width:(properties.o8 ? 8 : 4), zeropad:true, decimals:0});
if (programComment) {
writeln("O" + oFormat.format(programId) + " (" + filterText(String(programComment).toUpperCase(), permittedCommentChars) + ")");
} else {
writeln("O" + oFormat.format(programId));
}
} else {
error(localize("Program name has not been specified."));
return;
}

// dump machine configuration
var vendor = machineConfiguration.getVendor();
var model = machineConfiguration.getModel();
var description = machineConfiguration.getDescription();

if (properties.writeMachine && (vendor || model || description)) {
writeComment(localize("Machine"));
if (vendor) {
writeComment(" " + localize("vendor") + ": " + vendor);
}
if (model) {
writeComment(" " + localize("model") + ": " + model);
}
if (description) {
writeComment(" " + localize("description") + ": " + description);
}
}

// dump tool information
if (properties.writeTools) {
var zRanges = {};
if (is3D()) {
var numberOfSections = getNumberOfSections();
for (var i = 0; i < numberOfSections; ++i) {
var section = getSection(i);
var zRange = section.getGlobalZRange();
var tool = section.getTool();
if (zRanges[tool.number]) {
zRanges[tool.number].expandToRange(zRange);
} else {
zRanges[tool.number] = zRange;
}
}
}

var tools = getToolTable();
if (tools.getNumberOfTools() > 0) {
for (var i = 0; i < tools.getNumberOfTools(); ++i) {
var tool = tools.getTool(i);
var comment = "T" + toolFormat.format(tool.number) + " " +
"D=" + xyzFormat.format(tool.diameter) + " " +
localize("CR") + "=" + xyzFormat.format(tool.cornerRadius);
if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) {
comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg");
}
if (zRanges[tool.number]) {
comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum());
}
comment += " - " + getToolTypeName(tool.type);
writeComment(comment);
}
}
}

if (false) {
// check for duplicate tool number
for (var i = 0; i < getNumberOfSections(); ++i) {
var sectioni = getSection(i);
var tooli = sectioni.getTool();
for (var j = i + 1; j < getNumberOfSections(); ++j) {
var sectionj = getSection(j);
var toolj = sectionj.getTool();
if (tooli.number == toolj.number) {
if (xyzFormat.areDifferent(tooli.diameter, toolj.diameter) ||
xyzFormat.areDifferent(tooli.cornerRadius, toolj.cornerRadius) ||
abcFormat.areDifferent(tooli.taperAngle, toolj.taperAngle) ||
(tooli.numberOfFlutes != toolj.numberOfFlutes)) {
error(
subst(
localize("Using the same tool number for different cutter geometry for operation '%1' and '%2'."),
sectioni.hasParameter("operation-comment") ? sectioni.getParameter("operation-comment") : ("#" + (i + 1)),
sectionj.hasParameter("operation-comment") ? sectionj.getParameter("operation-comment") : ("#" + (j + 1))
)
);
return;
}
}
}
}
}

if ((getNumberOfSections() > 0) && (getSection(0).workOffset == 0)) {
for (var i = 0; i < getNumberOfSections(); ++i) {
if (getSection(i).workOffset > 0) {
error(localize("Using multiple work offsets is not possible if the initial work offset is 0."));
return;
}
}
}

// absolute coordinates and feed per min
writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(properties.useG95 ? 95 : 94), gPlaneModal.format(17), gFormat.format(49), gFormat.format(40), gFormat.format(80));

switch (unit) {
case IN:
writeBlock(gUnitModal.format(20));
break;
case MM:
writeBlock(gUnitModal.format(21));
break;
}

if (properties.useG95) {
feedFormat = createFormat({decimals:(unit == MM ? 4 : 5), forceDecimal:true});
feedOutput = createVariable({prefix:"F"}, feedFormat);
}
}

function onComment(message) {
var comments = String(message).split(";");
for (comment in comments) {
writeComment(comments[comment]);
}
}

/** 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() {
feedOutput.reset();
}

/** Force output of X, Y, Z, A, B, C, and F on next output. */
function forceAny() {
forceXYZ();
forceABC();
forceFeed();
}

var lengthCompensationActive = false;
var retracted = false; // specifies that the tool has been retracted to the safe plane

/** Disables length compensation if currently active or if forced. */
function disableLengthCompensation(force) {
if (lengthCompensationActive || force) {
validate(retracted, "Cannot cancel length compensation if the machine is not fully retracted.");
writeBlock(gFormat.format(49));
lengthCompensationActive = false;
}
}

var currentSmoothing = false;

function setSmoothing(mode) {
if (mode == currentSmoothing) {
return false;
}

// 1) Make sure G49 is called before the execution of G05.1 Q1 Rx
// 2) G05.1 Q1 Rx must be engaged BEFORE G43-Tool Length Comp
// 3) AICC and AIAPC need to be turned on and off for each tool
// 4) AICC and AIAPC does not apply to canned drilling cycles
validate(!lengthCompensationActive, "Length compensation is active while trying to update smoothing.");

currentSmoothing = mode;
writeBlock(gFormat.format(5.1), mode ? "Q1" : "Q0");
return true;
}

var currentWorkPlaneABC = undefined;

function forceWorkPlane() {
currentWorkPlaneABC = undefined;
}

function setWorkPlane(abc) {
if (!forceMultiAxisIndexing && is3D() && !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);

if (useMultiAxisFeatures) {
if (abc.isNonZero()) {
writeBlock(gFormat.format(68.2), "X" + xyzFormat.format(0), "Y" + xyzFormat.format(0), "Z" + xyzFormat.format(0), "A" + abcFormat.format(abc.x), "B" + abcFormat.format(abc.y), "C" + abcFormat.format(abc.z)); // set frame
writeBlock(gFormat.format(53.1)); // turn machine
} else {
writeBlock(gFormat.format(69)); // cancel frame
}
} else {
gMotionModal.reset();
writeBlock(
gMotionModal.format(0),
conditional(machineConfiguration.isMachineCoordinate(0), "A" + abcFormat.format(abc.x)),
conditional(machineConfiguration.isMachineCoordinate(1), "B" + abcFormat.format(abc.y)),
conditional(machineConfiguration.isMachineCoordinate(2), "C" + abcFormat.format(abc.z))
);
}

onCommand(COMMAND_LOCK_MULTI_AXIS);

currentWorkPlaneABC = abc;
}

var closestABC = false; // choose closest machine angles
var currentMachineABC;

function getWorkPlaneMachineABC(workPlane) {
var W = workPlane; // map to global frame

var abc = machineConfiguration.getABC(W);
if (closestABC) {
if (currentMachineABC) {
abc = machineConfiguration.remapToABC(abc, currentMachineABC);
} else {
abc = machineConfiguration.getPreferredABC(abc);
}
} else {
abc = machineConfiguration.getPreferredABC(abc);
}

try {
abc = machineConfiguration.remapABC(abc);
currentMachineABC = abc;
} catch (e) {
error(
localize("Machine angles not supported") + ":"
+ conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x))
+ conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y))
+ conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z))
);
}

var direction = machineConfiguration.getDirection(abc);
if (!isSameDirection(direction, W.forward)) {
error(localize("Orientation not supported."));
}

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 isProbeOperation() {
return (hasParameter("operation-strategy") &&
getParameter("operation-strategy") == "probe");
}

var probeOutputWorkOffset = 1;

function onParameter(name, value) {
if (name == "probe-output-work-offset") {
probeOutputWorkOffset = (value > 0) ? value : 1;
}
}

function onSection() {
var forceToolAndRetract = optionalSection && !currentSection.isOptional();
optionalSection = currentSection.isOptional();

var insertToolCall = forceToolAndRetract || isFirstSection() ||
currentSection.getForceToolChange && currentSection.getForceToolChange() ||
(tool.number != getPreviousSection().getTool().number);

var newWorkOffset = isFirstSection() ||
(getPreviousSection().workOffset != currentSection.workOffset); // work offset changes
var newWorkPlane = isFirstSection() ||
!isSameDirection(getPreviousSection().getGlobalFinalToolAxis(), currentSection.getGlobalInitialToolAxis());
var forceSmoothing = properties.useSmoothing &&
(hasParameter("operation-strategy") && (getParameter("operation-strategy") == "drill") ||
!isFirstSection() && getPreviousSection().hasParameter("operation-strategy") && (getPreviousSection().getParameter("operation-strategy") == "drill")); // force smoothing in case !insertToolCall (2d chamfer)
if (insertToolCall || newWorkOffset || newWorkPlane || forceSmoothing) {

// stop spindle before retract during tool change
if (insertToolCall && !isFirstSection()) {
onCommand(COMMAND_STOP_SPINDLE);
}

// retract to safe plane
retracted = true;
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract
writeBlock(gAbsIncModal.format(90));
forceXYZ();
if ((insertToolCall && !isFirstSection()) || forceSmoothing) {
disableLengthCompensation();
setSmoothing(false);
}
}

writeln("");

if (hasParameter("operation-comment")) {
var comment = getParameter("operation-comment");
if (comment) {
writeComment(comment);
}
}

if (properties.showNotes && hasParameter("notes")) {
var notes = getParameter("notes");
if (notes) {
var lines = String(notes).split("\n");
var r1 = new RegExp("^[\\s]+", "g");
var r2 = new RegExp("[\\s]+$", "g");
for (line in lines) {
var comment = lines[line].replace(r1, "").replace(r2, "");
if (comment) {
writeComment(comment);
}
}
}
}

if (insertToolCall) {
forceWorkPlane();

retracted = true;
onCommand(COMMAND_COOLANT_OFF);

if (!isFirstSection() && properties.optionalStop) {
onCommand(COMMAND_OPTIONAL_STOP);
}

if (tool.number > 99) {
warning(localize("Tool number exceeds maximum value."));
}

disableLengthCompensation();
writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6));
if (tool.comment) {
writeComment(tool.comment);
}
var showToolZMin = false;
if (showToolZMin) {
if (is3D()) {
var numberOfSections = getNumberOfSections();
var zRange = currentSection.getGlobalZRange();
var number = tool.number;
for (var i = currentSection.getId() + 1; i < numberOfSections; ++i) {
var section = getSection(i);
if (section.getTool().number != number) {
break;
}
zRange.expandToRange(section.getGlobalZRange());
}
writeComment(localize("ZMIN") + "=" + zRange.getMinimum());
}
}

if (properties.preloadTool) {
var nextTool = getNextTool(tool.number);
if (nextTool) {
writeBlock("T" + toolFormat.format(nextTool.number));
} else {
// preload first tool
var section = getSection(0);
var firstToolNumber = section.getTool().number;
if (tool.number != firstToolNumber) {
writeBlock("T" + toolFormat.format(firstToolNumber));
}
}
}
}

if (!isProbeOperation() &&
(insertToolCall ||
forceSpindleSpeed ||
isFirstSection() ||
(rpmFormat.areDifferent(tool.spindleRPM, sOutput.getCurrent())) ||
(tool.clockwise != getPreviousSection().getTool().clockwise))) {
forceSpindleSpeed = false;

if (tool.spindleRPM < 1) {
error(localize("Spindle speed out of range."));
return;
}
if (tool.spindleRPM > 99999) {
warning(localize("Spindle speed exceeds maximum value."));
}
writeBlock(
sOutput.format(tool.spindleRPM), mFormat.format(tool.clockwise ? 3 : 4)
);

onCommand(COMMAND_START_CHIP_TRANSPORT);
if (forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) {
// writeBlock(mFormat.format(xxx)); // shortest path traverse
}
}

// wcs
if (insertToolCall) { // force work offset when changing tool
currentWorkOffset = undefined;
}
var workOffset = currentSection.workOffset;
if (workOffset == 0) {
warningOnce(localize("Work offset has not been specified. Using G54 as WCS."), WARNING_WORK_OFFSET);
workOffset = 1;
}
if (workOffset > 0) {
if (workOffset > 6) {
var p = workOffset - 6; // 1->...
if (p > 300) {
error(localize("Work offset out of range."));
return;
} else {
if (workOffset != currentWorkOffset) {
writeBlock(gFormat.format(54.1), "P" + p); // G54.1P
currentWorkOffset = workOffset;
}
}
} else {
if (workOffset != currentWorkOffset) {
writeBlock(gFormat.format(53 + workOffset)); // G54->G59
currentWorkOffset = workOffset;
}
}
}

forceXYZ();

if (forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) { // use 5-axis indexing for multi-axis mode
// set working plane after datum shift

if (currentSection.isMultiAxis()) {
forceWorkPlane();
cancelTransformation();
} else {
var abc = new Vector(0, 0, 0);
if (useMultiAxisFeatures) {
var eulerXYZ = currentSection.workPlane.getTransposed().eulerZYX_R;
abc = new Vector(-eulerXYZ.x, -eulerXYZ.y, -eulerXYZ.z);
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
setCoolant(tool.coolant);

if (properties.useSmoothing) {
if (hasParameter("operation-strategy") && (getParameter("operation-strategy") != "drill")) {
if (setSmoothing(true)) {
// we force G43 using lengthCompensationActive
}
} else {
if (setSmoothing(false)) {
// we force G43 using lengthCompensationActive
}
}
}

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 || !lengthCompensationActive || retracted || (!isFirstSection() && getPreviousSection().isMultiAxis())) {
var lengthOffset = tool.lengthOffset;
if (lengthOffset > 99) {
error(localize("Length offset out of range."));
return;
}

gMotionModal.reset();
writeBlock(gPlaneModal.format(17));

if (!machineConfiguration.isHeadConfiguration()) {
writeBlock(
gAbsIncModal.format(90),
gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y)
);
writeBlock(gMotionModal.format(0), gFormat.format(43), zOutput.format(initialPosition.z), hFormat.format(lengthOffset));
lengthCompensationActive = true;
} 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)
);
lengthCompensationActive = true;
}

gMotionModal.reset();
} else {
writeBlock(
gAbsIncModal.format(90),
gMotionModal.format(0),
xOutput.format(initialPosition.x),
yOutput.format(initialPosition.y)
);
}

validate(lengthCompensationActive, "Length compensation is not active.");

if (isProbeOperation()) {
if (g68RotationMode != 0) {
error(localize("You cannot probe while G68 Rotation is in effect."));
return;
}
angularProbingMode = getAngularProbingMode();
writeBlock(gFormat.format(65), "P" + 9832); // spin the probe on
}

retracted = false;


if (properties.useIncremental) {
writeBlock(gAbsIncModal.format(91));
xOutput = createIncrementalVariable({prefix:"X"}, xyzFormat);
xOutput.format(initialPosition.x);
xOutput.format(initialPosition.x);
yOutput = createIncrementalVariable({prefix:"Y"}, xyzFormat);
yOutput.format(initialPosition.y);
yOutput.format(initialPosition.y);
zOutput = createIncrementalVariable({prefix:"Z"}, xyzFormat);
zOutput.format(initialPosition.z);
zOutput.format(initialPosition.z);

var abc = new Vector(); // TAG: set if using multi-axis machine
aOutput = createIncrementalVariable({prefix:"A"}, abcFormat);
aOutput.format(abc.x);
aOutput.format(abc.x);
bOutput = createIncrementalVariable({prefix:"B"}, abcFormat);
bOutput.format(abc.y);
bOutput.format(abc.y);
cOutput = createIncrementalVariable({prefix:"C"}, abcFormat);
cOutput.format(abc.z);
cOutput.format(abc.z);

useIncremental = true;
} else {
xOutput = createVariable({prefix:"X"}, xyzFormat);
yOutput = createVariable({prefix:"Y"}, xyzFormat);
zOutput = createVariable({prefix:"Z"}, xyzFormat);
aOutput = createVariable({prefix:"A"}, abcFormat);
bOutput = createVariable({prefix:"B"}, abcFormat);
cOutput = createVariable({prefix:"C"}, abcFormat);
}

}

function onDwell(seconds) {
if (seconds > 99999.999) {
warning(localize("Dwelling time is out of range."));
}
milliseconds = clamp(1, seconds * 1000, 99999999);
writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + milliFormat.format(milliseconds));
writeBlock(gFeedModeModal.format(properties.useG95 ? 95 : 94)); // back to G95
}

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
if (useIncremental) {
return [xOutput.format(x), yOutput.format(y),
"Z" + xyzFormat.format(z - r),
"R" + xyzFormat.format(r - zOutput.getCurrent())];
} else {
return [xOutput.format(x), yOutput.format(y),
zOutput.format(z),
"R" + xyzFormat.format(r)];
}
}

/** Convert approach to sign. */
function approach(value) {
validate((value == "positive") || (value == "negative"), "Invalid approach.");
return (value == "positive") ? 1 : -1;
}

/**
Determine if angular probing is supported
*/
function getAngularProbingMode() {
if (machineConfiguration.isMultiAxisConfiguration()) {
if (machineConfiguration.isMachineCoordinate(2)) {
return ANGLE_PROBE_USE_CAXIS;
} else {
return ANGLE_PROBE_NOT_SUPPORTED;
}
} else {
return ANGLE_PROBE_USE_ROTATION;
}
}

/**
Output rotation offset based on angular probing cycle.
*/
function setProbingAngle() {
if ((g68RotationMode == 1) || (g68RotationMode == 2)) { // Rotate coordinate system for Angle Probing
if (!properties.useG54x4) {
gRotationModal.reset();
gAbsIncModal.reset();
writeBlock(
gRotationModal.format(68), gAbsIncModal.format(90),
(g68RotationMode == 1) ? "X0" : "X[#135]",
(g68RotationMode == 1) ? "Y0" : "Y[#136]",
"Z0", "I0.0", "J0.0", "K1.0", "R[#139]"
);
g68RotationMode = 3;
} else if (angularProbingMode != ANGLE_PROBE_NOT_SUPPORTED) {
writeBlock("#26010=#135");
writeBlock("#26011=#136");
writeBlock("#26012=#137");
writeBlock("#26015=#139");
writeBlock(gFormat.format(54.4), "P1");
g68RotationMode = 0;
} else {
error(localize("Angular probing is not supported for this machine configuration."));
return;
}
}
}

function onCyclePoint(x, y, z) {
var probeWorkOffsetCode;
if (isProbeOperation()) {
var workOffset = probeOutputWorkOffset ? probeOutputWorkOffset : currentWorkOffset;
if (workOffset > 99) {
error(localize("Work offset is out of range."));
return;
} else if (workOffset > 6) {
probeWorkOffsetCode = probe100Format.format(workOffset - 6 + 100);
} else {
probeWorkOffsetCode = workOffset + "."; // G54->G59
}
}

if (isFirstCyclePoint()) {
repositionToCycleClearance(cycle, x, y, z);

// return to initial Z which is clearance plane and set absolute mode

var F = cycle.feedrate;
if (properties.useG95) {
F /= spindleSpeed;
}
var P = (cycle.dwell == 0) ? 0 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds

switch (cycleType) {
case "drilling":
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 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(useIncremental ? 91 : 90), gCycleModal.format(82),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
feedOutput.format(F)
);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(81),
getCommonCycle(x, y, z, cycle.retract),
feedOutput.format(F)
);
}
break;
case "chip-breaking":
// cycle.accumulatedDepth is ignored
if (P > 0) {
expandCyclePoint(x, y, z);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(73),
getCommonCycle(x, y, z, cycle.retract),
"Q" + xyzFormat.format(cycle.incrementalDepth),
feedOutput.format(F)
);
}
break;
case "deep-drilling":
if (P > 0) {
expandCyclePoint(x, y, z);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(83),
getCommonCycle(x, y, z, cycle.retract),
"Q" + xyzFormat.format(cycle.incrementalDepth),
// conditional(P > 0, "P" + milliFormat.format(P)),
feedOutput.format(F)
);
}
break;
case "tapping":
writeBlock(mFormat.format(29), sOutput.format(tool.spindleRPM));
if (properties.usePitchForTapping) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
pitchOutput.format(tool.threadPitch)
);
forceFeed();
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
feedOutput.format(F)
);
}
break;
case "left-tapping":
writeBlock(mFormat.format(29), sOutput.format(tool.spindleRPM));
if (properties.usePitchForTapping) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(74),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
pitchOutput.format(tool.threadPitch)
);
forceFeed();
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(74),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
feedOutput.format(properties.useG95 ? tool.getTappingFeedrate()/spindleSpeed : tool.getTappingFeedrate())
);
}
break;
case "right-tapping":
writeBlock(mFormat.format(29), sOutput.format(tool.spindleRPM));
if (properties.usePitchForTapping) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(84),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
pitchOutput.format(tool.threadPitch)
);
forceFeed();
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(84),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
feedOutput.format(properties.useG95 ? tool.getTappingFeedrate()/spindleSpeed : tool.getTappingFeedrate())
);
}
break;
case "tapping-with-chip-breaking":
case "left-tapping-with-chip-breaking":
case "right-tapping-with-chip-breaking":
writeBlock(mFormat.format(29), sOutput.format(tool.spindleRPM));
if (properties.usePitchForTapping) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
"Q" + xyzFormat.format(cycle.incrementalDepth),
pitchOutput.format(tool.threadPitch)
);
forceFeed();
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
"Q" + xyzFormat.format(cycle.incrementalDepth),
feedOutput.format(properties.useG95 ? tool.getTappingFeedrate()/spindleSpeed : tool.getTappingFeedrate())
);
}
break;
case "fine-boring":
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(76),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P), // not optional
"Q" + xyzFormat.format(cycle.shift),
feedOutput.format(F)
);
break;
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(useIncremental ? 91 : 90), gCycleModal.format(87),
getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom),
"Q" + xyzFormat.format(cycle.shift),
"P" + milliFormat.format(P), // not optional
feedOutput.format(F)
);
break;
case "reaming":
if (P > 0) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(89),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
feedOutput.format(F)
);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(85),
getCommonCycle(x, y, z, cycle.retract),
feedOutput.format(F)
);
}
break;
case "stop-boring":
if (P > 0) {
expandCyclePoint(x, y, z);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(86),
getCommonCycle(x, y, z, cycle.retract),
feedOutput.format(F)
);
}
break;
case "manual-boring":
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(88),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P), // not optional
feedOutput.format(F)
);
break;
case "boring":
if (P > 0) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(89),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P), // not optional
feedOutput.format(F)
);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(useIncremental ? 91 : 90), gCycleModal.format(85),
getCommonCycle(x, y, z, cycle.retract),
feedOutput.format(F)
);
}
break;

case "probing-x":
forceXYZ();
// move slowly always from clearance not retract
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9811,
"X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter/2)),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"S" + probeWorkOffsetCode // "T" + toolFormat.format(probeToolDiameterOffset)
);
break;
case "probing-y":
forceXYZ();
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9811,
"Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter/2)),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"S" + probeWorkOffsetCode // "T" + toolFormat.format(probeToolDiameterOffset)
);
break;
case "probing-z":
forceXYZ();
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(Math.min(z - cycle.depth + cycle.probeClearance, cycle.retract)), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9811,
"Z" + xyzFormat.format(z - cycle.depth),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"S" + probeWorkOffsetCode // "T" + toolFormat.format(probeToolLengthOffset)
);
break;
case "probing-x-wall":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"X" + xyzFormat.format(cycle.width1),
zOutput.format(z - cycle.depth),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(cycle.probeClearance),
"S" + probeWorkOffsetCode // "T" + toolFormat.format(probeToolDiameterOffset)
);
break;
case "probing-y-wall":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"Y" + xyzFormat.format(cycle.width1),
zOutput.format(z - cycle.depth),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(cycle.probeClearance),
"S" + probeWorkOffsetCode // "T" + toolFormat.format(probeToolDiameterOffset)
);
break;
case "probing-x-channel":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"X" + xyzFormat.format(cycle.width1),
"Q" + xyzFormat.format(cycle.probeOvertravel),
// not required "R" + xyzFormat.format(cycle.probeClearance),
"S" + probeWorkOffsetCode // "T" + toolFormat.format(probeToolDiameterOffset)
);
break;
case "probing-x-channel-with-island":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"X" + xyzFormat.format(cycle.width1),
zOutput.format(z - cycle.depth),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-y-channel":
yOutput.reset();
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"Y" + xyzFormat.format(cycle.width1),
"Q" + xyzFormat.format(cycle.probeOvertravel),
// not required "R" + xyzFormat.format(cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-y-channel-with-island":
yOutput.reset();
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"Y" + xyzFormat.format(cycle.width1),
zOutput.format(z - cycle.depth),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-xy-circular-boss":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9814,
"D" + xyzFormat.format(cycle.width1),
"Z" + xyzFormat.format(z - cycle.depth),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-xy-circular-hole":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9814,
"D" + xyzFormat.format(cycle.width1),
"Q" + xyzFormat.format(cycle.probeOvertravel),
// not required "R" + xyzFormat.format(cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-xy-circular-hole-with-island":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9814,
"Z" + xyzFormat.format(z - cycle.depth),
"D" + xyzFormat.format(cycle.width1),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-xy-rectangular-hole":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"X" + xyzFormat.format(cycle.width1),
"Q" + xyzFormat.format(cycle.probeOvertravel),
// not required "R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
writeBlock(
gFormat.format(65), "P" + 9812,
"Y" + xyzFormat.format(cycle.width2),
"Q" + xyzFormat.format(cycle.probeOvertravel),
// not required "R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;
case "probing-xy-rectangular-boss":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"Z" + xyzFormat.format(z - cycle.depth),
"X" + xyzFormat.format(cycle.width1),
"R" + xyzFormat.format(cycle.probeClearance),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"S" + probeWorkOffsetCode
);
writeBlock(
gFormat.format(65), "P" + 9812,
"Z" + xyzFormat.format(z - cycle.depth),
"Y" + xyzFormat.format(cycle.width2),
"R" + xyzFormat.format(cycle.probeClearance),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"S" + probeWorkOffsetCode
);
break;
case "probing-xy-rectangular-hole-with-island":
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9812,
"Z" + xyzFormat.format(z - cycle.depth),
"X" + xyzFormat.format(cycle.width1),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
writeBlock(
gFormat.format(65), "P" + 9812,
"Z" + xyzFormat.format(z - cycle.depth),
"Y" + xyzFormat.format(cycle.width2),
"Q" + xyzFormat.format(cycle.probeOvertravel),
"R" + xyzFormat.format(-cycle.probeClearance),
"S" + probeWorkOffsetCode
);
break;

case "probing-xy-inner-corner":
var cornerX = x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter/2);
var cornerY = y + approach(cycle.approach2) * (cycle.probeClearance + tool.diameter/2);
var cornerI = 0;
var cornerJ = 0;
if (cycle.probeSpacing !== undefined) {
cornerI = cycle.probeSpacing;
cornerJ = cycle.probeSpacing;
}
if ((cornerI != 0) && (cornerJ != 0)) {
g68RotationMode = 2;
}
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9815, xOutput.format(cornerX), yOutput.format(cornerY),
conditional(cornerI != 0, "I" + xyzFormat.format(cornerI)),
conditional(cornerJ != 0, "J" + xyzFormat.format(cornerJ)),
"Q" + xyzFormat.format(cycle.probeOvertravel),
conditional((g68RotationMode == 0) || (angularProbingMode == ANGLE_PROBE_USE_CAXIS), "S" + probeWorkOffsetCode)
);
break;
case "probing-xy-outer-corner":
var cornerX = x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter/2);
var cornerY = y + approach(cycle.approach2) * (cycle.probeClearance + tool.diameter/2);
var cornerI = 0;
var cornerJ = 0;
if (cycle.probeSpacing !== undefined) {
cornerI = cycle.probeSpacing;
cornerJ = cycle.probeSpacing;
}
if ((cornerI != 0) && (cornerJ != 0)) {
g68RotationMode = 2;
}
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9816, xOutput.format(cornerX), yOutput.format(cornerY),
conditional(cornerI != 0, "I" + xyzFormat.format(cornerI)),
conditional(cornerJ != 0, "J" + xyzFormat.format(cornerJ)),
"Q" + xyzFormat.format(cycle.probeOvertravel),
conditional((g68RotationMode == 0) || (angularProbingMode == ANGLE_PROBE_USE_CAXIS), "S" + probeWorkOffsetCode)
);
break;
case "probing-x-plane-angle":
forceXYZ();
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9843,
"X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter/2)),
"D" + xyzFormat.format(cycle.probeSpacing),
"Q" + xyzFormat.format(cycle.probeOvertravel)
);
g68RotationMode = 1;
break;
case "probing-y-plane-angle":
forceXYZ();
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(z - cycle.depth), feedOutput.format(F)); // protected positioning move
writeBlock(
gFormat.format(65), "P" + 9843,
"Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter/2)),
"D" + xyzFormat.format(cycle.probeSpacing),
"Q" + xyzFormat.format(cycle.probeOvertravel)
);
g68RotationMode = 1;
break;
default:
expandCyclePoint(x, y, z);
}
} else {
if (isProbeOperation()) {
// do nothing
} else if (cycleExpanded) {
expandCyclePoint(x, y, z);
} else {
writeBlock(xOutput.format(x), yOutput.format(y));
}
}
}

function onCycleEnd() {
if (isProbeOperation()) {
writeBlock(gFormat.format(65), "P" + 9810, zOutput.format(cycle.clearance)); // protected retract move
writeBlock(gFormat.format(65), "P" + 9833); // spin the probe off
setProbingAngle(); // define rotation of part
// we can move in rapid from retract optionally
} else if (!cycleExpanded) {
writeBlock(gCycleModal.format(80));
zOutput.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 = feedOutput.format(feed);
if (x || y || z) {
if (pendingRadiusCompensation >= 0) {
pendingRadiusCompensation = -1;
var d = tool.diameterOffset;
if (d > 99) {
warning(localize("The diameter offset exceeds the maximum value."));
}
writeBlock(gPlaneModal.format(17));
switch (radiusCompensation) {
case RADIUS_COMPENSATION_LEFT:
dOutput.reset();
writeBlock(gFeedModeModal.format(94), gMotionModal.format(1), gFormat.format(41), x, y, z, dOutput.format(d), f);
break;
case RADIUS_COMPENSATION_RIGHT:
dOutput.reset();
writeBlock(gFeedModeModal.format(94), gMotionModal.format(1), gFormat.format(42), x, y, z, dOutput.format(d), f);
break;
default:
writeBlock(gFeedModeModal.format(94), gMotionModal.format(1), gFormat.format(40), x, y, z, f);
}
} else {
writeBlock(gFeedModeModal.format(94), 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(gFeedModeModal.format(94), gMotionModal.format(1), f);
}
}
}

function onRapid5D(_x, _y, _z, _a, _b, _c) {
if (pendingRadiusCompensation >= 0) {
error(localize("Radius compensation mode cannot be changed at rapid traversal."));
return;
}
var x = xOutput.format(_x);
var y = yOutput.format(_y);
var z = zOutput.format(_z);
var a = aOutput.format(_a);
var b = bOutput.format(_b);
var c = cOutput.format(_c);
writeBlock(gMotionModal.format(0), x, y, z, a, b, c);
feedOutput.reset();
}

function onLinear5D(_x, _y, _z, _a, _b, _c, feed) {
if (!currentSection.isOptimizedForMachine()) {
error(localize("This post configuration has not been customized for 5-axis simultaneous toolpath."));
return;
}
if (pendingRadiusCompensation >= 0) {
error(localize("Radius compensation cannot be activated/deactivated for 5-axis move."));
return;
}
var x = xOutput.format(_x);
var y = yOutput.format(_y);
var z = zOutput.format(_z);
var a = aOutput.format(_a);
var b = bOutput.format(_b);
var c = cOutput.format(_c);

// get feedrate number
var f = {frn:0, fmode:0};
if (a || b || c) {
f = getMultiaxisFeed(_x, _y, _z, _a, _b, _c, feed);
} else {
f.frn = feedOutput.format(feed);
f.fmode = 94;
}

if (x || y || z || a || b || c) {
writeBlock(gFeedModeModal.format(f.fmode), gMotionModal.format(1), x, y, z, a, b, c, f.frn);
} else if (f.frn) {
if (getNextRecord().isMotion()) { // try not to output feed without motion
feedOutput.reset(); // force feed on next line
} else {
writeBlock(gFeedModeModal.format(f.fmode), gMotionModal.format(1), f.frn);
}
}
}

// Start of multi-axis feedrate logic
/***** Be sure to add 'useInverseTime' to post properties if necessary. *****/
/***** 'inverseTimeOutput' must be defined. *****/
/***** 'headOffset' should be defined when a head rotary axis is defined. *****/
/***** The feedrate mode must be included in motion block output (linear, circular, etc. *****/
var dpmBPW = 0.1; // ratio of rotary accuracy to linear accuracy for DPM calculations
var inverseTimeUnits = 1.0; // 1.0 = minutes, 60.0 = seconds
var maxInverseTime = 9999; // maximum value to output for Inverse Time feeds

/** Calculate the multi-axis feedrate number. */
function getMultiaxisFeed(_x, _y, _z, _a, _b, _c, feed) {
var f = {frn:0, fmode:0};
if (feed <= 0) {
error(localize("Feedrate is less than or equal to 0."));
return f;
}

var length = getMoveLength(_x, _y, _z, _a, _b, _c);

if (true) { // inverse time
f.frn = inverseTimeOutput.format(getInverseTime(length[0], feed));
f.fmode = 93;
feedOutput.reset();
} else { // degrees per minute
f.frn = feedOutput.format(getFeedDPM(length, feed));
f.fmode = 94;
}
return f;
}

/** Calculate the DPM feedrate number. */
function getFeedDPM(_moveLength, _feed) {
// moveLength[0] = Tool tip, [1] = XYZ, [2] = ABC

if (false) { // TCP mode is supported, output feed as FPM
return feed;
} else { // DPM feedrate calculation
var moveTime = ((_moveLength[0] < 1.e-6) ? 0.001 : _moveLength[0]) / _feed;
var length = Math.sqrt(Math.pow(_moveLength[1], 2.0) + Math.pow((toDeg(_moveLength[2]) * dpmBPW), 2.0));
return length / moveTime;
}
}

/** Calculate the Inverse time feedrate number. */
function getInverseTime(_length, _feed) {
var inverseTime;
if (_length < 1.e-6) { // tool doesn't move
if (typeof maxInverseTime === "number") {
inverseTime = maxInverseTime;
} else {
inverseTime = 999999;
}
} else {
inverseTime = _feed / _length / inverseTimeUnits;
if (typeof maxInverseTime === "number") {
if (inverseTime > maxInverseTime) {
inverseTime = maxInverseTime;
}
}
}
return inverseTime;
}

/** Calculate the distance of the tool position to the center of a rotary axis. */
function getRotaryRadius(center, direction, toolPosition) {
var normal = direction.getNormalized();
var d1 = toolPosition.x - center.x;
var d2 = toolPosition.y - center.y;
var d3 = toolPosition.z - center.z;
var radius = Math.sqrt(
Math.pow((d1 * normal.y) - (d2 * normal.x), 2.0) +
Math.pow((d2 * normal.z) - (d3 * normal.y), 2.0) +
Math.pow((d3 * normal.x) - (d1 * normal.z), 2.0)
);
return radius;
}

/** Calculate the linear distance based on the rotation of a rotary axis. */
function getRadialDistance(axis, startTool, endTool, startABC, endABC) {
// rotary axis does not exist
if (!axis.isEnabled()) {
return 0.0;
}

// calculate the rotary center based on head/table
var center;
if (axis.isHead()) {
var pivot;
if (typeof headOffset === "number") {
pivot = headOffset;
} else {
pivot = tool.getBodyLength();
}
center = Vector.sum(startTool, Vector.product(machineConfiguration.getSpindleAxis(), pivot));
center = Vector.sum(center, axis.getOffset());
} else {
center = axis.getOffset();
}

// calculate the radius of the tool end point compared to the rotary center
var startRadius = getRotaryRadius(center, axis.getEffectiveAxis(), startTool);
var endRadius = getRotaryRadius(center, axis.getEffectiveAxis(), endTool);

// calculate length of radial move
var radius = Math.max(startRadius, endRadius);
var delta = Math.abs(endABC.getCoordinate(axis.getCoordinate()) - startABC.getCoordinate(axis.getCoordinate()));
if (delta > Math.PI) {
delta = 2 * Math.PI - delta;
}
var radialLength = (2 * Math.PI * radius) * (delta / (2 * Math.PI));
return radialLength;
}

/** Calculate tooltip, XYZ, and rotary move lengths. */
function getMoveLength(_x, _y, _z, _a, _b, _c) {
// get starting and ending positions
var moveLength = new Array();
var startTool;
var endTool;
var startXYZ;
var endXYZ;
var startABC = getCurrentDirection();
var endABC = new Vector(_a, _b, _c);

if (currentSection.getOptimizedTCPMode() == 0) {
startTool = getCurrentPosition();
endTool = new Vector(_x, _y, _z);
startXYZ = machineConfiguration.getOrientation(startABC).getTransposed().multiply(startTool);
endXYZ = machineConfiguration.getOrientation(endABC).getTransposed().multiply(endTool);
} else {
startXYZ = getCurrentPosition();
endXYZ = new Vector(_x, _y, _z);
startTool = machineConfiguration.getOrientation(startABC).multiply(startXYZ);
endTool = machineConfiguration.getOrientation(endABC).multiply(endXYZ);
}

// calculate the radial portion of the move
var radialLength = Math.sqrt(
Math.pow(getRadialDistance(machineConfiguration.getAxisU(), startTool, endTool, startABC, endABC), 2.0) +
Math.pow(getRadialDistance(machineConfiguration.getAxisV(), startTool, endTool, startABC, endABC), 2.0) +
Math.pow(getRadialDistance(machineConfiguration.getAxisW(), startTool, endTool, startABC, endABC), 2.0)
);

// calculate the lengths of move
// tool tip distance is the move distance based on a combination of linear and rotary axes movement
var linearLength = Vector.diff(endXYZ, startXYZ).length;
moveLength[0] = linearLength + radialLength;
moveLength[1] = Vector.diff(endXYZ, startXYZ).length;
moveLength[2] = 0;
for (var i = 0; i < 3; ++i) {
var delta = Math.abs(endABC[i] - startABC[i]);
if (delta > Math.PI) {
delta = 2 * Math.PI - delta;
}
moveLength[2] += Math.pow(delta, 2.0);
}
moveLength[2] = Math.sqrt(moveLength[2]);
return moveLength;
}
// End of multi-axis feedrate logic

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(useIncremental ? 91 : 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(useIncremental ? 91 : 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(useIncremental ? 91 : 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(useIncremental ? 91 : 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(useIncremental ? 91 : 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(useIncremental ? 91 : 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:
if (properties.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(gAbsIncModal.format(useIncremental ? 91 : 90), 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(gAbsIncModal.format(useIncremental ? 91 : 90), 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(gAbsIncModal.format(useIncremental ? 91 : 90), 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(gAbsIncModal.format(useIncremental ? 91 : 90), 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 (properties.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(gAbsIncModal.format(useIncremental ? 91 : 90), 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);
}
}
}
}

var currentCoolantMode = COOLANT_OFF;

function setCoolant(coolant) {
if (isProbeOperation()) { // avoid coolant output for probing
coolant = COOLANT_OFF;
}

if (coolant == currentCoolantMode) {
return; // coolant is already active
}

if (coolant == COOLANT_OFF) {
writeBlock(mFormat.format((currentCoolantMode == COOLANT_THROUGH_TOOL) ? 89 : 9));
currentCoolantMode = COOLANT_OFF;
return;
}

var m;
switch (coolant) {
case COOLANT_FLOOD:
m = 8;
break;
case COOLANT_THROUGH_TOOL:
m = 88;
break;
default:
onUnsupportedCoolant(coolant);
m = 9;
}

if (m) {
writeBlock(mFormat.format(m));
currentCoolantMode = coolant;
}
}

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
};

function onCommand(command) {
switch (command) {
case COMMAND_COOLANT_OFF:
setCoolant(COOLANT_OFF);
return;
case COMMAND_COOLANT_ON:
setCoolant(COOLANT_FLOOD);
return;
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_START_CHIP_TRANSPORT:
return;
case COMMAND_STOP_CHIP_TRANSPORT:
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));

xOutput = createVariable({prefix:"X"}, xyzFormat);
yOutput = createVariable({prefix:"Y"}, xyzFormat);
zOutput = createVariable({prefix:"Z"}, xyzFormat);
aOutput = createVariable({prefix:"A"}, abcFormat);
bOutput = createVariable({prefix:"B"}, abcFormat);
cOutput = createVariable({prefix:"C"}, abcFormat);
useIncremental = false;

if (((getCurrentSectionId() + 1) >= getNumberOfSections()) ||
(tool.number != getNextSection().getTool().number)) {
onCommand(COMMAND_BREAK_CONTROL);
}

forceAny();
}

/** Output block to do safe retract and/or move to home position. */
function writeRetract() {
if (arguments.length == 0) {
error(localize("No axis specified for writeRetract()."));
return;
}
var words = []; // store all retracted axes in an array
for (var i = 0; i < arguments.length; ++i) {
let instances = 0; // checks for duplicate retract calls
for (var j = 0; j < arguments.length; ++j) {
if (arguments[i] == arguments[j]) {
++instances;
}
}
if (instances > 1) { // error if there are multiple retract calls for the same axis
error(localize("Cannot retract the same axis twice in one line"));
return;
}
switch (arguments[i]) {
case X:
words.push("X" + xyzFormat.format(machineConfiguration.hasHomePositionX() ? machineConfiguration.getHomePositionX() : 0));
break;
case Y:
words.push("Y" + xyzFormat.format(machineConfiguration.hasHomePositionY() ? machineConfiguration.getHomePositionY() : 0));
break;
case Z:
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(machineConfiguration.getRetractPlane())); // retract
zOutput.reset();
retracted = true; // specifies that the tool has been retracted to the safe plane
break;
default:
error(localize("Bad axis specified for writeRetract()."));
return;
}
}
if (words.length > 0) {
gMotionModal.reset();
if (!machineConfiguration.hasHomePositionX() && !machineConfiguration.hasHomePositionY()) {
writeBlock(gFormat.format(28), gAbsIncModal.format(91), words); // retract
if (!properties.useIncremental) {
writeBlock(gAbsIncModal.format(90));
}
} else {
writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), words); // retract
writeBlock(gAbsIncModal.format(91));
}
}
}

function onClose() {
writeln("");
optionalSection = false;


onCommand(COMMAND_COOLANT_OFF);

writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract
retracted = true;

disableLengthCompensation(true);
setSmoothing(false);
zOutput.reset();

setWorkPlane(new Vector(0, 0, 0)); // reset working plane

if (properties.useG54x4) {
writeBlock(gFormat.format(54.4), "P0");
}

if (!machineConfiguration.hasHomePositionX() && !machineConfiguration.hasHomePositionY()) {
// 90/91 mode is don't care
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "X" + xyzFormat.format(0), "Y" + xyzFormat.format(0)); // return to home
} else {
var homeX;
if (machineConfiguration.hasHomePositionX()) {
homeX = "X" + xyzFormat.format(machineConfiguration.getHomePositionX());
}
var homeY;
if (machineConfiguration.hasHomePositionY()) {
homeY = "Y" + xyzFormat.format(machineConfiguration.getHomePositionY());
}
writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), homeX, homeY);
}

onImpliedCommand(COMMAND_END);
onImpliedCommand(COMMAND_STOP_SPINDLE);
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
writeln("%");
}
0 Likes