Motion Filter Plugin
Introduction
Overview
The MotionFilter plugin transforms axis positions between the motion planner (the "core") and the physical motors. It lets one axis influence another — gearing a slave to a master, overriding one axis from another, compensating a mechanical squaring error, applying a rotational transform, or correcting a linear taper — without changing the part program. Every transform is applied on the fly as positions stream to the motors and is exactly reversed on the way back so the control always sees a consistent picture.
The plugin is machine-type agnostic. The same features work on mills, lathes, and grinders. Axes are referenced by index (0 = X, 1 = Y, 2 = Z, 3 = A, …), so any pairing that makes physical sense is allowed.
Feature Summary
| Feature | What it does |
| Gearing | A slave axis motor follows a master axis motor at a configurable ratio. The slave’s planner position is untouched; only its motor output is scaled and added. Ratio may be negative to invert direction. |
| Axis Override | Commanded motion on a secondary axis is copied onto a primary axis. Moving the primary directly adds no extra motion. |
| Taper Compensation | A slave axis is corrected as a linear function of a master axis: correction = ratio × (master − pivot). Used to correct an unwanted taper so a nominally straight feature comes out straight. |
| Squaring Compensation | Compensates a mechanical out-of-square error between two axes by moving a following axis as a function of an angled axis. |
| Rotation Filters | Rotational coordinate transforms between axis triplets. |
| Position Logging | High-throughput binary logging of every push/pop stage for offline analysis and diagnostics. |
How It Works
Push / Pop Model
The plugin sits in the position pipeline as a two-way filter:
- Push (planner → motors): transforms commanded positions before they reach the motors.
- Pop (motors → planner): the exact inverse transform, so the core sees positions consistent with what it commanded.
On push, the stages run in order: sync → rotation → gearing → squaring → axis override → taper comp. On pop they run in the reverse order. Because push and pop are exact inverses, enabling or disabling a filter never causes a position jump when the control re-synchronizes.
Push and pop must remain exact inverses. A mismatch shows up as a sudden position jump on the DRO the moment the core re-synchronizes. Every filter caches the value it applied on push and subtracts that same value on pop for this reason.
Smooth Engage / Disengage
Filters that can be turned on or off mid-program (gearing recovery, taper comp) never step an axis. When a correction needs to change, the affected axis is eased from its current value to the new target with a 5th-order S-curve trajectory — zero velocity and zero acceleration at both ends, so there is no audible “bang” and no jerk step.
Taper Compensation
Concept
Taper compensation corrects an unwanted taper. If a part that should be a straight cylinder comes out with a slightly larger diameter at one end — from workhead misalignment, deflection, or wheel wear — taper comp continuously offsets the infeed axis as a function of the traverse axis so the finished feature is straight. The part program stays straight; the control does the correcting.
The correction applied to the slave axis is:
correction = ratio × (master_machine_position − pivot)
- Slave — the axis that receives the correction (X, the diameter/infeed axis, on an OD/ID grinder).
- Master — the axis the correction tracks (Z, the traverse axis).
- Ratio (Amount) — slave distance per one unit of master travel. Example:
0.005means X moves 0.005 for every 1.0 of Z travel. - Pivot — the master position where the correction is exactly zero. Set this to where the part was dialed in on size, so that point is left untouched and the rest is corrected around it.
On an OD/ID grinder you configure the X Axis taper comp with its master set to Z. The settings section is named for the slave (corrected) axis. Rule of thumb: the axis you would nudge to fix the diameter is the one you configure.
Pivot Anchoring
The pivot is captured as an absolute machine coordinate the moment comp is engaged and is never recomputed from live positions afterward. This means changing a work offset (G54…G59), re-zeroing, or motor drift while the machine is disabled does not move the pivot. The compensation stays anchored to the physical geometry, which is what keeps the dialed-in end on size.
Each axis has a Pivot Position Coordinate System setting:
- Part — the entered pivot is in part (work) coordinates and is converted to machine coordinates at engage time. On every tool change the pivot is automatically shifted by the new tool offset so it keeps following the part.
- Machine — the entered pivot is an absolute machine coordinate and is used verbatim, never adjusted.
The Arm Switch
Taper Comp Enabled is the overarching arm switch. It must be Yes for compensation to engage. When it is No, the M256 engage command becomes a silent no-op — a posted program still runs, just uncompensated — so the same program is portable to machines that do not use taper comp. Turning comp off (M257) is always honored regardless of the arm switch.
M-Codes
| M-code | Purpose |
| M256 | Engage (or update) taper compensation from the stored settings. Silent no-op when the arm switch is off. Blocks until the correction ramp settles so the next line runs fully compensated. |
| M257 | Disengage taper compensation. Ramps the correction to zero. Always honored. Idempotent. |
M256 optional words:
| Word | Meaning |
| Q | Pair selector: Q1 = X slave, Q2 = Y slave, Q3 = Z slave. Omitted = engage every configured pair. |
| P | Pivot position along the master, in part coordinates. Writes the stored Pivot setting, then engages. |
| R | Amount — slave distance per one unit of master travel. Writes the stored Amount setting, then engages. |
M257 optional word: Q selects a single pair to disengage (Q1/Q2/Q3); omitted disengages all active pairs.
The P and R words persist — they overwrite the stored settings, so a value posted by a program remains the machine’s taper setting after the program ends. Pair topology (which axes are paired) can only be changed in the settings, never from an M-code.
(Engage every configured pair from the stored settings)
M256
(X pair: 0.005 per unit of master, pivot at part zero, then engage)
M256 Q1 R0.005 P0
(Dress cycle choreography: comp off, dress, comp back on)
M257
G261 (dress)
M256
(Disengage all taper comp)
M257
Settings
Taper Comp settings live in the shared Common settings and appear under the Taper Comp category of the MachMotion configuration Parameters tab.
| Setting | Default | Range | Description |
| Taper Comp Enabled | No | Yes / No | Overarching arm switch. Must be Yes for comp to engage. |
| Ramp Speed — Percent | 25 | 1–100 % | Fraction of the slave axis max velocity and acceleration used by the engage / disengage / update ramp. |
| Ramp Minimum Duration | 0.5 | ≥ 0 s | Floor on the ramp duration. Lower it to make small corrections apply faster. |
| X/Y/Z Axis Taper Comp Configured | No | Yes / No | Enables that axis as a taper comp slave. |
| Master Axis That <axis> Follows | — | choice | Which of the other two axes is the master for this slave. |
| <axis> Distance Per One Unit Of Master Travel | 0 | float | The Amount (ratio). Signed. |
| Pivot — Position Along Master Where Correction Is Zero | 0 | float | The pivot position. |
| Pivot Position Coordinate System | Part | Part / Machine | Whether the pivot is part or machine coordinates (see Pivot Anchoring). |
Ramp Speed
The two ramp settings control different regimes of the same S-curve. For a given correction distance, the planner picks the shortest duration that respects all three limits: percent of max velocity, percent of max acceleration, and the minimum-duration floor.
- Ramp Speed Percent dominates large corrections — raise it toward 100 to apply big changes faster.
- Ramp Minimum Duration dominates small corrections — a tiny correction would otherwise apply almost instantly, so the floor keeps it smooth. Lower it toward zero to make small corrections snap in.
The ramp is always a quintic (5th-order) S-curve, so jerk is finite and continuous no matter how the two settings are chosen — there is no bang even at 100 % / 0 s.
Screen Controls
Four operator commands are available (assign them to buttons in the screen designer):
| Command | Action |
| Taper Comp Arm Toggle | Flips the arm switch. Disarming also disengages any active comp. Button LED reflects the armed state. |
| Taper Comp Adjust | Opens the adjust dialog (below). |
| Taper Comp On | Engages every configured pair from the stored settings. |
| Taper Comp Off | Disengages all pairs. |
The Taper Comp Adjust dialog shows the armed state, the active pair, and a live applied-correction readout with a color-coded state indicator (OFF / RAMPING / ACTIVE). The taper amount can be entered three ways — distance per unit, angle in degrees, or measured deviation over a length — and the resulting per-unit value is shown as you type. The pivot can be typed or captured from the current master position with Use Current. A Turn Comp On / Off button engages or disengages with exactly what the dialog shows; OK saves the settings (and ramps an update into an already-running comp).
If the Applied Correction reads 0 while the state shows ACTIVE, the master is simply sitting at the pivot — correction there is zero by definition. Jog the master away from the pivot and the applied value grows with distance.
Dressing Interaction
Dressing must run with comp off so the wheel is dressed straight (dresser positions are machine coordinates and would otherwise produce a tapered wheel). The wizard-posted program choreography is M257 before the dress cycle and M256 after it.
Gearing
Overview
Gearing slaves one axis motor to another at a fixed ratio. It is used where two axes must move together mechanically — for example a gantry or a linked rotary. The slave’s planner position is unaffected; only the motor output receives the extra, ratioed motion.
| M-code | Purpose |
| M34 | Gear a slave to a master. Q = master axis, S = slave axis, R = ratio (default 1). |
| M35 | Un-gear a slave from a master. Q = master axis, S = slave axis. |
(Gear Y (slave) to X (master) at 1.5:1)
M34 Q0 S1 R1.5
(Un-gear Y from X)
M35 Q0 S1
Gearing can optionally enforce the slave’s soft limits, clamping (and optionally alarming) if the master would drive the slave past its travel. See MotionFilterModule.SetGearingSoftLimits.
Lua Module Reference
MotionFilterModule (loaded as mf in the screen and M-code environments) is the scripting interface. Every function that sends a command first checks that the plugin is enabled. Functions return (success, rc, response) where response is the plugin’s reply string ("OK" on success) unless noted otherwise.
General
| Function | Purpose |
IsMotionFilterPluginEnabled() |
Returns true if the plugin is enabled in the profile. |
SendCommand(command) |
Send a raw command string to the plugin API register. |
Gearing
| Function | Purpose |
GearAxis(master, slave, ratio) |
Gear the slave to the master at ratio (negative inverts). |
UngearAxis(master, slave) |
Remove gearing. |
IsGearingActive(master, slave) |
True while the pair is geared. |
SetGearingSoftLimits(slave, enable, ramp_distance, alarm) |
Configure slave soft-limit enforcement during gearing. |
GetGearingSoftLimits(slave) |
Query the current soft-limit setting. |
IsGearingAtSoftLimit(slave) |
True while the slave is being clamped at a soft limit. |
Axis Override
| Function | Purpose |
OverrideAxis(primary, secondary) |
Copy commanded motion of the secondary axis onto the primary. |
RemoveOverrideAxis(primary, secondary) |
Remove the override. |
IsAxisOverridden(primary, secondary) |
True while the override is active. |
VerifyAxisAtZero(axis_id, message) |
Pre-check used before applying / removing an override. |
Taper Compensation
| Function | Purpose |
SetTaperComp(slave, master, ratio, pivot_mach, track_part, ramp_percent, ramp_min_s) |
Engage or update taper comp. pivot_mach is machine coordinates; track_part makes the pivot follow the part on tool changes. |
RemoveTaperComp(slave) |
Ramp the correction to zero and disengage. Idempotent. |
GetTaperComp(slave) |
Read the feedback registers: returns a table { ratio, pivot, master, applied, state }. |
IsTaperCompActive(slave) |
True while the pair is engaged (ramping or active). |
WaitForTaperCompSettled(slave, timeout_ms) |
Block until the ramp settles (ACTIVE or OFF). Used by M256 / M257. |
The state value from GetTaperComp is: 0 = off, 1 = ramping in, 2 = active, 3 = ramping out.
Squaring
| Function | Purpose |
SetSquaringAngle(angled_axis, following_axis, degrees) |
Set the out-of-square angle and the axis that compensates. |
LockSquaring(enable, adjust_units) |
Activate squaring (all angles must be set first). |
UnlockSquaring() |
Release squaring. |
Logging
| Function | Purpose |
EnableLogging(enable) / DisableLogging() |
Turn position logging on or off. |
LogAxis(axis) |
Enable detailed logging for one axis. |
QuickLog(axis) / QuickLogAll() |
Capture a brief position snapshot for one or all axes. |
Command Protocol
Scripts talk to the plugin by sending semicolon-delimited command strings to the MotionFilter/API register via mc.mcRegSendCommand() (wrapped by MotionFilterModule.SendCommand). The command surface:
| Command string | Lua wrapper |
lock axis gearing;{slave};{master};{ratio} |
GearAxis |
unlock axis gearing;{slave};{master} |
UngearAxis |
set gearing soft limits;{slave};{0|1} |
SetGearingSoftLimits |
override axis;{primary};{secondary} |
OverrideAxis |
remove override axis;{primary};{secondary} |
RemoveOverrideAxis |
taper comp;{slave};{master};{ratio};{pivot};{track};{ramp%};{ramp_min_s} |
SetTaperComp |
remove taper comp;{slave} |
RemoveTaperComp |
get taper comp;{slave} |
GetTaperComp (reads registers) |
set squaring angle;{angled};{following};{degrees} |
SetSquaringAngle |
lock squaring;{enable};{adjust_units} / unlock squaring |
LockSquaring / UnlockSquaring |
enable logging;{0|1} / disable logging |
EnableLogging / DisableLogging |
open diagnostics / close diagnostics |
— |
Diagnostics Window
The plugin’s diagnostics window (opened with the open diagnostics command) has a tab per filter family — Gearing Filters, Squaring Compensation, Rotation Filters, and Taper Comp. Each shows live per-axis state. The Taper Comp tab lists one row per slave axis with an Active LED and read-only Ratio, Pivot, and Applied columns, so you can confirm the correction the plugin is actually applying independently of the screen dialog.
If the adjust dialog and the diagnostics window disagree on the applied correction, the diagnostics window is authoritative — it reads the plugin’s live state directly.
Components
| File | Purpose |
Plugins/MotionFilter/MotionFilter.cpp |
Plugin entry point, message handling, command dispatch, push/pop orchestration. |
Plugins/MotionFilter/RatioFilter.cpp |
Gearing filter implementation. |
Plugins/MotionFilter/AxisOverride.cpp |
Axis override filter implementation. |
Plugins/MotionFilter/TaperComp.cpp |
Taper compensation filter implementation. |
Modules/MotionFilterModule.lua |
Lua scripting interface (mf). |
Modules/CommonMCodeModule.lua |
Hosts _m34, _m35, _m256, _m257 implementations. |
Profiles/<profile>/Macros/m256.mcs, m257.mcs |
G-code macro wrappers for taper comp. |
Profiles/<profile>/Settings/Standard/Common/settings.TaperComp.csv |
Taper Comp OEM parameter definitions. |