Just for fun heres the code for it.
[code// Start of multi-axis feedrate logic
/***** Be sure to add 'useInverseTime' to post properties if necessary. *****/
/***** 'inverseTimeOutput' must be defined. *****/
/***** 'headOffset' should be defined when a head rotary axis is defined. *****/
/***** The feedrate mode must be included in motion block output (linear, circular, etc. *****/
var dpmBPW = 0.1; // ratio of rotary accuracy to linear accuracy for DPM calculations
var inverseTimeUnits = 1.0; // 1.0 = minutes, 60.0 = seconds
var maxInverseTime = 9999; // maximum value to output for Inverse Time feeds
/** Calculate the multi-axis feedrate number. */
function getMultiaxisFeed(_x, _y, _z, _a, _b, _c, feed) {
var f = {frn:0, fmode:0};
if (feed <= 0) {
error(localize("Feedrate is less than or equal to 0."));
return f;
}
var length = getMoveLength(_x, _y, _z, _a, _b, _c);
if (true) { // inverse time
f.frn = inverseTimeOutput.format(getInverseTime(length[0], feed));
f.fmode = 93;
feedOutput.reset();
} else { // degrees per minute
f.frn = feedOutput.format(getFeedDPM(length, feed));
f.fmode = 94;
}
return f;
}
/** Calculate the DPM feedrate number. */
function getFeedDPM(_moveLength, _feed) {
// moveLength[0] = Tool tip, [1] = XYZ, [2] = ABC
if (false) { // TCP mode is supported, output feed as FPM
return feed;
} else { // DPM feedrate calculation
var moveTime = ((_moveLength[0] < 1.e-6) ? 0.001 : _moveLength[0]) / _feed;
var length = Math.sqrt(Math.pow(_moveLength[1], 2.0) + Math.pow((toDeg(_moveLength[2]) * dpmBPW), 2.0));
return length / moveTime;
}
}
/** Calculate the Inverse time feedrate number. */
function getInverseTime(_length, _feed) {
var inverseTime;
if (_length < 1.e-6) { // tool doesn't move
if (typeof maxInverseTime === "number") {
inverseTime = maxInverseTime;
} else {
inverseTime = 999999;
}
} else {
inverseTime = _feed / _length / inverseTimeUnits;
if (typeof maxInverseTime === "number") {
if (inverseTime > maxInverseTime) {
inverseTime = maxInverseTime;
}
}
}
return inverseTime;
}
/** Calculate the distance of the tool position to the center of a rotary axis. */
function getRotaryRadius(center, direction, toolPosition) {
var normal = direction.getNormalized();
var d1 = toolPosition.x - center.x;
var d2 = toolPosition.y - center.y;
var d3 = toolPosition.z - center.z;
var radius = Math.sqrt(
Math.pow((d1 * normal.y) - (d2 * normal.x), 2.0) +
Math.pow((d2 * normal.z) - (d3 * normal.y), 2.0) +
Math.pow((d3 * normal.x) - (d1 * normal.z), 2.0)
);
return radius;
}
/** Calculate the linear distance based on the rotation of a rotary axis. */
function getRadialDistance(axis, startTool, endTool, startABC, endABC) {
// rotary axis does not exist
if (!axis.isEnabled()) {
return 0.0;
}
// calculate the rotary center based on head/table
var center;
if (axis.isHead()) {
var pivot;
if (typeof headOffset === "number") {
pivot = headOffset;
} else {
pivot = tool.getBodyLength();
}
center = Vector.sum(startTool, Vector.product(machineConfiguration.getSpindleAxis(), pivot));
center = Vector.sum(center, axis.getOffset());
} else {
center = axis.getOffset();
}
// calculate the radius of the tool end point compared to the rotary center
var startRadius = getRotaryRadius(center, axis.getEffectiveAxis(), startTool);
var endRadius = getRotaryRadius(center, axis.getEffectiveAxis(), endTool);
// calculate length of radial move
var radius = Math.max(startRadius, endRadius);
var delta = Math.abs(endABC.getCoordinate(axis.getCoordinate()) - startABC.getCoordinate(axis.getCoordinate()));
if (delta > Math.PI) {
delta = 2 * Math.PI - delta;
}
var radialLength = (2 * Math.PI * radius) * (delta / (2 * Math.PI));
return radialLength;
}
/** Calculate tooltip, XYZ, and rotary move lengths. */
function getMoveLength(_x, _y, _z, _a, _b, _c) {
// get starting and ending positions
var moveLength = new Array();
var startTool;
var endTool;
var startXYZ;
var endXYZ;
var startABC = getCurrentDirection();
var endABC = new Vector(_a, _b, _c);
if (currentSection.getOptimizedTCPMode() == 0) {
startTool = getCurrentPosition();
endTool = new Vector(_x, _y, _z);
startXYZ = machineConfiguration.getOrientation(startABC).getTransposed().multiply(startTool);
endXYZ = machineConfiguration.getOrientation(endABC).getTransposed().multiply(endTool);
} else {
startXYZ = getCurrentPosition();
endXYZ = new Vector(_x, _y, _z);
startTool = machineConfiguration.getOrientation(startABC).multiply(startXYZ);
endTool = machineConfiguration.getOrientation(endABC).multiply(endXYZ);
}
// calculate the radial portion of the move
var radialLength = Math.sqrt(
Math.pow(getRadialDistance(machineConfiguration.getAxisU(), startTool, endTool, startABC, endABC), 2.0) +
Math.pow(getRadialDistance(machineConfiguration.getAxisV(), startTool, endTool, startABC, endABC), 2.0) +
Math.pow(getRadialDistance(machineConfiguration.getAxisW(), startTool, endTool, startABC, endABC), 2.0)
);
// calculate the lengths of move
// tool tip distance is the move distance based on a combination of linear and rotary axes movement
var linearLength = Vector.diff(endXYZ, startXYZ).length;
moveLength[0] = linearLength + radialLength;
moveLength[1] = Vector.diff(endXYZ, startXYZ).length;
moveLength[2] = 0;
for (var i = 0; i < 3; ++i) {
var delta = Math.abs(endABC[i] - startABC[i]);
if (delta > Math.PI) {
delta = 2 * Math.PI - delta;
}
moveLength[2] += Math.pow(delta, 2.0);
}
moveLength[2] = Math.sqrt(moveLength[2]);
return moveLength;
}
// End of multi-axis feedrate logic]