Skip to content

feat: drag knife and tangential knife cutting support - #397

Open
knipknap wants to merge 4 commits into
mainfrom
feat/359-knife-support
Open

knipknap wants to merge 4 commits into
mainfrom
feat/359-knife-support

Conversation

@knipknap

Copy link
Copy Markdown
Contributor

Summary

Implements knife-cutting support requested in #359 as a new builtin
addon (rayforge-addon-dragknife) plus the core head/capability
groundwork it needs.

Depends on raygeo PR barebaric/raygeo#28 (DragKnifeSpec /
TangentialKnifeSpec transformers). CI for the pipeline tests needs
the raygeo pin bumped after that merges.

Core (part C)

  • MachineCapability: new DRAG_KNIFE and TANGENTIAL_KNIFE
    values with labels/descriptions. Step offering is gated through
    the existing REQUIRED_MACHINE_CAPS subset check, so the new
    steps only appear on machines with a matching head.
  • machine/models/knife.py: DragKnifeHead (reviewable blade
    offset setting) and TangentialKnifeHead, dispatched in
    head_from_dict and editable in the machine settings heads page
    (new add-head popover entries + detail widget).
  • The Rust encoder heads table now includes non-laser heads so
    knife head UIDs resolve (e.g. for tool changes); non-laser heads
    never scale laser power.

Addon (part B)

  • Drag Knife Cut step — cuts contours on the centerline via the
    contour assembler and internally attaches a
    DragKnifeTransformer (raygeo DragKnifeSpec): blade-offset
    compensation, arc-in to align the blade, swivel arcs within the
    swivel tolerance, lift–pivot–plunge at sharper corners, arc-out.
  • Tangential Knife Cut step — rotary knife whose A axis follows
    the path heading (TangentialKnifeSpec): heading changes beyond
    the angle tolerance or arcs tighter than the radius tolerance
    lift to a safe Z; stamps an M3-only spindle command for the blade
    motor (no M4).
  • Both steps: capability-gated, recipe varsets (knife head picker,
    blade offset, tolerances, safe Z, speeds), serialization
    round-trips, setters keep the internal transformer dicts in sync
    (the transformer is an implementation detail — users configure
    the knife through the step).
  • Settings pages registered per assembler name, symbolic icons,
    locale template.

Test plan

  • 25 new addon tests: transformer spec mapping/dict
    round-trips/clamping, step setters + signals, transformer dict
    sync, serialization round-trips, create() head resolution,
    create_initial_ops spindle command, frontend page registry
  • tests/machine/models, tests/core, tests/addon_mgr,
    tests/pipeline, tests/doceditor all green
  • cnc/post addon test suites still green
  • ruff + pyright clean for all new/changed files
  • Addon validates through Addon.load_from_directory

Follow-ups (not in this PR): device-profile wizard integration for
knife heads, example device profiles for cutter conversions.

Implements #359 as a new builtin addon plus the
core head/capability groundwork it needs.

Core:
- MachineCapability: new DRAG_KNIFE and TANGENTIAL_KNIFE values with
  labels and descriptions.
- machine/models/knife.py: DragKnifeHead (blade offset setting) and
  TangentialKnifeHead; both dispatch correctly in head_from_dict and
  are editable in the machine settings heads page.
- The encoder heads table now includes non-laser heads so knife head
  UIDs resolve for tool changes.

Addon (rayforge-addon-dragknife):
- DragKnifeCutStep: cuts contours with a trailing-blade drag knife.
  Internally attaches a DragKnifeTransformer (backed by raygeo's
  DragKnifeSpec) that compensates the blade offset, swivels around
  corners within the swivel tolerance, lifts at sharper corners,
  and emits arc-in/arc-out blade alignment moves.
- TangentialKnifeCutStep: cuts with a rotary knife whose A axis
  follows the path heading (TangentialKnifeSpec). Heading changes
  beyond the angle tolerance, or arcs tighter than the radius
  tolerance, lift the knife to a safe Z. Stamps an M3-only spindle
  command for the blade motor.
- Both steps cut on the centerline via the contour assembler, are
  gated to machines whose heads provide the matching capability,
  expose their settings through recipe varsets (head picker, blade
  offset, swivel/angle tolerances, safe Z, speeds), and keep the
  internal transformer dicts in sync via setters.
- Settings pages registered per assembler name; symbolic icons and
  a locale template included.
- Tests: transformers, step setters/serialization/sync, create()
  head resolution, and frontend page registration.
CI installs the raygeo pin from PyPI, which predates the knife
transform specs (barebaric/raygeo#28). The addon now gates its
registration on a raygeo availability check: without the specs it
logs a warning and registers nothing instead of failing to import,
the transformers import their specs lazily, and the addon test
suite is ignored via collect_ignore_glob so test collection no
longer errors. Once the raygeo pin includes the knife transforms,
everything activates automatically.
The CI lint job also runs flake8 (79 char limit). Replace the
compat module's static imports with importlib.import_module so no
pyright ignore comments are needed, and shorten the lazy-import
ignore comments to fit within the line limit.
@knipknap
knipknap marked this pull request as draft September 10, 2026 20:18
Comment thread rayforge/builtin_addons/rayforge-addon-dragknife/dragknife/compat.py Outdated
Comment thread rayforge/machine/models/knife.py Outdated
Comment thread rayforge/pipeline/encoder/rust_helpers.py Outdated
Comment thread rayforge/ui_gtk/machine/head_preferences_page.py Outdated
- Drop the raygeo availability gate: the dragknife steps and
  transformers register unconditionally again, importing the knife
  specs directly (raygeo 1.51.0 provides them).
- Pin raygeo to 1.51.0 in pixi.toml, requirements.txt, and the
  Debian bundle requirements; refresh pixi.lock.
- Make HEAD_SERIALIZED_KEYS public so the knife head module does
  not import private names.
- Replace the getattr fallbacks with explicit isinstance branches
  in the encoder heads table, the knife head detail widget, and
  the drag knife step's head defaults hook.
- Move the addon maturity marker to the top of the manifest.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant