freecad-cam/Mod/cam-dev/ref-fusion/CAM360/Data/Posts/torchmate.cps

1729 lines
66 KiB
Plaintext

/**
Copyright (C) 2012-2025 by Autodesk, Inc.
All rights reserved.
Torchmate Mill/Plasma post processor configuration.
$Revision: 45608 b291a8a39e704678228667016237559bb9f87f7c $
$Date: 2025-09-16 08:34:14 $
FORKID {7B91741C-EF71-49D7-9E87-E53C2C071888}
*/
/* additional commands
M100 Wait for input line (normal state)
M101 Wait for input line (tripped state)
*/
description = "Torchmate 3.0 Mill/Plasma";
vendor = "Torchmate";
vendorUrl = "http://torchmate.com";
legal = "Copyright (C) 2012-2025 by Autodesk, Inc.";
certificationLevel = 2;
minimumRevision = 45917;
longDescription = "Generic post for Torchmate 3.0 Mill/Plasma. Enable property 'Use Z Values' to output Z moves. Turn off property 'Use work offsets' if G54, G55, ... work offsets are not used. Disable property 'Use M30' to avoid M30 at end of program. Disable property 'Use coolant' to avoid coolant M-codes. Disable property 'Use tool' if tool calls should not be output.";
extension = "fgc";
setCodePage("ascii");
capabilities = CAPABILITY_MILLING | CAPABILITY_JET | CAPABILITY_MACHINE_SIMULATION;
tolerance = spatial(0.002, MM);
minimumChordLength = spatial(0.25, MM);
minimumCircularRadius = spatial(0.01, MM);
maximumCircularRadius = spatial(1000, MM);
minimumCircularSweep = toRad(0.01);
maximumCircularSweep = toRad(180);
allowHelicalMoves = true; // for milling
allowedCircularPlanes = undefined; // allow any circular motion
highFeedrate = (unit == MM) ? 5000 : 200;
// user-defined properties
properties = {
safePositionMethod: {
title : "Safe Retracts",
description: "Select your desired retract option. 'Clearance Height' retracts to the operation clearance height.",
group : "homePositions",
type : "enum",
values : [
{title:"G28", id:"G28"},
{title:"Clearance Height", id:"clearanceHeight"}
],
value: "G28",
scope: "post"
},
showSequenceNumbers: {
title : "Use sequence numbers",
description: "'Yes' outputs sequence numbers on each block, 'Only on tool change' outputs sequence numbers on tool change blocks only, and 'No' disables the output of sequence numbers.",
group : "formats",
type : "enum",
values : [
{title:"Yes", id:"true"},
{title:"No", id:"false"},
{title:"Only on tool change", id:"toolChange"}
],
value: "true",
scope: "post"
},
sequenceNumberStart: {
title : "Start sequence number",
description: "The number at which to start the sequence numbers.",
group : "formats",
type : "integer",
value : 10,
scope : "post"
},
sequenceNumberIncrement: {
title : "Sequence number increment",
description: "The amount by which the sequence number is incremented by in each block.",
group : "formats",
type : "integer",
value : 1,
scope : "post"
},
separateWordsWithSpace: {
title : "Separate words with space",
description: "Adds spaces between words if 'yes' is selected.",
group : "formats",
type : "boolean",
value : true,
scope : "post"
},
useRadius: {
title : "Radius arcs",
description: "If yes is selected, arcs are outputted using radius values rather than IJK.",
group : "preferences",
type : "boolean",
value : false,
scope : "post"
},
dwellInSeconds: {
title : "Dwell in seconds",
description: "Specifies the unit for dwelling, set to 'Yes' for seconds and 'No' for milliseconds.",
group : "preferences",
type : "boolean",
value : true,
scope : "post"
},
useZAxis: {
title : "Use Z Values",
description: "If disabled, all Z values are ommited.",
group : "configuration",
type : "boolean",
value : false,
scope : "post"
},
useWorkOffsets: {
title : "Use work offsets",
description: "Enable to allow the use of work offsets.",
group : "preferences",
type : "boolean",
value : true,
scope : "post"
},
useCoolant: {
title : "Use coolant",
description: "Specifies that coolant commands should be output",
group : "preferences",
type : "boolean",
value : true,
scope : "post"
},
useToolCall: {
title : "Use tool",
description: "Enable to ouptut tool calls. E.g. T1.",
group : "preferences",
type : "boolean",
value : true,
scope : "post"
},
useM30: {
title : "Use M30",
description: "Enable to output M30 for program end.",
group : "preferences",
type : "boolean",
value : true,
scope : "post"
}
};
// wcs definiton
wcsDefinitions = {
useZeroOffset: false,
wcs : [
{name:"Standard", format:"G", range:[54, 59]},
{name:"Extended", format:"G54.1 P", range:[1, 99]}
]
};
var gFormat = createFormat({prefix:"G", decimals:1});
var mFormat = createFormat({prefix:"M", decimals:0});
var hFormat = createFormat({prefix:"H", decimals:0});
var diameterOffsetFormat = createFormat({prefix:"D", decimals:0});
var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL});
var rFormat = xyzFormat; // radius
var feedFormat = createFormat({decimals:(unit == MM ? 1 : 2), type:FORMAT_REAL});
var toolFormat = createFormat({decimals:0});
var rpmFormat = createFormat({decimals:0});
var secFormat = createFormat({decimals:3, type:FORMAT_REAL}); // seconds - range 0.001-99999.999
var milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999
var taperFormat = createFormat({decimals:1, scale:DEG});
var xOutput = createOutputVariable({onchange:function() {state.retractedX = false;}, prefix:"X"}, xyzFormat);
var yOutput = createOutputVariable({onchange:function() {state.retractedY = false;}, prefix:"Y"}, xyzFormat);
// var zOutput = createOutputVariable({prefix:"Z"}, xyzFormat);
var zOutput = createOutputVariable({onchange:function() {state.retractedZ = false;}, prefix:"Z"}, xyzFormat);
var feedOutput = createOutputVariable({prefix:"F"}, feedFormat);
var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat);
// circular output
var iOutput = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, xyzFormat);
var jOutput = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, xyzFormat);
var kOutput = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, xyzFormat);
var gMotionModal = createOutputVariable({}, gFormat); // modal group 1 // G0-G3
var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19
var gAbsIncModal = createOutputVariable({}, gFormat); // modal group 3 // G90-91
var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G93-94
var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G20-21 or G70-71
var gCycleModal = createOutputVariable({}, gFormat); // modal group 9 // G81, ...
var gRetractModal = createOutputVariable({}, gFormat); // modal group 10 // G98-99
var settings = {
coolant: {
// samples:
// {id: COOLANT_THROUGH_TOOL, on: 88, off: 89}
// {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]}
// {id: COOLANT_THROUGH_TOOL, on: "M88 P3 (myComment)", off: "M89"}
coolants: [
{id:COOLANT_FLOOD, on:8},
{id:COOLANT_MIST, on:7},
{id:COOLANT_THROUGH_TOOL},
{id:COOLANT_AIR},
{id:COOLANT_AIR_THROUGH_TOOL},
{id:COOLANT_SUCTION},
{id:COOLANT_FLOOD_MIST},
{id:COOLANT_FLOOD_THROUGH_TOOL},
{id:COOLANT_OFF, off:9}
],
singleLineCoolant: false, // specifies to output multiple coolant codes in one line rather than in separate lines
},
retract: {
cancelRotationOnRetracting: false, // specifies that rotations (G68) need to be canceled prior to retracting
methodXY : undefined, // special condition, overwrite retract behavior per axis
methodZ : undefined, // special condition, overwrite retract behavior per axis
useZeroValues : ["G28", "G30"], // enter property value id(s) for using "0" value instead of machineConfiguration axes home position values (ie G30 Z0)
homeXY : {onIndexing:false, onToolChange:false, onProgramEnd:false} // Specifies when the machine should be homed in X/Y. Sample: onIndexing:{axes:[X, Y], singleLine:false}
},
comments: {
permittedCommentChars: " abcdefghijklmnopqrstuvwxyz0123456789.,=_-", // letters are not case sensitive, use option 'outputFormat' below. Set to 'undefined' to allow any character
prefix : "(", // specifies the prefix for the comment
suffix : ")", // specifies the suffix for the comment
outputFormat : "ignoreCase", // can be set to "upperCase", "lowerCase" and "ignoreCase". Set to "ignoreCase" to write comments without upper/lower case formatting
maximumLineLength : 80 // the maximum number of characters allowed in a line, set to 0 to disable comment output
},
maximumSequenceNumber : 99999, // the maximum sequence number (Nxxx), use 'undefined' for unlimited
supportsOptionalBlocks: false, // specifies if optional block output is supported
// fixed settings below, do not modify
supportsTCP : false // this postprocessor does not support TCP
};
function onOpen() {
if (machineConfiguration.isMultiAxisConfiguration()) {
error(localize("This postprocessor does not support multi axis machine configurations."));
}
if (getProperty("useRadius")) {
maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC
}
if (!getProperty("useZAxis")) {
zOutput.disable();
}
if (!getProperty("separateWordsWithSpace")) {
setWordSeparator("");
}
writeComment(programComment);
writeProgramHeader();
writeBlock(gUnitModal.format(unit == MM ? 71 : 70));
// absolute coordinates
writeBlock(gAbsIncModal.format(90), conditional(getProperty("useZAxis"), gPlaneModal.format(17)));
validateCommonParameters();
}
function writeInitialPositioning(position, insertToolCall) {
if (!state.retractedZ && getProperty("useZAxis") && !insertToolCall) {
if (xyzFormat.getResultingValue(getCurrentPosition().z) < xyzFormat.getResultingValue(position.z)) {
writeBlock(gMotionModal.format(0), zOutput.format(position.z));
}
}
// prepositioning
gMotionModal.reset();
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(17)));
forceXYZ();
writeBlock(
gAbsIncModal.format(90),
gMotionModal.format(0), conditional(getProperty("useZAxis"), gFormat.format(43)),
xOutput.format(position.x), yOutput.format(position.y), zOutput.format(position.z),
conditional(getProperty("useZAxis"), hFormat.format(tool.lengthOffset))
);
machineSimulation({x:position.x, y:position.y, z:position.z});
}
function onSection() {
var forceSectionRestart = optionalSection && !currentSection.isOptional();
optionalSection = currentSection.isOptional();
var insertToolCall = isToolChangeNeeded("number") || forceSectionRestart;
var newWorkOffset = isNewWorkOffset() || forceSectionRestart;
var newWorkPlane = isNewWorkPlane() || forceSectionRestart || (typeof defineWorkPlane == "function" &&
Vector.diff(defineWorkPlane(getPreviousSection(), false), defineWorkPlane(currentSection, false)).length > 1e-4);
if (insertToolCall || newWorkOffset || newWorkPlane) {
if (insertToolCall && !isFirstSection()) {
onCommand(COMMAND_COOLANT_OFF); // turn off coolant before retract during tool change
onCommand(COMMAND_STOP_SPINDLE); // stop spindle before retract during tool change
}
writeRetract(Z);
}
writeln("");
writeComment(getParameter("operation-comment", ""));
writeToolCall(tool, true); // tool change
if (currentSection.type == TYPE_MILLING) {
startSpindle(tool, insertToolCall);
}
// Output modal commands here
writeBlock(gAbsIncModal.format(90), conditional(getProperty("useZAxis"), gPlaneModal.format(17)));
// wcs
if (getProperty("useWorkOffsets")) {
if (insertToolCall) { // force work offset when changing tool
currentWorkOffset = undefined;
}
writeWCS(currentSection, true);
}
{ // pure 3D
var remaining = currentSection.workPlane;
if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) {
error(localize("Tool orientation is not supported."));
}
setRotation(remaining);
}
setCoolant(tool.coolant); // writes the required coolant codes
forceXYZ();
forceFeed();
var initialPosition = getFramePosition(currentSection.getInitialPosition());
writeInitialPositioning(initialPosition, insertToolCall);
// could use G31 Zz Ii Ss Cc Ff for seek sensing
}
function onDwell(seconds) {
var maxValue = 99999.999;
if (seconds > maxValue) {
warning(subst(localize("Dwelling time of '%1' exceeds the maximum value of '%2' in operation '%3'"), seconds, maxValue, getParameter("operation-comment", "")));
}
if (getProperty("dwellInSeconds")) {
writeBlock(gFormat.format(4), "X" + secFormat.format(seconds));
} else {
// P unit is setting in control!
var milliseconds = clamp(1, seconds * 1000, 99999999);
writeBlock(gFormat.format(4), "P" + milliFormat.format(milliseconds));
}
}
function onSpindleSpeed(spindleSpeed) {
writeBlock(sOutput.format(spindleSpeed));
}
function onCycle() {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(17)));
}
function getCommonCycle(x, y, z, r) {
forceXYZ();
return [xOutput.format(x), yOutput.format(y),
zOutput.format(z),
"R" + xyzFormat.format(r)];
}
function onCyclePoint(x, y, z) {
if (!getProperty("useZAxis")) {
error(localize("Z must be enabled by setting the 'Use Z Values' property to use drilling cycles."));
}
if (!isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(currentSection))) {
expandCyclePoint(x, y, z);
return;
}
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 : clamp(1, cycle.dwell * 1000, 99999); // in milliseconds
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" + milliFormat.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),
feedOutput.format(F)
);
}
break;
case "fine-boring": // not supported
expandCyclePoint(x, y, z);
break;
case "reaming":
if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) {
expandCyclePoint(x, y, z);
break;
}
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85),
getCommonCycle(x, y, z, cycle.retract),
feedOutput.format(F)
);
break;
case "boring":
if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) {
expandCyclePoint(x, y, z);
break;
}
if (P > 0) {
expandCyclePoint(x, y, z);
} 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);
if (!_x && !_y) {
xOutput.reset(); // at least one axis is required
_x = xOutput.format(x);
}
writeBlock(_x, _y);
}
}
}
function onCycleEnd() {
if (!cycleExpanded) {
writeBlock(gCycleModal.format(80));
zOutput.reset();
}
}
var shapeArea = 0;
var shapePerimeter = 0;
var shapeSide = "inner";
var cuttingSequence = "";
function onParameter(name, value) {
if ((name == "action") && (value == "pierce")) {
// add delay if desired
} else if (name == "shapeArea") {
shapeArea = value;
} else if (name == "shapePerimeter") {
shapePerimeter = value;
} else if (name == "shapeSide") {
shapeSide = value;
} else if (name == "beginSequence") {
if (value == "piercing") {
if (cuttingSequence != "piercing") {
if (getProperty("allowHeadSwitches")) {
// Allow head to be switched here
// writeBlock(mFormat.format(0), '"Switch head for piercing."');
}
}
} else if (value == "cutting") {
if (cuttingSequence == "piercing") {
if (getProperty("allowHeadSwitches")) {
// Allow head to be switched here
// writeBlock(mFormat.format(0), '"Switch head for cutting."');
}
}
}
cuttingSequence = value;
}
}
function onPower(power) {
writeBlock(mFormat.format(power ? 50 : 51)); // plasma on/off
}
function onRapid(_x, _y, _z) {
// manual states linear interpolation - so not dog-leg motion expected
// at least one axis is required
if (pendingRadiusCompensation >= 0) {
// ensure that we end at desired position when compensation is turned off
xOutput.reset();
yOutput.reset();
}
var x = xOutput.format(_x);
var y = yOutput.format(_y);
var z = zOutput.format(_z);
if (x || y || z) {
if (pendingRadiusCompensation >= 0) {
pendingRadiusCompensation = -1;
var toolNumber = tool.number;
if (currentSection.type == TYPE_JET) {
toolNumber = 1; // plasma
if (currentSection.jetMode == JET_MODE_ETCHING) {
toolNumber = 2; // marker
}
}
switch (radiusCompensation) {
case RADIUS_COMPENSATION_LEFT:
writeBlock(gFormat.format(41), diameterOffsetFormat.format(toolNumber));
break;
case RADIUS_COMPENSATION_RIGHT:
writeBlock(gFormat.format(42), diameterOffsetFormat.format(toolNumber));
break;
default:
writeBlock(gFormat.format(40));
}
}
writeBlock(gMotionModal.format(0), x, y, z);
feedOutput.reset();
}
}
function onLinear(_x, _y, _z, feed) {
// at least one axis is required
if (pendingRadiusCompensation >= 0) {
// ensure that we end at desired position when compensation is turned off
xOutput.reset();
yOutput.reset();
}
var x = xOutput.format(_x);
var y = yOutput.format(_y);
var z = zOutput.format(_z);
var f = feedOutput.format(feed);
if (x || y || z) {
if (pendingRadiusCompensation >= 0) {
pendingRadiusCompensation = -1;
var toolNumber = tool.number;
if (currentSection.type == TYPE_JET) {
toolNumber = 1; // plasma
if (currentSection.jetMode == JET_MODE_ETCHING) {
toolNumber = 2; // marker
}
}
switch (radiusCompensation) {
case RADIUS_COMPENSATION_LEFT:
writeBlock(gFormat.format(41), diameterOffsetFormat.format(toolNumber));
break;
case RADIUS_COMPENSATION_RIGHT:
writeBlock(gFormat.format(42), diameterOffsetFormat.format(toolNumber));
break;
default:
}
}
writeBlock(gMotionModal.format(1), x, y, z, f);
} else if (f) {
if (getNextRecord().isMotion()) { // try not to output feed without motion
feedOutput.reset(); // force feed on next line
} else {
writeBlock(gMotionModal.format(1), f);
}
}
}
function onCircular(clockwise, cx, cy, cz, x, y, z, feed) {
// one of X/Y and I/J are required and likewise
if (pendingRadiusCompensation >= 0) {
error(localize("Radius compensation cannot be activated/deactivated for a circular move."));
}
var start = getCurrentPosition();
if (isFullCircle()) {
if (getProperty("useRadius") || isHelical()) { // radius mode does not support full arcs
linearize(tolerance);
return;
}
switch (getCircularPlane()) {
case PLANE_XY:
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(17)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), iOutput.format(cx - start.x), jOutput.format(cy - start.y), feedOutput.format(feed));
break;
case PLANE_ZX:
if (getProperty("useZAxis")) {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(18)), gMotionModal.format(clockwise ? 2 : 3), zOutput.format(z), iOutput.format(cx - start.x), kOutput.format(cz - start.z), feedOutput.format(feed));
} else {
linearize(tolerance);
}
break;
case PLANE_YZ:
if (getProperty("useZAxis")) {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(19)), gMotionModal.format(clockwise ? 2 : 3), yOutput.format(y), jOutput.format(cy - start.y), kOutput.format(cz - start.z), feedOutput.format(feed));
} else {
linearize(tolerance);
}
break;
default:
linearize(tolerance);
}
} else if (!getProperty("useRadius")) {
switch (getCircularPlane()) {
case PLANE_XY:
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(17)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), jOutput.format(cy - start.y), feedOutput.format(feed));
break;
case PLANE_ZX:
if (getProperty("useZAxis")) {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(18)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), kOutput.format(cz - start.z), feedOutput.format(feed));
} else {
linearize(tolerance);
}
break;
case PLANE_YZ:
if (getProperty("useZAxis")) {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(19)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y), kOutput.format(cz - start.z), feedOutput.format(feed));
} else {
linearize(tolerance);
}
break;
default:
linearize(tolerance);
}
} else { // use radius mode
var r = getCircularRadius();
if (toDeg(getCircularSweep()) > 180) {
r = -r; // allow up to <360 deg arcs
}
switch (getCircularPlane()) {
case PLANE_XY:
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(17)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), "R" + rFormat.format(r), feedOutput.format(feed));
break;
case PLANE_ZX:
if (getProperty("useZAxis")) {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(18)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), feedOutput.format(feed));
} else {
linearize(tolerance);
}
break;
case PLANE_YZ:
if (getProperty("useZAxis")) {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(19)), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), feedOutput.format(feed));
} else {
linearize(tolerance);
}
break;
default:
linearize(tolerance);
}
}
}
var mapCommand = {
COMMAND_STOP_SPINDLE: 5
};
function onCommand(command) {
switch (command) {
case COMMAND_COOLANT_OFF:
setCoolant(COOLANT_OFF);
return;
case COMMAND_COOLANT_ON:
setCoolant(tool.coolant);
return;
case COMMAND_STOP:
writeBlock(mFormat.format(0));
forceSpindleSpeed = true;
return;
case COMMAND_OPTIONAL_STOP:
writeBlock(mFormat.format(1));
forceSpindleSpeed = true;
return;
case COMMAND_START_SPINDLE:
forceSpindleSpeed = false;
writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4));
return;
case COMMAND_LOAD_TOOL:
var toolNumber = 1; // plasma
if (currentSection.type == TYPE_JET) {
if (tool.type != TOOL_PLASMA_CUTTER) {
error(localize("The CNC does not support the required tool/process. Only plasma cutting is supported."));
}
switch (currentSection.jetMode) {
case JET_MODE_THROUGH:
break;
case JET_MODE_ETCHING:
toolNumber = 2; // marker
break;
case JET_MODE_VAPORIZE:
error(localize("Vaporize cutting mode is not supported."));
break;
default:
error(localize("Unsupported cutting mode."));
}
} else {
toolNumber = tool.number;
}
if (getProperty("useToolCall")) {
writeToolBlock(mFormat.format(6), "T" + toolFormat.format(toolNumber));
} else {
var comment = formatComment(localize("CHANGE TO T") + toolFormat.format(toolNumber));
writeToolBlock(mFormat.format(0), comment);
}
writeComment(tool.comment);
return;
case COMMAND_POWER_ON:
return;
case COMMAND_POWER_OFF:
return;
case COMMAND_LOCK_MULTI_AXIS:
return;
case COMMAND_UNLOCK_MULTI_AXIS:
return;
case COMMAND_BREAK_CONTROL:
return;
case COMMAND_TOOL_MEASURE:
return;
}
var stringId = getCommandStringId(command);
var mcode = mapCommand[stringId];
if (mcode != undefined) {
writeBlock(mFormat.format(mcode));
} else {
onUnsupportedCommand(command);
}
}
function onSectionEnd() {
writeBlock(conditional(getProperty("useZAxis"), gPlaneModal.format(17)));
if (!isLastSection()) {
if (getNextSection().getTool().coolant != tool.coolant) {
setCoolant(COOLANT_OFF);
}
if (tool.breakControl && isToolChangeNeeded(getNextSection(), getProperty("toolAsName") ? "description" : "number")) {
onCommand(COMMAND_BREAK_CONTROL);
}
}
forceXYZ();
forceFeed();
}
function writeRetract() {
if (!getProperty("useZAxis")) {
return;
}
var retract = getRetractParameters.apply(this, arguments);
if (retract && retract.words.length > 0) {
if (typeof cancelWCSRotation == "function" && getSetting("retract.cancelRotationOnRetracting", false)) { // cancel rotation before retracting
cancelWCSRotation();
}
for (var i in retract.words) {
var words = retract.singleLine ? retract.words : retract.words[i];
switch (retract.method) {
case "G28":
writeBlock(gFormat.format(28), gAbsIncModal.format(91), words); // retract
writeBlock(gAbsIncModal.format(90));
break;
default:
error(subst(localize("Unsupported safe position method '%1'"), retract.method));
}
machineSimulation({
x : retract.singleLine || words.indexOf("X") != -1 ? retract.positions.x : undefined,
y : retract.singleLine || words.indexOf("Y") != -1 ? retract.positions.y : undefined,
z : retract.singleLine || words.indexOf("Z") != -1 ? retract.positions.z : undefined,
coordinates: MACHINE
});
if (retract.singleLine) {
break;
}
}
}
}
function onClose() {
optionalSection = false;
if (getProperty("useZAxis") || getProperty("useM30")) {
writeln("");
}
writeRetract(Z);
if (getProperty("useZAxis")) {
writeBlock(gFormat.format(28)); // move to reference point #1 - tool change position by default
} else {
if (getSetting("retract.homeXY.onProgramEnd", false)) {
writeRetract(settings.retract.homeXY.onProgramEnd);
}
}
if (getProperty("useM30")) {
writeBlock(mFormat.format(30));
}
}
// >>>>> INCLUDED FROM include_files/commonFunctions.cpi
// internal variables, do not change
var receivedMachineConfiguration;
var tcp = {isSupportedByControl:getSetting("supportsTCP", true), isSupportedByMachine:false, isSupportedByOperation:false};
var state = {
retractedX : false, // specifies that the machine has been retracted in X
retractedY : false, // specifies that the machine has been retracted in Y
retractedZ : false, // specifies that the machine has been retracted in Z
tcpIsActive : false, // specifies that TCP is currently active
twpIsActive : false, // specifies that TWP is currently active
lengthCompensationActive: !getSetting("outputToolLengthCompensation", true), // specifies that tool length compensation is active
mainState : true // specifies the current context of the state (true = main, false = optional)
};
var validateLengthCompensation = getSetting("outputToolLengthCompensation", true); // disable validation when outputToolLengthCompensation is disabled
var multiAxisFeedrate;
var sequenceNumber;
var optionalSection = false;
var currentWorkOffset;
var forceSpindleSpeed = false;
var operationNeedsSafeStart = false; // used to convert blocks to optional for safeStartAllOperations
function activateMachine() {
// disable unsupported rotary axes output
if (!machineConfiguration.isMachineCoordinate(0) && (typeof aOutput != "undefined")) {
aOutput.disable();
}
if (!machineConfiguration.isMachineCoordinate(1) && (typeof bOutput != "undefined")) {
bOutput.disable();
}
if (!machineConfiguration.isMachineCoordinate(2) && (typeof cOutput != "undefined")) {
cOutput.disable();
}
// setup usage of useTiltedWorkplane
settings.workPlaneMethod.useTiltedWorkplane = getProperty("useTiltedWorkplane") != undefined ? getProperty("useTiltedWorkplane") :
getSetting("workPlaneMethod.useTiltedWorkplane", false);
settings.workPlaneMethod.useABCPrepositioning = getSetting("workPlaneMethod.useABCPrepositioning", true);
if (!machineConfiguration.isMultiAxisConfiguration()) {
return; // don't need to modify any settings for 3-axis machines
}
// identify if any of the rotary axes has TCP enabled
var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()];
tcp.isSupportedByMachine = axes.some(function(axis) {return axis.isEnabled() && axis.isTCPEnabled();}); // true if TCP is enabled on any rotary axis
// save multi-axis feedrate settings from machine configuration
var mode = machineConfiguration.getMultiAxisFeedrateMode();
var type = mode == FEED_INVERSE_TIME ? machineConfiguration.getMultiAxisFeedrateInverseTimeUnits() :
(mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateDPMType() : DPM_STANDARD);
multiAxisFeedrate = {
mode : mode,
maximum : machineConfiguration.getMultiAxisFeedrateMaximum(),
type : type,
tolerance: mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateOutputTolerance() : 0,
bpwRatio : mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateBpwRatio() : 1
};
// setup of retract/reconfigure TAG: Only needed until post kernel supports these machine config settings
if (receivedMachineConfiguration && machineConfiguration.performRewinds()) {
safeRetractDistance = machineConfiguration.getSafeRetractDistance();
safePlungeFeed = machineConfiguration.getSafePlungeFeedrate();
safeRetractFeed = machineConfiguration.getSafeRetractFeedrate();
}
if (typeof safeRetractDistance == "number" && getProperty("safeRetractDistance") != undefined && getProperty("safeRetractDistance") != 0) {
safeRetractDistance = getProperty("safeRetractDistance");
}
if (revision >= 50294) {
activateAutoPolarMode({tolerance:tolerance / 2, optimizeType:OPTIMIZE_AXIS, expandCycles:getSetting("polarCycleExpandMode", EXPAND_ALL)});
}
if (machineConfiguration.isHeadConfiguration() && getSetting("workPlaneMethod.compensateToolLength", false)) {
for (var i = 0; i < getNumberOfSections(); ++i) {
var section = getSection(i);
if (section.isMultiAxis()) {
machineConfiguration.setToolLength(getBodyLength(section.getTool())); // define the tool length for head adjustments
section.optimizeMachineAnglesByMachine(machineConfiguration, OPTIMIZE_AXIS);
}
}
} else {
optimizeMachineAngles2(OPTIMIZE_AXIS);
}
}
function getBodyLength(tool) {
for (var i = 0; i < getNumberOfSections(); ++i) {
var section = getSection(i);
if (tool.number == section.getTool().number) {
if (section.hasParameter("operation:tool_assemblyGaugeLength")) { // For Fusion
return section.getParameter("operation:tool_assemblyGaugeLength", tool.bodyLength + tool.holderLength);
} else { // Legacy products
return section.getParameter("operation:tool_overallLength", tool.bodyLength + tool.holderLength);
}
}
}
return tool.bodyLength + tool.holderLength;
}
function getFeed(f) {
if (getProperty("useG95")) {
return feedOutput.format(f / spindleSpeed); // use feed value
}
if (typeof activeMovements != "undefined" && activeMovements) {
var feedContext = activeMovements[movement];
if (feedContext != undefined) {
if (!feedFormat.areDifferent(feedContext.feed, f)) {
if (feedContext.id == currentFeedId) {
return ""; // nothing has changed
}
forceFeed();
currentFeedId = feedContext.id;
return settings.parametricFeeds.feedOutputVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id);
}
}
currentFeedId = undefined; // force parametric feed next time
}
return feedOutput.format(f); // use feed value
}
function validateCommonParameters() {
validateToolData();
for (var i = 0; i < getNumberOfSections(); ++i) {
var section = getSection(i);
if (getSection(0).workOffset == 0 && section.workOffset > 0) {
if (!(typeof wcsDefinitions != "undefined" && wcsDefinitions.useZeroOffset)) {
error(localize("Using multiple work offsets is not possible if the initial work offset is 0."));
}
}
if (section.isMultiAxis()) {
if (!section.isOptimizedForMachine() &&
(!getSetting("workPlaneMethod.useTiltedWorkplane", false) || !getSetting("supportsToolVectorOutput", false))) {
error(localize("This postprocessor requires a machine configuration for 5-axis simultaneous toolpath."));
}
if (machineConfiguration.getMultiAxisFeedrateMode() == FEED_INVERSE_TIME && !getSetting("supportsInverseTimeFeed", true)) {
error(localize("This postprocessor does not support inverse time feedrates."));
}
if (getSetting("supportsToolVectorOutput", false) && !tcp.isSupportedByControl) {
error(localize("Incompatible postprocessor settings detected." + EOL +
"Setting 'supportsToolVectorOutput' requires setting 'supportsTCP' to be enabled as well."));
}
}
}
if (!tcp.isSupportedByControl && tcp.isSupportedByMachine) {
error(localize("The machine configuration has TCP enabled which is not supported by this postprocessor."));
}
if (getProperty("safePositionMethod") == "clearanceHeight") {
var msg = "-Attention- Property 'Safe Retracts' is set to 'Clearance Height'." + EOL +
"Ensure the clearance height will clear the part and or fixtures." + EOL +
"Raise the Z-axis to a safe height before starting the program.";
warning(msg);
writeComment(msg);
}
}
function validateToolData() {
var _default = 99999;
var _maximumSpindleRPM = machineConfiguration.getMaximumSpindleSpeed() > 0 ? machineConfiguration.getMaximumSpindleSpeed() :
settings.maximumSpindleRPM == undefined ? _default : settings.maximumSpindleRPM;
var _maximumToolNumber = machineConfiguration.isReceived() && machineConfiguration.getNumberOfTools() > 0 ? machineConfiguration.getNumberOfTools() :
settings.maximumToolNumber == undefined ? _default : settings.maximumToolNumber;
var _maximumToolLengthOffset = settings.maximumToolLengthOffset == undefined ? _default : settings.maximumToolLengthOffset;
var _maximumToolDiameterOffset = settings.maximumToolDiameterOffset == undefined ? _default : settings.maximumToolDiameterOffset;
var header = ["Detected maximum values are out of range.", "Maximum values:"];
var warnings = {
toolNumber : {msg:"Tool number value exceeds the maximum value for tool: " + EOL, max:" Tool number: " + _maximumToolNumber, values:[]},
lengthOffset : {msg:"Tool length offset value exceeds the maximum value for tool: " + EOL, max:" Tool length offset: " + _maximumToolLengthOffset, values:[]},
diameterOffset: {msg:"Tool diameter offset value exceeds the maximum value for tool: " + EOL, max:" Tool diameter offset: " + _maximumToolDiameterOffset, values:[]},
spindleSpeed : {msg:"Spindle speed exceeds the maximum value for operation: " + EOL, max:" Spindle speed: " + _maximumSpindleRPM, values:[]}
};
var toolIds = [];
for (var i = 0; i < getNumberOfSections(); ++i) {
var section = getSection(i);
if (toolIds.indexOf(section.getTool().getToolId()) === -1) { // loops only through sections which have a different tool ID
var toolNumber = section.getTool().number;
var lengthOffset = section.getTool().lengthOffset;
var diameterOffset = section.getTool().diameterOffset;
var comment = section.getParameter("operation-comment", "");
if (toolNumber > _maximumToolNumber && !getProperty("toolAsName")) {
warnings.toolNumber.values.push(SP + toolNumber + EOL);
}
if (lengthOffset > _maximumToolLengthOffset) {
warnings.lengthOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Length offset: " + lengthOffset + ")" + EOL);
}
if (diameterOffset > _maximumToolDiameterOffset) {
warnings.diameterOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Diameter offset: " + diameterOffset + ")" + EOL);
}
toolIds.push(section.getTool().getToolId());
}
// loop through all sections regardless of tool id for idenitfying spindle speeds
// identify if movement ramp is used in current toolpath, use ramp spindle speed for comparisons
var ramp = section.getMovements() & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_ZIG_ZAG) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_HELIX));
var _sectionSpindleSpeed = Math.max(section.getTool().spindleRPM, ramp ? section.getTool().rampingSpindleRPM : 0, 0);
if (_sectionSpindleSpeed > _maximumSpindleRPM) {
warnings.spindleSpeed.values.push(SP + section.getParameter("operation-comment", "") + " (" + _sectionSpindleSpeed + " RPM" + ")" + EOL);
}
}
// sort lists by tool number
warnings.toolNumber.values.sort(function(a, b) {return a - b;});
warnings.lengthOffset.values.sort(function(a, b) {return a.localeCompare(b);});
warnings.diameterOffset.values.sort(function(a, b) {return a.localeCompare(b);});
var warningMessages = [];
for (var key in warnings) {
if (warnings[key].values != "") {
header.push(warnings[key].max); // add affected max values to the header
warningMessages.push(warnings[key].msg + warnings[key].values.join(""));
}
}
if (warningMessages.length != 0) {
warningMessages.unshift(header.join(EOL) + EOL);
warning(warningMessages.join(EOL));
}
}
function forceFeed() {
currentFeedId = undefined;
feedOutput.reset();
}
/** Force output of X, Y, and Z. */
function forceXYZ() {
xOutput.reset();
yOutput.reset();
zOutput.reset();
}
/** Force output of A, B, and C. */
function forceABC() {
aOutput.reset();
bOutput.reset();
cOutput.reset();
}
/** Force output of X, Y, Z, A, B, C, and F on next output. */
function forceAny() {
forceXYZ();
forceABC();
forceFeed();
}
/**
Writes the specified block.
*/
function writeBlock() {
var text = formatWords(arguments);
if (!text) {
return;
}
var prefix = getSetting("sequenceNumberPrefix", "N");
var suffix = getSetting("writeBlockSuffix", "");
if ((optionalSection || skipBlocks) && !getSetting("supportsOptionalBlocks", true)) {
error(localize("Optional blocks are not supported by this post."));
}
if (getProperty("showSequenceNumbers") == "true") {
if (sequenceNumber == undefined || sequenceNumber >= settings.maximumSequenceNumber) {
sequenceNumber = getProperty("sequenceNumberStart");
}
if (optionalSection || skipBlocks) {
writeWords2("/", prefix + sequenceNumber, text + suffix);
} else {
writeWords2(prefix + sequenceNumber, text + suffix);
}
sequenceNumber += getProperty("sequenceNumberIncrement");
} else {
if (optionalSection || skipBlocks) {
writeWords2("/", text + suffix);
} else {
writeWords(text + suffix);
}
}
}
validate(settings.comments, "Setting 'comments' is required but not defined.");
function formatComment(text) {
var prefix = settings.comments.prefix;
var suffix = settings.comments.suffix;
var _permittedCommentChars = settings.comments.permittedCommentChars == undefined ? "" : settings.comments.permittedCommentChars;
switch (settings.comments.outputFormat) {
case "upperCase":
text = text.toUpperCase();
_permittedCommentChars = _permittedCommentChars.toUpperCase();
break;
case "lowerCase":
text = text.toLowerCase();
_permittedCommentChars = _permittedCommentChars.toLowerCase();
break;
case "ignoreCase":
_permittedCommentChars = _permittedCommentChars.toUpperCase() + _permittedCommentChars.toLowerCase();
break;
default:
error(localize("Unsupported option specified for setting 'comments.outputFormat'."));
}
if (_permittedCommentChars != "") {
text = filterText(String(text), _permittedCommentChars);
}
text = String(text).substring(0, settings.comments.maximumLineLength - prefix.length - suffix.length);
return text != "" ? prefix + text + suffix : "";
}
/**
Output a comment.
*/
function writeComment(text) {
if (!text) {
return;
}
var comments = String(text).split(EOL);
for (comment in comments) {
var _comment = formatComment(comments[comment]);
if (_comment) {
if (getSetting("comments.showSequenceNumbers", false)) {
writeBlock(_comment);
} else {
writeln(_comment);
}
}
}
}
function onComment(text) {
writeComment(text);
}
/**
Writes the specified block - used for tool changes only.
*/
function writeToolBlock() {
var show = getProperty("showSequenceNumbers");
setProperty("showSequenceNumbers", (show == "true" || show == "toolChange") ? "true" : "false");
writeBlock(arguments);
setProperty("showSequenceNumbers", show);
machineSimulation({/*x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE,*/ mode:TOOLCHANGE}); // move machineSimulation to a tool change position
}
var skipBlocks = false;
var initialState = JSON.parse(JSON.stringify(state)); // save initial state
var optionalState = JSON.parse(JSON.stringify(state));
var saveCurrentSectionId = undefined;
function writeStartBlocks(isRequired, code) {
var saveSkipBlocks = skipBlocks;
var saveMainState = state; // save main state
if (!isRequired) {
if (!getProperty("safeStartAllOperations", false)) {
return; // when safeStartAllOperations is disabled, dont output code and return
}
if (saveCurrentSectionId != getCurrentSectionId()) {
saveCurrentSectionId = getCurrentSectionId();
forceModals(); // force all modal variables when entering a new section
optionalState = Object.create(initialState); // reset optionalState to initialState when entering a new section
}
skipBlocks = true; // if values are not required, but safeStartAllOperations is enabled - write following blocks as optional
state = optionalState; // set state to optionalState if skipBlocks is true
state.mainState = false;
}
code(); // writes out the code which is passed to this function as an argument
state = saveMainState; // restore main state
skipBlocks = saveSkipBlocks; // restore skipBlocks value
}
var pendingRadiusCompensation = -1;
function onRadiusCompensation() {
pendingRadiusCompensation = radiusCompensation;
if (pendingRadiusCompensation >= 0 && !getSetting("supportsRadiusCompensation", true)) {
error(localize("Radius compensation mode is not supported."));
return;
}
}
function onPassThrough(text) {
var commands = String(text).split(",");
for (text in commands) {
writeBlock(commands[text]);
}
}
function forceModals() {
if (arguments.length == 0) { // reset all modal variables listed below
var modals = [
"gMotionModal",
"gPlaneModal",
"gAbsIncModal",
"gFeedModeModal",
"feedOutput"
];
if (operationNeedsSafeStart && (typeof currentSection != "undefined" && currentSection.isMultiAxis())) {
modals.push("fourthAxisClamp", "fifthAxisClamp", "sixthAxisClamp");
}
for (var i = 0; i < modals.length; ++i) {
if (typeof this[modals[i]] != "undefined") {
this[modals[i]].reset();
}
}
} else {
for (var i in arguments) {
arguments[i].reset(); // only reset the modal variable passed to this function
}
}
}
/** Helper function to be able to use a default value for settings which do not exist. */
function getSetting(setting, defaultValue) {
var result = defaultValue;
var keys = setting.split(".");
var obj = settings;
for (var i in keys) {
if (obj[keys[i]] != undefined) { // setting does exist
result = obj[keys[i]];
if (typeof [keys[i]] === "object") {
obj = obj[keys[i]];
continue;
}
} else { // setting does not exist, use default value
if (defaultValue != undefined) {
result = defaultValue;
} else {
error("Setting '" + keys[i] + "' has no default value and/or does not exist.");
return undefined;
}
}
}
return result;
}
function getForwardDirection(_section) {
var forward = undefined;
var _optimizeType = settings.workPlaneMethod && settings.workPlaneMethod.optimizeType;
if (_section.isMultiAxis()) {
forward = _section.workPlane.forward;
} else if (!getSetting("workPlaneMethod.useTiltedWorkplane", false) && machineConfiguration.isMultiAxisConfiguration()) {
if (_optimizeType == undefined) {
var saveRotation = getRotation();
getWorkPlaneMachineABC(_section, true);
forward = getRotation().forward;
setRotation(saveRotation); // reset rotation
} else {
var abc = getWorkPlaneMachineABC(_section, false);
var forceAdjustment = settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH;
forward = machineConfiguration.getOptimizedDirection(_section.workPlane.forward, abc, false, forceAdjustment);
}
} else {
forward = getRotation().forward;
}
return forward;
}
function getRetractParameters() {
var _arguments = typeof arguments[0] === "object" ? arguments[0].axes : arguments;
var singleLine = arguments[0].singleLine == undefined ? true : arguments[0].singleLine;
var words = []; // store all retracted axes in an array
var retractAxes = new Array(false, false, false);
var method = getProperty("safePositionMethod", "undefined");
if (method == "clearanceHeight") {
if (!is3D()) {
error(localize("Safe retract option 'Clearance Height' is only supported when all operations are along the setup Z-axis."));
}
return undefined;
}
validate(settings.retract, "Setting 'retract' is required but not defined.");
validate(_arguments.length != 0, "No axis specified for getRetractParameters().");
for (i in _arguments) {
retractAxes[_arguments[i]] = true;
}
if ((retractAxes[0] || retractAxes[1]) && !state.retractedZ) { // retract Z first before moving to X/Y home
error(localize("Retracting in X/Y is not possible without being retracted in Z."));
return undefined;
}
// special conditions
if (retractAxes[0] || retractAxes[1]) {
method = getSetting("retract.methodXY", method);
}
if (retractAxes[2]) {
method = getSetting("retract.methodZ", method);
}
// define home positions
var useZeroValues = (settings.retract.useZeroValues && settings.retract.useZeroValues.indexOf(method) != -1);
var _xHome = machineConfiguration.hasHomePositionX() && !useZeroValues ? machineConfiguration.getHomePositionX() : toPreciseUnit(0, MM);
var _yHome = machineConfiguration.hasHomePositionY() && !useZeroValues ? machineConfiguration.getHomePositionY() : toPreciseUnit(0, MM);
var _zHome = machineConfiguration.getRetractPlane() != 0 && !useZeroValues ? machineConfiguration.getRetractPlane() : toPreciseUnit(0, MM);
for (var i = 0; i < _arguments.length; ++i) {
switch (_arguments[i]) {
case X:
if (!state.retractedX) {
words.push("X" + xyzFormat.format(_xHome));
xOutput.reset();
state.retractedX = true;
}
break;
case Y:
if (!state.retractedY) {
words.push("Y" + xyzFormat.format(_yHome));
yOutput.reset();
state.retractedY = true;
}
break;
case Z:
if (!state.retractedZ) {
words.push("Z" + xyzFormat.format(_zHome));
zOutput.reset();
state.retractedZ = true;
}
break;
default:
error(localize("Unsupported axis specified for getRetractParameters()."));
return undefined;
}
}
return {
method : method,
retractAxes: retractAxes,
words : words,
positions : {
x: retractAxes[0] ? _xHome : undefined,
y: retractAxes[1] ? _yHome : undefined,
z: retractAxes[2] ? _zHome : undefined},
singleLine: singleLine};
}
/** Returns true when subprogram logic does exist into the post. */
function subprogramsAreSupported() {
return typeof subprogramState != "undefined";
}
// Start of machine simulation connection move support
var debugSimulation = false; // enable to output debug information for connection move support in the NC program
var TCPON = "TCP ON";
var TCPOFF = "TCP OFF";
var TWPON = "TWP ON";
var TWPOFF = "TWP OFF";
var TOOLCHANGE = "TOOL CHANGE";
var RETRACTTOOLAXIS = "RETRACT TOOLAXIS";
var WORK = "WORK CS";
var MACHINE = "MACHINE CS";
var MIN = "MIN";
var MAX = "MAX";
var WARNING_NON_RANGE = [0, 1, 2];
var isTwpOn;
var isTcpOn;
/**
* Helper function for connection moves in machine simulation.
* @param {Object} parameters An object containing the desired options for machine simulation.
* @note Available properties are:
* @param {Number} x X axis position, alternatively use MIN or MAX to move to the axis limit
* @param {Number} y Y axis position, alternatively use MIN or MAX to move to the axis limit
* @param {Number} z Z axis position, alternatively use MIN or MAX to move to the axis limit
* @param {Number} a A axis position (in radians)
* @param {Number} b B axis position (in radians)
* @param {Number} c C axis position (in radians)
* @param {Number} feed desired feedrate, automatically set to high/current feedrate if not specified
* @param {String} mode mode TCPON | TCPOFF | TWPON | TWPOFF | TOOLCHANGE | RETRACTTOOLAXIS
* @param {String} coordinates WORK | MACHINE - if undefined, work coordinates will be used by default
* @param {Number} eulerAngles the calculated Euler angles for the workplane
* @example
machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE});
machineSimulation({x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE, mode:TOOLCHANGE});
*/
function machineSimulation(parameters) {
if (revision < 50198 || skipBlocks) {
return; // return when post kernel revision is lower than 50198 or when skipBlocks is enabled
}
getAxisLimit = function(axis, limit) {
validate(limit == MIN || limit == MAX, subst(localize("Invalid argument \"%1\" passed to the machineSimulation function."), limit));
var range = axis.getRange();
if (range.isNonRange()) {
var axisLetters = ["X", "Y", "Z"];
var warningMessage = subst(localize("An attempt was made to move the \"%1\" axis to its MIN/MAX limits during machine simulation, but its range is set to \"unlimited\"." + EOL +
"A limited range must be set for the \"%1\" axis in the machine definition, or these motions will not be shown in machine simulation."), axisLetters[axis.getCoordinate()]);
warningOnce(warningMessage, WARNING_NON_RANGE[axis.getCoordinate()]);
return undefined;
}
return limit == MIN ? range.minimum : range.maximum;
};
var x = (isNaN(parameters.x) && parameters.x) ? getAxisLimit(machineConfiguration.getAxisX(), parameters.x) : parameters.x;
var y = (isNaN(parameters.y) && parameters.y) ? getAxisLimit(machineConfiguration.getAxisY(), parameters.y) : parameters.y;
var z = (isNaN(parameters.z) && parameters.z) ? getAxisLimit(machineConfiguration.getAxisZ(), parameters.z) : parameters.z;
var rotaryAxesErrorMessage = localize("Invalid argument for rotary axes passed to the machineSimulation function. Only numerical values are supported.");
var a = (isNaN(parameters.a) && parameters.a) ? error(rotaryAxesErrorMessage) : parameters.a;
var b = (isNaN(parameters.b) && parameters.b) ? error(rotaryAxesErrorMessage) : parameters.b;
var c = (isNaN(parameters.c) && parameters.c) ? error(rotaryAxesErrorMessage) : parameters.c;
var coordinates = parameters.coordinates;
var eulerAngles = parameters.eulerAngles;
var feed = parameters.feed;
if (feed === undefined && typeof gMotionModal !== "undefined") {
feed = gMotionModal.getCurrent() !== 0;
}
var mode = parameters.mode;
var performToolChange = mode == TOOLCHANGE;
if (mode !== undefined && ![TCPON, TCPOFF, TWPON, TWPOFF, TOOLCHANGE, RETRACTTOOLAXIS].includes(mode)) {
error(subst("Mode '%1' is not supported.", mode));
}
// mode takes precedence over TCP/TWP states
var enableTCP = isTcpOn;
var enableTWP = isTwpOn;
if (mode === TCPON || mode === TCPOFF) {
enableTCP = mode === TCPON;
} else if (mode === TWPON || mode === TWPOFF) {
enableTWP = mode === TWPON;
} else {
enableTCP = typeof state !== "undefined" && state.tcpIsActive;
enableTWP = typeof state !== "undefined" && state.twpIsActive;
}
var disableTCP = !enableTCP;
var disableTWP = !enableTWP;
if (disableTWP) {
simulation.setTWPModeOff();
isTwpOn = false;
}
if (disableTCP) {
simulation.setTCPModeOff();
isTcpOn = false;
}
if (enableTCP) {
simulation.setTCPModeOn();
isTcpOn = true;
}
if (enableTWP) {
if (settings.workPlaneMethod.eulerConvention == undefined) {
simulation.setTWPModeAlignToCurrentPose();
} else if (eulerAngles) {
simulation.setTWPModeByEulerAngles(settings.workPlaneMethod.eulerConvention, eulerAngles.x, eulerAngles.y, eulerAngles.z);
}
isTwpOn = true;
}
if (mode == RETRACTTOOLAXIS) {
simulation.retractAlongToolAxisToLimit();
}
if (debugSimulation) {
writeln(" DEBUG" + JSON.stringify(parameters));
writeln(" DEBUG" + JSON.stringify({isTwpOn:isTwpOn, isTcpOn:isTcpOn, feed:feed}));
}
if (x !== undefined || y !== undefined || z !== undefined || a !== undefined || b !== undefined || c !== undefined) {
if (x !== undefined) {simulation.setTargetX(x);}
if (y !== undefined) {simulation.setTargetY(y);}
if (z !== undefined) {simulation.setTargetZ(z);}
if (a !== undefined) {simulation.setTargetA(a);}
if (b !== undefined) {simulation.setTargetB(b);}
if (c !== undefined) {simulation.setTargetC(c);}
if (feed != undefined && feed) {
simulation.setMotionToLinear();
simulation.setFeedrate(typeof feed == "number" ? feed : feedOutput.getCurrent() == 0 ? highFeedrate : feedOutput.getCurrent());
} else {
simulation.setMotionToRapid();
}
if (coordinates != undefined && coordinates == MACHINE) {
simulation.moveToTargetInMachineCoords();
} else {
simulation.moveToTargetInWorkCoords();
}
}
if (performToolChange) {
simulation.performToolChangeCycle();
simulation.moveToTargetInMachineCoords();
}
}
// <<<<< INCLUDED FROM include_files/commonFunctions.cpi
// >>>>> INCLUDED FROM include_files/writeToolCall.cpi
function writeToolCall(tool, insertToolCall) {
if (!isFirstSection()) {
writeStartBlocks(!getProperty("safeStartAllOperations") && insertToolCall, function () {
writeRetract(Z); // write optional Z retract before tool change if safeStartAllOperations is enabled
});
}
writeStartBlocks(insertToolCall, function () {
writeRetract(Z);
if (getSetting("retract.homeXY.onToolChange", false)) {
writeRetract(settings.retract.homeXY.onToolChange);
}
if (!isFirstSection() && insertToolCall) {
if (typeof forceWorkPlane == "function") {
forceWorkPlane();
}
onCommand(COMMAND_COOLANT_OFF); // turn off coolant on tool change
if (typeof disableLengthCompensation == "function") {
disableLengthCompensation(false);
}
}
if (tool.manualToolChange) {
onCommand(COMMAND_STOP);
writeComment("MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number));
} else {
if (!isFirstSection() && getProperty("optionalStop") && insertToolCall) {
onCommand(COMMAND_OPTIONAL_STOP);
}
onCommand(COMMAND_LOAD_TOOL);
}
});
if (typeof forceModals == "function" && (insertToolCall || getProperty("safeStartAllOperations"))) {
forceModals();
}
}
// <<<<< INCLUDED FROM include_files/writeToolCall.cpi
// >>>>> INCLUDED FROM include_files/startSpindle.cpi
function startSpindle(tool, insertToolCall) {
if (tool.type != TOOL_PROBE) {
var spindleSpeedIsRequired = insertToolCall || forceSpindleSpeed || isFirstSection() ||
rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent()) ||
(tool.clockwise != getPreviousSection().getTool().clockwise);
writeStartBlocks(spindleSpeedIsRequired, function () {
if (spindleSpeedIsRequired || operationNeedsSafeStart) {
onCommand(COMMAND_START_SPINDLE);
}
});
}
}
// <<<<< INCLUDED FROM include_files/startSpindle.cpi
// >>>>> INCLUDED FROM include_files/writeWCS.cpi
function writeWCS(section, wcsIsRequired) {
if (section.workOffset != currentWorkOffset) {
if (getSetting("workPlaneMethod.cancelTiltFirst", false) && wcsIsRequired) {
cancelWorkPlane();
}
if (typeof forceWorkPlane == "function" && wcsIsRequired) {
forceWorkPlane();
}
writeStartBlocks(wcsIsRequired, function () {
writeBlock(section.wcs);
});
currentWorkOffset = section.workOffset;
}
}
// <<<<< INCLUDED FROM include_files/writeWCS.cpi
// >>>>> INCLUDED FROM include_files/coolant.cpi
var currentCoolantMode = COOLANT_OFF;
var coolantOff = undefined;
var isOptionalCoolant = false;
var forceCoolant = false;
function setCoolant(coolant) {
var coolantCodes = getCoolantCodes(coolant);
if (Array.isArray(coolantCodes)) {
writeStartBlocks(!isOptionalCoolant, function () {
if (settings.coolant.singleLineCoolant) {
writeBlock(coolantCodes.join(getWordSeparator()));
} else {
for (var c in coolantCodes) {
writeBlock(coolantCodes[c]);
}
}
});
return undefined;
}
return coolantCodes;
}
function getCoolantCodes(coolant, format) {
if (!getProperty("useCoolant", true)) {
return undefined; // coolant output is disabled by property if it exists
}
isOptionalCoolant = false;
if (typeof operationNeedsSafeStart == "undefined") {
operationNeedsSafeStart = false;
}
var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line
var coolants = settings.coolant.coolants;
if (!coolants) {
error(localize("Coolants have not been defined."));
}
if (tool.type && tool.type == TOOL_PROBE) { // avoid coolant output for probing
coolant = COOLANT_OFF;
}
if (coolant == currentCoolantMode) {
if (operationNeedsSafeStart && coolant != COOLANT_OFF) {
isOptionalCoolant = true;
} else if (!forceCoolant || coolant == COOLANT_OFF) {
return undefined; // coolant is already active
}
}
if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined) && !forceCoolant && !isOptionalCoolant) {
if (Array.isArray(coolantOff)) {
for (var i in coolantOff) {
multipleCoolantBlocks.push(coolantOff[i]);
}
} else {
multipleCoolantBlocks.push(coolantOff);
}
}
forceCoolant = false;
var m;
var coolantCodes = {};
for (var c in coolants) { // find required coolant codes into the coolants array
if (coolants[c].id == coolant) {
coolantCodes.on = coolants[c].on;
if (coolants[c].off != undefined) {
coolantCodes.off = coolants[c].off;
break;
} else {
for (var i in coolants) {
if (coolants[i].id == COOLANT_OFF) {
coolantCodes.off = coolants[i].off;
break;
}
}
}
}
}
if (coolant == COOLANT_OFF) {
m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified
} else {
coolantOff = coolantCodes.off;
m = coolantCodes.on;
}
if (!m) {
onUnsupportedCoolant(coolant);
m = 9;
} else {
if (Array.isArray(m)) {
for (var i in m) {
multipleCoolantBlocks.push(m[i]);
}
} else {
multipleCoolantBlocks.push(m);
}
currentCoolantMode = coolant;
for (var i in multipleCoolantBlocks) {
if (typeof multipleCoolantBlocks[i] == "number") {
multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]);
}
}
if (format == undefined || format) {
return multipleCoolantBlocks; // return the single formatted coolant value
} else {
return m; // return unformatted coolant value
}
}
return undefined;
}
// <<<<< INCLUDED FROM include_files/coolant.cpi
// >>>>> INCLUDED FROM include_files/writeProgramHeader.cpi
properties.writeMachine = {
title : "Write machine",
description: "Output the machine settings in the header of the program.",
group : "formats",
type : "boolean",
value : true,
scope : "post"
};
properties.writeTools = {
title : "Write tool list",
description: "Output a tool list in the header of the program.",
group : "formats",
type : "boolean",
value : true,
scope : "post"
};
function writeProgramHeader() {
// dump machine configuration
var vendor = machineConfiguration.getVendor();
var model = machineConfiguration.getModel();
var mDescription = machineConfiguration.getDescription();
if (getProperty("writeMachine") && (vendor || model || mDescription)) {
writeComment(localize("Machine"));
if (vendor) {
writeComment(" " + localize("vendor") + ": " + vendor);
}
if (model) {
writeComment(" " + localize("model") + ": " + model);
}
if (mDescription) {
writeComment(" " + localize("description") + ": " + mDescription);
}
}
// dump tool information
if (getProperty("writeTools")) {
if (false) { // set to true to use the post kernel version of the tool list
writeToolTable(TOOL_NUMBER_COL);
} else {
var zRanges = {};
if (is3D()) {
var numberOfSections = getNumberOfSections();
for (var i = 0; i < numberOfSections; ++i) {
var section = getSection(i);
var zRange = section.getGlobalZRange();
var tool = section.getTool();
if (zRanges[tool.number]) {
zRanges[tool.number].expandToRange(zRange);
} else {
zRanges[tool.number] = zRange;
}
}
}
var tools = getToolTable();
if (tools.getNumberOfTools() > 0) {
for (var i = 0; i < tools.getNumberOfTools(); ++i) {
var tool = tools.getTool(i);
var comment = (getProperty("toolAsName") ? "\"" + tool.description.toUpperCase() + "\"" : "T" + toolFormat.format(tool.number)) + " " +
"D=" + xyzFormat.format(tool.diameter) + " " +
localize("CR") + "=" + xyzFormat.format(tool.cornerRadius);
if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) {
comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg");
}
if (zRanges[tool.number]) {
comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum());
}
comment += " - " + getToolTypeName(tool.type);
writeComment(comment);
}
}
}
}
}
// <<<<< INCLUDED FROM include_files/writeProgramHeader.cpi
properties.writeTools.value = false;