Skip to content
CADCAMFUN
Docs

Documentation

CAM machining kernel

From a manufacturing job to NC and evidence: planning, cutters, voxel stock with a remaining-volume bracket, and certified collision checks.

What the CAM kernel is

The CAM kernel in packages/core/src/cam/kernel (20 source files, about 5 260 lines) takes a revisioned manufacturing job to machine NC plus evidence about that NC. It chooses cutters and cutting data, plans operations from the CAD features, runs the strategies, posts G-code, replays the NC independently against volumetric stock, and checks the motion of the tool assembly for collisions. Its algorithm identity is cadcamfun-cam-kernel@1.

ModuleRole
materialsworkpiece grades with their machinability data
cutterstool assemblies and the default library (70 cutters)
cutting-dataspeeds, feeds, depths, load and deflection for a cutter in a material
plannerCAD features → ordered operations with their cutters
executeprepare / run: strategies, post, independent NC replay, stock lineage, claims and release level
kinematics, headtrunnion table (AC / BC) and tilting head (B about Y)
assemblythe 3D tool assembly (cutting zone, shank, holder) as a profile and its solid of revolution
collisioncontinuous check of a joint move: certified clear, collision or unresolved
motionsimultaneous five-axis: locations → table poses, each move split and checked
stockvolumetric stock as voxels with a remaining-volume bracket
machine-clearanceholder and shank against the table over every NC move
convexexact distance between convex hulls (GJK)
Entry points (execute.ts)
export const prepareJob: (job: ManufacturingJob) => CamResult<PreparedJob>
export const executeJob: (prepared: PreparedJob) => CamResult<CamArtifact>
export const runJob: (job: ManufacturingJob) => CamResult<CamArtifact>   // prepare, then execute
export const planOnly: (job: ManufacturingJob) => CamResult<{ operations; notes; unmachined }>
export const KERNEL_ALGORITHM = "cadcamfun-cam-kernel@1"

Feature-based planning

The planner sequences a prismatic part the way a CAM programmer does, from the features the parametric history really has:

  1. face the stock top
  2. rough around the outlines and inside the pockets (adaptive or contour, with a wall allowance)
  3. counterbores, spot drilling, drilling or helical boring, countersinks, thread milling
  4. finish the walls
  5. break the top edges with a 2D chamfer when deburring is asked
  6. 3D roughing and finishing of freeform bodies

A body without a feature history (a mesh, a Boolean of primitives, a sculpted part) is machined with the 3D surface strategies. Planning chooses tools and regions only; cutting data is computed per operation when the job runs. A real run on a 44 × 44 × 11 mm POM-C blank planned three operations: face with facemill-50, surface-rough with flat-16 and surface-finish with ball-10, released as verified-program with a 149 s cycle time. That run is drawn in native manufacturing.

Cutters and the tool assembly

The default library has 70 cutters of nine kinds: flat (Ø1–16, plus aluminium ZrN variants), ball (Ø1–10), bull nose, face mill, spot drill, chamfer mill, engraver, thread mills (P0.5–P2) and drills. A cutter's assembly is its half-section profile from the tip, split into cutting zone, shank and holder.

flat-6 and assemblyProfile(flat-6) — real output
{"id":"flat-6","name":"End mill Ø6 3F carbide ALTIN","kind":"flat","diameter":6,"flutes":3,
 "material":"carbide","coating":"altin","fluteLength":15,"shankDiameter":6,"stickout":29,
 "holder":{"diameter":40,"length":50}}

{"points":[{"r":0,"z":0},{"r":3,"z":0},{"r":3,"z":15},{"r":3,"z":29},{"r":20,"z":29},{"r":20,"z":79},{"r":0,"z":79}],
 "parts":["cutting","cutting","shank","holder","holder","holder"],"length":79,"assumedHolder":false}
flat-6 assembly over its sweep Drag to orbit · scroll to zoom · right-drag to pan
The assembly profile revolved: flutes r 3 from z 0 to 15 (amber), shank to z 29, holder r 20 to z 79. Tip at the start of the slot below, 3 mm into the stock top.

Voxel stock and the remaining-volume bracket

Stock is a voxel grid. After a set of moves each voxel is material, removed sure (its whole cube lay inside the cutter at some sampled position) or removed possible (its cube came within the cutter's expansion: half a diagonal plus half the sample spacing). The remaining volume is therefore a bracket: material not possibly removed is definitely left, material not surely removed may be left. A voxel is never called removed without a sampled cutter covering it. Tilted tools carry their axis per tip point, so five-axis sweeps use the same two tests.

stock.ts
export const voxelStock: (min: Vec3, max: Vec3, voxel: number) => VoxelStock   // sample step = voxel / 2
export const removeTipPath: (stock: VoxelStock, cutter: Cutter, path: ReadonlyArray<Vec3>, axes?: ReadonlyArray<Vec3>) => void
export const remainingVolume: (stock: VoxelStock) => { lower: number; upper: number }
Slot and ring 3 mm deep with flat-6 — real output
const s = voxelStock({ x: 0, y: 0, z: -10 }, { x: 40, y: 30, z: 0 }, 0.5)
// 80 × 60 × 20 = 96 000 voxels, step 0.25
removeTipPath(s, flat6, path)          // slot y = 15, x 8→32, then the ring 8..32 × 8..22, all at z −3
remainingVolume(s)                     // {"lower":9749.5,"upper":10740}   124 ms
// stock 12 000 mm³: between 1 260 and 2 250.5 mm³ removed
Replayed stock (outer bound) Drag to orbit · scroll to zoom · right-drag to pan
Top surface of every voxel column that is not even possibly removed, from the run above: the slot and the ring are cut 3 mm deep (one voxel of slack shows as steps along the walls).

The bracket narrows with the voxel size: halving the voxel halves the slack band along every wall.

Continuous collision checking

A controller moves its joints linearly between two points, and a clash can happen between them. checkMotion checks the whole move: probes (the holder and shank, each non-cutting profile segment enclosed by a capsule) against obstacles (the table envelope and the part box). The lower bound is a Lipschitz argument: a signed distance changes by at most the displacement of the moving solid, so the move is bisected until every interval is proven clear by margin, an overlap is sampled, or the depth (12) runs out.

VerdictMeaning
clearon every interval the lower bound of the clearance is at least margin
collisiona sampled probe point lies inside an obstacle; at says where along the move (0 to 1)
unresolvedan interval could not be proven clear within the depth, and no overlap was found
flat-6 in a linear scene over tableBox(20, 15, −10, 200, 100, 20) — real output
// rapid along X at nose z 60
{"verdict":"clear","clearance":26.875,"evaluations":2}
// plunge from nose z 60 to nose z 0
{"verdict":"collision","clearance":-10,"at":1,"evaluations":2}
// standing poses
z 60 {"verdict":"clear","clearance":46.875,"evaluations":2}
z 20 {"verdict":"clear","clearance":6.875,"evaluations":2}
z 10 {"verdict":"unresolved","clearance":-3.125,"evaluations":4097}
z  5 {"verdict":"collision","clearance":-5,"at":0,"evaluations":1}

The rapid reports 26.875 rather than the standing 46.875 because a moving check certifies a lower bound: it subtracts the displacement over each interval it did not subdivide further. The nose-z-10 pose shows why unresolved exists: the certified lower bound is negative (the envelope might overlap) yet no sampled point is inside, so after 4 097 evaluations the checker reports what it can prove instead of guessing. Envelopes are conservative: a capsule encloses its holder segment, so an overlap can be reported where the real tool would only come close.

Troubleshooting

SymptomCauseFix
job status failed: Unsupported job schema versionjob built for a different kernel schemarebuild the job with the current schemaVersion
remaining-volume bracket widevoxel too coarse for the featuresuse a smaller voxel; the slack is about one voxel along each wall
collision on a rapidholder or shank envelope reaches the table or partraise the clearance plane or shorten the stickout
unresolved on a long rotary movethe Lipschitz bound is weak far from the rotation centresplit the move, or accept the margin the checker could prove
operation planned with an unexpected cuttercutter suitability for the material and rigiditypass a tool library with the cutter you want