Remove state class usage

This is an effort to synchronize the working of this script with how CuraEngine's time estimation works. This includes tracking only one value for acceleration and multiple Jerk stuff, that sort of thing. We need to ensure it's exactly the same.

Contributes to issue CURA-5561.
This commit is contained in:
Ghostkeeper 2018-09-04 16:19:01 +02:00
parent c559763c88
commit 5d292e1a79
No known key found for this signature in database
GPG key ID: 5252B696FB5E7C7A

View file

@ -15,7 +15,7 @@ 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. #Setting values for Ultimaker S5.
MACHINE_MAX_FEEDRATE_X = 300 MACHINE_MAX_FEEDRATE_X = 300
MACHINE_MAX_FEEDRATE_Y = 300 MACHINE_MAX_FEEDRATE_Y = 300
MACHINE_MAX_FEEDRATE_Z = 40 MACHINE_MAX_FEEDRATE_Z = 40
@ -86,52 +86,9 @@ def calc_intersection_distance(initial_feedrate: float, final_feedrate: float, a
return 0 return 0
return (2 * acceleration * distance - initial_feedrate * initial_feedrate + final_feedrate * final_feedrate) / (4 * acceleration) return (2 * acceleration * distance - initial_feedrate * initial_feedrate + final_feedrate * final_feedrate) / (4 * acceleration)
class State:
def __init__(self, previous_state: Optional["State"]) -> None:
self.X = 0.0
self.Y = 0.0
self.Z = 0.0
self.E = 0.0
self.F = 0.0
self.speed = {"X": 0.0,
"Y": 0.0,
"Z": 0.0,
"E": 0.0,
}
self.accelerations = {"X": 0.0,
"Y": 0.0,
"Z": 0.0,
"E": 0.0,
"S": 0.0, # printing
"T": 0.0, # travel
}
self.jerks = {"X": 0.0,
"Y": 0.0,
"Z": 0.0,
"E": 0.0,
}
self.in_relative_positioning_mode = False # type: bool
self.in_relative_extrusion_mode = False # type: bool
if previous_state is not None:
self.X = previous_state.X
self.Y = previous_state.Y
self.Z = previous_state.Z
self.E = previous_state.E
self.F = previous_state.F
self.speed = copy.deepcopy(previous_state.speed)
self.accelerations = copy.deepcopy(previous_state.accelerations)
self.jerks = copy.deepcopy(previous_state.jerks)
self.in_relative_positioning_mode = previous_state.in_relative_positioning_mode
self.in_relative_extrusion_mode = previous_state.in_relative_extrusion_mode
class Command: class Command:
def __init__(self, cmd_str: str, previous_state: "State") -> None: def __init__(self, cmd_str: str) -> None:
self._cmd_str = cmd_str # type: str self._cmd_str = cmd_str # type: str
self._previous_state = previous_state # type: State
self._after_state = State(previous_state) # type: State
self._distance_in_mm = 0.0 # type float self._distance_in_mm = 0.0 # type float
self._estimated_exec_time_in_ms = 0.0 # type: float self._estimated_exec_time_in_ms = 0.0 # type: float
@ -188,9 +145,6 @@ class Command:
self._initial_feedrate = initial_feedrate self._initial_feedrate = initial_feedrate
self._final_feedrate = final_feedrate self._final_feedrate = final_feedrate
def get_after_state(self) -> State:
return self._after_state
@property @property
def is_command(self) -> bool: def is_command(self) -> bool:
return not self._is_comment and not self._is_empty return not self._is_comment and not self._is_empty
@ -205,7 +159,7 @@ class Command:
distance_in_mm = round(self._distance_in_mm, 5) distance_in_mm = round(self._distance_in_mm, 5)
info = "d=%s f=%s t=%s" % (distance_in_mm, self._after_state.F, self._estimated_exec_time_in_ms) info = "d=%s t=%s" % (distance_in_mm, self._estimated_exec_time_in_ms)
return self._cmd_str.strip() + " ; --- " + info + os.linesep return self._cmd_str.strip() + " ; --- " + info + os.linesep
@ -242,31 +196,25 @@ class Command:
distance = 0.0 distance = 0.0
if len(parts) > 0: if len(parts) > 0:
value_dict = get_value_dict(parts[1:]) value_dict = get_value_dict(parts[1:])
for key, value in value_dict.items():
setattr(self._after_state, key, float(value))
current_position = {"X": self._previous_state.X, new_position = copy.deepcopy(buf.current_position)
"Y": self._previous_state.Y, new_position[0] = value_dict.get("X", new_position[0])
"Z": self._previous_state.Z, new_position[1] = value_dict.get("Y", new_position[1])
"E": self._previous_state.E, new_position[2] = value_dict.get("Z", new_position[2])
} new_position[3] = value_dict.get("E", new_position[3])
new_position = copy.deepcopy(current_position)
for key in new_position:
new_value = float(value_dict.get(key, new_position[key]))
new_position[key] = new_value
distance = calc_distance(current_position, new_position) distance = calc_distance(buf.current_position, new_position)
self._distance_in_mm = distance self._distance_in_mm = distance
self._delta = [ self._delta = [
new_position["X"] - current_position["X"], new_position[0] - buf.current_position[0],
new_position["Y"] - current_position["Y"], new_position[1] - buf.current_position[1],
new_position["Z"] - current_position["Z"], new_position[2] - buf.current_position[2],
new_position["E"] - current_position["E"] new_position[3] - buf.current_position[3]
] ]
self._abs_delta = [abs(x) for x in self._delta] self._abs_delta = [abs(x) for x in self._delta]
self._max_travel = max(self._abs_delta) self._max_travel = max(self._abs_delta)
if self._max_travel > 0: if self._max_travel > 0:
feedrate = self._previous_state.F feedrate = buf.current_feedrate
if "F" in value_dict: if "F" in value_dict:
feedrate = value_dict["F"] feedrate = value_dict["F"]
if feedrate < MACHINE_MINIMUM_FEEDRATE: if feedrate < MACHINE_MINIMUM_FEEDRATE:
@ -296,16 +244,16 @@ class Command:
vmax_junction = MACHINE_MAX_JERK_XY / 2 vmax_junction = MACHINE_MAX_JERK_XY / 2
vmax_junction_factor = 1.0 vmax_junction_factor = 1.0
if current_abs_feedrate[2] > MACHINE_MAX_JERK_Z / 2: if current_abs_feedrate[2] > buf.max_z_jerk / 2:
vmax_junction = min(vmax_junction, MACHINE_MAX_JERK_Z) vmax_junction = min(vmax_junction, buf.max_z_jerk)
if current_abs_feedrate[3] > MACHINE_MAX_JERK_E / 2: if current_abs_feedrate[3] > buf.max_e_jerk / 2:
vmax_junction = min(vmax_junction, MACHINE_MAX_JERK_E) vmax_junction = min(vmax_junction, buf.max_e_jerk)
vmax_junction = min(vmax_junction, self._nominal_feedrate) vmax_junction = min(vmax_junction, self._nominal_feedrate)
safe_speed = vmax_junction safe_speed = vmax_junction
#TODO: Compute junction maximum speed factor and apply this to entry speed, set flags and calculate trapezoid. #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._nominal_feedrate / 60.0) * 1000.0
estimated_exec_time_in_ms = travel_time_in_ms estimated_exec_time_in_ms = travel_time_in_ms
@ -336,20 +284,15 @@ class Command:
# G90: Set to absolute positioning. Assume 0 seconds. # G90: Set to absolute positioning. Assume 0 seconds.
if cmd_num == 90: if cmd_num == 90:
self._after_state.in_relative_positioning_mode = False
estimated_exec_time_in_ms = 0.0 estimated_exec_time_in_ms = 0.0
# G91: Set to relative positioning. Assume 0 seconds. # G91: Set to relative positioning. Assume 0 seconds.
if cmd_num == 91: if cmd_num == 91:
self._after_state.in_relative_positioning_mode = True
estimated_exec_time_in_ms = 0.0 estimated_exec_time_in_ms = 0.0
# G92: Set position. Assume 0 seconds. # G92: Set position. Assume 0 seconds.
if cmd_num == 92: if cmd_num == 92:
# TODO: check estimated_exec_time_in_ms = 0.0
value_dict = get_value_dict(parts[1:])
for key, value in value_dict.items():
setattr(self._previous_state, key, value)
# G280: Prime. Assume 10 seconds for using blob and 5 seconds for no blob. # G280: Prime. Assume 10 seconds for using blob and 5 seconds for no blob.
if cmd_num == 280: if cmd_num == 280:
@ -368,12 +311,10 @@ class Command:
# M82: Set extruder to absolute mode. Assume 0 execution time. # M82: Set extruder to absolute mode. Assume 0 execution time.
if cmd_num == 82: if cmd_num == 82:
self._after_state.in_relative_extrusion_mode = False
estimated_exec_time_in_ms = 0.0 estimated_exec_time_in_ms = 0.0
# M83: Set extruder to relative mode. Assume 0 execution time. # M83: Set extruder to relative mode. Assume 0 execution time.
if cmd_num == 83: if cmd_num == 83:
self._after_state.in_relative_extrusion_mode = True
estimated_exec_time_in_ms = 0.0 estimated_exec_time_in_ms = 0.0
# M104: Set extruder temperature (no wait). Assume 0 execution time. # M104: Set extruder temperature (no wait). Assume 0 execution time.
@ -399,15 +340,15 @@ class Command:
# M204: Set default acceleration. Assume 0 execution time. # M204: Set default acceleration. Assume 0 execution time.
if cmd_num == 204: if cmd_num == 204:
value_dict = get_value_dict(parts[1:]) value_dict = get_value_dict(parts[1:])
for key, value in value_dict.items(): buf.acceleration = value_dict.get("S", buf.acceleration)
self._after_state.accelerations[key] = float(value)
estimated_exec_time_in_ms = 0.0 estimated_exec_time_in_ms = 0.0
# M205: Advanced settings, we only set jerks for Griffin. Assume 0 execution time. # M205: Advanced settings, we only set jerks for Griffin. Assume 0 execution time.
if cmd_num == 205: if cmd_num == 205:
value_dict = get_value_dict(parts[1:]) value_dict = get_value_dict(parts[1:])
for key, value in value_dict.items(): buf.max_xy_jerk = value_dict.get("XY", buf.max_xy_jerk)
self._after_state.jerks[key] = float(value) buf.max_z_jerk = value_dict.get("Z", buf.max_z_jerk)
buf.max_e_jerk = value_dict.get("E", buf.max_e_jerk)
estimated_exec_time_in_ms = 0.0 estimated_exec_time_in_ms = 0.0
self._estimated_exec_time_in_ms = estimated_exec_time_in_ms self._estimated_exec_time_in_ms = estimated_exec_time_in_ms
@ -430,6 +371,13 @@ class CommandBuffer:
self._buffer_filling_rate = buffer_filling_rate # type: float self._buffer_filling_rate = buffer_filling_rate # type: float
self._buffer_size = buffer_size # type: int self._buffer_size = buffer_size # type: int
self.acceleration = 3000
self.current_position = [0, 0, 0, 0]
self.current_feedrate = 0
self.max_xy_jerk = MACHINE_MAX_JERK_XY
self.max_z_jerk = MACHINE_MAX_JERK_Z
self.max_e_jerk = MACHINE_MAX_JERK_E
# If the buffer can depletes less than this amount time, it can be filled up in time. # If the buffer can depletes less than this amount time, it can be filled up in time.
lower_bound_buffer_depletion_time = self._buffer_size / self._buffer_filling_rate # type: float lower_bound_buffer_depletion_time = self._buffer_size / self._buffer_filling_rate # type: float
@ -441,15 +389,13 @@ class CommandBuffer:
self._bad_frame_ranges = [] self._bad_frame_ranges = []
def process(self) -> None: def process(self) -> None:
previous_state = None
cmd0_idx = 0 cmd0_idx = 0
total_frame_time_in_ms = 0.0 total_frame_time_in_ms = 0.0
cmd_count = 0 cmd_count = 0
for idx, line in enumerate(self._all_lines): for idx, line in enumerate(self._all_lines):
cmd = Command(line, previous_state) cmd = Command(line)
cmd.parse() cmd.parse()
self._all_commands.append(cmd) self._all_commands.append(cmd)
previous_state = cmd.get_after_state()
if not cmd.is_command: if not cmd.is_command:
continue continue