Program Zero Alignment
Program zero is the point an NC program treats as X0 Y0 Z0. The machine finds it by adding a work
offset — G54, G55 and the rest — to machine zero, so a simulation only cuts where the real machine
cuts if the program zero on the model and the work offset in the controller agree. Making them agree
is this task, and it runs in one of two directions depending on why the simulation is being built.
Which direction to align
| You are | Align | Because |
|---|---|---|
| Planning a job from an NC file, before the part is set up on the machine | the work offset onto program zero | The workpiece and fixture can sit wherever is convenient; the offset has probably not been measured yet, and the model does not have to match a real table |
| Reproducing a cut from a controller log, a machine-coordinate feed, or a job already running | program zero onto the work offset | The recorded data is in absolute machine coordinates, so the part has to sit where it really sits, or collisions, overcut and engagement will not match what happened |
Both directions need the workpiece already placed on the fixture and the fixture on the table — that is Anchors and Roles, and it comes first.
Where program zero sits on the workpiece
Program zero is the workpiece's Program-Zero Anchor role, and the offset from the workpiece
geometry to it is the transformer on the workpiece branch that arrives at that anchor from the
workpiece's Geometry Anchor. It is edited in the Equipment page's Topology column:
select the Workpiece item of the Control Tree (/equipment?tree=equipment/mechanism/workpiece)
and, in the Topology column — the fourth column, right of the canvas; the fourth button of the menu
bar's column row (Toggle the Topology column) shows it on a window narrower than 1280 px, where
it starts hidden — click the branch that arrives at the anchor badged Workpiece · Program-Zero Anchor in the
graph's cluster badged Workpiece. The editor card below the graph carries that branch's transformer.
Set it to whatever point the NC program was written around: for most milling programs that is a
corner or the centre of the stock's top face. Nothing else on this page makes sense until that
point is where the programmer put it. Which anchor plays the role is bound in the Roles section
at the foot of the Workpiece item's editor.
A workpiece that arrives as a mesh exported from a CAM tool is usually in that tool's own frame — often machine coordinates — so the programmer's point is not at the mesh's origin, and has to be found in the mesh before this transform can be set. That is Building the Workpiece from a Reference Mesh.
Planning: write the offset from where the workpiece is
The Controller branch's Work Coordinates (G54…) leaf
(/equipment?tree=equipment/controller/program-data/work-coordinates) holds the table the run
resolves G54 against, one row per coordinate id.
- Place the workpiece and fixture wherever the scene is convenient to work in.
- Select the Work Coordinates leaf and find the row the program uses —
G54for most programs. - Press P0 in that row. It writes the machine coordinate the workpiece's program-zero anchor is currently sitting at into the row, which is exactly the number the machine's operator would key in after touching off. M0 beside it writes machine zero instead, which is how a row is returned to no offset at all.
The leaf on a demo project, at
/equipment?tree=equipment/controller/program-data/work-coordinates. The grey line above the
table names where this brand keeps the offsets — on Fanuc, its own parameter table, with
G59.1–G59.9 in the brand-neutral table behind it — and the rows below it are the G54 series
those tables hold, with only G54 carrying a value here; the Show all toggle beside the line
adds the G54.1P rows. P0 and M0 sit at the right-hand end of each row; widen the editor
column if they are cut off.

P0 needs a machine tool, and trusts whatever placement it finds. It works out where the program-zero anchor is by walking the equipment's assembly from the machine tool to it with every axis at machine zero, so a project with no machine tool attached reports that it could not get the machine position at program zero and writes nothing. It does not check the placement: a workpiece still at its default transformers yields wherever its program-zero anchor happens to sit, and a project with no workpiece yields the position of the machine's Table Mount. Either way a number is written, and nothing says it is the wrong one — place the workpiece before pressing P0.
On a machine with error terms, P0 measures the machine without them, as the simulated controller sees it, and so does the alignment call below. A touch-off on the real machine finds an offset that already holds the shift the machine's errors cause with every axis at zero, while P0 leaves that shift in the simulated cut; to reproduce a given shop's cut, type the offset that shop measured.
The row's values can also be typed in directly when the offset is already known from the machine. Clicking anywhere in a row marks that coordinate on the canvas, so the offset can be seen rather than only read.
Reproducing a real cut: place the workpiece on the offset
The Equipment page has no control for this direction. The Work Coordinates leaf's two row actions both write the row — P0 from where program zero sits, M0 to machine zero — and neither moves the part. The operation itself exists outside the page, as an HTTP call and as a mission-script call: both rewrite the transformer of the fixture branch that leads from its Geometry Anchor straight to its Table Mount, as a static translation, so that program zero lands on a recorded offset — and both refuse, changing nothing, when the fixture's topology has no such branch, when that branch carries a dynamic transformer, when the parts are not joined, or when that branch is not the one link between the fixture geometry and the table. They read the offset from a separate, legacy copy of the work-offset table rather than from this leaf, so the row has to be written there as well; Project Construction has the calls. On the page, the part is placed by hand, and a spare row checks the placement:
- Type the recorded offset into the row the program uses — the values can be entered directly, as above — and click the row so the canvas marks that coordinate.
- Move the part to meet the mark by changing where the fixture sits on the machine table: in the
Topology column, click the branch from the anchor badged Fixture · Geometry Anchor to the one
badged Fixture · Table Mount in the cluster badged Fixture; its transformer is in the editor card below the graph —
Anchors and Roles. (The Fixture item of the Control Tree,
/equipment?tree=equipment/mechanism/fixture, is where those two roles are bound.) The workpiece rides on the fixture, so its program-zero anchor moves with it. The canvas's Role Anchors display option (in its Anchors group) draws every bound role anchor's axes, the Program-Zero Anchor among them, so the move can be watched against the mark. - Once the program-zero anchor sits on the mark, check it on a row the program never selects —
G59is a common choice when the program uses onlyG54. Press P0 on that spare row and compare it with the recorded row: the two agree when the placement is right, and any difference is how far it is off. Return the spare row to machine zero with M0 afterwards. Do not press P0 on the row the run reads — it would replace the recorded offset with the scene's, and the run resolves against whatever the row holds.
Once the part is aligned this way, an error in the recorded offset no longer changes what the NC program cuts — the tool still meets program zero — but it moves the whole setup in machine coordinates, where stroke checks and machine collisions see it. Data recorded in machine coordinates is another matter: played against a misplaced part, it cuts in the wrong place, which is why the offset has to be the real one — see below.
Several parts, several offsets
A program that machines identical parts side by side — one fixture, the same subprogram called once
per part, each call under its own work offset: G54 for the first part, G55 for the second, and
so on — still has only one program-zero anchor on the model. Put it on the part the first offset
serves, and model all the parts as the one workpiece geometry.
P0 writes that one anchor's position whichever row it is pressed on, so it can fill only the first row. Every other row is the first row plus the spacing between the parts' program zeros, expressed along the machine axes:
- Align the first row as above, in whichever direction applies.
- Fill each further row from the recorded offsets or, when planning, as the first row plus the part
spacing — two parts 90 mm apart along X give a
G55that isG54with 90 added to its X. Do not press P0 on a further row: that writes the first part's position again, and every call then plays on the first part. - Check the spacing against the geometry: on a machine whose linear axes are parallel to the part's, the difference between two rows equals the distance between the two parts' program zeros on the model.
When a reference mesh shows the parts at slightly different heights while the recorded offsets say they are level, decide which to trust. Keeping the offsets reproduces the machine, and the geometry comparison after the run shows the difference; shifting each further row's Z by the measured height difference reproduces the mesh and gives every part the same allowance. Write the choice down with the project.
A part played in the wrong place raises no message of its own. The no-contact warning,
Play-Touch--None, is raised only when not a single step of the whole play touched the workpiece,
and the first part is still cut. Check every part after the run — on the
Program branch the called file shows one pass per call — or
play each part's block on its own and confirm that it cuts.
Checking that it worked
A wrong alignment — a wrong offset, or a workpiece at the wrong height — shows up as overcut, collision or nocut, and it shows up early: usually within the first hundred or so NC lines. Check it cheaply before committing to a full run.
- Set a coarse Initial Resolution on the workpiece's Mesh item — around an eighth of the cutter diameter is enough to see gross errors, and it runs quickly. That is Workpiece. Give the mission's Machining Resolution row the same value: a cut is meshed at the finer of the two, so a fine row there keeps the check slow.
- Run, and watch the opening Z plunge. This is where a wrong offset shows first.
- Before the full run, set both back to the widths the job needs. Where the mission caches the stock in a stage-0 Record Meshed Geometry entry above the first program, Reset that entry or delete its file as well: it cached the stock at the coarse width during the check, and every later run reads the coarse stock back without a word — see A Mission That Resumes.
Tip
If the tool plunges far deeper than the programmed depth and the holder gouges the stock, the work offset's Z is almost certainly wrong — the workpiece is modelled higher or lower than it really sits.
One false positive is worth knowing: a roughing cut with a spiral entrance into tough material can legitimately exceed the modelled cutting conditions while the setup is perfectly correct. It is uncommon, and early overcut, collision or nocut usually does mean the alignment is wrong.
When the planned offset is not the real one
In the reproducing direction, the offset aligned to must be the offset the machine was actually using, not the one the job was planned with. Operators re-zero between setups — after a manual tool change, after re-cutting stock — so a planned G54 and the real one can differ by an amount that cannot be assumed in advance.
When the data comes from a controller log, derive the offset from the log's own machine coordinates rather than trusting the plan: an invariant that survives an operator's edits — a known cutting depth, the span of a feature — mapped onto the recorded coordinates recovers the real offset on those axes. Axes the operator may have shifted with nothing to key on are not recoverable this way. A wrong Z is the one that bites hardest, because it places the workpiece away from its true height and the tool over- or under-plunges from the first block.
Two conventions change what a recorded number means, and both have to be settled before it is typed into a row:
A row is measured to the tool mount, not to a tool tip. A work offset in the simulated
controller is the machine position at which the spindle's gauge line — the tool-end anchor of the
machine tool, the one its Tool Mount role is bound to — meets
program zero, with every axis at machine zero. Tool length reaches the run separately, through the height offset G43 H selects, which
covers the holder and the tool's stick-out. An offset that was touched off with a tool, on a machine
whose programs apply no length compensation, carries that tool's length in its Z, and has to be
converted before it is entered. Such a program adds no length of its own, so without one more
change the tip runs a whole tool length below every programmed Z. Either give the copy of the
program the simulation plays a G43 H with the tool's number before its first move down — it adds
the height on that row of Tool Offsets, which follows the tool house by default
(Controller) — or, once the part is placed, put the length back into the Z of the
row the run reads, one row per tool, as the shop keeps it.
An external offset is folded into each row. Fanuc-family controllers can add a common external work offset (EXT) on top of every work coordinate system. The simulated controller has no such row, so add the external offset into each row the program uses. Once the part is aligned onto its row, the external offset does not change what the NC program cuts — the tool still meets program zero — but leaving it out shifts the whole setup in machine coordinates, and stroke checks, machine collisions and any comparison with a machine-coordinate log all see that shift.
A placement convention that makes this easier
In the default topology a fixture's branches run from its Geometry Anchor to each of its mounts, and a workpiece's from its Geometry Anchor to its Fixture Mount and to its Program-Zero Anchor; each branch is named after the anchor it arrives at. Besides the fixture's Table Mount branch — the one placement and the alignment write — three branch transformers hold the assembly together. They can be put anywhere, but a block-on-plate setup is easiest to reason about when each sits at the middle of the face it meets:
| Branch | A good default |
|---|---|
Fixture, Geometry Anchor → Workpiece Mount (WorkpieceMount) |
The top centre of the fixture geometry |
Workpiece, Geometry Anchor → Fixture Mount (FixtureMount) |
The bottom centre of the workpiece geometry |
Workpiece, Geometry Anchor → Program-Zero Anchor (ProgramZeroAnchor) |
The top centre of the workpiece geometry, or whichever top point the program was written around |
Nothing above depends on this convention — P0 walks the assembly as it stands, whatever the transformers hold — but a scene built this way is far easier to check by eye, and far easier to place by hand in the reproducing direction.
See Also
- Anchors and Roles — placing the workpiece, fixture and tool relative to the machine, which comes before this
- Assembly Anchors — the named mount anchors this alignment resolves against
- Workpiece — the item whose Program-Zero Anchor role and Geometry Anchor bound the branch this task sets, and the Mesh resolution the check above uses
- Fixture — the item whose Geometry Anchor → Table Mount branch moves the part onto a recorded offset in the reproducing direction
- Fixture Page — the component behind the Fixture item, and what the align call does to the fixture's Geometry Anchor → Table Mount branch
- Controller — the branch whose work-offset table a run resolves against
- Machine Tool — the machine whose Tool Mount every work offset is measured from
- A Mission That Resumes — the stage-0 stock cache a coarse check leaves behind, and when to reset it
- When Something Goes Wrong — a program with no tool change builds no step, and one with no length runs its tip a whole tool length low
- NC Dialects — how each brand's code names the work offset this alignment is expressed against
- Workflow: Constructing a Project through the Web API — the HTTP calls that align the part to a recorded offset and fill the work-offset tables
- Building the Workpiece from a Reference Mesh — finding program zero in a mesh exported in a CAM tool's frame
- Project Data Checklist — the collection step this alignment closes
- Workflow: Basic Machining Simulation — driving a simulation from an NC file or a controller log
- Workflow: Milling Force Parameter Training — milling force training, which depends on a correct setup
- Setup — the rest of the pre-simulation configuration