From 321548a7c4fadcd3a6a5421fdebb029dea09325a Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 3 Nov 2011 22:40:21 +0100 Subject: [PATCH 1/9] Naive implementation to estimate the duration of a print --- duration.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100755 duration.py diff --git a/duration.py b/duration.py new file mode 100755 index 0000000..be53fb6 --- /dev/null +++ b/duration.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +from math import sqrt + +of=open("../PrusaMendel/stl/calibration_export.gcode") +g=[i.replace("\n","").replace("\r","") for i in of] +of.close + +def get_value(axis, parts): + for i in parts: + if (axis in i): + return float(i[1:]) + return None + + +total_duration = 0 +starting_velocity = 0 +global_feedrate = 0 +initial_feedrate = 0 +X_last_position = 0 +Y_last_position = 0 +for i in g: + if "G1" in i and ("X" in i or "Y" in i or "F" in i): + parts = i.split(" ") + X = get_value("X", parts[1:]) + Y = get_value("Y", parts[1:]) + F = get_value("F", parts[1:]) + + if (X is None and Y is None and F is not None): + global_feedrate = F + continue + + feedrate = 0 + if (F is None): + feedrate = global_feedrate + else: + feedrate = F + + distance = 0 + if (X is not None and Y is None): + distance = X - X_last_position + X_last_position = X + elif (X is None and Y is not None): + distance = Y - Y_last_position + Y_last_position = Y + elif (X is not None and Y is not None): + X_distance = X - X_last_position + Y_distance = Y - Y_last_position + distance = sqrt(X_distance * X_distance + Y_distance * Y_distance) + X_last_position = X + Y_last_position = Y + + time_for_move = distance / (feedrate / 60) + acceleration = (feedrate - initial_feedrate) / time_for_move + + halfway_feedrate = initial_feedrate + acceleration * time_for_move / 2 + + duration = 0 + if (halfway_feedrate == feedrate): + time_full_feedrate = (feedrate - initial_feedrate) / acceleration + distance_full_feedrate = (0.5 * (feedrate + initial_feedrate)) * time_full_feedrate + duration = time_full_feedrate * 2 + (distance - distance_full_feedrate * 2) / feedrate + else: + duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration + + total_duration += duration + + +print ("Total duration (in minutes): {0}".format(total_duration / 60)) From ca5e7f11b49e662ab6fa4dcf4c65885e1696fa63 Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 09:00:27 +0100 Subject: [PATCH 2/9] Divide feedrate by 60 seconds --- duration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/duration.py b/duration.py index be53fb6..56e0f31 100755 --- a/duration.py +++ b/duration.py @@ -31,9 +31,9 @@ for i in g: feedrate = 0 if (F is None): - feedrate = global_feedrate + feedrate = global_feedrate / 60 else: - feedrate = F + feedrate = F / 60 distance = 0 if (X is not None and Y is None): @@ -49,7 +49,7 @@ for i in g: X_last_position = X Y_last_position = Y - time_for_move = distance / (feedrate / 60) + time_for_move = distance / feedrate acceleration = (feedrate - initial_feedrate) / time_for_move halfway_feedrate = initial_feedrate + acceleration * time_for_move / 2 From 1ea631c84bf2b7ae7a493c60c0bd61ca67c7a120 Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 11:29:05 +0100 Subject: [PATCH 3/9] Nice formating of duration; renamed variables; added extra cost per movement --- duration.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/duration.py b/duration.py index 56e0f31..8780959 100755 --- a/duration.py +++ b/duration.py @@ -12,9 +12,9 @@ def get_value(axis, parts): return None +extra_cost_per_movement = 0.05 total_duration = 0 -starting_velocity = 0 -global_feedrate = 0 +fallback_feedrate = 0 initial_feedrate = 0 X_last_position = 0 Y_last_position = 0 @@ -26,12 +26,12 @@ for i in g: F = get_value("F", parts[1:]) if (X is None and Y is None and F is not None): - global_feedrate = F + fallback_feedrate = F continue feedrate = 0 if (F is None): - feedrate = global_feedrate / 60 + feedrate = fallback_feedrate / 60 else: feedrate = F / 60 @@ -62,7 +62,9 @@ for i in g: else: duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration - total_duration += duration + total_duration += duration + extra_cost_per_movement - -print ("Total duration (in minutes): {0}".format(total_duration / 60)) + +mod_minutes = total_duration % (60 * 60) +mod_seconds = mod_minutes % 60 +print ("Estimated total duration (pessimistic): {0:02d}H{1:02d}M".format(int((total_duration - mod_minutes) / (60 * 60)), int((mod_minutes - mod_seconds) / 60))) From be5f0e4900c1c3478786a55e8e3f8f91ef8db86a Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 11:49:05 +0100 Subject: [PATCH 4/9] Moved estimated duration code to pronterface --- duration.py | 70 -------------------------------------------------- pronsole.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++ pronterface.py | 1 + 3 files changed, 66 insertions(+), 70 deletions(-) delete mode 100755 duration.py diff --git a/duration.py b/duration.py deleted file mode 100755 index 8780959..0000000 --- a/duration.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -from math import sqrt - -of=open("../PrusaMendel/stl/calibration_export.gcode") -g=[i.replace("\n","").replace("\r","") for i in of] -of.close - -def get_value(axis, parts): - for i in parts: - if (axis in i): - return float(i[1:]) - return None - - -extra_cost_per_movement = 0.05 -total_duration = 0 -fallback_feedrate = 0 -initial_feedrate = 0 -X_last_position = 0 -Y_last_position = 0 -for i in g: - if "G1" in i and ("X" in i or "Y" in i or "F" in i): - parts = i.split(" ") - X = get_value("X", parts[1:]) - Y = get_value("Y", parts[1:]) - F = get_value("F", parts[1:]) - - if (X is None and Y is None and F is not None): - fallback_feedrate = F - continue - - feedrate = 0 - if (F is None): - feedrate = fallback_feedrate / 60 - else: - feedrate = F / 60 - - distance = 0 - if (X is not None and Y is None): - distance = X - X_last_position - X_last_position = X - elif (X is None and Y is not None): - distance = Y - Y_last_position - Y_last_position = Y - elif (X is not None and Y is not None): - X_distance = X - X_last_position - Y_distance = Y - Y_last_position - distance = sqrt(X_distance * X_distance + Y_distance * Y_distance) - X_last_position = X - Y_last_position = Y - - time_for_move = distance / feedrate - acceleration = (feedrate - initial_feedrate) / time_for_move - - halfway_feedrate = initial_feedrate + acceleration * time_for_move / 2 - - duration = 0 - if (halfway_feedrate == feedrate): - time_full_feedrate = (feedrate - initial_feedrate) / acceleration - distance_full_feedrate = (0.5 * (feedrate + initial_feedrate)) * time_full_feedrate - duration = time_full_feedrate * 2 + (distance - distance_full_feedrate * 2) / feedrate - else: - duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration - - total_duration += duration + extra_cost_per_movement - - -mod_minutes = total_duration % (60 * 60) -mod_seconds = mod_minutes % 60 -print ("Estimated total duration (pessimistic): {0:02d}H{1:02d}M".format(int((total_duration - mod_minutes) / (60 * 60)), int((mod_minutes - mod_seconds) / 60))) diff --git a/pronsole.py b/pronsole.py index 7feea62..5f51863 100755 --- a/pronsole.py +++ b/pronsole.py @@ -2,6 +2,7 @@ import cmd, printcore, sys import glob, os, time import sys, subprocess +from math import sqrt if os.name=="nt": try: import _winreg @@ -80,7 +81,71 @@ def totalelength(g): tot+=cur return tot +def get_coordinate_value(axis, parts): + for i in parts: + if (axis in i): + return float(i[1:]) + return None + + +def estimate_duration(g): + extra_cost_per_movement = 0.05 + total_duration = 0 + fallback_feedrate = 0 + initial_feedrate = 0 + X_last_position = 0 + Y_last_position = 0 + for i in g: + if "G1" in i and ("X" in i or "Y" in i or "F" in i): + parts = i.split(" ") + X = get_coordinate_value("X", parts[1:]) + Y = get_coordinate_value("Y", parts[1:]) + F = get_coordinate_value("F", parts[1:]) + if (X is None and Y is None and F is not None): + fallback_feedrate = F + continue + + feedrate = 0 + if (F is None): + feedrate = fallback_feedrate / 60 + else: + feedrate = F / 60 + + distance = 0 + if (X is not None and Y is None): + distance = X - X_last_position + X_last_position = X + elif (X is None and Y is not None): + distance = Y - Y_last_position + Y_last_position = Y + elif (X is not None and Y is not None): + X_distance = X - X_last_position + Y_distance = Y - Y_last_position + distance = sqrt(X_distance * X_distance + Y_distance * Y_distance) + X_last_position = X + Y_last_position = Y + + time_for_move = distance / feedrate + acceleration = (feedrate - initial_feedrate) / time_for_move + + halfway_feedrate = initial_feedrate + acceleration * time_for_move / 2 + + duration = 0 + if (halfway_feedrate == feedrate): + time_full_feedrate = (feedrate - initial_feedrate) / acceleration + distance_full_feedrate = (0.5 * (feedrate + initial_feedrate)) * time_full_feedrate + duration = time_full_feedrate * 2 + (distance - distance_full_feedrate * 2) / feedrate + else: + duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration + + total_duration += duration + extra_cost_per_movement + + mod_minutes = total_duration % (60 * 60) + mod_seconds = mod_minutes % 60 + + return "{0:02d}H{1:02d}M".format(int((total_duration - mod_minutes) / (60 * 60)), int((mod_minutes - mod_seconds) / 60)) + class Settings: #def _temperature_alias(self): return {"pla":210,"abs":230,"off":0} #def _temperature_validate(self,v): diff --git a/pronterface.py b/pronterface.py index 1b713f4..c1d6729 100755 --- a/pronterface.py +++ b/pronterface.py @@ -1164,6 +1164,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): print _("the print goes from"),Xmin,_("mm to"),Xmax,_("mm in X\nand is"),Xtot,_("mm wide\n") print _("the print goes from"),Ymin,_("mm to"),Ymax,_("mm in Y\nand is"),Ytot,_("mm wide\n") print _("the print goes from"),Zmin,_("mm to"),Zmax,_("mm in Z\nand is"),Ztot,_("mm high\n") + print _("Estimated duration (pessimistic): "), pronsole.estimate_duration(self.f) self.gviz.clear() self.gwindow.p.clear() for i in self.f: From 0bff3c93e4a6039a30e4dd74dcea7038ca5f597a Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 12:41:13 +0100 Subject: [PATCH 5/9] Added retraction to calculation, format time in lower case --- pronsole.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pronsole.py b/pronsole.py index 5f51863..4624213 100755 --- a/pronsole.py +++ b/pronsole.py @@ -96,13 +96,14 @@ def estimate_duration(g): X_last_position = 0 Y_last_position = 0 for i in g: - if "G1" in i and ("X" in i or "Y" in i or "F" in i): + if "G1" in i and ("X" in i or "Y" in i or "F" in i or "E" in i): parts = i.split(" ") X = get_coordinate_value("X", parts[1:]) Y = get_coordinate_value("Y", parts[1:]) F = get_coordinate_value("F", parts[1:]) + E = get_coordinate_value("E", parts[1:]) - if (X is None and Y is None and F is not None): + if (X is None and Y is None and E is None and F is not None): fallback_feedrate = F continue @@ -113,7 +114,9 @@ def estimate_duration(g): feedrate = F / 60 distance = 0 - if (X is not None and Y is None): + if (X is None and Y is None and E is not None and E < 0.0): + distance = abs(E) + elif (X is not None and Y is None): distance = X - X_last_position X_last_position = X elif (X is None and Y is not None): @@ -124,8 +127,11 @@ def estimate_duration(g): Y_distance = Y - Y_last_position distance = sqrt(X_distance * X_distance + Y_distance * Y_distance) X_last_position = X - Y_last_position = Y + Y_last_position = Y + else: + continue + time_for_move = distance / feedrate acceleration = (feedrate - initial_feedrate) / time_for_move @@ -144,7 +150,7 @@ def estimate_duration(g): mod_minutes = total_duration % (60 * 60) mod_seconds = mod_minutes % 60 - return "{0:02d}H{1:02d}M".format(int((total_duration - mod_minutes) / (60 * 60)), int((mod_minutes - mod_seconds) / 60)) + return "{0:02d}h{1:02d}m".format(int((total_duration - mod_minutes) / (60 * 60)), int((mod_minutes - mod_seconds) / 60)) class Settings: #def _temperature_alias(self): return {"pla":210,"abs":230,"off":0} From 05003322672b48cd3586509ac617371753607b21 Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 12:48:38 +0100 Subject: [PATCH 6/9] Also take forward movement after retraction into account --- pronsole.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pronsole.py b/pronsole.py index 4624213..44d717f 100755 --- a/pronsole.py +++ b/pronsole.py @@ -114,7 +114,7 @@ def estimate_duration(g): feedrate = F / 60 distance = 0 - if (X is None and Y is None and E is not None and E < 0.0): + if (X is None and Y is None and E is not None): distance = abs(E) elif (X is not None and Y is None): distance = X - X_last_position @@ -128,9 +128,8 @@ def estimate_duration(g): distance = sqrt(X_distance * X_distance + Y_distance * Y_distance) X_last_position = X Y_last_position = Y - else: - continue + if (feedrate == 0 or distance == 0): continue time_for_move = distance / feedrate acceleration = (feedrate - initial_feedrate) / time_for_move From e89eba8c9b36f7b10056876c0be1ca8688c15a57 Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 13:03:54 +0100 Subject: [PATCH 7/9] Use latest feedrate, no need to fall back --- pronsole.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/pronsole.py b/pronsole.py index 44d717f..118bfd7 100755 --- a/pronsole.py +++ b/pronsole.py @@ -89,10 +89,10 @@ def get_coordinate_value(axis, parts): def estimate_duration(g): - extra_cost_per_movement = 0.05 + extra_cost_per_movement = 0.02 total_duration = 0 - fallback_feedrate = 0 initial_feedrate = 0 + feedrate = 0 X_last_position = 0 Y_last_position = 0 for i in g: @@ -103,16 +103,9 @@ def estimate_duration(g): F = get_coordinate_value("F", parts[1:]) E = get_coordinate_value("E", parts[1:]) - if (X is None and Y is None and E is None and F is not None): - fallback_feedrate = F - continue - - feedrate = 0 - if (F is None): - feedrate = fallback_feedrate / 60 - else: + if (F is not None): feedrate = F / 60 - + distance = 0 if (X is None and Y is None and E is not None): distance = abs(E) From 80a1301bfdd25738e0feb1dfc8a2594364a9a988 Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 13:51:36 +0100 Subject: [PATCH 8/9] Simplified duration calculation, acceleration calculation is not realistic anyways --- pronsole.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pronsole.py b/pronsole.py index 118bfd7..273c3de 100755 --- a/pronsole.py +++ b/pronsole.py @@ -126,16 +126,8 @@ def estimate_duration(g): time_for_move = distance / feedrate acceleration = (feedrate - initial_feedrate) / time_for_move - halfway_feedrate = initial_feedrate + acceleration * time_for_move / 2 - - duration = 0 - if (halfway_feedrate == feedrate): - time_full_feedrate = (feedrate - initial_feedrate) / acceleration - distance_full_feedrate = (0.5 * (feedrate + initial_feedrate)) * time_full_feedrate - duration = time_full_feedrate * 2 + (distance - distance_full_feedrate * 2) / feedrate - else: - duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration + duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration total_duration += duration + extra_cost_per_movement From 262b000f7aac81e6253722246378d5e79f7f5b51 Mon Sep 17 00:00:00 2001 From: Steven Devijver Date: Fri, 4 Nov 2011 14:12:18 +0100 Subject: [PATCH 9/9] Removed initial_feedrate, isn't used anyways, will only confuse people --- pronsole.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pronsole.py b/pronsole.py index 273c3de..78e274b 100755 --- a/pronsole.py +++ b/pronsole.py @@ -91,7 +91,6 @@ def get_coordinate_value(axis, parts): def estimate_duration(g): extra_cost_per_movement = 0.02 total_duration = 0 - initial_feedrate = 0 feedrate = 0 X_last_position = 0 Y_last_position = 0 @@ -125,9 +124,9 @@ def estimate_duration(g): if (feedrate == 0 or distance == 0): continue time_for_move = distance / feedrate - acceleration = (feedrate - initial_feedrate) / time_for_move - halfway_feedrate = initial_feedrate + acceleration * time_for_move / 2 - duration = (halfway_feedrate * 2 - initial_feedrate) / acceleration + acceleration = feedrate / time_for_move + halfway_feedrate = acceleration * time_for_move / 2 + duration = halfway_feedrate * 2 / acceleration total_duration += duration + extra_cost_per_movement