A hands-on project exploring Autodesk's Fanuc post processor architecture: modeling a part, generating CAM toolpaths in Fusion 360, and customizing the post processor (.cps) that translates those toolpaths into G-code.
Built while preparing for a Post Processor and Machine Simulation Specialist interview, to get real, working hands-on exposure to the post processor entry-function architecture described in Autodesk's CAM Post Processor documentation.
A simple 100 x 60 x 12mm plate with a 4mm-deep rectangular pocket and 4 through-holes — modeled in Fusion 360 to give a facing, pocketing, and drilling operation to work with.
Three operations were programmed in Fusion 360's Manufacture workspace:
| Operation | Tool | Purpose |
|---|---|---|
| Face | Ø10mm flat endmill | Skim the top surface flat |
| 2D Pocket | Ø6mm flat endmill | Clear the rectangular pocket, ramp-entry into the cut |
| Drill | Ø6mm 118° drill | Drill the 4 through-holes using a canned cycle |
Each was posted separately using Autodesk's factory Fanuc post processor (Fusion for personal use only supports posting one tool per program — a limitation of the free tier, so each operation is a separate .nc file: 1001.nc, 1002.nc, 1003.nc).
The post processor (fanuc.cps) is a JavaScript script — separate from the .nc output it generates. Fusion calls specific entry functions at defined moments during posting:
onOpen()— runs once, at the very start, before any toolpath code — writes the program headeronClose()— runs once, at the end — writes the program footer, retracts, spindle/coolant offonCyclePoint(x, y, z)— runs once per hole in a drilling-type operation. It's a dispatcher: it checks what kind of operation this is (real machining, inspection, probing) and routes to the right handler — in this casewriteDrillCycle()writeDrillCycle()— the actual logic: a switch statement that maps operation type (drilling,counter-boring,chip-breaking,tapping,fine-boring, etc.) to the correct Fanuc canned cycle G-code (G81, G82, G73, G83, G84, G76...)
This part's holes use cycleType = "drilling", which maps to a simple G98 G81 cycle — no pecking, no dwell, straight through-hole.
a) Custom program header — added to onOpen(), right after the % program-start marker:
writeln("(POST PROCESSOR CUSTOMIZATION PROJECT)");
writeln("(AUTHOR: AATHITHYAN VENKATESH)");
writeln("(DATE: " + new Date().toDateString() + ")");
writeln("(PURPOSE: DEMONSTRATING POST PROCESSOR ENTRY FUNCTION CUSTOMIZATION)");Before:
%
O1002
(T2 D=6. CR=0. - ZMIN=-3.5 - FLAT END MILL)
After:
%
(POST PROCESSOR CUSTOMIZATION PROJECT)
(AUTHOR: AATHITHYAN VENKATESH)
(DATE: TUE JUL 14 2026)
(PURPOSE: DEMONSTRATING POST PROCESSOR ENTRY FUNCTION CUSTOMIZATION)
O1002
(T2 D=6. CR=0. - ZMIN=-3.5 - FLAT END MILL)
b) Cycle-specific diagnostic comment — added inside writeDrillCycle(), in the "drilling" branch of the switch statement, right before the cycle's G-code is written:
case "drilling":
writeComment("CYCLE TYPE: SIMPLE DRILLING (G81) - NO PECK, NO DWELL - THROUGH HOLE");
writeBlock(
gRetractModal.format(98), gCycleModal.format(81),
getCommonCycle(x, y, z, cycle.retract, cycle.clearance),
feedOutput.format(F)
);
break;Result in the output (note: the post processor's comment formatter strips punctuation like : and - to match Fanuc's accepted character set):
(CYCLE TYPE SIMPLE DRILLING G81 - NO PECK, NO DWELL - THROUGH HOLE)
N70 G98 G81 X10. Y-50. Z-12. R5. F1000.
Both changes are traced to a specific, understood function — not blind trial and error.
Separately, I started exploring whether a small Python script could parse the generated G-code and flag basic safety/consistency issues before a program reaches a real machine — things like: does the program leave itself in the correct positioning mode, does the tool number in the header match the tool-change command, is the tool at a safe height before a fast rapid move.
This is still a work in progress — I'm continuing to build my understanding of G-code's modal (state-carrying) behavior, which turned out to be the trickiest part conceptually. Along the way, an early version of the checker produced a false alarm caused by not distinguishing between absolute (G90) and incremental (G91) positioning modes — a good reminder of how much state a post processor (and any tool that reads its output) has to track correctly. Code is included in /nc_validator for anyone curious, but I'd treat it as an early draft rather than a finished tool.
- Customizing a second cycle type (e.g. peck drilling / G83) to compare against the simple drilling case
- Multi-axis considerations and machine configuration (
defineMachine()) - Building out the Python checker further once I've spent more time with real post-processor edge cases
Files in this repo:
1001.nc,1002.nc,1003.nc— posted G-code (facing, pocket, drill)fanuc_onOpen_before_after.js— header customization snippetfanuc_drillcycle_before_after.js— cycle diagnostic snippet/nc_validator— Python G-code checker (in progress)



