Add rigid tapping support to linuxcnc_post.py and annotate tapping commands in Tapping.py

- Added --rigid-tap argument to linuxcnc_post.py to enable G33.1 rigid tapping cycle output.
- Implemented logic to skip G80, G98, G99 commands with tapping annotation when rigid tapping is enabled.
- Enhanced handling of G84/G74 tapping cycles for rigid tapping, including pitch (K), depth (Z), dwell (G04 P), spindle reversal (M3/M4/M5), and reverse-out moves.
- Updated Tapping.py to annotate G98/G99 and G80 commands with {"operation": "tapping"} for improved post processor handling.
This commit is contained in:
Billy Huddleston
2025-10-15 14:09:18 -04:00
parent 736ffd0140
commit bbfd84d7b1
2 changed files with 89 additions and 11 deletions

View File

@@ -174,7 +174,9 @@ class ObjectTapping(PathCircularHoleBase.ObjectOp):
endoffset = PathUtils.drillTipLength(self.tool) * 2
# http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g98-g99
self.commandlist.append(Path.Command(obj.ReturnLevel))
self.commandlist.append(
Path.Command(obj.ReturnLevel).addAnnotations({"operation": "tapping"})
)
# This section is technical debt. The computation of the
# target shapes should be factored out for reuse.
@@ -265,7 +267,7 @@ class ObjectTapping(PathCircularHoleBase.ObjectOp):
machine.addCommand(command)
# Cancel canned tapping cycle
self.commandlist.append(Path.Command("G80"))
self.commandlist.append(Path.Command("G80").addAnnotations({"operation": "tapping"}))
# command = Path.Command("G0", {"Z": obj.SafeHeight.Value}) DLH- Not needed, adds unnecessary move to Z SafeHeight.
# self.commandlist.append(command)
# machine.addCommand(command) DLH - Not needed.

View File

@@ -79,6 +79,7 @@ parser.add_argument(
action="store_true",
help="suppress tool length offset (G43) following tool changes",
)
parser.add_argument("--rigid-tap", action="store_true", help="Enable G33.1 rigid tapping cycle")
TOOLTIP_ARGS = parser.format_help()
@@ -103,6 +104,8 @@ CORNER_MIN = {"x": 0, "y": 0, "z": 0}
CORNER_MAX = {"x": 500, "y": 300, "z": 300}
PRECISION = 3
RIGID_TAP = False
# Preamble text will appear at the beginning of the GCODE output file.
PREAMBLE = """G17 G54 G40 G49 G80 G90
"""
@@ -137,6 +140,7 @@ def processArguments(argstring):
global MODAL
global USE_TLO
global OUTPUT_DOUBLES
global RIGID_TAP
try:
args = parser.parse_args(shlex.split(argstring))
@@ -166,6 +170,8 @@ def processArguments(argstring):
if args.axis_modal:
print("here")
OUTPUT_DOUBLES = False
if args.rigid_tap:
RIGID_TAP = True
except Exception:
return False
@@ -349,6 +355,15 @@ def parse(pathobj):
if c.Name.startswith("(") and not OUTPUT_COMMENTS: # command is a comment
continue
# Check for G80, G98, G99 with rigid tapping and annotation
if (
command in ("G80", "G98", "G99")
and RIGID_TAP
and hasattr(c, "Annotations")
and c.Annotations.get("operation") == "tapping"
):
continue # Skip this command
# Handle G84/G74 tapping cycles
if command in ("G84", "G74") and "F" in c.Parameters:
pitch_mm = float(c.Parameters["F"])
@@ -366,16 +381,77 @@ def parse(pathobj):
else:
pitch = pitch_mm
# Calculate feed rate
if spindle_speed is not None:
feed_rate = pitch * spindle_speed
speed = Units.Quantity(feed_rate, UNIT_SPEED_FORMAT)
outstring.append(
"F" + format(float(speed.getValueAs(UNIT_SPEED_FORMAT)), precision_string)
)
# Rigid tapping logic
if RIGID_TAP:
# Output initial tapping command
outstring[0] = "G33.1"
outstring.append("K" + format(pitch, precision_string))
if "Z" in c.Parameters:
outstring.append("Z" + format(float(c.Parameters["Z"]), precision_string))
# Output the tapping line
if len(outstring) >= 1:
if OUTPUT_LINE_NUMBERS:
outstring.insert(0, (linenumber()))
for w in outstring:
out += w + COMMAND_SPACE
out += "\n"
if "P" in c.Parameters:
# Issue spindle stop
out += linenumber() + "M5\n"
# Issue dwell with P value
out += linenumber() + f"G04 P{c.Parameters['P']}\n"
# Now handle reverse out and spindle restore
if command == "G84":
# Reverse spindle (M4) with spindle speed
out += linenumber() + "M4\n"
# Repeat tapping command to reverse out, use R for Z
reverse_z = c.Parameters.get("R")
if reverse_z is not None:
pos = Units.Quantity(reverse_z, FreeCAD.Units.Length)
reverse_z = float(pos.getValueAs(UNIT_FORMAT))
out += (
linenumber()
+ f"G33.1 K{format(pitch, precision_string)} Z{format(float(reverse_z), precision_string)}\n"
)
else:
out += linenumber() + f"G33.1 K{format(pitch, precision_string)}\n"
# Restore original spindle direction (M3) with spindle speed
out += linenumber() + "M3\n"
elif command == "G74":
# Forward spindle (M3) with spindle speed
out += linenumber() + "M3\n"
# Repeat tapping command to reverse out, use R for Z
reverse_z = c.Parameters.get("R")
if reverse_z is not None:
pos = Units.Quantity(reverse_z, FreeCAD.Units.Length)
reverse_z = float(pos.getValueAs(UNIT_FORMAT))
out += (
linenumber()
+ f"G33.1 K{format(pitch, precision_string)} Z{format(float(reverse_z), precision_string)}\n"
)
else:
out += linenumber() + f"G33.1 K{format(pitch, precision_string)}\n"
# Restore original spindle direction (M4) with spindle speed
out += linenumber() + "M4\n"
continue # Skip the rest of the parameter output for this command
else:
# No spindle speed found, output pitch as F
outstring.append("F" + format(pitch, precision_string))
# Calculate feed rate
if spindle_speed is not None:
feed_rate = pitch * spindle_speed
speed = Units.Quantity(feed_rate, UNIT_SPEED_FORMAT)
outstring.append(
"F"
+ format(float(speed.getValueAs(UNIT_SPEED_FORMAT)), precision_string)
)
else:
# No spindle speed found, output pitch as F
outstring.append("F" + format(pitch, precision_string))
# Now add the remaining parameters in order
for param in params: