mirror of
https://github.com/andreili/klipper.git
synced 2025-09-14 09:31:11 +02:00
motion_queuing: Automatically detect changes to kin_flush_delay
Remove the toolhead note_step_generation_scan_time() code and automatically detect the itersolve scan windows that are in use. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
d1974c0d3d
commit
5426943501
@ -56,6 +56,8 @@ defs_stepcompress = """
|
||||
, uint64_t start_clock, uint64_t end_clock);
|
||||
void stepcompress_set_stepper_kinematics(struct stepcompress *sc
|
||||
, struct stepper_kinematics *sk);
|
||||
struct stepper_kinematics *stepcompress_get_stepper_kinematics(
|
||||
struct stepcompress *sc);
|
||||
"""
|
||||
|
||||
defs_steppersync = """
|
||||
@ -76,11 +78,14 @@ defs_itersolve = """
|
||||
int32_t itersolve_is_active_axis(struct stepper_kinematics *sk, char axis);
|
||||
void itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
|
||||
, double step_dist);
|
||||
struct trapq *itersolve_get_trapq(struct stepper_kinematics *sk);
|
||||
double itersolve_calc_position_from_coord(struct stepper_kinematics *sk
|
||||
, double x, double y, double z);
|
||||
void itersolve_set_position(struct stepper_kinematics *sk
|
||||
, double x, double y, double z);
|
||||
double itersolve_get_commanded_pos(struct stepper_kinematics *sk);
|
||||
double itersolve_get_gen_steps_pre_active(struct stepper_kinematics *sk);
|
||||
double itersolve_get_gen_steps_post_active(struct stepper_kinematics *sk);
|
||||
"""
|
||||
|
||||
defs_trapq = """
|
||||
@ -157,8 +162,6 @@ defs_kin_extruder = """
|
||||
"""
|
||||
|
||||
defs_kin_shaper = """
|
||||
double input_shaper_get_step_generation_window(
|
||||
struct stepper_kinematics *sk);
|
||||
int input_shaper_set_shaper_params(struct stepper_kinematics *sk, char axis
|
||||
, int n, double a[], double t[]);
|
||||
int input_shaper_set_sk(struct stepper_kinematics *sk
|
||||
|
@ -248,6 +248,12 @@ itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
|
||||
sk->step_dist = step_dist;
|
||||
}
|
||||
|
||||
struct trapq * __visible
|
||||
itersolve_get_trapq(struct stepper_kinematics *sk)
|
||||
{
|
||||
return sk->tq;
|
||||
}
|
||||
|
||||
double __visible
|
||||
itersolve_calc_position_from_coord(struct stepper_kinematics *sk
|
||||
, double x, double y, double z)
|
||||
@ -273,3 +279,15 @@ itersolve_get_commanded_pos(struct stepper_kinematics *sk)
|
||||
{
|
||||
return sk->commanded_pos;
|
||||
}
|
||||
|
||||
double __visible
|
||||
itersolve_get_gen_steps_pre_active(struct stepper_kinematics *sk)
|
||||
{
|
||||
return sk->gen_steps_pre_active;
|
||||
}
|
||||
|
||||
double __visible
|
||||
itersolve_get_gen_steps_post_active(struct stepper_kinematics *sk)
|
||||
{
|
||||
return sk->gen_steps_post_active;
|
||||
}
|
||||
|
@ -31,10 +31,13 @@ double itersolve_check_active(struct stepper_kinematics *sk, double flush_time);
|
||||
int32_t itersolve_is_active_axis(struct stepper_kinematics *sk, char axis);
|
||||
void itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
|
||||
, double step_dist);
|
||||
struct trapq *itersolve_get_trapq(struct stepper_kinematics *sk);
|
||||
double itersolve_calc_position_from_coord(struct stepper_kinematics *sk
|
||||
, double x, double y, double z);
|
||||
void itersolve_set_position(struct stepper_kinematics *sk
|
||||
, double x, double y, double z);
|
||||
double itersolve_get_commanded_pos(struct stepper_kinematics *sk);
|
||||
double itersolve_get_gen_steps_pre_active(struct stepper_kinematics *sk);
|
||||
double itersolve_get_gen_steps_post_active(struct stepper_kinematics *sk);
|
||||
|
||||
#endif // itersolve.h
|
||||
|
@ -239,14 +239,6 @@ input_shaper_set_shaper_params(struct stepper_kinematics *sk, char axis
|
||||
return status;
|
||||
}
|
||||
|
||||
double __visible
|
||||
input_shaper_get_step_generation_window(struct stepper_kinematics *sk)
|
||||
{
|
||||
struct input_shaper *is = container_of(sk, struct input_shaper, sk);
|
||||
return is->sk.gen_steps_pre_active > is->sk.gen_steps_post_active
|
||||
? is->sk.gen_steps_pre_active : is->sk.gen_steps_post_active;
|
||||
}
|
||||
|
||||
struct stepper_kinematics * __visible
|
||||
input_shaper_alloc(void)
|
||||
{
|
||||
|
@ -674,6 +674,13 @@ stepcompress_set_stepper_kinematics(struct stepcompress *sc
|
||||
sc->sk = sk;
|
||||
}
|
||||
|
||||
// Report current stepper_kinematics
|
||||
struct stepper_kinematics * __visible
|
||||
stepcompress_get_stepper_kinematics(struct stepcompress *sc)
|
||||
{
|
||||
return sc->sk;
|
||||
}
|
||||
|
||||
// Generate steps (via itersolve) and flush
|
||||
int32_t
|
||||
stepcompress_generate_steps(struct stepcompress *sc, double gen_steps_time
|
||||
|
@ -41,6 +41,8 @@ int stepcompress_extract_old(struct stepcompress *sc
|
||||
struct stepper_kinematics;
|
||||
void stepcompress_set_stepper_kinematics(struct stepcompress *sc
|
||||
, struct stepper_kinematics *sk);
|
||||
struct stepper_kinematics *stepcompress_get_stepper_kinematics(
|
||||
struct stepcompress *sc);
|
||||
int32_t stepcompress_generate_steps(struct stepcompress *sc
|
||||
, double gen_steps_time
|
||||
, uint64_t flush_clock);
|
||||
|
@ -146,12 +146,8 @@ class InputShaper:
|
||||
is_sk = self._get_input_shaper_stepper_kinematics(s)
|
||||
if is_sk is None:
|
||||
continue
|
||||
old_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk)
|
||||
self.toolhead.flush_step_generation()
|
||||
ffi_lib.input_shaper_update_sk(is_sk)
|
||||
new_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk)
|
||||
if old_delay != new_delay:
|
||||
self.toolhead.note_step_generation_scan_time(new_delay,
|
||||
old_delay)
|
||||
def _update_input_shaping(self, error=None):
|
||||
self.toolhead.flush_step_generation()
|
||||
ffi_main, ffi_lib = chelper.get_ffi()
|
||||
@ -163,16 +159,11 @@ class InputShaper:
|
||||
is_sk = self._get_input_shaper_stepper_kinematics(s)
|
||||
if is_sk is None:
|
||||
continue
|
||||
old_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk)
|
||||
for shaper in self.shapers:
|
||||
if shaper in failed_shapers:
|
||||
continue
|
||||
if not shaper.set_shaper_kinematics(is_sk):
|
||||
failed_shapers.append(shaper)
|
||||
new_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk)
|
||||
if old_delay != new_delay:
|
||||
self.toolhead.note_step_generation_scan_time(new_delay,
|
||||
old_delay)
|
||||
if failed_shapers:
|
||||
error = error or self.printer.command_error
|
||||
raise error("Failed to configure shaper(s) %s with given parameters"
|
||||
|
@ -49,6 +49,7 @@ class PrinterMotionQueuing:
|
||||
if self.mcu.is_fileoutput():
|
||||
self.can_pause = False
|
||||
# Kinematic step generation scan window time tracking
|
||||
self.need_calc_kin_flush_delay = True
|
||||
self.kin_flush_delay = SDS_CHECK_TIME
|
||||
# Register handlers
|
||||
printer.register_event_handler("klippy:shutdown", self._handle_shutdown)
|
||||
@ -118,8 +119,6 @@ class PrinterMotionQueuing:
|
||||
def lookup_trapq_append(self):
|
||||
ffi_main, ffi_lib = chelper.get_ffi()
|
||||
return ffi_lib.trapq_append
|
||||
def set_step_generate_scan_time(self, delay):
|
||||
self.kin_flush_delay = delay
|
||||
def stats(self, eventtime):
|
||||
# Hack to globally invoke mcu check_active()
|
||||
for m in self.all_mcus:
|
||||
@ -128,6 +127,24 @@ class PrinterMotionQueuing:
|
||||
est_print_time = self.mcu.estimated_print_time(eventtime)
|
||||
self.clear_history_time = est_print_time - MOVE_HISTORY_EXPIRE
|
||||
return False, ""
|
||||
# Kinematic step generation scan window time tracking
|
||||
def get_kin_flush_delay(self):
|
||||
return self.kin_flush_delay
|
||||
def _calc_kin_flush_delay(self):
|
||||
self.need_calc_kin_flush_delay = False
|
||||
ffi_main, ffi_lib = chelper.get_ffi()
|
||||
kin_flush_delay = SDS_CHECK_TIME
|
||||
for mcu, sc in self.stepcompress:
|
||||
sk = ffi_lib.stepcompress_get_stepper_kinematics(sc)
|
||||
if sk == ffi_main.NULL:
|
||||
continue
|
||||
trapq = ffi_lib.itersolve_get_trapq(sk)
|
||||
if trapq == ffi_main.NULL:
|
||||
continue
|
||||
pre_active = ffi_lib.itersolve_get_gen_steps_pre_active(sk)
|
||||
post_active = ffi_lib.itersolve_get_gen_steps_post_active(sk)
|
||||
kin_flush_delay = max(kin_flush_delay, pre_active, post_active)
|
||||
self.kin_flush_delay = kin_flush_delay
|
||||
# Flush tracking
|
||||
def _handle_shutdown(self):
|
||||
self.can_pause = False
|
||||
@ -137,6 +154,7 @@ class PrinterMotionQueuing:
|
||||
if target_time is None:
|
||||
# This is a full flush
|
||||
target_time = self.need_step_gen_time
|
||||
self.need_calc_kin_flush_delay = True
|
||||
want_flush_time = want_step_gen_time = target_time
|
||||
if lazy_target:
|
||||
# Account for step gen scan windows and optimize step compression
|
||||
@ -162,6 +180,8 @@ class PrinterMotionQueuing:
|
||||
if flush_time >= want_flush_time:
|
||||
break
|
||||
def calc_step_gen_restart(self, est_print_time):
|
||||
if self.need_calc_kin_flush_delay:
|
||||
self._calc_kin_flush_delay()
|
||||
kin_time = max(est_print_time + MIN_KIN_TIME, self.last_step_gen_time)
|
||||
return kin_time + self.kin_flush_delay
|
||||
def _flush_handler(self, eventtime):
|
||||
|
@ -69,11 +69,13 @@ class ExtruderStepper:
|
||||
if not pressure_advance:
|
||||
new_smooth_time = 0.
|
||||
toolhead = self.printer.lookup_object("toolhead")
|
||||
if new_smooth_time != old_smooth_time:
|
||||
toolhead.note_step_generation_scan_time(
|
||||
new_smooth_time * .5, old_delay=old_smooth_time * .5)
|
||||
ffi_main, ffi_lib = chelper.get_ffi()
|
||||
espa = ffi_lib.extruder_set_pressure_advance
|
||||
if new_smooth_time != old_smooth_time:
|
||||
# Need full kinematic flush to change the smooth time
|
||||
toolhead.flush_step_generation()
|
||||
espa(self.sk_extruder, 0., pressure_advance, new_smooth_time)
|
||||
else:
|
||||
toolhead.register_lookahead_callback(
|
||||
lambda print_time: espa(self.sk_extruder, print_time,
|
||||
pressure_advance, new_smooth_time))
|
||||
|
@ -193,7 +193,6 @@ class LookAheadQueue:
|
||||
BUFFER_TIME_LOW = 1.0
|
||||
BUFFER_TIME_HIGH = 2.0
|
||||
BUFFER_TIME_START = 0.250
|
||||
SDS_CHECK_TIME = 0.001 # step+dir+step filter in stepcompress.c
|
||||
|
||||
# Main code to track events (and their timing) on the printer toolhead
|
||||
class ToolHead:
|
||||
@ -225,9 +224,6 @@ class ToolHead:
|
||||
self.print_time = 0.
|
||||
self.special_queuing_state = "NeedPrime"
|
||||
self.priming_timer = None
|
||||
# Kinematic step generation scan window time tracking
|
||||
self.kin_flush_delay = SDS_CHECK_TIME
|
||||
self.kin_flush_times = []
|
||||
# Setup for generating moves
|
||||
self.motion_queuing = self.printer.load_object(config, 'motion_queuing')
|
||||
self.motion_queuing.setup_lookahead_flush_callback(
|
||||
@ -469,7 +465,8 @@ class ToolHead:
|
||||
if move.move_d:
|
||||
self.kin.check_move(move)
|
||||
# Make sure stepper movement doesn't start before nominal start time
|
||||
self.dwell(self.kin_flush_delay)
|
||||
kin_flush_delay = self.motion_queuing.get_kin_flush_delay()
|
||||
self.dwell(kin_flush_delay)
|
||||
# Transmit move in "drip" mode
|
||||
self._process_lookahead()
|
||||
start_time, end_time = self._drip_load_trapq(move)
|
||||
@ -510,15 +507,6 @@ class ToolHead:
|
||||
return self.kin
|
||||
def get_trapq(self):
|
||||
return self.trapq
|
||||
def note_step_generation_scan_time(self, delay, old_delay=0.):
|
||||
self.flush_step_generation()
|
||||
if old_delay:
|
||||
self.kin_flush_times.pop(self.kin_flush_times.index(old_delay))
|
||||
if delay:
|
||||
self.kin_flush_times.append(delay)
|
||||
new_delay = max(self.kin_flush_times + [SDS_CHECK_TIME])
|
||||
self.kin_flush_delay = new_delay
|
||||
self.motion_queuing.set_step_generate_scan_time(new_delay)
|
||||
def register_lookahead_callback(self, callback):
|
||||
last_move = self.lookahead.get_last()
|
||||
if last_move is None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user