I was so annoyed that the estimates for my 3d printing jobs were so far off
(estimated 2 hours, took 8) that I modified the axis code. It looks at the
Velocity and acceleration of each axis and tries to calculate a more
accurate time. It only looks at moves - no G64 or probing. It isn't
perfect, but much closer.
The attached file is the changes - a new gcode_properties function and some
additional routines.
My version of linuxcnc is pretty old, so a diff or patch wouldn't be useful.
Frank
> -----Original Message-----
> From: Sebastian Kuzminsky [mailto:s...@highlab.com]
> Sent: Thursday, 9 October 2014 1:45 AM
> To: Enhanced Machine Controller (EMC)
> Subject: Re: [Emc-users] Thoughts on a Python script to calculate
estimated
> run time, for G code and my first hacked sub routine
>
> On 10/8/14 9:01 AM, Schooner wrote:
> > First Q
> >
> > From Axis
> >
> > File > Properties
> >
> > Brings up the properties of the currently loaded gcode including
> > estimated run time
> >
> > Always underestimates as it takes no account of time used in
> > acceleration and deceleration to/from the required Feed speed
>
> Yep, the estimate is off. It's based on the gcode only, and does not take
into
> account important things like machine acceleration and spindle
acceleration
> as you say, as well as things like tolerance (G64 P) and probing.
>
> The only way I can think of to improve the estimate would be to run the
> motion controller, disconnected from actual motion, and see how long the
> motion actually takes. That's probably possible, but it's not a small
change to
> design & implement.
>
>
> --
> Sebastian Kuzminsky
>
>
----------------------------------------------------------------------------
--
> Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer Achieve
> PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports Are you
> Audit-Ready for PCI DSS 3.0 Compliance? Download White paper Comply to
> PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer
> http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.cl
> ktrk
> _______________________________________________
> Emc-users mailing list
> Emc-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/emc-users
class AxisParam:
def __init__(self, vel, acc):
self.vel = vel
self.acc = acc
def StraightExecutionTime( self, distance, feedrate ):
t = 0.0
if feedrate is None:
v = self.vel
elif feedrate > self.vel:
v = self.vel
else:
v = feedrate
distance = abs(distance)
a = self.acc
if distance > 0:
# calc time and distance to accelerate to v
# v = at
# s = 1/2 a t^2 + v0 t, assume v0 = 0
t = v / a
s = 1.0 / 2.0 * a * t *t
# check if accelerating to v then decelerating to v fits in the
distance
if 2.0*s < distance:
t = 2.0 * t + (distance - 2.0*s) / v
else:
t = 2.0*math.sqrt( 2.0 * (distance/2.0) / a )
#print "distance=",distance, "a=", a, "v=", v, "t=", t
return t
def CalcExecutionTime( axis_params, start_point, end_point, feedrate=None ):
distance = sum( (s-e)**2 for s, e in zip(start_point, end_point))
distance = math.sqrt(distance)
longest_time = 0
for ap,start,end in zip(axis_params, start_point, end_point ):
if not ap is None:
f = feedrate
if not feedrate is None:
f = feedrate * abs(end-start)/distance
time = ap.StraightExecutionTime( end - start, f )
if time > longest_time:
longest_time = time
return longest_time
def CalcArcExecutionTime( ap, arcfeed ):
# Arcs have already been converted into line segments.
# We calculate absolute distance travelled in dx, dy, dz, etc
# and estimate the time in each axis. This wont take into
# account an axis with low acceleration, but should be close enough.
time = 0
last_line = 0
last_feed = 0
arclen = [0,]*9
segcount = 0
for arcseg in arcfeed:
# Each record contains, line number, start, end, feedrate.
# We determine the end of an arc when the line # changes or the feed
changes
line = arcseg[0]
start = arcseg[1]
end = arcseg[2]
feed = arcseg[3]
if line != last_line or feed != last_feed:
if segcount > 0:
t = CalcExecutionTime( ap, [0,]*9, arclen, last_feed )
time += t
arclen = [0,]*9
segcount = 0
# sum the distance travelled in each axis
for i in range(0,9):
arclen[i] += abs(end[i]-start[i])
segcount += 1
last_feed = feed
last_line = line
if segcount > 0:
t = CalcExecutionTime( ap, (0,)*9, arclen, last_feed )
time += t
return time
#Replace in class TclCommands(nf.TclCommands):
def gcode_properties(event=None):
props = {}
if not loaded_file:
props['name'] = _("No file loaded")
else:
ext = os.path.splitext(loaded_file)[1]
program_filter = None
if ext:
program_filter = inifile.find("FILTER", ext[1:])
name = os.path.basename(loaded_file)
if program_filter:
props['name'] = _("generated from %s") % name
else:
props['name'] = name
size = os.stat(loaded_file).st_size
lines = int(widgets.text.index("end").split(".")[0])-2
props['size'] = _("%(size)s bytes\n%(lines)s gcode lines") %
{'size': size, 'lines': lines}
if vars.metric.get():
conv = 1
units = _("mm")
fmt = "%.3f"
else:
conv = 1/25.4
units = _("in")
fmt = "%.4f"
# read max_vel and max_acc for each axis
ap = []
lscale = 1.0
for a in range(0,8):
vel = inifile.find("AXIS_%d"%a, "MAX_VELOCITY")
acc = inifile.find("AXIS_%d"%a, "MAX_ACCELERATION")
#print "vel=", vel, " acc=", acc
if not vel is None and not acc is None:
ap.append( AxisParam( float(vel) * lscale,
float(acc) * lscale ) )
else:
ap.append( None )
g0 = sum(dist(l[1][:3], l[2][:3]) for l in o.canon.traverse)
g1 = (sum(dist(l[1][:3], l[2][:3]) for l in o.canon.feed) +
sum(dist(l[1][:3], l[2][:3]) for l in o.canon.arcfeed))
gt = sum( CalcExecutionTime( ap, l[1], l[2] ) for l in
o.canon.traverse)
gt += sum( CalcExecutionTime( ap, l[1], l[2], l[3] ) for l in
o.canon.feed)
gt += CalcArcExecutionTime( ap, o.canon.arcfeed )
gt += o.canon.dwell_time
props['g0'] = "%f %s".replace("%f", fmt) %
(from_internal_linear_unit(g0, conv), units)
props['g1'] = "%f %s".replace("%f", fmt) %
(from_internal_linear_unit(g1, conv), units)
h = gt/(60*60)
m = (gt/60) % 60
s = gt%60
props['run'] = "%d:%02d:%02d" % (int(h),int(m),int(s))
min_extents = from_internal_units(o.canon.min_extents, conv)
max_extents = from_internal_units(o.canon.max_extents, conv)
for (i, c) in enumerate("xyz"):
a = min_extents[i]
b = max_extents[i]
if a != b:
props[c] = _("%(a)f to %(b)f = %(diff)f
%(units)s").replace("%f", fmt) % {'a': a, 'b': b, 'diff': b-a, 'units': units}
properties(root_window, _("G-Code Properties"), property_names, props)
------------------------------------------------------------------------------
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
_______________________________________________
Emc-users mailing list
Emc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-users