CAM: Fixed F parameter handling for only rotary axes

with tests
      and the commit for converting the refactored*
      postprocessors to the new API
This commit is contained in:
Lawrence Woestman
2025-02-10 10:35:25 -08:00
committed by Chris Hennes
parent 68e934ba18
commit b9c4bee4e3
2 changed files with 489 additions and 4 deletions

View File

@@ -28,6 +28,7 @@
# * *
# ***************************************************************************
import math
import re
from typing import Any, Callable, Dict, List, Tuple, Union
@@ -208,13 +209,19 @@ def default_axis_parameter(
command: str, # pylint: disable=unused-argument
param: str,
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters,
) -> str:
"""Process an axis parameter."""
#
# used to compare two floating point numbers for "close-enough equality"
#
epsilon: float = 0.00001
if (
not values["OUTPUT_DOUBLES"]
and param in current_location
and current_location[param] == param_value
and math.fabs(current_location[param] - param_value) < epsilon
):
return ""
return format_for_axis(values, Units.Quantity(param_value, Units.Length))
@@ -225,6 +232,7 @@ def default_D_parameter(
command: str,
param: str, # pylint: disable=unused-argument
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters, # pylint: disable=unused-argument
) -> str:
"""Process the D parameter."""
@@ -243,13 +251,20 @@ def default_F_parameter(
command: str,
param: str,
param_value: PathParameter,
parameters: PathParameters,
current_location: PathParameters,
) -> str:
"""Process the F parameter."""
#
# used to compare two floating point numbers for "close-enough equality"
#
epsilon: float = 0.00001
found: bool
if (
not values["OUTPUT_DOUBLES"]
and param in current_location
and current_location[param] == param_value
and math.fabs(current_location[param] - param_value) < epsilon
):
return ""
# Many posts don't use rapid speeds, but eventually
@@ -261,6 +276,26 @@ def default_F_parameter(
feed = Units.Quantity(param_value, Units.Velocity)
if feed.getValueAs(values["UNIT_SPEED_FORMAT"]) <= 0.0:
return ""
# if any of X, Y, Z, U, V, or W are in the parameters
# and any of their values is different than where the device currently should be
# then feed is in linear units
found = False
for key in ("X", "Y", "Z", "U", "V", "W"):
if key in parameters and math.fabs(current_location[key] - parameters[key]) > epsilon:
found = True
if found:
return format_for_feed(values, feed)
# else if any of A, B, or C are in the paramters, the feed is in degrees,
# which should not be converted when in --inches mode
found = False
for key in ("A", "B", "C"):
if key in parameters:
found = True
if found:
# converting from degrees per second to degrees per minute as well
return format(float(feed * 60.0), f'.{str(values["FEED_PRECISION"])}f')
# which leaves none of X, Y, Z, U, V, W, A, B, C,
# which should not be valid but return a converted value just in case
return format_for_feed(values, feed)
@@ -269,6 +304,7 @@ def default_int_parameter(
command: str, # pylint: disable=unused-argument
param: str, # pylint: disable=unused-argument
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters, # pylint: disable=unused-argument
) -> str:
"""Process a parameter that is treated like an integer."""
@@ -280,6 +316,7 @@ def default_length_parameter(
command: str, # pylint: disable=unused-argument
param: str, # pylint: disable=unused-argument
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters, # pylint: disable=unused-argument
) -> str:
"""Process a parameter that is treated like a length."""
@@ -291,6 +328,7 @@ def default_P_parameter(
command: str,
param: str, # pylint: disable=unused-argument
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters, # pylint: disable=unused-argument
) -> str:
"""Process the P parameter."""
@@ -309,6 +347,7 @@ def default_Q_parameter(
command: str,
param: str, # pylint: disable=unused-argument
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters, # pylint: disable=unused-argument
) -> str:
"""Process the Q parameter."""
@@ -324,13 +363,19 @@ def default_rotary_parameter(
command: str, # pylint: disable=unused-argument
param: str,
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters,
) -> str:
"""Process a rotarty parameter (such as A, B, and C)."""
#
# used to compare two floating point numbers for "close-enough equality"
#
epsilon: float = 0.00001
if (
not values["OUTPUT_DOUBLES"]
and param in current_location
and current_location[param] == param_value
and math.fabs(current_location[param] - param_value) < epsilon
):
return ""
# unlike other axis, rotary axis such as A, B, and C are always in degrees
@@ -343,6 +388,7 @@ def default_S_parameter(
command: str, # pylint: disable=unused-argument
param: str, # pylint: disable=unused-argument
param_value: PathParameter,
parameters: PathParameters, # pylint: disable=unused-argument
current_location: PathParameters, # pylint: disable=unused-argument
) -> str:
"""Process the S parameter."""
@@ -662,7 +708,25 @@ def parse_a_path(values: Values, gcode: Gcode, pathobj) -> None:
swap_tool_change_order = False
if "TOOL_BEFORE_CHANGE" in values and values["TOOL_BEFORE_CHANGE"]:
swap_tool_change_order = True
current_location.update(Path.Command("G0", {"X": -1, "Y": -1, "Z": -1, "F": 0.0}).Parameters)
current_location.update(
# the goal is to have initial values that aren't likely to match
# any "real" first parameter values
Path.Command(
"G0",
{
"X": 123456789.0,
"Y": 123456789.0,
"Z": 123456789.0,
"U": 123456789.0,
"V": 123456789.0,
"W": 123456789.0,
"A": 123456789.0,
"B": 123456789.0,
"C": 123456789.0,
"F": 123456789.0,
},
).Parameters
)
adaptive_op_variables = determine_adaptive_op(values, pathobj)
for c in pathobj.Path.Commands:
@@ -692,6 +756,7 @@ def parse_a_path(values: Values, gcode: Gcode, pathobj) -> None:
command,
parameter,
c.Parameters[parameter],
c.Parameters,
current_location,
)
if parameter_value: