Multi-Axis Feedrates
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
During multi-axis contouring moves the machine control will typically expect the feedrate numbers to be either in Inverse Time or some form of Degrees per Minute. Inverse Time feedrates are simply the inverse of the time that the move takes, i.e. 1 / movetime. If your control supports both Inverse Time and Degrees Per Minute feedrates, it is recommended that you use Inverse Time as this is the most accurate. Please note that if your machine supports TCP (Tool Control Point) programming, then it probably supports direct Feed Per Minute (FPM) feed rates during multi-axis contouring moves and does not require either Inverse Time or DPM feedrates.
To implement multi-axis feedrate support into your post, you will first need to copy the code from a post processor that already supports this feature. You will find this code in various multi-axis post processors including the following.
- 5axismaker.cps
- fadal.cps
- fanuc with a-axis.cps
- haas trunnion.cps
- machmill4.cps
- pocket nc.cps
- tormach.cps
All the lines between and including the following lines should be copied.
// Start of multi-axis feedrate logic … // End of multi-axis feedrate logic
This code is generic in nature and will work with all machine configurations; table/table, head/head, and head/table. Because of this most of the functions included in this code will not have to be modified by you, though you will have to modify other sections of the post processor to fully implement this feedrate logic.
One capability of the multi-axis feedrate calculation is that it considers the actual tool tip movement in reference to the rotary axes movement and not just the straight line move along the programmed tool tip, creating more accurate multi-axis feedrates. In the following picture the move along the arc caused by the movement of the rotary axis (green arc) is used in the calculation instead of the straight-line move generated by HSM (blue line).
The useInverseTimeOutput property can be added to the post property table at the start of the post processor file. It is typically used to allow the user to select either Inverse Time (true) or DPM feedrates (false) for multi-axis moves. If the post processor only supports one of these modes, then this property does not have to be defined.
properties = { … useInverseTime: true // true = inverse time feedrates, false = degrees per minute feedrates }
If Inverse Time feedrates are supported you will need to create the inverseTimeOutput variable at the top of the post processor code and if the accuracy of the Inverse Time feedrates is different than the standard FPM feedrate you will also need to create a new format to associate with it.
var inverseFormat = createFormat({decimals:4, forceDecimal:true}); … var inverseTimeOutput = createVariable({prefix:"F", force:true}, feedFormat);
The variables at the top of the multi-axis feedrate code define variables used in the calculation of Inverse Time and DPM feedrates.
Variable |
Description |
dpmBPW |
Defines the pulse weight ratio for the rotary axes when DPM feedrates are supported. The pulse weight is the minimum increment that each axis can move and can be different for the linear and rotary axes. For example, if the accuracy of linear axes is .0001 and the accuracy for rotary axis is .001, then the dpmBPW variable should be set to 0.1. |
inverseTimeUnits |
Defines the unit of time for Inverse Time feedrates. Specify 1.0 for minutes and 60.0 for seconds. |
maxInverseTime |
Specifies the maximum value that can be output for Inverse Time feedrates. |
headOffset |
For machines that have a rotary head, the headOffset variable must be defined. It contains the fixed pivot length combined with the tool length and is used to calculate the length of the move. Basically, it is the distance from the tool tip to the pivot point of the head. This variable is typically defined in post processors that support rotary heads. |
getMultiaxisFeed is the controlling function used for multi-axis feedrate calculations. It retrieves the total move length and determines whether to use Inverse Time or DPM feedrates.
/** 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 (properties.useInverseTime) { // 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; }
If your machine does not support DPM feedrates you can change the following line in this function so that Inverse Time feedrates are always calculated. Conversely, you can set the condition to false for support of only DPM feedrates for multi-axis moves.
if (true) { // inverse time
The only other function that you may have to modify in the included code is the getFeedDPM function that calculates the Degrees Per Minute feedrates. By default, it is setup to calculate the feedrate number based on the combined movement of the linear and rotary axes, sometimes referred to as Pulses Per Minute. This is standard on most controls, though there are some controls that use a proprietary calculation for DPM feedrates, such as the Fadal control. You can see a sample of this calculation in the generic fadal.cps post processor.
/** 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; } }
Now there are other areas of the post processor that have to be changed to support these feedrate modes. First, the onLinear5D function must have support added to call the function and output the correct feedrate codes.
function onLinear5D(_x, _y, _z, _a, _b, _c, feed) { … // get feedrate number var f = {frn:0, fmode:0}; if (a || b || c) { f = getMultiaxisFeed(_x, _y, _z, _a, _b, _c, feed); } else { f.frn = getFeed(feed); f.fmode = 94; } if (x || y || z || a || b || c) { writeBlock(gFeedModeModal.format(f.fmode), gMotionModal.format(1), x, y, z, a, b, c, f.frn); } else if (f.frn) {
if (getNextRecord().isMotion()) { // try not to output feed without motion
feedOutput.reset(); // force feed on next line
} else {
writeBlock(gFeedModeModal.format(f.fmode), gMotionModal.format(1), f.frn);
}
You will need to reset the feedrate mode to FPM either at the end of the multi-axis operation or on a standard 3-axis move.
function onSectionEnd() { … if (currentSection.isMultiAxis()) { writeBlock(gFeedModeModal.format(94)); // inverse time feed off }
It is much easier to do this at the end of the section, otherwise you would have to modify all instances that output feedrates, such as in onLinear, onCircular, onCycle, etc.
writeBlock(gFeedModeModal.format(94), gMotionModal.format(1), gFormat.format(40), x, y, z, f);

Bob Schultz
Sr. Post Processor Developer