mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-19 04:37:51 -06:00
Partially implement acceleration and jerk estimation algorithm
This stuff is complex and I hardly understand it. It's basically just a translation of the C++ code in the engine. Contributes to issue CURA-5561.
This commit is contained in:
parent
5bf90df6be
commit
c559763c88
1 changed files with 69 additions and 3 deletions
|
@ -15,6 +15,21 @@ from typing import Dict, List, Optional, Tuple
|
||||||
DEFAULT_BUFFER_FILLING_RATE_IN_C_PER_MS = 50.0 / 1000.0 # The buffer filling rate in #commands/ms
|
DEFAULT_BUFFER_FILLING_RATE_IN_C_PER_MS = 50.0 / 1000.0 # The buffer filling rate in #commands/ms
|
||||||
DEFAULT_BUFFER_SIZE = 15 # The buffer size in #commands
|
DEFAULT_BUFFER_SIZE = 15 # The buffer size in #commands
|
||||||
|
|
||||||
|
#Values for Ultimaker S5.
|
||||||
|
MACHINE_MAX_FEEDRATE_X = 300
|
||||||
|
MACHINE_MAX_FEEDRATE_Y = 300
|
||||||
|
MACHINE_MAX_FEEDRATE_Z = 40
|
||||||
|
MACHINE_MAX_FEEDRATE_E = 45
|
||||||
|
MACHINE_MAX_ACCELERATION_X = 9000
|
||||||
|
MACHINE_MAX_ACCELERATION_Y = 9000
|
||||||
|
MACHINE_MAX_ACCELERATION_Z = 100
|
||||||
|
MACHINE_MAX_ACCELERATION_E = 10000
|
||||||
|
MACHINE_MAX_JERK_XY = 20
|
||||||
|
MACHINE_MAX_JERK_Z = 0.4
|
||||||
|
MACHINE_MAX_JERK_E = 5
|
||||||
|
MACHINE_MINIMUM_FEEDRATE = 0
|
||||||
|
MACHINE_ACCELERATION = 3000
|
||||||
|
|
||||||
## Gets the code and number from the given g-code line.
|
## Gets the code and number from the given g-code line.
|
||||||
def get_code_and_num(gcode_line: str) -> Tuple[str, str]:
|
def get_code_and_num(gcode_line: str) -> Tuple[str, str]:
|
||||||
gcode_line = gcode_line.strip()
|
gcode_line = gcode_line.strip()
|
||||||
|
@ -73,7 +88,6 @@ def calc_intersection_distance(initial_feedrate: float, final_feedrate: float, a
|
||||||
|
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
|
|
||||||
def __init__(self, previous_state: Optional["State"]) -> None:
|
def __init__(self, previous_state: Optional["State"]) -> None:
|
||||||
self.X = 0.0
|
self.X = 0.0
|
||||||
self.Y = 0.0
|
self.Y = 0.0
|
||||||
|
@ -83,15 +97,19 @@ class State:
|
||||||
self.speed = {"X": 0.0,
|
self.speed = {"X": 0.0,
|
||||||
"Y": 0.0,
|
"Y": 0.0,
|
||||||
"Z": 0.0,
|
"Z": 0.0,
|
||||||
|
"E": 0.0,
|
||||||
}
|
}
|
||||||
self.accelerations = {"XY": 0.0,
|
self.accelerations = {"X": 0.0,
|
||||||
|
"Y": 0.0,
|
||||||
"Z": 0.0,
|
"Z": 0.0,
|
||||||
|
"E": 0.0,
|
||||||
"S": 0.0, # printing
|
"S": 0.0, # printing
|
||||||
"T": 0.0, # travel
|
"T": 0.0, # travel
|
||||||
}
|
}
|
||||||
self.jerks = {"X": 0.0,
|
self.jerks = {"X": 0.0,
|
||||||
"Y": 0.0,
|
"Y": 0.0,
|
||||||
"Z": 0.0,
|
"Z": 0.0,
|
||||||
|
"E": 0.0,
|
||||||
}
|
}
|
||||||
self.in_relative_positioning_mode = False # type: bool
|
self.in_relative_positioning_mode = False # type: bool
|
||||||
self.in_relative_extrusion_mode = False # type: bool
|
self.in_relative_extrusion_mode = False # type: bool
|
||||||
|
@ -110,7 +128,6 @@ class State:
|
||||||
|
|
||||||
|
|
||||||
class Command:
|
class Command:
|
||||||
|
|
||||||
def __init__(self, cmd_str: str, previous_state: "State") -> None:
|
def __init__(self, cmd_str: str, previous_state: "State") -> None:
|
||||||
self._cmd_str = cmd_str # type: str
|
self._cmd_str = cmd_str # type: str
|
||||||
self._previous_state = previous_state # type: State
|
self._previous_state = previous_state # type: State
|
||||||
|
@ -231,6 +248,7 @@ class Command:
|
||||||
current_position = {"X": self._previous_state.X,
|
current_position = {"X": self._previous_state.X,
|
||||||
"Y": self._previous_state.Y,
|
"Y": self._previous_state.Y,
|
||||||
"Z": self._previous_state.Z,
|
"Z": self._previous_state.Z,
|
||||||
|
"E": self._previous_state.E,
|
||||||
}
|
}
|
||||||
new_position = copy.deepcopy(current_position)
|
new_position = copy.deepcopy(current_position)
|
||||||
for key in new_position:
|
for key in new_position:
|
||||||
|
@ -239,6 +257,54 @@ class Command:
|
||||||
|
|
||||||
distance = calc_distance(current_position, new_position)
|
distance = calc_distance(current_position, new_position)
|
||||||
self._distance_in_mm = distance
|
self._distance_in_mm = distance
|
||||||
|
self._delta = [
|
||||||
|
new_position["X"] - current_position["X"],
|
||||||
|
new_position["Y"] - current_position["Y"],
|
||||||
|
new_position["Z"] - current_position["Z"],
|
||||||
|
new_position["E"] - current_position["E"]
|
||||||
|
]
|
||||||
|
self._abs_delta = [abs(x) for x in self._delta]
|
||||||
|
self._max_travel = max(self._abs_delta)
|
||||||
|
if self._max_travel > 0:
|
||||||
|
feedrate = self._previous_state.F
|
||||||
|
if "F" in value_dict:
|
||||||
|
feedrate = value_dict["F"]
|
||||||
|
if feedrate < MACHINE_MINIMUM_FEEDRATE:
|
||||||
|
feedrate = MACHINE_MINIMUM_FEEDRATE
|
||||||
|
self._nominal_feedrate = feedrate
|
||||||
|
self._distance = math.sqrt(self._abs_delta[0] ** 2 + self._abs_delta[1] ** 2 + self._abs_delta[2] ** 2)
|
||||||
|
if self._distance == 0:
|
||||||
|
self._distance = self._abs_delta[3]
|
||||||
|
|
||||||
|
current_feedrate = [d * feedrate / self._distance for d in self._delta]
|
||||||
|
current_abs_feedrate = [abs(f) for f in current_feedrate]
|
||||||
|
feedrate_factor = min(1.0, MACHINE_MAX_FEEDRATE_X)
|
||||||
|
feedrate_factor = min(feedrate_factor, MACHINE_MAX_FEEDRATE_Y)
|
||||||
|
feedrate_factor = min(feedrate_factor, MACHINE_MAX_FEEDRATE_Z)
|
||||||
|
feedrate_factor = min(feedrate_factor, MACHINE_MAX_FEEDRATE_E)
|
||||||
|
#TODO: XY_FREQUENCY_LIMIT
|
||||||
|
|
||||||
|
current_feedrate = [f * feedrate_factor for f in current_feedrate]
|
||||||
|
current_abs_feedrate = [f * feedrate_factor for f in current_abs_feedrate]
|
||||||
|
self._nominal_feedrate *= feedrate_factor
|
||||||
|
|
||||||
|
self._acceleration = MACHINE_ACCELERATION
|
||||||
|
max_accelerations = [MACHINE_MAX_ACCELERATION_X, MACHINE_MAX_ACCELERATION_Y, MACHINE_MAX_ACCELERATION_Z, MACHINE_MAX_ACCELERATION_E]
|
||||||
|
for n in range(len(max_accelerations)):
|
||||||
|
if self._acceleration * self._abs_delta[n] / self._distance > max_accelerations[n]:
|
||||||
|
self._acceleration = max_accelerations[n]
|
||||||
|
|
||||||
|
vmax_junction = MACHINE_MAX_JERK_XY / 2
|
||||||
|
vmax_junction_factor = 1.0
|
||||||
|
if current_abs_feedrate[2] > MACHINE_MAX_JERK_Z / 2:
|
||||||
|
vmax_junction = min(vmax_junction, MACHINE_MAX_JERK_Z)
|
||||||
|
if current_abs_feedrate[3] > MACHINE_MAX_JERK_E / 2:
|
||||||
|
vmax_junction = min(vmax_junction, MACHINE_MAX_JERK_E)
|
||||||
|
vmax_junction = min(vmax_junction, self._nominal_feedrate)
|
||||||
|
safe_speed = vmax_junction
|
||||||
|
|
||||||
|
#TODO: Compute junction maximum speed factor and apply this to entry speed, set flags and calculate trapezoid.
|
||||||
|
|
||||||
travel_time_in_ms = distance / (self._after_state.F / 60.0) * 1000.0
|
travel_time_in_ms = distance / (self._after_state.F / 60.0) * 1000.0
|
||||||
|
|
||||||
estimated_exec_time_in_ms = travel_time_in_ms
|
estimated_exec_time_in_ms = travel_time_in_ms
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue