freecad-cam/Mod/CAM/docs/post.md
2026-02-01 19:47:58 +01:00

4.8 KiB

FreeCAD CAM Post Processors

How it Works

FreeCAD CAM uses Python scripts to generate G-code. When you post-process a job, FreeCAD:

  1. Locates the selected post-processor script (e.g., heidenhain_1_post.py).
  2. Passes the list of Operations (the path objects) to the script's export function.
  3. The script iterates through the operations, reads the underlying commands (G1, G2, etc.), and formats them into the specific string dialect required by the machine.

The Files

Post processors are standard Python (.py) files located in Mod/CAM/Path/Post/scripts/ (or your user macro directory).

Key Functions

A post-processor must implement at least:

def export(objectslist, filename, argstring):
    # objectslist: List of Path objects involved in the job
    # filename: output file path (or "-" for memory)
    # argstring: arguments passed from the job properties
    
    # Logic to iterate objects and generate G-code string
    # ...
    return gcode_string

Porting from Fusion 360

You cannot directly use Fusion 360 post processors (.cps files) in FreeCAD.

The Difference

  • Fusion 360 / Autodesk HSM: Uses CPS files, which are JavaScript based. They rely on an event-driven system (e.g., onOpen(), onLinear(), onRapid(), onCycle()). The engine calls these functions as it processes the toolpath.
  • FreeCAD: Uses Python. It gives you the entire list of path commands upfront. You iterate through them and decide how to translate each command.

Porting Strategy: The "Manual Transpiler" Approach

To "port" a Fusion 360 post to FreeCAD, you are essentially re-writing the logic from JavaScript to Python, but more importantly, you are adapting to a different data flow.

1. Data Flow Difference: Event-Driven vs. Object Iteration

  • Fusion 360 (Event-Driven): The CAM engine "drives" the post. It calls onLinear(x, y, z) or onRapid(x, y, z) for every single move. You just write the handler.
  • FreeCAD (Object Iteration): You receive a list of Feature Objects (e.g., [OpDrill, OpPocket, OpContour]). You must:
    1. Iterate through this list.
    2. Extract the Path object from each operation.
    3. Iterate through the Commands inside that path.
    4. Switch on the command name (G0, G1, G2, G38.2).

2. The "Flattening" Problem (Tool Changes)

In Fusion, tool changes happens via onSection triggers. In FreeCAD, the input list might just contain operations. You need to explicitly detect when the tool changes between operations and insert your own "Tool Change" logic.

Best Practice: Implement a buildPostList(objects) function (local to your script) that flattens the hierarchy:

  • Input: [OpA (Tool 1), OpB (Tool 1), OpC (Tool 2)]
  • Output: [ToolController(1), OpA, OpB, ToolController(2), OpC]

Note: Do not try to import buildPostList from Path.Post.Utils as it is internal APIs. Implement it locally.

3. Logic Mapping Table

Logic Fusion 360 (.cps) FreeCAD (.py)
Header onOpen() Function called at start of export. Manually checks valid Stock object.
Tool Change onSection() (new tool detected) Logic inside your main loop needed to compare obj.ToolController vs current_tool.
Rapid Move onRapid(_x, _y, _z) if cmd.Name == "G0": ...
Linear Move onLinear(_x, _y, _z) if cmd.Name == "G1": ...
Arcs onCircular(...) if cmd.Name in ["G2", "G3"]: ...
Probing onCyclePoint(...) (probe) if cmd.Name == "G38.2": ... (FreeCAD uses G38.2 internally for probing)
Footer onClose() Function called after loop.

4. Probing Example

FreeCAD usually represents probing moves as G38.2 (Probe toward workpiece). A ported post-processor must intercept this G-code and generate the machine-specific cycle.

Example (Heidenhain):

  • FreeCAD: G38.2 Z-10 F100
  • Output:
    TCH PROBE 427 MEASURE COORDINATE
     Q263=+0.000 ...
     ...
    

Debugging & Validation

Validate Syntax

Since post-processors are loaded dynamically, syntax errors might cause silent failures or generic "Failed to load" errors. Use the bundled Python executable to validate your script syntax:

"C:\Program Files\FreeCAD 1.0\bin\python.exe" -m py_compile your_post.py

Common Gotchas

  • Imports: Do not assume standard FreeCAD internal modules (like Path.Post.Utils) expose all their helper functions. Check the source or implement helpers locally.
  • Output Policy: The export function can return a string. If the filename argument is "-", return the string directly (used for displaying in the editor window). If it's a path, write to the file.