3396 lines
145 KiB
Plaintext
3396 lines
145 KiB
Plaintext
/**
|
|
Copyright (C) 2012-2025 by Autodesk, Inc.
|
|
All rights reserved.
|
|
|
|
Tormach PathPilot post processor configuration.
|
|
|
|
$Revision: 45610 b7cb0c82774d12cdcc570eac00379624457b3298 $
|
|
$Date: 2025-09-16 09:45:33 $
|
|
|
|
FORKID {3CFDE807-BE2F-4A4C-B12A-03080F4B1285}
|
|
*/
|
|
|
|
description = "Tormach PathPilot";
|
|
vendor = "Tormach";
|
|
vendorUrl = "http://www.tormach.com";
|
|
legal = "Copyright (C) 2012-2025 by Autodesk, Inc.";
|
|
certificationLevel = 2;
|
|
minimumRevision = 45917;
|
|
|
|
longDescription = "Tormach PathPilot post for 3-axis and 4-axis milling with SmartCool support.";
|
|
|
|
extension = "nc";
|
|
setCodePage("ascii");
|
|
|
|
capabilities = CAPABILITY_MILLING | CAPABILITY_MACHINE_SIMULATION;
|
|
tolerance = spatial(0.002, MM);
|
|
|
|
minimumChordLength = spatial(0.25, MM);
|
|
minimumCircularRadius = spatial(0.01, MM);
|
|
maximumCircularRadius = spatial(1000, MM);
|
|
minimumCircularSweep = toRad(0.01);
|
|
maximumCircularSweep = toRad(180);
|
|
allowHelicalMoves = true;
|
|
allowedCircularPlanes = undefined; // allow any circular motion
|
|
highFeedrate = (unit == MM) ? 5000 : 200;
|
|
|
|
// user-defined properties
|
|
properties = {
|
|
writeVersion: {
|
|
title : "Write version",
|
|
description: "Write the version number in the header of the code.",
|
|
group : "formats",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
safePositionMethod: {
|
|
title : "Safe Retracts",
|
|
description: "Select your desired retract option. 'Clearance Height' retracts to the operation clearance height.",
|
|
group : "homePositions",
|
|
type : "enum",
|
|
values : [
|
|
{title:"G28", id:"G28"},
|
|
{title:"Clearance Height", id:"clearanceHeight"},
|
|
{title:"G30", id:"G30"}
|
|
],
|
|
value: "G30",
|
|
scope: "post"
|
|
},
|
|
useM06: {
|
|
title : "Use M6",
|
|
description: "Disable to avoid outputting M6.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : true,
|
|
scope : "post"
|
|
},
|
|
showSequenceNumbers: {
|
|
title : "Use sequence numbers",
|
|
description: "'Yes' outputs sequence numbers on each block, 'Only on tool change' outputs sequence numbers on tool change blocks only, and 'No' disables the output of sequence numbers.",
|
|
group : "formats",
|
|
type : "enum",
|
|
values : [
|
|
{title:"Yes", id:"true"},
|
|
{title:"No", id:"false"},
|
|
{title:"Only on tool change", id:"toolChange"},
|
|
{title:"Only on operation start", id:"operation"}
|
|
],
|
|
value: "operation",
|
|
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 : 10,
|
|
scope : "post"
|
|
},
|
|
optionalStop: {
|
|
title : "Optional stop",
|
|
description: "Outputs optional stop code prior to a tool change.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : true,
|
|
scope : "post"
|
|
},
|
|
optionalStopOperation: {
|
|
title : "Optional stop between operations",
|
|
description: "Outputs optional stop code between all operations.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
separateWordsWithSpace: {
|
|
title : "Separate words with space",
|
|
description: "Adds spaces between words if 'yes' is selected.",
|
|
group : "formats",
|
|
type : "boolean",
|
|
value : true,
|
|
scope : "post"
|
|
},
|
|
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"
|
|
},
|
|
forceWorkOffset: {
|
|
title : "Force work offset",
|
|
description: "Forces the work offset code at tool changes.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
rotaryTableAxis: {
|
|
title : "Rotary table axis",
|
|
description: "Select rotary table axis. Check the table direction on the machine and use the (Reversed) selection if the table is moving in the opposite direction.",
|
|
group : "configuration",
|
|
type : "enum",
|
|
values : [
|
|
{title:"No rotary", id:"none"},
|
|
{title:"X", id:"x"},
|
|
{title:"Y", id:"y"},
|
|
{title:"Z", id:"z"},
|
|
{title:"X (Reversed)", id:"-x"},
|
|
{title:"Y (Reversed)", id:"-y"},
|
|
{title:"Z (Reversed)", id:"-z"}
|
|
],
|
|
value: "none",
|
|
scope: "post"
|
|
},
|
|
smartCoolEquipped: {
|
|
title : "SmartCool equipped",
|
|
description: "Specifies if the machine has the SmartCool attachment.",
|
|
group : "coolant",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
multiCoolEquipped: {
|
|
title : "Multi-Coolant equipped",
|
|
description: "Specifies if the machine has the Multi-Coolant module.",
|
|
group : "coolant",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
smartCoolToolSweepPercentage: {
|
|
title : "SmartCool sweep percentage",
|
|
description: "Sets the tool length percentage to sweep coolant.",
|
|
group : "coolant",
|
|
type : "integer",
|
|
value : 100,
|
|
scope : "post"
|
|
},
|
|
multiCoolAirBlastSeconds: {
|
|
title : "Multi-Coolant air blast in seconds",
|
|
description: "Sets the Multi-Coolant air blast time in seconds.",
|
|
group : "coolant",
|
|
type : "integer",
|
|
value : 4,
|
|
scope : "post"
|
|
},
|
|
useCoolant: {
|
|
title : "Use coolant",
|
|
description: "Specifies that coolant commands should be output",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : true,
|
|
scope : "post"
|
|
},
|
|
useRigidTapping: {
|
|
title : "Tapping style",
|
|
description: "Choose standard (G84), Rigid (G33.1), or Self-reversing tapping head, which will expand tapping cycles.",
|
|
group : "tapping",
|
|
type : "enum",
|
|
values : [
|
|
{title:"Rigid (G33.1)", id:"yes"},
|
|
{title:"Standard (G84)", id:"no"},
|
|
{title:"Self-reversing head", id:"reversing"}
|
|
],
|
|
value: "no",
|
|
scope: "post"
|
|
},
|
|
reversingHeadFeed: {
|
|
title : "Self-reversing head feed ratio",
|
|
description: "The percentage of the tapping feedrate for retracting the tool when the Tapping style is set to 'Self-reversing head'.",
|
|
group : "tapping",
|
|
type : "number",
|
|
value : 2,
|
|
scope : "post"
|
|
},
|
|
tappingSpeed: {
|
|
title : "Tapping retract speed ratio",
|
|
description: "The percentage of the spindle speed used when retracting the tool during a tapping cycle.",
|
|
group : "tapping",
|
|
type : "number",
|
|
value : 1,
|
|
range : [0.01, 2.0],
|
|
scope : "post"
|
|
},
|
|
toolBreakageTolerance: {
|
|
title : "Tool breakage tolerance",
|
|
description: "Specifies the tolerance for which tool break detection will raise an alarm.",
|
|
group : "preferences",
|
|
type : "spatial",
|
|
value : 0.1,
|
|
scope : "post"
|
|
},
|
|
measureTools: {
|
|
title : "Optionally measure tools at start",
|
|
description: "Measure each tool used at the beginning of the program when the control parameter specified in 'Parameter number to enable tool measurement' is set to 0.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
measureToolsParameter: {
|
|
title : "Parameter number to enable tool measurement",
|
|
description: "Enter the parameter number used to enable tool measurements when the program is run.\nThis parameter must be set to 0 to enable the tool measurement operation on the machine.\nThe 'Optionally measure tools at start' property must be enabled.",
|
|
group : "preferences",
|
|
type : "number",
|
|
value : 1,
|
|
scope : "post"
|
|
},
|
|
allowAllProbeTools: {
|
|
title : "Allow all tool numbers for probes",
|
|
description: "FOR TESTING PURPOSES ONLY. DO NOT ENABLE.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post",
|
|
visible : false
|
|
},
|
|
gotChipConveyor: {
|
|
title : "Use chip transport",
|
|
description: "Enable to turn on chip transport at start of program.",
|
|
group : "configuration",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
chipConveyorOn: {
|
|
title : "Chip conveyor run time",
|
|
description: "The amount of time in seconds that the chip conveyor runs before becoming idle for the time specified in the 'Chip conveyor idle time' parameter.",
|
|
group : "configuration",
|
|
type : "number",
|
|
range : [0, 3600],
|
|
value : 0,
|
|
scope : "post"
|
|
},
|
|
chipConveyorIdle: {
|
|
title : "Chip conveyor idle time",
|
|
description: "The amount of time in seconds that the chip conveyor is idle before starting again.",
|
|
group : "configuration",
|
|
type : "number",
|
|
range : [0, 3600],
|
|
value : 0,
|
|
scope : "post"
|
|
},
|
|
washdownCoolant: {
|
|
title : "Washdown coolant",
|
|
description: "Specifies whether washdown coolant should be used.",
|
|
group : "preferences",
|
|
type : "boolean",
|
|
value : false,
|
|
scope : "post"
|
|
},
|
|
useSmoothing: {
|
|
title : "Smoothing level",
|
|
description: "Select the high smoothing level to use for machining.",
|
|
group : "preferences",
|
|
type : "enum",
|
|
values : [
|
|
{title:"Off", id:"-1"},
|
|
{title:"Automatic", id:"9999"},
|
|
{title:"Fine finishing", id:"2"},
|
|
{title:"Finishing", id:"3"},
|
|
{title:"Roughing", id:"4"},
|
|
{title:"High speed roughing", id:"5"},
|
|
],
|
|
value: "-1"
|
|
}
|
|
};
|
|
|
|
// define the custom property groups
|
|
groupDefinitions = {
|
|
coolant: {title:"Coolant", order:51, collapsed:true, description:"Smart/Multi-Coolant options."},
|
|
tapping: {title:"Tapping", order:52, collapsed:true, description:"Tapping options."}
|
|
};
|
|
|
|
// wcs definiton
|
|
wcsDefinitions = {
|
|
useZeroOffset: false,
|
|
wcs : [
|
|
{name:"Standard", format:"G", range:[54, 59]},
|
|
{name:"Extended", format:"G59.", range:[1, 3]},
|
|
{name:"Extra", format:"G54.1 P", range:[10, 500]}
|
|
]
|
|
};
|
|
|
|
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), forceDecimal:true});
|
|
var rFormat = xyzFormat; // radius
|
|
var abcFormat = createFormat({decimals:3, forceDecimal:true, scale:DEG});
|
|
var feedFormat = createFormat({decimals:(unit == MM ? 2 : 3), forceDecimal:true});
|
|
var inverseTimeFormat = createFormat({decimals:4, forceDecimal:true});
|
|
var pitchFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:true}); // thread pitch
|
|
var toolFormat = createFormat({decimals:0});
|
|
var rpmFormat = createFormat({decimals:0});
|
|
var coolantOptionFormat = 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 qFormat = createFormat({prefix:"Q", decimals:0});
|
|
|
|
var xOutput = createOutputVariable({onchange:function() {state.retractedX = false;}, prefix:"X"}, xyzFormat);
|
|
var yOutput = createOutputVariable({onchange:function() {state.retractedY = false;}, prefix:"Y"}, xyzFormat);
|
|
var zOutput = createOutputVariable({onchange:function() {state.retractedZ = false;}, prefix:"Z"}, xyzFormat);
|
|
var aOutput = createOutputVariable({prefix:"A"}, abcFormat);
|
|
var bOutput = createOutputVariable({prefix:"B"}, abcFormat);
|
|
var cOutput = createOutputVariable({prefix:"C"}, abcFormat);
|
|
var feedOutput = createOutputVariable({prefix:"F"}, feedFormat);
|
|
var inverseTimeOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, inverseTimeFormat);
|
|
var pitchOutput = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, pitchFormat);
|
|
var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat);
|
|
|
|
// circular output
|
|
var iOutput = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, xyzFormat);
|
|
var jOutput = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, xyzFormat);
|
|
var kOutput = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, xyzFormat);
|
|
|
|
var gMotionModal = createOutputVariable({control:CONTROL_FORCE}, gFormat); // modal group 1 // G0-G3, ...
|
|
var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19
|
|
var gAbsIncModal = createOutputVariable({}, gFormat); // modal group 3 // G90-91
|
|
var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G93-94
|
|
var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G20-21
|
|
var gCycleModal = createOutputVariable({}, gFormat); // modal group 9 // G81, ...
|
|
var gRetractModal = createOutputVariable({control:CONTROL_FORCE}, gFormat); // modal group 10 // G98-99
|
|
var fourthAxisClamp = createOutputVariable({}, mFormat);
|
|
var fifthAxisClamp = createOutputVariable({}, mFormat);
|
|
var washdownModal = createOutputVariable({}, mFormat);
|
|
|
|
// fixed settings
|
|
var maxTappingRetractSpeed = 2000;
|
|
|
|
// collected state
|
|
var coolantZHeight;
|
|
var toolChecked = false; // specifies that the tool has been checked with the probe
|
|
|
|
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, on:207},
|
|
{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
|
|
},
|
|
smoothing: {
|
|
roughing : 5, // roughing level for smoothing in automatic mode
|
|
semi : 4, // semi-roughing level for smoothing in automatic mode
|
|
semifinishing : 3, // semi-finishing level for smoothing in automatic mode
|
|
finishing : 2, // finishing level for smoothing in automatic mode
|
|
thresholdRoughing : toPreciseUnit(0.5, MM), // operations with stock/tolerance above that threshold will use roughing level in automatic mode
|
|
thresholdFinishing : toPreciseUnit(0.05, MM), // operations with stock/tolerance below that threshold will use finishing level in automatic mode
|
|
thresholdSemiFinishing: toPreciseUnit(0.1, MM), // operations with stock/tolerance above finishing and below threshold roughing that threshold will use semi finishing level in automatic mode
|
|
|
|
differenceCriteria: "level", // options: "level", "tolerance", "both". Specifies criteria when output smoothing codes
|
|
autoLevelCriteria : "stock", // use "stock" or "tolerance" to determine levels in automatic mode
|
|
cancelCompensation: false // tool length compensation must be canceled prior to changing the smoothing level
|
|
},
|
|
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:{axes:[X, Y]}} // Specifies when the machine should be homed in X/Y. Sample: onIndexing:{axes:[X, Y], singleLine:false}
|
|
},
|
|
unwind: {
|
|
method : 2, // 1 (move to closest 0 (G28)) or 2 (table does not move (G92))
|
|
codes : [mFormat.format(29)], // formatted code(s) that will (virtually) unwind axis (G90 G28), (G92), etc.
|
|
workOffsetCode: "", // prefix for workoffset number if it is required to be output
|
|
useAngle : "false", // 'true' outputs angle with standard output variable, 'prefix' uses 'anglePrefix', 'false' does not output angle
|
|
anglePrefix : [], // optional prefixes for output angles specified as ["", "", "C"], use blank string if axis does not unwind
|
|
resetG90 : false // set to 'true' if G90 needs to be output after the unwind block
|
|
},
|
|
machineAngles: { // refer to https://cam.autodesk.com/posts/reference/classMachineConfiguration.html#a14bcc7550639c482492b4ad05b1580c8
|
|
controllingAxis: ABC,
|
|
type : PREFER_PREFERENCE,
|
|
options : ENABLE_ALL
|
|
},
|
|
workPlaneMethod: {
|
|
useTiltedWorkplane : false, // specifies that tilted workplanes should be used (ie. G68.2, G254, PLANE SPATIAL, CYCLE800), can be overwritten by property
|
|
eulerConvention : undefined, // specifies the euler convention (ie EULER_XYZ_R), set to undefined to use machine angles for TWP commands ('undefined' requires machine configuration)
|
|
eulerCalculationMethod: "standard", // ('standard' / 'machine') 'machine' adjusts euler angles to match the machines ABC orientation, machine configuration required
|
|
cancelTiltFirst : true, // cancel tilted workplane prior to WCS (G54-G59) blocks
|
|
forceMultiAxisIndexing: false, // force multi-axis indexing for 3D programs
|
|
optimizeType : OPTIMIZE_AXIS // can be set to OPTIMIZE_NONE, OPTIMIZE_BOTH, OPTIMIZE_TABLES, OPTIMIZE_HEADS, OPTIMIZE_AXIS. 'undefined' uses legacy rotations
|
|
},
|
|
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 : 100 // the maximum number of characters allowed in a line, set to 0 to disable comment output
|
|
},
|
|
maximumSequenceNumber: undefined, // the maximum sequence number (Nxxx), use 'undefined' for unlimited
|
|
maximumToolNumber : 1000, // specifies the maximum allowed tool number
|
|
// fixed settings below, do not modify
|
|
supportsTCP : false // specifies if the postprocessor does support TCP
|
|
};
|
|
|
|
var washdownCoolant = {on:208, off:209};
|
|
|
|
/**
|
|
Writes the specified block - only at operations.
|
|
*/
|
|
function writeOperationBlock() {
|
|
var show = getProperty("showSequenceNumbers");
|
|
setProperty("showSequenceNumbers", (show == "true" || show == "operation") ? "true" : "false");
|
|
writeBlock(arguments);
|
|
setProperty("showSequenceNumbers", show);
|
|
}
|
|
|
|
function prepareForToolCheck() {
|
|
writeBlock(mFormat.format(5), getCoolantCodes(COOLANT_OFF));
|
|
washdownModal.setCurrent(washdownCoolant.off);
|
|
}
|
|
|
|
function writeToolMeasureBlock(tool, preMeasure) {
|
|
var comment = formatComment("MEASURE TOOL");
|
|
if (!preMeasure) {
|
|
prepareForToolCheck();
|
|
}
|
|
writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6), comment);
|
|
writeBlock(gFormat.format(37));
|
|
}
|
|
|
|
/**
|
|
Compare a text string to acceptable choices.
|
|
|
|
Returns -1 if there is no match.
|
|
*/
|
|
function parseChoice() {
|
|
for (var i = 1; i < arguments.length; ++i) {
|
|
if (String(arguments[0]).toUpperCase() == String(arguments[i]).toUpperCase()) {
|
|
return i - 1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function defineMachine() {
|
|
var useTCP = false;
|
|
if (getProperty("rotaryTableAxis") != "none") {
|
|
// Define rotary attributes from properties
|
|
var rotary = parseChoice(getProperty("rotaryTableAxis"), "-Z", "-Y", "-X", "NONE", "X", "Y", "Z");
|
|
if (rotary < 0) {
|
|
error(localize("Valid rotaryTableAxis values are: None, X, Y, Z, -X, -Y, -Z"));
|
|
}
|
|
rotary -= 3;
|
|
|
|
// Define Master (carrier) axis
|
|
var masterAxis = Math.abs(rotary) - 1;
|
|
if (masterAxis >= 0) {
|
|
var rotaryVector = [0, 0, 0];
|
|
rotaryVector[masterAxis] = rotary / Math.abs(rotary);
|
|
var aAxis = createAxis({coordinate:0, table:true, axis:rotaryVector, cyclic:true, preference:0, tcp:useTCP, reset:3});
|
|
machineConfiguration = new MachineConfiguration(aAxis);
|
|
|
|
setMachineConfiguration(machineConfiguration);
|
|
if (receivedMachineConfiguration) {
|
|
warning(localize("The provided CAM machine configuration is overwritten by the postprocessor."));
|
|
receivedMachineConfiguration = false; // CAM provided machine configuration is overwritten
|
|
}
|
|
}
|
|
} else {
|
|
if (false) { // note: setup your machine here
|
|
var aAxis = createAxis({coordinate:0, table:true, axis:[1, 0, 0], range:[-120, 120], preference:1, tcp:useTCP});
|
|
var cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], range:[-360, 360], preference:0, tcp:useTCP});
|
|
machineConfiguration = new MachineConfiguration(aAxis, cAxis);
|
|
|
|
setMachineConfiguration(machineConfiguration);
|
|
if (receivedMachineConfiguration) {
|
|
warning(localize("The provided CAM machine configuration is overwritten by the postprocessor."));
|
|
receivedMachineConfiguration = false; // CAM provided machine configuration is overwritten
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!receivedMachineConfiguration) {
|
|
// multiaxis settings
|
|
if (machineConfiguration.isHeadConfiguration()) {
|
|
machineConfiguration.setVirtualTooltip(false); // translate the pivot point to the virtual tool tip for nonTCP rotary heads
|
|
}
|
|
|
|
// retract / reconfigure
|
|
var performRewinds = false; // set to true to enable the rewind/reconfigure logic
|
|
if (performRewinds) {
|
|
machineConfiguration.enableMachineRewinds(); // enables the retract/reconfigure logic
|
|
safeRetractDistance = (unit == IN) ? 1 : 25; // additional distance to retract out of stock, can be overridden with a property
|
|
safeRetractFeed = (unit == IN) ? 20 : 500; // retract feed rate
|
|
safePlungeFeed = (unit == IN) ? 10 : 250; // plunge feed rate
|
|
machineConfiguration.setSafeRetractDistance(safeRetractDistance);
|
|
machineConfiguration.setSafeRetractFeedrate(safeRetractFeed);
|
|
machineConfiguration.setSafePlungeFeedrate(safePlungeFeed);
|
|
var stockExpansion = new Vector(toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN)); // expand stock XYZ values
|
|
machineConfiguration.setRewindStockExpansion(stockExpansion);
|
|
}
|
|
|
|
// multi-axis feedrates
|
|
if (machineConfiguration.isMultiAxisConfiguration()) {
|
|
machineConfiguration.setMultiAxisFeedrate(
|
|
useTCP ? FEED_FPM : getProperty("useDPMFeeds") ? FEED_DPM : FEED_INVERSE_TIME,
|
|
99999.9999, // maximum output value for inverse time feed rates
|
|
getProperty("useDPMFeeds") ? DPM_COMBINATION : INVERSE_MINUTES, // INVERSE_MINUTES/INVERSE_SECONDS or DPM_COMBINATION/DPM_STANDARD
|
|
0.5, // tolerance to determine when the DPM feed has changed
|
|
1.0 // ratio of rotary accuracy to linear accuracy for DPM calculations
|
|
);
|
|
setMachineConfiguration(machineConfiguration);
|
|
}
|
|
|
|
/* home positions */
|
|
// machineConfiguration.setHomePositionX(toPreciseUnit(0, IN));
|
|
// machineConfiguration.setHomePositionY(toPreciseUnit(0, IN));
|
|
// machineConfiguration.setRetractPlane(toPreciseUnit(0, IN));
|
|
|
|
/* maximum spindle speed */
|
|
machineConfiguration.setMaximumSpindleSpeed(10000);
|
|
}
|
|
}
|
|
|
|
function writeMeasureTool() {
|
|
// measure tools
|
|
if (getProperty("measureTools")) {
|
|
var tools = getToolTable();
|
|
if (tools.getNumberOfTools() > 0) {
|
|
writeln("");
|
|
writeBlock(mFormat.format(0), formatComment(localize("Read note"))); // wait for operator
|
|
var cmt = localize("With parameter #" + getProperty("measureToolsParameter") + " set to 0 each tool will cycle through the spindle" + EOL +
|
|
"to verify that the correct tool is in the tool magazine and to automatically measure it." + EOL +
|
|
"Once the tools are verified set parameter #" + getProperty("measureToolsParameter") + " to 1 with" + EOL +
|
|
"an MDI command of '#" + getProperty("measureToolsParameter") + " = 1' to skip verification." + EOL +
|
|
"The value of parameter #" + getProperty("measureToolsParameter") + " can be checked with a '(DEBUG, #" + getProperty("measureToolsParameter") + ")' command." + EOL +
|
|
"The value will be shown on the Status page.");
|
|
writeComment(cmt);
|
|
writeln("o100 sub");
|
|
writeln("o110 if [#" + getProperty("measureToolsParameter") + " LT 1]");
|
|
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");
|
|
}
|
|
comment += " - " + getToolTypeName(tool.type);
|
|
writeComment(comment);
|
|
writeToolMeasureBlock(tool, true);
|
|
}
|
|
writeln("o110 endif");
|
|
writeln("o100 endsub");
|
|
writeln("");
|
|
writeln("o100 call");
|
|
writeln("");
|
|
}
|
|
}
|
|
}
|
|
|
|
function onOpen() {
|
|
// define and enable machine configuration
|
|
receivedMachineConfiguration = machineConfiguration.isReceived();
|
|
if (typeof defineMachine == "function") {
|
|
defineMachine(); // hardcoded machine configuration
|
|
}
|
|
activateMachine(); // enable the machine optimizations and settings
|
|
|
|
if (getProperty("useRadius")) {
|
|
maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC
|
|
}
|
|
|
|
if (!getProperty("separateWordsWithSpace")) {
|
|
setWordSeparator("");
|
|
}
|
|
washdownModal.format(washdownCoolant.off);
|
|
// Add addtional coolant codes when smart coolant is enabled
|
|
if (getProperty("smartCoolEquipped")) {
|
|
settings.coolant.coolants = updateCoolantCode(COOLANT_AIR, {on:7});
|
|
settings.coolant.coolants = updateCoolantCode(COOLANT_FLOOD_MIST, {on:8});
|
|
}
|
|
|
|
// set optional stop to false if optional stop operation is enabled
|
|
setProperty("optionalStop", (!getProperty("optionalStopOperation") && getProperty("optionalStop")));
|
|
toolLengthCompOutput.setControl(CONTROL_CHANGED);
|
|
|
|
writeln("%");
|
|
writeComment(programName);
|
|
writeComment(programComment);
|
|
|
|
if (getProperty("writeVersion")) {
|
|
if (typeof getHeaderVersion == "function" && getHeaderVersion()) {
|
|
writeComment(localize("post version") + ": " + getHeaderVersion());
|
|
}
|
|
if (typeof getHeaderDate == "function" && getHeaderDate()) {
|
|
writeComment(localize("post modified") + ": " + getHeaderDate());
|
|
}
|
|
}
|
|
|
|
writeProgramHeader();
|
|
writeMeasureTool();
|
|
|
|
// absolute coordinates and feed per min
|
|
writeBlock(gAbsIncModal.format(90), gFormat.format(54),
|
|
conditional(getProperty("useSmoothing") == -1, gFormat.format(64)), gFormat.format(50), gPlaneModal.format(17), gFormat.format(40), gFormat.format(80), gFeedModeModal.format(94), gFormat.format(91.1), gFormat.format(49));
|
|
|
|
writeBlock(gUnitModal.format(unit == MM ? 21 : 20), formatComment(localize(unit == MM ? "Metric" : "Inch")));
|
|
|
|
onCommand(COMMAND_START_CHIP_TRANSPORT);
|
|
validateCommonParameters();
|
|
}
|
|
|
|
function onParameter(name, value) {
|
|
if (name == "display") {
|
|
writeComment("MSG, " + value);
|
|
}
|
|
}
|
|
|
|
function setSmoothing(mode) {
|
|
if (mode == smoothing.isActive && (!mode || !smoothing.isDifferent) && !smoothing.force) {
|
|
return; // return if smoothing is already active or is not different
|
|
}
|
|
|
|
var level = mode ? (currentSection.isMultiAxis() ? 6 : smoothing.level) : 3;
|
|
writeBlock(mFormat.format(59), "L" + level);
|
|
smoothing.isActive = mode;
|
|
smoothing.force = false;
|
|
smoothing.isDifferent = false;
|
|
}
|
|
|
|
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);
|
|
initializeSmoothing(); // initialize smoothing mode
|
|
|
|
if (insertToolCall || newWorkOffset || newWorkPlane || smoothing.cancel || currentSection.isMultiAxis()) {
|
|
writeRetract(Z); // retract
|
|
if (isFirstSection()) {
|
|
cancelWorkPlane(machineConfiguration.isMultiAxisConfiguration() && settings.workPlaneMethod.useTiltedWorkplane);
|
|
if (machineConfiguration.isMultiAxisConfiguration()) {
|
|
positionABC(new Vector(0, 0, 0));
|
|
}
|
|
forceABC();
|
|
} else {
|
|
if (insertToolCall || newWorkPlane) {
|
|
cancelWorkPlane();
|
|
}
|
|
if (insertToolCall || smoothing.cancel) {
|
|
setSmoothing(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process Manual NC commands
|
|
executeManualNC();
|
|
|
|
writeln("");
|
|
writeOperationBlock(formatComment(getParameter("operation-comment", "")));
|
|
|
|
if (isProbeOperation() && !getProperty("allowAllProbeTools")) {
|
|
validate(tool.number == 99, subst(localize("The tool number for a probe must be 99 but is defined as %1."), tool.number));
|
|
validate(tool.lengthOffset == 99, subst(localize("The tool length offset for a probe must be 99 but is defined as %1."), tool.lengthOffset));
|
|
}
|
|
|
|
// optional stop
|
|
if (!isFirstSection() && getProperty("optionalStopOperation")) {
|
|
onCommand(COMMAND_OPTIONAL_STOP);
|
|
}
|
|
// tool change
|
|
writeToolCall(tool, insertToolCall);
|
|
if (tool.manualToolChange) {
|
|
onCommand(COMMAND_LOAD_TOOL); // force tool call for manual tool change
|
|
}
|
|
startSpindle(tool, true);
|
|
|
|
if (toolChecked) {
|
|
forceSpindleSpeed = true; // spindle must be restarted if tool is checked without a tool change
|
|
toolChecked = false; // state of tool is not known at the beginning of a section since it could be broken for the previous section
|
|
}
|
|
|
|
// Output modal commands here
|
|
writeBlock(gPlaneModal.format(17), gAbsIncModal.format(90), gFeedModeModal.format(94));
|
|
|
|
// wcs
|
|
if (insertToolCall && getProperty("forceWorkOffset")) { // force work offset when changing tool
|
|
currentWorkOffset = undefined;
|
|
}
|
|
writeWCS(currentSection, true);
|
|
forceXYZ();
|
|
|
|
var abc = defineWorkPlane(currentSection, !machineConfiguration.isHeadConfiguration());
|
|
|
|
setSmoothing(smoothing.isAllowed);
|
|
|
|
// prepositioning
|
|
if (!insertToolCall && state.retractedZ) {
|
|
toolLengthCompOutput.reset(); // force G43 to be output
|
|
}
|
|
settings.outputToolLengthOffset = !insertToolCall && state.retractedZ;
|
|
|
|
if (getProperty("washdownCoolant")) {
|
|
writeBlock(washdownModal.format(tool.type == TOOL_PROBE ? washdownCoolant.off : washdownCoolant.on));
|
|
}
|
|
|
|
var initialPosition = getFramePosition(currentSection.getInitialPosition());
|
|
var isRequired = insertToolCall || state.retractedZ || !state.lengthCompensationActive || (!isFirstSection() && getPreviousSection().isMultiAxis()) || settings.outputToolLengthOffset;
|
|
writeInitialPositioning(initialPosition, isRequired);
|
|
}
|
|
|
|
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), "P" + secFormat.format(seconds));
|
|
} else {
|
|
milliseconds = clamp(1, seconds * 1000, 99999999);
|
|
writeBlock(gFormat.format(4), "P" + milliFormat.format(milliseconds));
|
|
}
|
|
}
|
|
|
|
function onSpindleSpeed(spindleSpeed) {
|
|
writeBlock(sOutput.format(spindleSpeed));
|
|
}
|
|
|
|
function getAdditionalCoolantCodes(coolant, workpieceTop) {
|
|
if (!getProperty("useCoolant", true)) {
|
|
return undefined; // coolant output is disabled by property if it exists
|
|
}
|
|
if (workpieceTop == undefined) {
|
|
workpieceTop = getParameter("operation:surfaceZHigh", undefined);
|
|
}
|
|
coolantZHeight = workpieceTop;
|
|
var c = ["", "", "", ""];
|
|
if (getProperty("multiCoolEquipped") && coolant == COOLANT_FLOOD_MIST && getProperty("multiCoolAirBlastSeconds") != 0) {
|
|
c[3] = qFormat.format(getProperty("multiCoolAirBlastSeconds"));
|
|
}
|
|
var endPointMillingStrategies = ["face", "engrave", "contour_new", "horizontal_new", "parallel_new", "scallop_new",
|
|
"pencil_new", "radial_new", "spiral_new", "morphed_spiral", "ramp", "project"];
|
|
|
|
var strategy = getParameter("operation-strategy", undefined);
|
|
if (strategy && getProperty("smartCoolEquipped") && coolant != COOLANT_OFF) {
|
|
// Drilling strategy. Keep coolant at top of part
|
|
if (strategy == "drill") {
|
|
if (workpieceTop != undefined) {
|
|
c[1] = "E" + xyzFormat.format(coolantZHeight);
|
|
}
|
|
// Tool end point milling. Keep coolant at end of tool
|
|
} else if (endPointMillingStrategies.indexOf(strategy) > -1) {
|
|
c[1] = "P" + coolantOptionFormat.format(0);
|
|
// Side Milling. Sweep the coolant along the length of the tool
|
|
} else {
|
|
c[1] = "P" + coolantOptionFormat.format(0);
|
|
c[2] = "R" + xyzFormat.format(tool.fluteLength * (getProperty("smartCoolToolSweepPercentage") / 100.0));
|
|
}
|
|
}
|
|
return formatWords(c);
|
|
}
|
|
|
|
function updateCoolantCode(coolantId, values) {
|
|
var coolants = settings.coolant.coolants;
|
|
for (var i = 0; i < coolants.length; i++) {
|
|
if (coolants[i].id === coolantId) {
|
|
coolants[i].on = values.on;
|
|
coolants[i].off = values.off;
|
|
break;
|
|
}
|
|
}
|
|
return coolants;
|
|
}
|
|
|
|
function onCycle() {
|
|
writeBlock(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 expandTappingPoint(x, y, z) {
|
|
onExpandedRapid(x, y, cycle.clearance);
|
|
onExpandedLinear(x, y, z, cycle.feedrate);
|
|
onExpandedLinear(x, y, cycle.clearance, cycle.feedrate * getProperty("reversingHeadFeed"));
|
|
}
|
|
|
|
/** Convert approach to sign. */
|
|
function approach(value) {
|
|
validate((value == "positive") || (value == "negative"), "Invalid approach.");
|
|
return (value == "positive") ? 1 : -1;
|
|
}
|
|
|
|
var PROBE_RAPID = 0;
|
|
var PROBE_FEED = 1;
|
|
function protectedProbeMove(x, y, z, feedType) {
|
|
writeBlock(gMotionModal.format(1), xOutput.format(x), yOutput.format(y), zOutput.format(z),
|
|
feedType == PROBE_RAPID ? "F#<_probe_rapid_feed_per_min>" : "F#<_probe_rough_feed_per_min>");
|
|
}
|
|
|
|
function onCyclePoint(x, y, z) {
|
|
if (isInspectionOperation()) {
|
|
if (typeof inspectionCycleInspect == "function") {
|
|
inspectionCycleInspect(cycle, x, y, z);
|
|
return;
|
|
} else {
|
|
cycleNotSupported();
|
|
}
|
|
} else if (isProbeOperation()) {
|
|
writeProbeCycle(cycle, x, y, z);
|
|
} else {
|
|
writeDrillCycle(cycle, x, y, z);
|
|
}
|
|
}
|
|
|
|
function writeDrillCycle(cycle, x, y, z) {
|
|
if (!isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(currentSection))) {
|
|
expandCyclePoint(x, y, z);
|
|
return;
|
|
}
|
|
|
|
var forceCycle = false;
|
|
if ((isTappingCycle() && getProperty("useRigidTapping") == "yes") || cycleType == "tapping-with-chip-breaking") {
|
|
forceCycle = true;
|
|
gCycleModal.reset();
|
|
if (!isFirstCyclePoint()) {
|
|
if (getProperty("useRigidTapping") != "yes") {
|
|
writeBlock(gCycleModal.format(80));
|
|
}
|
|
gMotionModal.reset();
|
|
}
|
|
}
|
|
var useTappingSpeed = false;
|
|
if (isTappingCycle() && getProperty("useRigidTapping") == "yes" && getProperty("tappingSpeed") != 1) {
|
|
if ((spindleSpeed * getProperty("tappingSpeed")) > maxTappingRetractSpeed) {
|
|
warning(subst(localize("Tapping retract spindle speed is greater than %1."), maxTappingRetractSpeed));
|
|
}
|
|
useTappingSpeed = true;
|
|
}
|
|
|
|
if (forceCycle || isFirstCyclePoint()) {
|
|
repositionToCycleClearance(cycle, x, y, z);
|
|
|
|
// return to initial Z which is clearance plane and set absolute mode
|
|
|
|
var F = cycle.feedrate;
|
|
var P = !cycle.dwell ? 0 : cycle.dwell; // in seconds
|
|
|
|
// Adjust SmartCool to top of part if it changes
|
|
if (currentCoolantMode != COOLANT_OFF && getProperty("smartCoolEquipped") && xyzFormat.areDifferent((z + cycle.depth), coolantZHeight)) {
|
|
forceCoolant = true;
|
|
writeBlock(getCoolantCodes(tool.coolant), getAdditionalCoolantCodes(tool.coolant, z + cycle.depth));
|
|
}
|
|
switch (cycleType) {
|
|
case "drilling":
|
|
case "counter-boring":
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(P > 0 ? 82 : 81),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
(P > 0 ? "P" + secFormat.format(P) : ""),
|
|
feedOutput.format(F)
|
|
);
|
|
break;
|
|
case "chip-breaking":
|
|
if ((P > 0) || (cycle.accumulatedDepth < cycle.depth)) {
|
|
expandCyclePoint(x, y, z);
|
|
} else {
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(73),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
"Q" + xyzFormat.format(cycle.incrementalDepth),
|
|
feedOutput.format(F)
|
|
);
|
|
}
|
|
break;
|
|
case "deep-drilling":
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(83),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
"Q" + xyzFormat.format(cycle.incrementalDepth),
|
|
// conditional(P > 0, "P" + secFormat.format(P)),
|
|
feedOutput.format(F)
|
|
);
|
|
break;
|
|
case "tapping":
|
|
case "left-tapping":
|
|
case "right-tapping":
|
|
if (getProperty("useRigidTapping") == "reversing") {
|
|
expandTappingPoint(x, y, z);
|
|
} else if (getProperty("useRigidTapping") == "yes") {
|
|
writeBlock(
|
|
gAbsIncModal.format(90),
|
|
gCycleModal.format(33.1),
|
|
xOutput.format(x), yOutput.format(y), zOutput.format(z),
|
|
conditional(useTappingSpeed, "I" + xyzFormat.format(getProperty("tappingSpeed"))),
|
|
pitchOutput.format(tool.threadPitch)
|
|
);
|
|
} else {
|
|
if (!F) {
|
|
F = tool.getTappingFeedrate();
|
|
}
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90),
|
|
gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
"P" + secFormat.format(P), // dwell is required
|
|
conditional(useTappingSpeed, "I" + xyzFormat.format(getProperty("tappingSpeed"))),
|
|
feedOutput.format(F)
|
|
);
|
|
}
|
|
break;
|
|
case "tapping-with-chip-breaking":
|
|
if (getProperty("useRigidTapping") == "reversing") {
|
|
error(subst(localize("Tapping with chip breaking is not supported when property '%1' is set to 'Self-reversing head'."), properties.useRigidTapping.title));
|
|
}
|
|
if (!F) {
|
|
F = tool.getTappingFeedrate();
|
|
}
|
|
var u = cycle.stock;
|
|
var step = cycle.incrementalDepth;
|
|
var first = true;
|
|
while (u > cycle.bottom) {
|
|
if (step < cycle.minimumIncrementalDepth) {
|
|
step = cycle.minimumIncrementalDepth;
|
|
}
|
|
|
|
u -= step;
|
|
step -= cycle.incrementalDepthReduction;
|
|
gCycleModal.reset(); // required
|
|
if ((u - 0.001) <= cycle.bottom) {
|
|
u = cycle.bottom;
|
|
}
|
|
if (first) {
|
|
first = false;
|
|
if (getProperty("useRigidTapping") == "yes") {
|
|
writeBlock(
|
|
gAbsIncModal.format(90),
|
|
gCycleModal.format(33.1),
|
|
xOutput.format((gPlaneModal.getCurrent() == 19) ? u : x),
|
|
yOutput.format((gPlaneModal.getCurrent() == 18) ? u : y),
|
|
zOutput.format((gPlaneModal.getCurrent() == 17) ? u : z),
|
|
conditional(useTappingSpeed, "I" + xyzFormat.format(getProperty("tappingSpeed"))),
|
|
pitchOutput.format(tool.threadPitch)
|
|
);
|
|
} else {
|
|
writeBlock(
|
|
gRetractModal.format(99), gAbsIncModal.format(90),
|
|
gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84),
|
|
getCommonCycle((gPlaneModal.getCurrent() == 19) ? u : x, (gPlaneModal.getCurrent() == 18) ? u : y, (gPlaneModal.getCurrent() == 17) ? u : z, cycle.retract, cycle.clearance),
|
|
"P" + secFormat.format(P), // dwell is required
|
|
conditional(useTappingSpeed, "I" + xyzFormat.format(getProperty("tappingSpeed"))),
|
|
feedOutput.format(F)
|
|
);
|
|
}
|
|
} else {
|
|
var position;
|
|
var depth;
|
|
switch (gPlaneModal.getCurrent()) {
|
|
case 17:
|
|
xOutput.reset();
|
|
position = xOutput.format(x);
|
|
depth = zOutput.format(u);
|
|
break;
|
|
case 18:
|
|
zOutput.reset();
|
|
position = zOutput.format(z);
|
|
depth = yOutput.format(u);
|
|
break;
|
|
case 19:
|
|
yOutput.reset();
|
|
position = yOutput.format(y);
|
|
depth = xOutput.format(u);
|
|
break;
|
|
}
|
|
if (getProperty("useRigidTapping") != "yes") {
|
|
writeBlock(conditional((u <= cycle.bottom), gRetractModal.format(98)), position, depth);
|
|
} else {
|
|
writeBlock(
|
|
gAbsIncModal.format(90),
|
|
gCycleModal.format(33.1),
|
|
depth,
|
|
conditional(useTappingSpeed, "I" + xyzFormat.format(getProperty("tappingSpeed"))),
|
|
pitchOutput.format(tool.threadPitch)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
feedOutput.reset();
|
|
break;
|
|
case "fine-boring":
|
|
case "back-boring":
|
|
error(localize(subst("The %1 canned cycle is not supported.", cycleType)));
|
|
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(P > 0 ? 89 : 85),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
P > 0 ? "P" + secFormat.format(P) : "",
|
|
feedOutput.format(F)
|
|
);
|
|
break;
|
|
case "stop-boring":
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(86),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
"P" + secFormat.format(P),
|
|
feedOutput.format(F)
|
|
);
|
|
forceSpindleSpeed = true;
|
|
break;
|
|
case "manual-boring":
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(88),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
"P" + secFormat.format(P),
|
|
feedOutput.format(F)
|
|
);
|
|
break;
|
|
case "boring":
|
|
if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) {
|
|
expandCyclePoint(x, y, z);
|
|
break;
|
|
}
|
|
if (P > 0) {
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
"P" + secFormat.format(P),
|
|
feedOutput.format(F)
|
|
);
|
|
} else {
|
|
writeBlock(
|
|
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85),
|
|
getCommonCycle(x, y, z, cycle.retract),
|
|
feedOutput.format(F)
|
|
);
|
|
}
|
|
break;
|
|
default:
|
|
expandCyclePoint(x, y, z);
|
|
}
|
|
} else {
|
|
if (cycleExpanded) {
|
|
expandCyclePoint(x, y, z);
|
|
} else if (isTappingCycle() && getProperty("useRigidTapping") == "reversingHead") {
|
|
expandTappingPoint(x, y, z);
|
|
} else {
|
|
writeBlock(xOutput.format(x), yOutput.format(y));
|
|
}
|
|
}
|
|
}
|
|
|
|
function writeProbeCycle(cycle, x, y, z) {
|
|
if (isProbeOperation()) {
|
|
var isMirrored = currentSection.getInternalPatternId && currentSection.getInternalPatternId() != currentSection.getPatternId();
|
|
validate(!isMirrored, "Mirror pattern is not supported for Probing toolpaths.");
|
|
if (currentSection.isPatterned && currentSection.isPatterned()) {
|
|
// probe cycles that cannot be used with patterns
|
|
var unsupportedCycleTypes = ["probing-x", "probing-y", "probing-xy-inner-corner", "probing-xy-outer-corner", "probing-x-plane-angle", "probing-y-plane-angle"];
|
|
if (unsupportedCycleTypes.indexOf(cycleType) > -1 && (!Matrix.diff(new Matrix(), currentSection.workPlane).isZero())) {
|
|
error(subst("Rotary type patterns are not supported for the Probing cycle type '%1'.", cycleType));
|
|
}
|
|
}
|
|
var probeRadius = tool.diameter / 2;
|
|
switch (cycleType) {
|
|
case "probing-x":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, y, z - cycle.depth, PROBE_FEED);
|
|
var probeExpected = x + approach(cycle.approach1) * (cycle.probeClearance + probeRadius);
|
|
writeProbePosition(probeExpected + approach(cycle.approach1) * (cycle.probeOvertravel + probeRadius));
|
|
writeProbeExpectedX(probeExpected, true);
|
|
writeBlock("o<probe_x_edge> call", formatComment("Probe in X"));
|
|
break;
|
|
case "probing-y":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, y, z - cycle.depth, PROBE_FEED);
|
|
var probeExpected = y + approach(cycle.approach1) * (cycle.probeClearance + probeRadius);
|
|
writeProbePosition(probeExpected + approach(cycle.approach1) * (cycle.probeOvertravel + probeRadius));
|
|
writeProbeExpectedY(probeExpected, true);
|
|
writeBlock("o<probe_y_edge> call", formatComment("Probe in Y"));
|
|
break;
|
|
case "probing-z":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
var probePosition = z - cycle.depth;
|
|
writeProbePosition(probePosition - cycle.probeOvertravel);
|
|
writeProbeExpectedZ(probePosition, true);
|
|
writeBlock("o<probe_z> call", formatComment("Probe in Z"));
|
|
break;
|
|
case "probing-x-wall":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = x + probeWidth + (cycle.probeClearance + probeRadius);
|
|
var p2 = x - probeWidth - (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(p1, y, cycle.clearance);
|
|
protectedProbeMove(p1, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(p1, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(x + probeWidth - (cycle.probeOvertravel - probeRadius), x - probeWidth + (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(p2, y, z - cycle.depth);
|
|
writeProbeExpectedX(x, true);
|
|
writeBlock("o<probe_x_boss> call", formatComment("Probe X-Boss"));
|
|
break;
|
|
case "probing-y-wall":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = y + probeWidth + (cycle.probeClearance + probeRadius);
|
|
var p2 = y - probeWidth - (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(x, p1, cycle.clearance);
|
|
protectedProbeMove(x, p1, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, p1, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(y + probeWidth - (cycle.probeOvertravel - probeRadius), y - probeWidth + (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(x, p2, z - cycle.depth);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_y_boss> call", formatComment("Probe Y-Boss"));
|
|
break;
|
|
case "probing-x-channel":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = x + probeWidth - (cycle.probeClearance + probeRadius);
|
|
var p2 = x - probeWidth + (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(p1, y, cycle.clearance);
|
|
protectedProbeMove(p1, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(p1, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(0); // no island
|
|
writeProbePosition(x + probeWidth + (cycle.probeOvertravel - probeRadius), x - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(p2, y, z - cycle.depth);
|
|
writeProbeExpectedX(x, true);
|
|
writeBlock("o<probe_x_pocket> call", formatComment("Probe X-Pocket"));
|
|
break;
|
|
case "probing-x-channel-with-island":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = x + probeWidth - (cycle.probeClearance + probeRadius);
|
|
var p2 = x - probeWidth + (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(p1, y, cycle.clearance);
|
|
protectedProbeMove(p1, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(p1, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(x + probeWidth + (cycle.probeOvertravel - probeRadius), x - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(p2, y, z - cycle.depth);
|
|
writeProbeExpectedX(x, true);
|
|
writeBlock("o<probe_x_pocket> call", formatComment("Probe X-Pocket"));
|
|
break;
|
|
case "probing-y-channel":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = y + probeWidth - (cycle.probeClearance + probeRadius);
|
|
var p2 = y - probeWidth + (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(x, p1, cycle.clearance);
|
|
protectedProbeMove(x, p1, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, p1, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(0);
|
|
writeProbePosition(y + probeWidth + (cycle.probeOvertravel - probeRadius), y - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(x, p2, z - cycle.depth);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_y_pocket> call", formatComment("Probe Y-Pocket"));
|
|
break;
|
|
case "probing-y-channel-with-island":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = y + probeWidth - (cycle.probeClearance + probeRadius);
|
|
var p2 = y - probeWidth + (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(x, p1, cycle.clearance);
|
|
protectedProbeMove(x, p1, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, p1, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(y + probeWidth + (cycle.probeOvertravel - probeRadius), y - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(x, p2, z - cycle.depth);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_y_pocket> call", formatComment("Probe Y-Pocket"));
|
|
break;
|
|
case "probing-xy-circular-boss":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
writeProbePosition(z - cycle.depth);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbeDiameter(cycle.width1 - (cycle.probeOvertravel - probeRadius), cycle.width1 + (cycle.probeClearance + probeRadius));
|
|
writeProbeExpectedX(x, false);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_circular_boss> call", formatComment("Probe Circular Boss"));
|
|
break;
|
|
case "probing-xy-circular-partial-boss":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
writeProbePosition(z - cycle.depth);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbeDiameter(cycle.width1 - (cycle.probeOvertravel - probeRadius), cycle.width1 + (cycle.probeClearance + probeRadius));
|
|
writeProbeVector(cycle.partialCircleAngleA, cycle.partialCircleAngleB, cycle.partialCircleAngleC);
|
|
writeProbeExpectedX(x, false);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_boss_three_point> call", formatComment("Probe Partial Circular Boss"));
|
|
break;
|
|
case "probing-xy-circular-hole":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(0); // no island
|
|
writeProbeDiameter(cycle.width1 + (cycle.probeOvertravel - probeRadius), cycle.width1 - (cycle.probeClearance + probeRadius));
|
|
writeProbeExpectedX(x, false);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_circular_bore> call", formatComment("Probe Circular Bore"));
|
|
break;
|
|
case "probing-xy-circular-partial-hole":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeDiameter(cycle.width1 + (cycle.probeOvertravel - probeRadius), cycle.width1 - (cycle.probeClearance + probeRadius));
|
|
writeProbeVector(cycle.partialCircleAngleA, cycle.partialCircleAngleB, cycle.partialCircleAngleC);
|
|
writeProbeExpectedX(x, false);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_bore_three_point> call", formatComment("Probe Partial Circular Bore"));
|
|
break;
|
|
case "probing-xy-circular-hole-with-island":
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbeDiameter(cycle.width1 + (cycle.probeOvertravel - probeRadius), cycle.width1 - (cycle.probeClearance + probeRadius));
|
|
writeProbeExpectedX(x, false);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_circular_bore> call", formatComment("Probe Circular Bore"));
|
|
break;
|
|
case "probing-xy-rectangular-hole":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = x + probeWidth - (cycle.probeClearance + probeRadius);
|
|
var p2 = x - probeWidth + (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(p1, y, cycle.clearance);
|
|
protectedProbeMove(p1, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(p1, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(0); // no island
|
|
writeProbePosition(x + probeWidth + (cycle.probeOvertravel - probeRadius), x - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(p2, y, z - cycle.depth);
|
|
writeProbeExpectedX(x, true);
|
|
writeBlock("o<probe_x_pocket> call", formatComment("Probe X-Pocket"));
|
|
|
|
probeWidth = cycle.width2 / 2;
|
|
p1 = y + probeWidth - (cycle.probeClearance + probeRadius);
|
|
p2 = y - probeWidth + (cycle.probeClearance + probeRadius);
|
|
protectedProbeMove(x, p1, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, p1, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(0); // no island
|
|
writeProbePosition(y + probeWidth + (cycle.probeOvertravel - probeRadius), y - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(x, p2, z - cycle.depth);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_y_pocket> call", formatComment("Probe Y-Pocket"));
|
|
break;
|
|
case "probing-xy-rectangular-boss":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = x + probeWidth + (cycle.probeClearance + probeRadius);
|
|
var p2 = x - probeWidth - (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(p1, y, cycle.clearance);
|
|
protectedProbeMove(p1, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(p1, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(x + probeWidth - (cycle.probeOvertravel - probeRadius), x - probeWidth + (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(p2, y, z - cycle.depth);
|
|
writeProbeExpectedX(x, true);
|
|
writeBlock("o<probe_x_boss> call", formatComment("Probe X-Boss"));
|
|
|
|
probeWidth = cycle.width2 / 2;
|
|
p1 = y + probeWidth + (cycle.probeClearance + probeRadius);
|
|
p2 = y - probeWidth - (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(x, p1, cycle.clearance);
|
|
protectedProbeMove(x, p1, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, p1, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(y + probeWidth - (cycle.probeOvertravel - probeRadius), y - probeWidth + (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(x, p2, z - cycle.depth);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_y_boss> call", formatComment("Probe Y-Boss"));
|
|
break;
|
|
case "probing-xy-rectangular-hole-with-island":
|
|
var probeWidth = cycle.width1 / 2;
|
|
var p1 = x + probeWidth - (cycle.probeClearance + probeRadius);
|
|
var p2 = x - probeWidth + (cycle.probeClearance + probeRadius);
|
|
onExpandedRapid(p1, y, cycle.clearance);
|
|
protectedProbeMove(p1, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(p1, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(x + probeWidth + (cycle.probeOvertravel - probeRadius), x - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(p2, y, z - cycle.depth);
|
|
writeProbeExpectedX(x, true);
|
|
writeBlock("o<probe_x_pocket> call", formatComment("Probe X-Pocket"));
|
|
|
|
probeWidth = cycle.width2 / 2;
|
|
p1 = y + probeWidth - (cycle.probeClearance + probeRadius);
|
|
p2 = y - probeWidth + (cycle.probeClearance + probeRadius);
|
|
protectedProbeMove(x, p1, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, p1, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(y + probeWidth + (cycle.probeOvertravel - probeRadius), y - probeWidth - (cycle.probeOvertravel - probeRadius));
|
|
writeProbeXYZPosition(x, p2, z - cycle.depth);
|
|
writeProbeExpectedY(y, true);
|
|
writeBlock("o<probe_y_pocket> call", formatComment("Probe Y-Pocket"));
|
|
break;
|
|
|
|
case "probing-xy-inner-corner":
|
|
var probeExpectedX = x + approach(cycle.approach1) * (cycle.probeClearance + probeRadius * 2);
|
|
var probeExpectedY = y + approach(cycle.approach2) * (cycle.probeClearance + probeRadius * 2);
|
|
var probeX = x + approach(cycle.approach1) * (cycle.probeClearance + cycle.probeOvertravel + probeRadius * 2);
|
|
var probeY = y + approach(cycle.approach2) * (cycle.probeClearance + cycle.probeOvertravel + probeRadius * 2);
|
|
protectedProbeMove(x, y, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, y, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(probeX, probeY);
|
|
writeProbeXYZPosition(x, y, z - cycle.depth);
|
|
writeProbeExpectedX(probeExpectedX, false);
|
|
writeProbeExpectedY(probeExpectedY, true);
|
|
writeBlock("o<probe_xy_corner> call", formatComment("Probe XY Inner Corner"));
|
|
break;
|
|
case "probing-xy-outer-corner":
|
|
var probeExpectedX = x + approach(cycle.approach1) * (cycle.probeClearance + probeRadius);
|
|
var probeExpectedY = y + approach(cycle.approach2) * (cycle.probeClearance + probeRadius);
|
|
// TAG: contact point is not provided by CAM system
|
|
var px = x + approach(cycle.approach1) * ((cycle.probeOvertravel * 1.5) + cycle.probeOvertravel + probeRadius * 2);
|
|
var py = y + approach(cycle.approach2) * ((cycle.probeOvertravel * 1.5) + cycle.probeOvertravel + probeRadius * 2);
|
|
var probeX = x + approach(cycle.approach1) * (cycle.probeClearance + cycle.probeOvertravel + probeRadius * 2);
|
|
var probeY = y + approach(cycle.approach2) * (cycle.probeClearance + cycle.probeOvertravel + probeRadius * 2);
|
|
onExpandedRapid(x, py, cycle.clearance);
|
|
protectedProbeMove(x, py, cycle.retract, PROBE_RAPID);
|
|
protectedProbeMove(x, py, z - cycle.depth, PROBE_FEED);
|
|
writeProbeClearance(cycle.retract);
|
|
writeProbePosition(probeX, probeY);
|
|
writeProbeXYZPosition(px, y, z - cycle.depth);
|
|
writeProbeExpectedX(probeExpectedX, false);
|
|
writeProbeExpectedY(probeExpectedY, true);
|
|
writeBlock("o<probe_xy_corner> call", formatComment("Probe XY Outer Corner"));
|
|
break;
|
|
case "probing-x-plane-angle":
|
|
error(localize("Probing cycle '" + cycleType + "' is not supported."));
|
|
break;
|
|
case "probing-y-plane-angle":
|
|
error(localize("Probing cycle '" + cycleType + "' is not supported."));
|
|
break;
|
|
default:
|
|
expandCyclePoint(x, y, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
function writeProbePosition(position1, position2) { // position2 is optional
|
|
writeBlock("#<_first_position_to_probe> = " + xyzFormat.format(position1));
|
|
if (typeof position2 == "number") {
|
|
writeBlock("#<_second_position_to_probe> = " + xyzFormat.format(position2));
|
|
}
|
|
}
|
|
|
|
function writeProbeXYZPosition(x, y, z) {
|
|
writeBlock("#<_second_x_position> = " + xyzFormat.format(x));
|
|
writeBlock("#<_second_y_position> = " + xyzFormat.format(y));
|
|
writeBlock("#<_second_z_position> = " + xyzFormat.format(z));
|
|
}
|
|
|
|
function writeProbeExpectedX(x, updateWCS) {
|
|
writeBlock("#<_x_wcs_offset> = " + xyzFormat.format(x));
|
|
writeProbeWCS(updateWCS);
|
|
}
|
|
|
|
function writeProbeExpectedY(y, updateWCS) {
|
|
writeBlock("#<_y_wcs_offset> = " + xyzFormat.format(y));
|
|
writeProbeWCS(updateWCS);
|
|
}
|
|
|
|
function writeProbeExpectedZ(z, updateWCS) {
|
|
writeBlock("#<_z_wcs_offset> = " + xyzFormat.format(z));
|
|
writeProbeWCS(updateWCS);
|
|
}
|
|
|
|
function writeProbeDiameter(probeDiameter, clearanceDiameter) {
|
|
writeBlock("#<_diameter_to_probe> = " + xyzFormat.format(probeDiameter));
|
|
writeBlock("#<_diameter_to_position> = " + xyzFormat.format(clearanceDiameter));
|
|
}
|
|
|
|
function writeProbeVector(a, b, c) {
|
|
writeBlock("#<_first_vector> = " + xyzFormat.format(a < 0 ? a + 360 : a));
|
|
writeBlock("#<_second_vector> = " + xyzFormat.format(b < 0 ? b + 360 : b));
|
|
writeBlock("#<_third_vector> = " + xyzFormat.format(c < 0 ? c + 360 : c));
|
|
}
|
|
|
|
function writeProbeClearance(clearance) {
|
|
writeBlock("#<_z_clearance_position> = " + xyzFormat.format(clearance));
|
|
}
|
|
|
|
function writeProbeWCS(updateWCS) {
|
|
if (updateWCS) {
|
|
if (currentSection.strategy == "probe") { // WCS probing
|
|
var probeOutputWorkOffset = currentSection.probeWorkOffset;
|
|
validate(
|
|
probeOutputWorkOffset > 0 && (probeOutputWorkOffset > 6 ? probeOutputWorkOffset - 6 : probeOutputWorkOffset) <= 500,
|
|
"Probe work offset is out of range."
|
|
);
|
|
var nextWorkOffset = hasNextSection() ? getNextSection().workOffset == 0 ? 1 : getNextSection().workOffset : -1;
|
|
if (probeOutputWorkOffset == nextWorkOffset) {
|
|
currentWorkOffset = undefined;
|
|
}
|
|
writeBlock("#<_measuring_wcs> = " + probeOutputWorkOffset);
|
|
} else { // Geometry probing
|
|
error(localize("Geometry probing is not supported by the CNC control."));
|
|
// writeBlock("#<_inspect_only> = 1");
|
|
}
|
|
}
|
|
}
|
|
|
|
function onCycleEnd() {
|
|
if (!isProbeOperation()) {
|
|
if (!cycleExpanded && (!isTappingCycle() || getProperty("useRigidTapping") != "yes")) {
|
|
writeBlock(gCycleModal.format(80));
|
|
zOutput.reset();
|
|
}
|
|
} else {
|
|
if (currentSection.strategy == "probe") { // WCS probing
|
|
writeBlock(currentSection.wcs);
|
|
}
|
|
gAbsIncModal.reset();
|
|
writeBlock(gAbsIncModal.format(90));
|
|
}
|
|
}
|
|
|
|
function onLinear(_x, _y, _z, feed) {
|
|
if (pendingRadiusCompensation >= 0) {
|
|
xOutput.reset();
|
|
yOutput.reset();
|
|
}
|
|
var x = xOutput.format(_x);
|
|
var y = yOutput.format(_y);
|
|
var z = zOutput.format(_z);
|
|
var f = getFeed(feed);
|
|
if (x || y || z) {
|
|
if (pendingRadiusCompensation >= 0) {
|
|
pendingRadiusCompensation = -1;
|
|
var d = getSetting("outputToolDiameterOffset", true) ? diameterOffsetFormat.format(tool.diameterOffset) : "";
|
|
var wear = getParameter("operation:compensationType", "") == "wear" || getParameter("operation:compensationType", "") == "inverseWear";
|
|
writeBlock(gPlaneModal.format(17));
|
|
switch (radiusCompensation) {
|
|
case RADIUS_COMPENSATION_LEFT:
|
|
writeBlock(gMotionModal.format(1), gFormat.format(wear ? 41.2 : 41), x, y, z, d, f);
|
|
break;
|
|
case RADIUS_COMPENSATION_RIGHT:
|
|
writeBlock(gMotionModal.format(1), gFormat.format(wear ? 42.2 : 42), x, y, z, d, f);
|
|
break;
|
|
default:
|
|
writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f);
|
|
}
|
|
} else {
|
|
writeBlock(gMotionModal.format(1), x, y, z, f);
|
|
}
|
|
} else if (f) {
|
|
if (getNextRecord().isMotion()) { // try not to output feed without motion
|
|
forceFeed(); // force feed on next line
|
|
} else {
|
|
writeBlock(gMotionModal.format(1), f);
|
|
}
|
|
}
|
|
}
|
|
|
|
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."));
|
|
}
|
|
|
|
var transitionMoves = [
|
|
MOVEMENT_LEAD_IN,
|
|
MOVEMENT_LEAD_OUT,
|
|
MOVEMENT_RAMP,
|
|
MOVEMENT_PLUNGE,
|
|
MOVEMENT_RAMP_HELIX,
|
|
MOVEMENT_RAMP_PROFILE,
|
|
MOVEMENT_RAMP_ZIG_ZAG
|
|
];
|
|
// controller does not handle transition between planes well
|
|
if (transitionMoves.indexOf(movement) > -1 && (getCircularPlane() != PLANE_XY)) {
|
|
linearize(tolerance);
|
|
return;
|
|
}
|
|
|
|
var start = getCurrentPosition();
|
|
|
|
if (isFullCircle()) {
|
|
if (getProperty("useRadius") || isHelical()) { // radius mode does not support full arcs
|
|
linearize(tolerance);
|
|
return;
|
|
}
|
|
switch (getCircularPlane()) {
|
|
case PLANE_XY:
|
|
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gFeedModeModal.format(94), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), jOutput.format(cy - start.y), feedOutput.format(feed));
|
|
break;
|
|
case PLANE_ZX:
|
|
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gFeedModeModal.format(94), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), kOutput.format(cz - start.z), feedOutput.format(feed));
|
|
break;
|
|
case PLANE_YZ:
|
|
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gFeedModeModal.format(94), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y), kOutput.format(cz - start.z), feedOutput.format(feed));
|
|
break;
|
|
default:
|
|
linearize(tolerance);
|
|
}
|
|
} else if (!getProperty("useRadius")) {
|
|
switch (getCircularPlane()) {
|
|
case PLANE_XY:
|
|
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gFeedModeModal.format(94), 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:
|
|
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gFeedModeModal.format(94), 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));
|
|
break;
|
|
case PLANE_YZ:
|
|
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gFeedModeModal.format(94), 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));
|
|
break;
|
|
default:
|
|
linearize(tolerance);
|
|
}
|
|
} else { // use radius mode
|
|
var r = getCircularRadius();
|
|
if (toDeg(getCircularSweep()) > (180 + 1e-9)) {
|
|
r = -r; // allow up to <360 deg arcs
|
|
}
|
|
switch (getCircularPlane()) {
|
|
case PLANE_XY:
|
|
writeBlock(gPlaneModal.format(17), gFeedModeModal.format(94), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), feedOutput.format(feed));
|
|
break;
|
|
case PLANE_ZX:
|
|
writeBlock(gPlaneModal.format(18), gFeedModeModal.format(94), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), feedOutput.format(feed));
|
|
break;
|
|
case PLANE_YZ:
|
|
writeBlock(gPlaneModal.format(19), gFeedModeModal.format(94), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), feedOutput.format(feed));
|
|
break;
|
|
default:
|
|
linearize(tolerance);
|
|
}
|
|
}
|
|
}
|
|
|
|
var mapCommand = {
|
|
COMMAND_END : 2,
|
|
COMMAND_SPINDLE_CLOCKWISE : 3,
|
|
COMMAND_SPINDLE_COUNTERCLOCKWISE: 4,
|
|
COMMAND_STOP_SPINDLE : 5,
|
|
COMMAND_ORIENTATE_SPINDLE : 19,
|
|
COMMAND_LOAD_TOOL : 6
|
|
};
|
|
|
|
function onCommand(command) {
|
|
switch (command) {
|
|
case COMMAND_COOLANT_OFF:
|
|
setCoolant(COOLANT_OFF);
|
|
washdownModal.setCurrent(washdownCoolant.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:
|
|
// Define coolant code
|
|
var c = formatWords(getCoolantCodes(tool.coolant), getAdditionalCoolantCodes(tool.coolant));
|
|
if (spindleSpeed == 0) {
|
|
writeBlock(mFormat.format(5), c, formatComment("SPINDLE IS OFF"));
|
|
} else {
|
|
writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4), c);
|
|
if ((spindleSpeed > 5000) && getProperty("waitForSpindle")) {
|
|
onDwell(getProperty("waitForSpindle"));
|
|
}
|
|
}
|
|
return;
|
|
case COMMAND_LOAD_TOOL:
|
|
toolLengthCompOutput.reset();
|
|
writeToolBlock("T" + toolFormat.format(tool.number), getOffsetCode(),
|
|
hFormat.format(tool.lengthOffset), getProperty("useM06") ? mFormat.format(6) : "");
|
|
writeComment(tool.comment);
|
|
return;
|
|
case COMMAND_LOCK_MULTI_AXIS:
|
|
if (machineConfiguration.isMultiAxisConfiguration()) {
|
|
// writeBlock(fourthAxisClamp.format(25)); // lock 4th axis
|
|
if (machineConfiguration.getNumberOfAxes() > 4) {
|
|
// writeBlock(fifthAxisClamp.format(35)); // lock 5th axis
|
|
}
|
|
}
|
|
return;
|
|
case COMMAND_UNLOCK_MULTI_AXIS:
|
|
if (machineConfiguration.isMultiAxisConfiguration()) {
|
|
// writeBlock(fourthAxisClamp.format(26)); // unlock 4th axis
|
|
if (machineConfiguration.getNumberOfAxes() > 4) {
|
|
// writeBlock(fifthAxisClamp.format(36)); // unlock 5th axis
|
|
}
|
|
}
|
|
return;
|
|
case COMMAND_BREAK_CONTROL:
|
|
if (!toolChecked) { // avoid duplicate COMMAND_BREAK_CONTROL
|
|
prepareForToolCheck();
|
|
writeBlock(gFormat.format(37), "P" + xyzFormat.format(getProperty("toolBreakageTolerance")));
|
|
toolChecked = true;
|
|
}
|
|
return;
|
|
case COMMAND_TOOL_MEASURE:
|
|
return;
|
|
case COMMAND_START_CHIP_TRANSPORT:
|
|
if (getProperty("gotChipConveyor")) {
|
|
var chipConveyorOn = getProperty("chipConveyorOn");
|
|
var chipConveyorIdle = getProperty("chipConveyorIdle");
|
|
if (chipConveyorOn != 0 && chipConveyorIdle == 0) {
|
|
error(localize("You must specify a chip conveyor idle time if it is enabled and a run time is specified."));
|
|
}
|
|
writeBlock(mFormat.format(231),
|
|
conditional(chipConveyorOn != 0, "P" + secFormat.format(chipConveyorOn)),
|
|
conditional(chipConveyorIdle != 0, "Q" + secFormat.format(chipConveyorIdle))
|
|
);
|
|
}
|
|
return;
|
|
case COMMAND_STOP_CHIP_TRANSPORT:
|
|
writeBlock(mFormat.format(233));
|
|
return;
|
|
}
|
|
|
|
var stringId = getCommandStringId(command);
|
|
var mcode = mapCommand[stringId];
|
|
if (mcode != undefined) {
|
|
writeBlock(mFormat.format(mcode));
|
|
} else {
|
|
onUnsupportedCommand(command);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Buffer Manual NC commands for processing later
|
|
*/
|
|
var manualNC = [];
|
|
function onManualNC(command, value) {
|
|
if (getCurrentSectionId() != -1) { // output commands processed during a section immediately
|
|
expandManualNC(command, value);
|
|
} else {
|
|
manualNC.push({command:command, value:value});
|
|
}
|
|
}
|
|
|
|
/**
|
|
Processes the Manual NC commands
|
|
Pass the desired command to process or leave argument list blank to process all buffered commands
|
|
*/
|
|
function executeManualNC(command) {
|
|
for (var i = 0; i < manualNC.length; ++i) {
|
|
if (!command || (command == manualNC[i].command)) {
|
|
expandManualNC(manualNC[i].command, manualNC[i].value);
|
|
}
|
|
}
|
|
for (var i = manualNC.length - 1; i >= 0; --i) {
|
|
if (!command || (command == manualNC[i].command)) {
|
|
manualNC.splice(i, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
function onSectionEnd() {
|
|
writeBlock(gPlaneModal.format(17));
|
|
|
|
if (currentSection.isMultiAxis()) {
|
|
writeBlock(gFeedModeModal.format(94)); // inverse time feed off
|
|
}
|
|
|
|
if (!isLastSection()) {
|
|
if (getNextSection().getTool().coolant != tool.coolant) {
|
|
onCommand(COMMAND_COOLANT_OFF);
|
|
}
|
|
if (tool.breakControl && isToolChangeNeeded(getNextSection(), getProperty("toolAsName") ? "description" : "number")) {
|
|
onCommand(COMMAND_BREAK_CONTROL);
|
|
} else {
|
|
toolChecked = false;
|
|
}
|
|
}
|
|
|
|
forceAny();
|
|
forceCoolant = true;
|
|
|
|
if ((((getCurrentSectionId() + 1) >= getNumberOfSections()) ||
|
|
(tool.number != getNextSection().getTool().number)) && !toolChecked) {
|
|
prepareForToolCheck();
|
|
}
|
|
}
|
|
|
|
function writeRetract() {
|
|
var retract = getRetractParameters.apply(this, arguments);
|
|
if (retract && retract.words.length > 0) {
|
|
if (typeof cancelWCSRotation == "function" && getSetting("retract.cancelRotationOnRetracting", false)) { // cancel rotation before retracting
|
|
cancelWCSRotation();
|
|
}
|
|
if (retract.retractAxes[2] && retract.method == "G28") {
|
|
return; // skip retracting Z axis if G28 is used
|
|
}
|
|
if ((retract.retractAxes[0] || retract.retractAxes[1]) && retract.method == "G30") {
|
|
return; // skip retracting X and Y axes if G30 is used
|
|
}
|
|
for (var i in retract.words) {
|
|
var words = retract.singleLine ? retract.words : retract.words[i];
|
|
switch (retract.method) {
|
|
case "G28":
|
|
case "G30":
|
|
writeBlock(retract.method);
|
|
state.retractedX = state.retractedY = state.retractedZ = true;
|
|
machineSimulation({
|
|
x : machineConfiguration.getHomePositionX(),
|
|
y : machineConfiguration.getHomePositionY(),
|
|
z : machineConfiguration.getRetractPlane(),
|
|
coordinates: MACHINE
|
|
});
|
|
break;
|
|
case "G53":
|
|
forceModals(gMotionModal);
|
|
writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), words);
|
|
break;
|
|
default:
|
|
error(subst(localize("Unsupported safe position method '%1'"), retract.method));
|
|
}
|
|
if (retract.method != "G30") {
|
|
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;
|
|
writeln("");
|
|
writeRetract(Z);
|
|
if (getSetting("retract.homeXY.onProgramEnd", false)) {
|
|
writeRetract(settings.retract.homeXY.onProgramEnd);
|
|
}
|
|
setSmoothing(false);
|
|
if (machineConfiguration.isMultiAxisConfiguration()) {
|
|
unwindABC(new Vector(0, 0, 0), true);
|
|
positionABC(new Vector(0, 0, 0), true);
|
|
}
|
|
// Process Manual NC commands
|
|
executeManualNC();
|
|
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
|
|
writeln("%");
|
|
}
|
|
|
|
// >>>>> 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/defineWorkPlane.cpi
|
|
validate(settings.workPlaneMethod, "Setting 'workPlaneMethod' is required but not defined.");
|
|
function defineWorkPlane(_section, _setWorkPlane) {
|
|
var abc = new Vector(0, 0, 0);
|
|
if (settings.workPlaneMethod.forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) {
|
|
if (isPolarModeActive()) {
|
|
abc = getCurrentDirection();
|
|
} else if (_section.isMultiAxis()) {
|
|
forceWorkPlane();
|
|
cancelTransformation();
|
|
abc = _section.isOptimizedForMachine() ? _section.getInitialToolAxisABC() : _section.getGlobalInitialToolAxis();
|
|
} else if (settings.workPlaneMethod.useTiltedWorkplane && settings.workPlaneMethod.eulerConvention != undefined) {
|
|
if (settings.workPlaneMethod.eulerCalculationMethod == "machine" && machineConfiguration.isMultiAxisConfiguration()) {
|
|
abc = machineConfiguration.getOrientation(getWorkPlaneMachineABC(_section, true)).getEuler2(settings.workPlaneMethod.eulerConvention);
|
|
} else {
|
|
abc = _section.workPlane.getEuler2(settings.workPlaneMethod.eulerConvention);
|
|
}
|
|
} else {
|
|
abc = getWorkPlaneMachineABC(_section, true);
|
|
}
|
|
|
|
if (_setWorkPlane) {
|
|
if (_section.isMultiAxis() || isPolarModeActive()) { // 4-5x simultaneous operations
|
|
cancelWorkPlane();
|
|
if (_section.isOptimizedForMachine()) {
|
|
positionABC(abc, true);
|
|
} else {
|
|
setCurrentDirection(abc);
|
|
}
|
|
} else { // 3x and/or 3+2x operations
|
|
setWorkPlane(abc);
|
|
}
|
|
}
|
|
} else {
|
|
var remaining = _section.workPlane;
|
|
if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) {
|
|
error(localize("Tool orientation is not supported."));
|
|
return abc;
|
|
}
|
|
setRotation(remaining);
|
|
}
|
|
tcp.isSupportedByOperation = isTCPSupportedByOperation(_section);
|
|
return abc;
|
|
}
|
|
|
|
function isTCPSupportedByOperation(_section) {
|
|
var _tcp = _section.getOptimizedTCPMode() == OPTIMIZE_NONE;
|
|
if (!_section.isMultiAxis() && (settings.workPlaneMethod.useTiltedWorkplane ||
|
|
(machineConfiguration.isMultiAxisConfiguration() && settings.workPlaneMethod.optimizeType != undefined ?
|
|
getWorkPlaneMachineABC(_section, false).isZero() : isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(_section))) ||
|
|
settings.workPlaneMethod.optimizeType == OPTIMIZE_HEADS ||
|
|
settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES ||
|
|
settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH)) {
|
|
_tcp = false;
|
|
}
|
|
return _tcp;
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/defineWorkPlane.cpi
|
|
// >>>>> INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi
|
|
validate(settings.machineAngles, "Setting 'machineAngles' is required but not defined.");
|
|
function getWorkPlaneMachineABC(_section, rotate) {
|
|
var currentABC = isFirstSection() ? new Vector(0, 0, 0) : getCurrentABC();
|
|
var abc = _section.getABCByPreference(machineConfiguration, _section.workPlane, currentABC, settings.machineAngles.controllingAxis, settings.machineAngles.type, settings.machineAngles.options);
|
|
if (!isSameDirection(machineConfiguration.getDirection(abc), _section.workPlane.forward)) {
|
|
error(localize("Orientation not supported."));
|
|
}
|
|
if (rotate) {
|
|
if (settings.workPlaneMethod.optimizeType == undefined || settings.workPlaneMethod.useTiltedWorkplane) { // legacy
|
|
var useTCP = false;
|
|
var R = machineConfiguration.getRemainingOrientation(abc, _section.workPlane);
|
|
setRotation(useTCP ? _section.workPlane : R);
|
|
} else {
|
|
if (!_section.isOptimizedForMachine()) {
|
|
machineConfiguration.setToolLength(getSetting("workPlaneMethod.compensateToolLength", false) ? getBodyLength(_section.getTool()) : 0); // define the tool length for head adjustments
|
|
_section.optimize3DPositionsByMachine(machineConfiguration, abc, settings.workPlaneMethod.optimizeType);
|
|
}
|
|
}
|
|
}
|
|
return abc;
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi
|
|
// >>>>> INCLUDED FROM include_files/positionABC.cpi
|
|
function positionABC(abc, force) {
|
|
if (!machineConfiguration.isMultiAxisConfiguration()) {
|
|
error("Function 'positionABC' can only be used with multi-axis machine configurations.");
|
|
}
|
|
if (typeof unwindABC == "function") {
|
|
unwindABC(abc);
|
|
}
|
|
if (force) {
|
|
forceABC();
|
|
}
|
|
var a = aOutput.format(abc.x);
|
|
var b = bOutput.format(abc.y);
|
|
var c = cOutput.format(abc.z);
|
|
if (a || b || c) {
|
|
writeRetract(Z);
|
|
if (getSetting("retract.homeXY.onIndexing", false)) {
|
|
writeRetract(settings.retract.homeXY.onIndexing);
|
|
}
|
|
onCommand(COMMAND_UNLOCK_MULTI_AXIS);
|
|
gMotionModal.reset();
|
|
writeBlock(gMotionModal.format(0), a, b, c);
|
|
setCurrentABC(abc); // required for machine simulation
|
|
machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE});
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/positionABC.cpi
|
|
// >>>>> INCLUDED FROM include_files/unwindABC.cpi
|
|
function unwindABC(abc) {
|
|
if (settings.unwind == undefined || machineConfiguration.isHeadConfiguration()) {
|
|
return;
|
|
}
|
|
if (settings.unwind.method != 1 && settings.unwind.method != 2) {
|
|
error(localize("Unsupported unwindABC method."));
|
|
return;
|
|
}
|
|
|
|
var axes = new Array(machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW());
|
|
var currentDirection = getCurrentDirection();
|
|
for (var i in axes) {
|
|
if (axes[i].isEnabled() && axes[i].isCyclic() && (settings.unwind.useAngle != "prefix" || settings.unwind.anglePrefix[axes[i].getCoordinate] != "")) {
|
|
var j = axes[i].getCoordinate();
|
|
|
|
// only use the active axis in calculations
|
|
var tempABC = new Vector(0, 0, 0);
|
|
tempABC.setCoordinate(j, abc.getCoordinate(j));
|
|
var tempCurrent = new Vector(0, 0, 0); // only use the active axis in calculations
|
|
tempCurrent.setCoordinate(j, currentDirection.getCoordinate(j));
|
|
var orientation = machineConfiguration.getOrientation(tempCurrent);
|
|
|
|
// get closest angle without respecting 'reset' flag
|
|
// and distance from previous angle to closest abc
|
|
var nearestABC = machineConfiguration.getABCByPreference(orientation, tempABC, ABC, PREFER_PREFERENCE, ENABLE_WCS);
|
|
var distanceABC = abcFormat.getResultingValue(Math.abs(Vector.diff(getCurrentDirection(), abc).getCoordinate(j)));
|
|
|
|
// calculate distance from calculated abc to closest abc
|
|
// include move to origin for G28 moves
|
|
var distanceOrigin = 0;
|
|
if (settings.unwind.method == 2) {
|
|
distanceOrigin = abcFormat.getResultingValue(Math.abs(Vector.diff(nearestABC, abc).getCoordinate(j)));
|
|
} else { // closest angle
|
|
distanceOrigin = abcFormat.getResultingValue(Math.abs(getCurrentDirection().getCoordinate(j))) % 360; // calculate distance for unwinding axis
|
|
distanceOrigin = (distanceOrigin > 180) ? 360 - distanceOrigin : distanceOrigin; // take shortest route to 0
|
|
distanceOrigin += abcFormat.getResultingValue(Math.abs(abc.getCoordinate(j))); // add distance from 0 to new position
|
|
}
|
|
|
|
// determine if the axis needs to be rewound and rewind it if required
|
|
var revolutions = distanceABC / 360;
|
|
var angle = settings.unwind.method == 2 ? nearestABC.getCoordinate(j) : 0;
|
|
if (distanceABC > distanceOrigin && (settings.unwind.method == 2 || (revolutions > 1))) { // G28 method will move rotary, so make sure move is greater than 360 degrees
|
|
writeRetract(Z);
|
|
if (getSetting("retract.homeXY.onIndexing", false)) {
|
|
writeRetract(settings.retract.homeXY.onIndexing);
|
|
}
|
|
onCommand(COMMAND_UNLOCK_MULTI_AXIS);
|
|
var outputs = [aOutput, bOutput, cOutput];
|
|
outputs[j].reset();
|
|
writeBlock(
|
|
settings.unwind.codes,
|
|
settings.unwind.workOffsetCode ? settings.unwind.workOffsetCode + currentWorkOffset : "",
|
|
settings.unwind.useAngle == "true" ? outputs[j].format(angle) :
|
|
(settings.unwind.useAngle == "prefix" ? settings.unwind.anglePrefix[j] + abcFormat.format(angle) : "")
|
|
);
|
|
if (settings.unwind.resetG90) {
|
|
gAbsIncModal.reset();
|
|
writeBlock(gAbsIncModal.format(90));
|
|
}
|
|
outputs[j].reset();
|
|
|
|
// set the current rotary axis angle from the unwind block
|
|
currentDirection.setCoordinate(j, angle);
|
|
setCurrentDirection(currentDirection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/unwindABC.cpi
|
|
// >>>>> INCLUDED FROM include_files/writeWCS.cpi
|
|
function writeWCS(section, wcsIsRequired) {
|
|
if (section.workOffset != currentWorkOffset) {
|
|
if (getSetting("workPlaneMethod.cancelTiltFirst", false) && wcsIsRequired) {
|
|
cancelWorkPlane();
|
|
}
|
|
if (typeof forceWorkPlane == "function" && wcsIsRequired) {
|
|
forceWorkPlane();
|
|
}
|
|
writeStartBlocks(wcsIsRequired, function () {
|
|
writeBlock(section.wcs);
|
|
});
|
|
currentWorkOffset = section.workOffset;
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/writeWCS.cpi
|
|
// >>>>> INCLUDED FROM include_files/writeToolCall.cpi
|
|
function writeToolCall(tool, insertToolCall) {
|
|
if (!isFirstSection()) {
|
|
writeStartBlocks(!getProperty("safeStartAllOperations") && insertToolCall, function () {
|
|
writeRetract(Z); // write optional Z retract before tool change if safeStartAllOperations is enabled
|
|
});
|
|
}
|
|
writeStartBlocks(insertToolCall, function () {
|
|
writeRetract(Z);
|
|
if (getSetting("retract.homeXY.onToolChange", false)) {
|
|
writeRetract(settings.retract.homeXY.onToolChange);
|
|
}
|
|
if (!isFirstSection() && insertToolCall) {
|
|
if (typeof forceWorkPlane == "function") {
|
|
forceWorkPlane();
|
|
}
|
|
onCommand(COMMAND_COOLANT_OFF); // turn off coolant on tool change
|
|
if (typeof disableLengthCompensation == "function") {
|
|
disableLengthCompensation(false);
|
|
}
|
|
}
|
|
|
|
if (tool.manualToolChange) {
|
|
onCommand(COMMAND_STOP);
|
|
writeComment("MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number));
|
|
} else {
|
|
if (!isFirstSection() && getProperty("optionalStop") && insertToolCall) {
|
|
onCommand(COMMAND_OPTIONAL_STOP);
|
|
}
|
|
onCommand(COMMAND_LOAD_TOOL);
|
|
}
|
|
});
|
|
if (typeof forceModals == "function" && (insertToolCall || getProperty("safeStartAllOperations"))) {
|
|
forceModals();
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/writeToolCall.cpi
|
|
// >>>>> INCLUDED FROM include_files/startSpindle.cpi
|
|
function startSpindle(tool, insertToolCall) {
|
|
if (tool.type != TOOL_PROBE) {
|
|
var spindleSpeedIsRequired = insertToolCall || forceSpindleSpeed || isFirstSection() ||
|
|
rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent()) ||
|
|
(tool.clockwise != getPreviousSection().getTool().clockwise);
|
|
|
|
writeStartBlocks(spindleSpeedIsRequired, function () {
|
|
if (spindleSpeedIsRequired || operationNeedsSafeStart) {
|
|
onCommand(COMMAND_START_SPINDLE);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/startSpindle.cpi
|
|
// >>>>> INCLUDED FROM include_files/coolant.cpi
|
|
var currentCoolantMode = COOLANT_OFF;
|
|
var coolantOff = undefined;
|
|
var isOptionalCoolant = false;
|
|
var forceCoolant = false;
|
|
|
|
function setCoolant(coolant) {
|
|
var coolantCodes = getCoolantCodes(coolant);
|
|
if (Array.isArray(coolantCodes)) {
|
|
writeStartBlocks(!isOptionalCoolant, function () {
|
|
if (settings.coolant.singleLineCoolant) {
|
|
writeBlock(coolantCodes.join(getWordSeparator()));
|
|
} else {
|
|
for (var c in coolantCodes) {
|
|
writeBlock(coolantCodes[c]);
|
|
}
|
|
}
|
|
});
|
|
return undefined;
|
|
}
|
|
return coolantCodes;
|
|
}
|
|
|
|
function getCoolantCodes(coolant, format) {
|
|
if (!getProperty("useCoolant", true)) {
|
|
return undefined; // coolant output is disabled by property if it exists
|
|
}
|
|
isOptionalCoolant = false;
|
|
if (typeof operationNeedsSafeStart == "undefined") {
|
|
operationNeedsSafeStart = false;
|
|
}
|
|
var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line
|
|
var coolants = settings.coolant.coolants;
|
|
if (!coolants) {
|
|
error(localize("Coolants have not been defined."));
|
|
}
|
|
if (tool.type && tool.type == TOOL_PROBE) { // avoid coolant output for probing
|
|
coolant = COOLANT_OFF;
|
|
}
|
|
if (coolant == currentCoolantMode) {
|
|
if (operationNeedsSafeStart && coolant != COOLANT_OFF) {
|
|
isOptionalCoolant = true;
|
|
} else if (!forceCoolant || coolant == COOLANT_OFF) {
|
|
return undefined; // coolant is already active
|
|
}
|
|
}
|
|
if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined) && !forceCoolant && !isOptionalCoolant) {
|
|
if (Array.isArray(coolantOff)) {
|
|
for (var i in coolantOff) {
|
|
multipleCoolantBlocks.push(coolantOff[i]);
|
|
}
|
|
} else {
|
|
multipleCoolantBlocks.push(coolantOff);
|
|
}
|
|
}
|
|
forceCoolant = false;
|
|
|
|
var m;
|
|
var coolantCodes = {};
|
|
for (var c in coolants) { // find required coolant codes into the coolants array
|
|
if (coolants[c].id == coolant) {
|
|
coolantCodes.on = coolants[c].on;
|
|
if (coolants[c].off != undefined) {
|
|
coolantCodes.off = coolants[c].off;
|
|
break;
|
|
} else {
|
|
for (var i in coolants) {
|
|
if (coolants[i].id == COOLANT_OFF) {
|
|
coolantCodes.off = coolants[i].off;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (coolant == COOLANT_OFF) {
|
|
m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified
|
|
} else {
|
|
coolantOff = coolantCodes.off;
|
|
m = coolantCodes.on;
|
|
}
|
|
|
|
if (!m) {
|
|
onUnsupportedCoolant(coolant);
|
|
m = 9;
|
|
} else {
|
|
if (Array.isArray(m)) {
|
|
for (var i in m) {
|
|
multipleCoolantBlocks.push(m[i]);
|
|
}
|
|
} else {
|
|
multipleCoolantBlocks.push(m);
|
|
}
|
|
currentCoolantMode = coolant;
|
|
for (var i in multipleCoolantBlocks) {
|
|
if (typeof multipleCoolantBlocks[i] == "number") {
|
|
multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]);
|
|
}
|
|
}
|
|
if (format == undefined || format) {
|
|
return multipleCoolantBlocks; // return the single formatted coolant value
|
|
} else {
|
|
return m; // return unformatted coolant value
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/coolant.cpi
|
|
// >>>>> INCLUDED FROM include_files/smoothing.cpi
|
|
// collected state below, do not edit
|
|
validate(settings.smoothing, "Setting 'smoothing' is required but not defined.");
|
|
var smoothing = {
|
|
cancel : false, // cancel tool length prior to update smoothing for this operation
|
|
isActive : false, // the current state of smoothing
|
|
isAllowed : false, // smoothing is allowed for this operation
|
|
isDifferent: false, // tells if smoothing levels/tolerances/both are different between operations
|
|
level : -1, // the active level of smoothing
|
|
tolerance : -1, // the current operation tolerance
|
|
force : false // smoothing needs to be forced out in this operation
|
|
};
|
|
|
|
function initializeSmoothing() {
|
|
var smoothingSettings = settings.smoothing;
|
|
var previousLevel = smoothing.level;
|
|
var previousTolerance = xyzFormat.getResultingValue(smoothing.tolerance);
|
|
|
|
// format threshold parameters
|
|
var thresholdRoughing = xyzFormat.getResultingValue(smoothingSettings.thresholdRoughing);
|
|
var thresholdSemiFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdSemiFinishing);
|
|
var thresholdFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdFinishing);
|
|
|
|
// determine new smoothing levels and tolerances
|
|
smoothing.level = parseInt(getProperty("useSmoothing"), 10);
|
|
smoothing.level = isNaN(smoothing.level) ? -1 : smoothing.level;
|
|
smoothing.tolerance = xyzFormat.getResultingValue(Math.max(getParameter("operation:tolerance", thresholdFinishing), 0));
|
|
|
|
if (smoothing.level == 9999) {
|
|
if (smoothingSettings.autoLevelCriteria == "stock") { // determine auto smoothing level based on stockToLeave
|
|
var stockToLeave = xyzFormat.getResultingValue(getParameter("operation:stockToLeave", getParameter("operation:verticalStockToLeave", 0)));
|
|
var verticalStockToLeave = xyzFormat.getResultingValue(getParameter("operation:verticalStockToLeave", stockToLeave));
|
|
if (((stockToLeave >= thresholdRoughing) && (verticalStockToLeave >= thresholdRoughing)) || getParameter("operation:strategy", "") == "face") {
|
|
smoothing.level = smoothingSettings.roughing; // set roughing level
|
|
} else {
|
|
if (((stockToLeave >= thresholdSemiFinishing) && (stockToLeave < thresholdRoughing)) &&
|
|
((verticalStockToLeave >= thresholdSemiFinishing) && (verticalStockToLeave < thresholdRoughing))) {
|
|
smoothing.level = smoothingSettings.semi; // set semi level
|
|
} else if (((stockToLeave >= thresholdFinishing) && (stockToLeave < thresholdSemiFinishing)) &&
|
|
((verticalStockToLeave >= thresholdFinishing) && (verticalStockToLeave < thresholdSemiFinishing))) {
|
|
smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level
|
|
} else {
|
|
smoothing.level = smoothingSettings.finishing; // set finishing level
|
|
}
|
|
}
|
|
} else { // detemine auto smoothing level based on operation tolerance instead of stockToLeave
|
|
if (smoothing.tolerance >= thresholdRoughing || getParameter("operation:strategy", "") == "face") {
|
|
smoothing.level = smoothingSettings.roughing; // set roughing level
|
|
} else {
|
|
if (((smoothing.tolerance >= thresholdSemiFinishing) && (smoothing.tolerance < thresholdRoughing))) {
|
|
smoothing.level = smoothingSettings.semi; // set semi level
|
|
} else if (((smoothing.tolerance >= thresholdFinishing) && (smoothing.tolerance < thresholdSemiFinishing))) {
|
|
smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level
|
|
} else {
|
|
smoothing.level = smoothingSettings.finishing; // set finishing level
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (smoothing.level == -1) { // useSmoothing is disabled
|
|
smoothing.isAllowed = false;
|
|
} else { // do not output smoothing for the following operations
|
|
smoothing.isAllowed = !(currentSection.getTool().type == TOOL_PROBE || isDrillingCycle());
|
|
}
|
|
if (!smoothing.isAllowed) {
|
|
smoothing.level = -1;
|
|
smoothing.tolerance = -1;
|
|
}
|
|
|
|
switch (smoothingSettings.differenceCriteria) {
|
|
case "level":
|
|
smoothing.isDifferent = smoothing.level != previousLevel;
|
|
break;
|
|
case "tolerance":
|
|
smoothing.isDifferent = smoothing.tolerance != previousTolerance;
|
|
break;
|
|
case "both":
|
|
smoothing.isDifferent = smoothing.level != previousLevel || smoothing.tolerance != previousTolerance;
|
|
break;
|
|
default:
|
|
error(localize("Unsupported smoothing criteria."));
|
|
return;
|
|
}
|
|
|
|
// tool length compensation needs to be canceled when smoothing state/level changes
|
|
if (smoothingSettings.cancelCompensation) {
|
|
smoothing.cancel = !isFirstSection() && smoothing.isDifferent;
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/smoothing.cpi
|
|
// >>>>> INCLUDED FROM include_files/writeProgramHeader.cpi
|
|
properties.writeMachine = {
|
|
title : "Write machine",
|
|
description: "Output the machine settings in the header of the program.",
|
|
group : "formats",
|
|
type : "boolean",
|
|
value : true,
|
|
scope : "post"
|
|
};
|
|
properties.writeTools = {
|
|
title : "Write tool list",
|
|
description: "Output a tool list in the header of the program.",
|
|
group : "formats",
|
|
type : "boolean",
|
|
value : true,
|
|
scope : "post"
|
|
};
|
|
function writeProgramHeader() {
|
|
// dump machine configuration
|
|
var vendor = machineConfiguration.getVendor();
|
|
var model = machineConfiguration.getModel();
|
|
var mDescription = machineConfiguration.getDescription();
|
|
if (getProperty("writeMachine") && (vendor || model || mDescription)) {
|
|
writeComment(localize("Machine"));
|
|
if (vendor) {
|
|
writeComment(" " + localize("vendor") + ": " + vendor);
|
|
}
|
|
if (model) {
|
|
writeComment(" " + localize("model") + ": " + model);
|
|
}
|
|
if (mDescription) {
|
|
writeComment(" " + localize("description") + ": " + mDescription);
|
|
}
|
|
}
|
|
|
|
// dump tool information
|
|
if (getProperty("writeTools")) {
|
|
if (false) { // set to true to use the post kernel version of the tool list
|
|
writeToolTable(TOOL_NUMBER_COL);
|
|
} else {
|
|
var zRanges = {};
|
|
if (is3D()) {
|
|
var numberOfSections = getNumberOfSections();
|
|
for (var i = 0; i < numberOfSections; ++i) {
|
|
var section = getSection(i);
|
|
var zRange = section.getGlobalZRange();
|
|
var tool = section.getTool();
|
|
if (zRanges[tool.number]) {
|
|
zRanges[tool.number].expandToRange(zRange);
|
|
} else {
|
|
zRanges[tool.number] = zRange;
|
|
}
|
|
}
|
|
}
|
|
var tools = getToolTable();
|
|
if (tools.getNumberOfTools() > 0) {
|
|
for (var i = 0; i < tools.getNumberOfTools(); ++i) {
|
|
var tool = tools.getTool(i);
|
|
var comment = (getProperty("toolAsName") ? "\"" + tool.description.toUpperCase() + "\"" : "T" + toolFormat.format(tool.number)) + " " +
|
|
"D=" + xyzFormat.format(tool.diameter) + " " +
|
|
localize("CR") + "=" + xyzFormat.format(tool.cornerRadius);
|
|
if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) {
|
|
comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg");
|
|
}
|
|
if (zRanges[tool.number]) {
|
|
comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum());
|
|
}
|
|
comment += " - " + getToolTypeName(tool.type);
|
|
writeComment(comment);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/writeProgramHeader.cpi
|
|
|
|
// >>>>> INCLUDED FROM include_files/onRapid_fanuc.cpi
|
|
function onRapid(_x, _y, _z) {
|
|
var x = xOutput.format(_x);
|
|
var y = yOutput.format(_y);
|
|
var z = zOutput.format(_z);
|
|
if (x || y || z) {
|
|
if (pendingRadiusCompensation >= 0) {
|
|
error(localize("Radius compensation mode cannot be changed at rapid traversal."));
|
|
return;
|
|
}
|
|
writeBlock(gMotionModal.format(0), x, y, z);
|
|
forceFeed();
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/onRapid_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/onRapid5D_fanuc.cpi
|
|
function onRapid5D(_x, _y, _z, _a, _b, _c) {
|
|
if (pendingRadiusCompensation >= 0) {
|
|
error(localize("Radius compensation mode cannot be changed at rapid traversal."));
|
|
return;
|
|
}
|
|
if (!currentSection.isOptimizedForMachine()) {
|
|
forceXYZ();
|
|
}
|
|
var x = xOutput.format(_x);
|
|
var y = yOutput.format(_y);
|
|
var z = zOutput.format(_z);
|
|
var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a);
|
|
var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b);
|
|
var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c);
|
|
|
|
if (x || y || z || a || b || c) {
|
|
writeBlock(gMotionModal.format(0), x, y, z, a, b, c);
|
|
forceFeed();
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/onRapid5D_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/onLinear5D_fanuc.cpi
|
|
function onLinear5D(_x, _y, _z, _a, _b, _c, feed, feedMode) {
|
|
if (pendingRadiusCompensation >= 0) {
|
|
error(localize("Radius compensation cannot be activated/deactivated for 5-axis move."));
|
|
return;
|
|
}
|
|
if (!currentSection.isOptimizedForMachine()) {
|
|
forceXYZ();
|
|
}
|
|
var x = xOutput.format(_x);
|
|
var y = yOutput.format(_y);
|
|
var z = zOutput.format(_z);
|
|
var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a);
|
|
var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b);
|
|
var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c);
|
|
if (feedMode == FEED_INVERSE_TIME) {
|
|
forceFeed();
|
|
}
|
|
var f = feedMode == FEED_INVERSE_TIME ? inverseTimeOutput.format(feed) : getFeed(feed);
|
|
var fMode = feedMode == FEED_INVERSE_TIME ? 93 : getProperty("useG95") ? 95 : 94;
|
|
|
|
if (x || y || z || a || b || c) {
|
|
writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), x, y, z, a, b, c, f);
|
|
} else if (f) {
|
|
if (getNextRecord().isMotion()) { // try not to output feed without motion
|
|
forceFeed(); // force feed on next line
|
|
} else {
|
|
writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), f);
|
|
}
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/onLinear5D_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi
|
|
var gRotationModal = createOutputVariable({current : 69,
|
|
onchange: function () {
|
|
state.twpIsActive = gRotationModal.getCurrent() != 69;
|
|
if (typeof probeVariables != "undefined") {
|
|
probeVariables.outputRotationCodes = probeVariables.probeAngleMethod == "G68";
|
|
}
|
|
machineSimulation({}); // update machine simulation TWP state
|
|
}}, gFormat);
|
|
|
|
var currentWorkPlaneABC = undefined;
|
|
function forceWorkPlane() {
|
|
currentWorkPlaneABC = undefined;
|
|
}
|
|
|
|
function cancelWCSRotation() {
|
|
if (typeof gRotationModal != "undefined" && gRotationModal.getCurrent() == 68) {
|
|
cancelWorkPlane(true);
|
|
}
|
|
}
|
|
|
|
function cancelWorkPlane(force) {
|
|
if (typeof gRotationModal != "undefined") {
|
|
if (force) {
|
|
gRotationModal.reset();
|
|
}
|
|
var command = gRotationModal.format(69);
|
|
if (command) {
|
|
writeBlock(command); // cancel frame
|
|
forceWorkPlane();
|
|
}
|
|
}
|
|
}
|
|
|
|
function setWorkPlane(abc) {
|
|
if (!settings.workPlaneMethod.forceMultiAxisIndexing && is3D() && !machineConfiguration.isMultiAxisConfiguration()) {
|
|
return; // ignore
|
|
}
|
|
var workplaneIsRequired = (currentWorkPlaneABC == undefined) ||
|
|
abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) ||
|
|
abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) ||
|
|
abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z);
|
|
|
|
writeStartBlocks(workplaneIsRequired, function () {
|
|
writeRetract(Z);
|
|
if (getSetting("retract.homeXY.onIndexing", false)) {
|
|
writeRetract(settings.retract.homeXY.onIndexing);
|
|
}
|
|
if ((state.lengthCompensationActive || state.tcpIsActive) && typeof disableLengthCompensation == "function") {
|
|
disableLengthCompensation(); // cancel tool lenght compensation / TCP prior to output TWP
|
|
}
|
|
if (settings.workPlaneMethod.useTiltedWorkplane) {
|
|
onCommand(COMMAND_UNLOCK_MULTI_AXIS);
|
|
cancelWorkPlane();
|
|
if (machineConfiguration.isMultiAxisConfiguration()) {
|
|
var machineABC = abc.isNonZero() ? (currentSection.isMultiAxis() ? getCurrentDirection() : getWorkPlaneMachineABC(currentSection, false)) : abc;
|
|
if (settings.workPlaneMethod.useABCPrepositioning || machineABC.isZero()) {
|
|
positionABC(machineABC);
|
|
} else {
|
|
setCurrentABC(machineABC);
|
|
}
|
|
}
|
|
if (abc.isNonZero() || !machineConfiguration.isMultiAxisConfiguration()) {
|
|
gRotationModal.reset();
|
|
writeBlock(
|
|
gRotationModal.format(68.2), "X" + xyzFormat.format(currentSection.workOrigin.x), "Y" + xyzFormat.format(currentSection.workOrigin.y), "Z" + xyzFormat.format(currentSection.workOrigin.z),
|
|
"I" + abcFormat.format(abc.x), "J" + abcFormat.format(abc.y), "K" + abcFormat.format(abc.z)
|
|
); // set frame
|
|
writeBlock(gFormat.format(53.1)); // turn machine
|
|
machineSimulation({a:getCurrentABC().x, b:getCurrentABC().y, c:getCurrentABC().z, coordinates:MACHINE, eulerAngles:abc});
|
|
}
|
|
} else {
|
|
positionABC(abc, true);
|
|
}
|
|
if (!currentSection.isMultiAxis()) {
|
|
onCommand(COMMAND_LOCK_MULTI_AXIS);
|
|
}
|
|
currentWorkPlaneABC = abc;
|
|
});
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/initialPositioning_fanuc.cpi
|
|
/**
|
|
* Writes the initial positioning procedure for a section to get to the start position of the toolpath.
|
|
* @param {Vector} position The initial position to move to
|
|
* @param {boolean} isRequired true: Output full positioning, false: Output full positioning in optional state or output simple positioning only
|
|
* @param {String} codes1 Allows to add additional code to the first positioning line
|
|
* @param {String} codes2 Allows to add additional code to the second positioning line (if applicable)
|
|
* @example
|
|
var myVar1 = formatWords("T" + tool.number, currentSection.wcs);
|
|
var myVar2 = getCoolantCodes(tool.coolant);
|
|
writeInitialPositioning(initialPosition, isRequired, myVar1, myVar2);
|
|
*/
|
|
function writeInitialPositioning(position, isRequired, codes1, codes2) {
|
|
var motionCode = {single:0, multi:0};
|
|
switch (highFeedMapping) {
|
|
case HIGH_FEED_MAP_ANY:
|
|
motionCode = {single:1, multi:1}; // map all rapid traversals to high feed
|
|
break;
|
|
case HIGH_FEED_MAP_MULTI:
|
|
motionCode = {single:0, multi:1}; // map rapid traversal along more than one axis to high feed
|
|
break;
|
|
}
|
|
var feed = (highFeedMapping != HIGH_FEED_NO_MAPPING) ? getFeed(highFeedrate) : "";
|
|
var hOffset = getSetting("outputToolLengthOffset", true) ? hFormat.format(tool.lengthOffset) : "";
|
|
var additionalCodes = [formatWords(codes1), formatWords(codes2)];
|
|
|
|
forceModals(gMotionModal);
|
|
writeStartBlocks(isRequired, function() {
|
|
var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17));
|
|
if (typeof disableLengthCompensation == "function") {
|
|
disableLengthCompensation(!isRequired); // cancel tool length compensation prior to enabling it, required when switching G43/G43.4 modes
|
|
}
|
|
|
|
if (machineConfiguration.isHeadConfiguration()) { // head/head head/table kinematics
|
|
var machineABC = currentSection.isMultiAxis() ? defineWorkPlane(currentSection, false) : getWorkPlaneMachineABC(currentSection, false);
|
|
machineConfiguration.setToolLength(getSetting("workPlaneMethod.compensateToolLength", false) ? getBodyLength(currentSection.getTool()) : 0); // define the tool length for head adjustments
|
|
var mode = currentSection.isOptimizedForMachine() ? TCP_XYZ_OPTIMIZED : TCP_XYZ;
|
|
var globalPosition = getGlobalPosition(currentSection.getInitialPosition());
|
|
var machinePosition = machineConfiguration.getOptimizedPosition(globalPosition, machineABC, mode, OPTIMIZE_BOTH, true);
|
|
var prePosition = (currentSection.isOptimizedForMachine() || currentSection.isMultiAxis()) ? position :
|
|
(settings.workPlaneMethod.useTiltedWorkplane && !tcp.isSupportedByMachine) ? machinePosition : globalPosition;
|
|
|
|
cancelWorkPlane();
|
|
positionABC(machineABC);
|
|
if ((getSetting("workPlaneMethod.useTiltedWorkplane", false) && tcp.isSupportedByMachine && getCurrentDirection().isNonZero()) || tcp.isSupportedByOperation) {
|
|
writeBlock(getOffsetCode(true), hOffset); // force TCP for prepositioning although the operation may not require it
|
|
}
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(prePosition.x), yOutput.format(prePosition.y), feed, additionalCodes[0]);
|
|
machineSimulation({x:prePosition.x, y:prePosition.y});
|
|
if (currentSection.isMultiAxis() || getSetting("headPositioningMethod", 0) == 1) {
|
|
var lengthComp = state.lengthCompensationActive ? {code:undefined, hOffset:undefined} : {code:getOffsetCode(), hOffset:hOffset};
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.single), lengthComp.code, zOutput.format(prePosition.z), lengthComp.hOffset, additionalCodes[1]);
|
|
machineSimulation({z:prePosition.z});
|
|
}
|
|
|
|
if (!currentSection.isMultiAxis()) {
|
|
if (state.tcpIsActive && !tcp.isSupportedByOperation && typeof disableLengthCompensation == "function") {
|
|
disableLengthCompensation();
|
|
}
|
|
if (getSetting("workPlaneMethod.useTiltedWorkplane", false) && getCurrentDirection().isNonZero()) {
|
|
var saveRetractedState = [state.retractedX, state.retractedY, state.retractedZ];
|
|
state.retractedX = state.retractedY = state.retractedZ = true; // set retracted states to true to avoid retraction
|
|
defineWorkPlane(currentSection, true); // apply workplane for the operation if TWP is supported
|
|
[state.retractedX, state.retractedY, state.retractedZ] = saveRetractedState; // restore retracted states
|
|
}
|
|
if (!state.lengthCompensationActive) {
|
|
if (state.twpIsActive) {
|
|
forceXYZ();
|
|
}
|
|
if (getSetting("headPositioningMethod", 0) == 1) {
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y));
|
|
machineSimulation({x:position.x, y:position.y});
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.single), getOffsetCode(), zOutput.format(position.z), hOffset);
|
|
machineSimulation({z:position.z});
|
|
} else {
|
|
writeBlock(modalCodes, getOffsetCode(), gMotionModal.format(motionCode.single), xOutput.format(position.x), yOutput.format(position.y), zOutput.format(position.z), hOffset);
|
|
machineSimulation({x:position.x, y:position.y, z:position.z});
|
|
}
|
|
}
|
|
}
|
|
forceFeed();
|
|
} else {
|
|
// multi axis prepositioning with TWP
|
|
if (currentSection.isMultiAxis() && getSetting("workPlaneMethod.prepositionWithTWP", true) && getSetting("workPlaneMethod.useTiltedWorkplane", false) &&
|
|
tcp.isSupportedByOperation && getCurrentDirection().isNonZero()) {
|
|
var W = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) :
|
|
Matrix.getOrientationFromDirection(getCurrentDirection());
|
|
var prePosition = W.getTransposed().multiply(position);
|
|
var angles = W.getEuler2(settings.workPlaneMethod.eulerConvention);
|
|
setWorkPlane(angles);
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(prePosition.x), yOutput.format(prePosition.y), feed, additionalCodes[0]);
|
|
machineSimulation({x:prePosition.x, y:prePosition.y});
|
|
cancelWorkPlane();
|
|
writeBlock(getOffsetCode(), hOffset, additionalCodes[1]); // omit Z-axis output is desired
|
|
forceAny(); // required to output XYZ coordinates in the following line
|
|
} else {
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes[0]);
|
|
machineSimulation({x:position.x, y:position.y});
|
|
writeBlock(gMotionModal.format(motionCode.single), getOffsetCode(), zOutput.format(position.z), hOffset, additionalCodes[1]);
|
|
machineSimulation(tcp.isSupportedByOperation ? {x:position.x, y:position.y, z:position.z} : {z:position.z});
|
|
}
|
|
}
|
|
forceModals(gMotionModal);
|
|
if (isRequired) {
|
|
additionalCodes = []; // clear additionalCodes buffer
|
|
}
|
|
});
|
|
|
|
validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that lenght compensation is enabled
|
|
if (!isRequired) { // simple positioning
|
|
var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17));
|
|
forceXYZ();
|
|
if (!state.retractedZ && xyzFormat.getResultingValue(getCurrentPosition().z) < xyzFormat.getResultingValue(position.z)) {
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.single), zOutput.format(position.z), feed);
|
|
machineSimulation({z:position.z});
|
|
}
|
|
writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes);
|
|
machineSimulation({x:position.x, y:position.y});
|
|
}
|
|
if (machineConfiguration.isMultiAxisConfiguration() && !currentSection.isMultiAxis()) {
|
|
onCommand(COMMAND_LOCK_MULTI_AXIS);
|
|
}
|
|
}
|
|
|
|
Matrix.getOrientationFromDirection = function (ijk) {
|
|
var forward = ijk;
|
|
var unitZ = new Vector(0, 0, 1);
|
|
var W;
|
|
if (Math.abs(Vector.dot(forward, unitZ)) < 0.5) {
|
|
var imX = Vector.cross(forward, unitZ).getNormalized();
|
|
W = new Matrix(imX, Vector.cross(forward, imX), forward);
|
|
} else {
|
|
var imX = Vector.cross(new Vector(0, 1, 0), forward).getNormalized();
|
|
W = new Matrix(imX, Vector.cross(forward, imX), forward);
|
|
}
|
|
return W;
|
|
};
|
|
// <<<<< INCLUDED FROM include_files/initialPositioning_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/getOffsetCode_fanuc.cpi
|
|
var toolLengthCompOutput = createOutputVariable({control : CONTROL_FORCE,
|
|
onchange: function() {
|
|
state.tcpIsActive = toolLengthCompOutput.getCurrent() == 43.4 || toolLengthCompOutput.getCurrent() == 43.5;
|
|
state.lengthCompensationActive = toolLengthCompOutput.getCurrent() != 49;
|
|
machineSimulation({}); // update machine simulation TCP state
|
|
}
|
|
}, gFormat);
|
|
|
|
function getOffsetCode(forceTCP) {
|
|
if (!getSetting("outputToolLengthCompensation", true) && toolLengthCompOutput.isEnabled()) {
|
|
state.lengthCompensationActive = true; // always assume that length compensation is active
|
|
toolLengthCompOutput.disable();
|
|
}
|
|
var offsetCode = 43;
|
|
if (tcp.isSupportedByOperation || forceTCP) {
|
|
offsetCode = machineConfiguration.isMultiAxisConfiguration() ? 43.4 : 43.5;
|
|
}
|
|
return toolLengthCompOutput.format(offsetCode);
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/getOffsetCode_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/getProgramNumber_fanuc.cpi
|
|
function getProgramNumber() {
|
|
if (typeof oFormat != "undefined" && getProperty("o8")) {
|
|
oFormat.setMinDigitsLeft(8);
|
|
}
|
|
var minimumProgramNumber = getSetting("programNumber.min", 1);
|
|
var maximumProgramNumber = getSetting("programNumber.max", getProperty("o8") ? 99999999 : 9999);
|
|
var reservedProgramNumbers = getSetting("programNumber.reserved", [8000, 9999]);
|
|
if (programName) {
|
|
var _programNumber;
|
|
try {
|
|
_programNumber = getAsInt(programName);
|
|
} catch (e) {
|
|
error(localize("Program name must be a number."));
|
|
}
|
|
if (!((_programNumber >= minimumProgramNumber) && (_programNumber <= maximumProgramNumber))) {
|
|
error(subst(localize("Program number '%1' is out of range. Please enter a program number between '%2' and '%3'."), _programNumber, minimumProgramNumber, maximumProgramNumber));
|
|
}
|
|
if ((_programNumber >= reservedProgramNumbers[0]) && (_programNumber <= reservedProgramNumbers[1])) {
|
|
warning(subst(localize("Program number '%1' is potentially reserved by the machine tool builder. Reserved range is '%2' to '%3'."), _programNumber, reservedProgramNumbers[0], reservedProgramNumbers[1]));
|
|
}
|
|
} else {
|
|
error(localize("Program name has not been specified."));
|
|
}
|
|
return _programNumber;
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/getProgramNumber_fanuc.cpi
|
|
// >>>>> INCLUDED FROM include_files/rewind.cpi
|
|
function onMoveToSafeRetractPosition() {
|
|
if (!getSetting("allowCancelTCPBeforeRetracting", false)) {
|
|
writeRetract(Z);
|
|
}
|
|
if (state.tcpIsActive) { // cancel TCP so that tool doesn't follow rotaries
|
|
if (typeof setTCP == "function") {
|
|
setTCP(false);
|
|
} else {
|
|
disableLengthCompensation(false);
|
|
}
|
|
}
|
|
writeRetract(Z);
|
|
if (getSetting("retract.homeXY.onIndexing", false)) {
|
|
writeRetract(settings.retract.homeXY.onIndexing);
|
|
}
|
|
}
|
|
|
|
/** Rotate axes to new position above reentry position */
|
|
function onRotateAxes(_x, _y, _z, _a, _b, _c) {
|
|
// position rotary axes
|
|
xOutput.disable();
|
|
yOutput.disable();
|
|
zOutput.disable();
|
|
if (typeof unwindABC == "function") {
|
|
unwindABC(new Vector(_a, _b, _c), false);
|
|
}
|
|
onRapid5D(_x, _y, _z, _a, _b, _c);
|
|
setCurrentABC(new Vector(_a, _b, _c));
|
|
machineSimulation({a:_a, b:_b, c:_c, coordinates:MACHINE});
|
|
xOutput.enable();
|
|
yOutput.enable();
|
|
zOutput.enable();
|
|
forceXYZ();
|
|
}
|
|
|
|
/** Return from safe position after indexing rotaries. */
|
|
function onReturnFromSafeRetractPosition(_x, _y, _z) {
|
|
if (!machineConfiguration.isHeadConfiguration()) {
|
|
writeInitialPositioning(new Vector(_x, _y, _z), true);
|
|
if (highFeedMapping != HIGH_FEED_NO_MAPPING) {
|
|
onLinear5D(_x, _y, _z, getCurrentDirection().x, getCurrentDirection().y, getCurrentDirection().z, highFeedrate);
|
|
} else {
|
|
onRapid5D(_x, _y, _z, getCurrentDirection().x, getCurrentDirection().y, getCurrentDirection().z);
|
|
}
|
|
machineSimulation({x:_x, y:_y, z:_z, a:getCurrentDirection().x, b:getCurrentDirection().y, c:getCurrentDirection().z});
|
|
} else {
|
|
if (tcp.isSupportedByOperation) {
|
|
if (typeof setTCP == "function") {
|
|
setTCP(true);
|
|
} else {
|
|
writeBlock(getOffsetCode(), hFormat.format(tool.lengthOffset));
|
|
}
|
|
}
|
|
forceXYZ();
|
|
xOutput.reset();
|
|
yOutput.reset();
|
|
zOutput.disable();
|
|
if (highFeedMapping != HIGH_FEED_NO_MAPPING) {
|
|
onLinear(_x, _y, _z, highFeedrate);
|
|
} else {
|
|
onRapid(_x, _y, _z);
|
|
}
|
|
machineSimulation({x:_x, y:_y});
|
|
zOutput.enable();
|
|
invokeOnRapid(_x, _y, _z);
|
|
}
|
|
}
|
|
// <<<<< INCLUDED FROM include_files/rewind.cpi
|