mirror of https://github.com/Desuuuu/klipper.git
graph_extruder: Internal updates to graph calculation
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
17f2b4e960
commit
0e37f8c9b3
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
# Generate extruder pressure advance motion graphs
|
# Generate extruder pressure advance motion graphs
|
||||||
#
|
#
|
||||||
# Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2019-2020 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import math, optparse, datetime
|
import math, optparse, datetime
|
||||||
|
@ -17,7 +17,7 @@ INV_SEG_TIME = 1. / SEG_TIME
|
||||||
|
|
||||||
# List of moves: [(start_v, end_v, move_t), ...]
|
# List of moves: [(start_v, end_v, move_t), ...]
|
||||||
Moves = [
|
Moves = [
|
||||||
(0., 0., .200),
|
(0., 0., .100),
|
||||||
(0., 100., None), (100., 100., .200), (100., 60., None),
|
(0., 100., None), (100., 100., .200), (100., 60., None),
|
||||||
(60., 100., None), (100., 100., .200), (100., 0., None),
|
(60., 100., None), (100., 100., .200), (100., 0., None),
|
||||||
(0., 0., .300)
|
(0., 0., .300)
|
||||||
|
@ -47,85 +47,111 @@ def gen_positions():
|
||||||
start_t = end_t
|
start_t = end_t
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# List helper functions
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
MARGIN_TIME = 0.050
|
||||||
|
|
||||||
|
def time_to_index(t):
|
||||||
|
return int(t * INV_SEG_TIME + .5)
|
||||||
|
|
||||||
|
def indexes(positions):
|
||||||
|
drop = time_to_index(MARGIN_TIME)
|
||||||
|
return range(drop, len(positions)-drop)
|
||||||
|
|
||||||
|
def trim_lists(*lists):
|
||||||
|
keep = len(lists[0]) - time_to_index(2. * MARGIN_TIME)
|
||||||
|
for l in lists:
|
||||||
|
del l[keep:]
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Common data filters
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# Generate estimated first order derivative
|
||||||
def gen_deriv(data):
|
def gen_deriv(data):
|
||||||
return [0.] + [(data[i+1] - data[i]) * INV_SEG_TIME
|
return [0.] + [(data[i+1] - data[i]) * INV_SEG_TIME
|
||||||
for i in range(len(data)-1)]
|
for i in range(len(data)-1)]
|
||||||
|
|
||||||
def time_to_index(t):
|
# Simple average between two points smooth_time away
|
||||||
return int(t * INV_SEG_TIME + .5)
|
def calc_average(positions, smooth_time):
|
||||||
|
offset = time_to_index(smooth_time * .5)
|
||||||
|
out = [0.] * len(positions)
|
||||||
|
for i in indexes(positions):
|
||||||
|
out[i] = .5 * (positions[i-offset] + positions[i+offset])
|
||||||
|
return out
|
||||||
|
|
||||||
|
# Average (via integration) of smooth_time range
|
||||||
|
def calc_smooth(positions, smooth_time):
|
||||||
|
offset = time_to_index(smooth_time * .5)
|
||||||
|
weight = 1. / (2*offset - 1)
|
||||||
|
out = [0.] * len(positions)
|
||||||
|
for i in indexes(positions):
|
||||||
|
out[i] = sum(positions[i-offset+1:i+offset]) * weight
|
||||||
|
return out
|
||||||
|
|
||||||
|
# Time weighted average (via integration) of smooth_time range
|
||||||
|
def calc_weighted(positions, smooth_time):
|
||||||
|
offset = time_to_index(smooth_time * .5)
|
||||||
|
weight = 1. / offset**2
|
||||||
|
out = [0.] * len(positions)
|
||||||
|
for i in indexes(positions):
|
||||||
|
weighted_data = [positions[j] * (offset - abs(j-i))
|
||||||
|
for j in range(i-offset, i+offset)]
|
||||||
|
out[i] = sum(weighted_data) * weight
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Pressure advance
|
# Pressure advance
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
PA_HALF_SMOOTH_T = .040 / 2.
|
SMOOTH_TIME = .040
|
||||||
PRESSURE_ADVANCE = .045
|
PRESSURE_ADVANCE = .045
|
||||||
|
|
||||||
# Calculate raw pressure advance positions
|
# Calculate raw pressure advance positions
|
||||||
def calc_pa_raw(t, positions):
|
def calc_pa_raw(positions):
|
||||||
pa = PRESSURE_ADVANCE * INV_SEG_TIME
|
pa = PRESSURE_ADVANCE * INV_SEG_TIME
|
||||||
i = time_to_index(t)
|
out = [0.] * len(positions)
|
||||||
return positions[i] + pa * (positions[i+1] - positions[i])
|
for i in indexes(positions):
|
||||||
|
out[i] = positions[i] + pa * (positions[i+1] - positions[i])
|
||||||
|
return out
|
||||||
|
|
||||||
# Pressure advance smoothed using average velocity (for reference only)
|
# Pressure advance after smoothing
|
||||||
def calc_pa_average(t, positions):
|
def calc_pa(positions):
|
||||||
pa_factor = PRESSURE_ADVANCE / (2. * PA_HALF_SMOOTH_T)
|
return calc_weighted(calc_pa_raw(positions), SMOOTH_TIME)
|
||||||
base_pos = positions[time_to_index(t)]
|
|
||||||
start_pos = positions[time_to_index(t - PA_HALF_SMOOTH_T)]
|
|
||||||
end_pos = positions[time_to_index(t + PA_HALF_SMOOTH_T)]
|
|
||||||
return base_pos + (end_pos - start_pos) * pa_factor
|
|
||||||
|
|
||||||
# Pressure advance with simple time smoothing (for reference only)
|
|
||||||
def calc_pa_smooth(t, positions):
|
|
||||||
start_index = time_to_index(t - PA_HALF_SMOOTH_T) + 1
|
|
||||||
end_index = time_to_index(t + PA_HALF_SMOOTH_T)
|
|
||||||
pa = PRESSURE_ADVANCE * INV_SEG_TIME
|
|
||||||
pa_data = [positions[i] + pa * (positions[i+1] - positions[i])
|
|
||||||
for i in range(start_index, end_index)]
|
|
||||||
return sum(pa_data) / (end_index - start_index)
|
|
||||||
|
|
||||||
# Calculate pressure advance smoothed using a "weighted average"
|
|
||||||
def calc_pa_weighted(t, positions):
|
|
||||||
base_index = time_to_index(t)
|
|
||||||
start_index = time_to_index(t - PA_HALF_SMOOTH_T) + 1
|
|
||||||
end_index = time_to_index(t + PA_HALF_SMOOTH_T)
|
|
||||||
diff = .5 * (end_index - start_index)
|
|
||||||
pa = PRESSURE_ADVANCE * INV_SEG_TIME
|
|
||||||
pa_data = [(positions[i] + pa * (positions[i+1] - positions[i]))
|
|
||||||
* (diff - abs(i-base_index))
|
|
||||||
for i in range(start_index, end_index)]
|
|
||||||
return sum(pa_data) / diff**2
|
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Plotting and startup
|
# Plotting and startup
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
MARGIN_TIME = 0.100
|
|
||||||
|
|
||||||
def plot_motion():
|
def plot_motion():
|
||||||
# Nominal motion
|
# Nominal motion
|
||||||
positions = gen_positions()
|
positions = gen_positions()
|
||||||
drop = int(MARGIN_TIME * INV_SEG_TIME)
|
velocities = gen_deriv(positions)
|
||||||
times = [SEG_TIME * t for t in range(len(positions))][drop:-drop]
|
accels = gen_deriv(velocities)
|
||||||
velocities = gen_deriv(positions[drop:-drop])
|
|
||||||
# Motion with pressure advance
|
# Motion with pressure advance
|
||||||
pa_positions = [calc_pa_raw(t, positions) for t in times]
|
pa_positions = calc_pa_raw(positions)
|
||||||
pa_velocities = gen_deriv(pa_positions)
|
pa_velocities = gen_deriv(pa_positions)
|
||||||
# Smoothed motion
|
# Smoothed motion
|
||||||
sm_positions = [calc_pa_weighted(t, positions) for t in times]
|
sm_positions = calc_pa(positions)
|
||||||
sm_velocities = gen_deriv(sm_positions)
|
sm_velocities = gen_deriv(sm_positions)
|
||||||
# Build plot
|
# Build plot
|
||||||
shift_times = [t - MARGIN_TIME for t in times]
|
times = [SEG_TIME * i for i in range(len(positions))]
|
||||||
|
trim_lists(times, velocities, accels,
|
||||||
|
pa_positions, pa_velocities,
|
||||||
|
sm_positions, sm_velocities)
|
||||||
fig, ax1 = matplotlib.pyplot.subplots(nrows=1, sharex=True)
|
fig, ax1 = matplotlib.pyplot.subplots(nrows=1, sharex=True)
|
||||||
ax1.set_title("Extruder Velocity")
|
ax1.set_title("Extruder Velocity")
|
||||||
ax1.set_ylabel('Velocity (mm/s)')
|
ax1.set_ylabel('Velocity (mm/s)')
|
||||||
pa_plot, = ax1.plot(shift_times, pa_velocities, 'r',
|
pa_plot, = ax1.plot(times, pa_velocities, 'r',
|
||||||
label='Pressure Advance', alpha=0.3)
|
label='Pressure Advance', alpha=0.3)
|
||||||
nom_plot, = ax1.plot(shift_times, velocities, 'black', label='Nominal')
|
nom_plot, = ax1.plot(times, velocities, 'black', label='Nominal')
|
||||||
sm_plot, = ax1.plot(shift_times, sm_velocities, 'g', label='Smooth PA',
|
sm_plot, = ax1.plot(times, sm_velocities, 'g', label='Smooth PA', alpha=0.9)
|
||||||
alpha=0.9)
|
|
||||||
fontP = matplotlib.font_manager.FontProperties()
|
fontP = matplotlib.font_manager.FontProperties()
|
||||||
fontP.set_size('x-small')
|
fontP.set_size('x-small')
|
||||||
ax1.legend(handles=[nom_plot, pa_plot, sm_plot], loc='best', prop=fontP)
|
ax1.legend(handles=[nom_plot, pa_plot, sm_plot], loc='best', prop=fontP)
|
||||||
|
|
Loading…
Reference in New Issue