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:
Kevin O'Connor 2023-11-29 01:04:28 -05:00
parent d1974c0d3d
commit 5426943501
10 changed files with 68 additions and 42 deletions

View File

@ -56,6 +56,8 @@ defs_stepcompress = """
, uint64_t start_clock, uint64_t end_clock); , uint64_t start_clock, uint64_t end_clock);
void stepcompress_set_stepper_kinematics(struct stepcompress *sc void stepcompress_set_stepper_kinematics(struct stepcompress *sc
, struct stepper_kinematics *sk); , struct stepper_kinematics *sk);
struct stepper_kinematics *stepcompress_get_stepper_kinematics(
struct stepcompress *sc);
""" """
defs_steppersync = """ defs_steppersync = """
@ -76,11 +78,14 @@ defs_itersolve = """
int32_t itersolve_is_active_axis(struct stepper_kinematics *sk, char axis); int32_t itersolve_is_active_axis(struct stepper_kinematics *sk, char axis);
void itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq void itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
, double step_dist); , double step_dist);
struct trapq *itersolve_get_trapq(struct stepper_kinematics *sk);
double itersolve_calc_position_from_coord(struct stepper_kinematics *sk double itersolve_calc_position_from_coord(struct stepper_kinematics *sk
, double x, double y, double z); , double x, double y, double z);
void itersolve_set_position(struct stepper_kinematics *sk void itersolve_set_position(struct stepper_kinematics *sk
, double x, double y, double z); , double x, double y, double z);
double itersolve_get_commanded_pos(struct stepper_kinematics *sk); 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 = """ defs_trapq = """
@ -157,8 +162,6 @@ defs_kin_extruder = """
""" """
defs_kin_shaper = """ 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 input_shaper_set_shaper_params(struct stepper_kinematics *sk, char axis
, int n, double a[], double t[]); , int n, double a[], double t[]);
int input_shaper_set_sk(struct stepper_kinematics *sk int input_shaper_set_sk(struct stepper_kinematics *sk

View File

@ -248,6 +248,12 @@ itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
sk->step_dist = step_dist; sk->step_dist = step_dist;
} }
struct trapq * __visible
itersolve_get_trapq(struct stepper_kinematics *sk)
{
return sk->tq;
}
double __visible double __visible
itersolve_calc_position_from_coord(struct stepper_kinematics *sk itersolve_calc_position_from_coord(struct stepper_kinematics *sk
, double x, double y, double z) , double x, double y, double z)
@ -273,3 +279,15 @@ itersolve_get_commanded_pos(struct stepper_kinematics *sk)
{ {
return sk->commanded_pos; 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;
}

View File

@ -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); int32_t itersolve_is_active_axis(struct stepper_kinematics *sk, char axis);
void itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq void itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
, double step_dist); , double step_dist);
struct trapq *itersolve_get_trapq(struct stepper_kinematics *sk);
double itersolve_calc_position_from_coord(struct stepper_kinematics *sk double itersolve_calc_position_from_coord(struct stepper_kinematics *sk
, double x, double y, double z); , double x, double y, double z);
void itersolve_set_position(struct stepper_kinematics *sk void itersolve_set_position(struct stepper_kinematics *sk
, double x, double y, double z); , double x, double y, double z);
double itersolve_get_commanded_pos(struct stepper_kinematics *sk); 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 #endif // itersolve.h

View File

@ -239,14 +239,6 @@ input_shaper_set_shaper_params(struct stepper_kinematics *sk, char axis
return status; 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 struct stepper_kinematics * __visible
input_shaper_alloc(void) input_shaper_alloc(void)
{ {

View File

@ -674,6 +674,13 @@ stepcompress_set_stepper_kinematics(struct stepcompress *sc
sc->sk = sk; 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 // Generate steps (via itersolve) and flush
int32_t int32_t
stepcompress_generate_steps(struct stepcompress *sc, double gen_steps_time stepcompress_generate_steps(struct stepcompress *sc, double gen_steps_time

View File

@ -41,6 +41,8 @@ int stepcompress_extract_old(struct stepcompress *sc
struct stepper_kinematics; struct stepper_kinematics;
void stepcompress_set_stepper_kinematics(struct stepcompress *sc void stepcompress_set_stepper_kinematics(struct stepcompress *sc
, struct stepper_kinematics *sk); , struct stepper_kinematics *sk);
struct stepper_kinematics *stepcompress_get_stepper_kinematics(
struct stepcompress *sc);
int32_t stepcompress_generate_steps(struct stepcompress *sc int32_t stepcompress_generate_steps(struct stepcompress *sc
, double gen_steps_time , double gen_steps_time
, uint64_t flush_clock); , uint64_t flush_clock);

View File

@ -146,12 +146,8 @@ class InputShaper:
is_sk = self._get_input_shaper_stepper_kinematics(s) is_sk = self._get_input_shaper_stepper_kinematics(s)
if is_sk is None: if is_sk is None:
continue 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) 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): def _update_input_shaping(self, error=None):
self.toolhead.flush_step_generation() self.toolhead.flush_step_generation()
ffi_main, ffi_lib = chelper.get_ffi() ffi_main, ffi_lib = chelper.get_ffi()
@ -163,16 +159,11 @@ class InputShaper:
is_sk = self._get_input_shaper_stepper_kinematics(s) is_sk = self._get_input_shaper_stepper_kinematics(s)
if is_sk is None: if is_sk is None:
continue continue
old_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk)
for shaper in self.shapers: for shaper in self.shapers:
if shaper in failed_shapers: if shaper in failed_shapers:
continue continue
if not shaper.set_shaper_kinematics(is_sk): if not shaper.set_shaper_kinematics(is_sk):
failed_shapers.append(shaper) 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: if failed_shapers:
error = error or self.printer.command_error error = error or self.printer.command_error
raise error("Failed to configure shaper(s) %s with given parameters" raise error("Failed to configure shaper(s) %s with given parameters"

View File

@ -49,6 +49,7 @@ class PrinterMotionQueuing:
if self.mcu.is_fileoutput(): if self.mcu.is_fileoutput():
self.can_pause = False self.can_pause = False
# Kinematic step generation scan window time tracking # Kinematic step generation scan window time tracking
self.need_calc_kin_flush_delay = True
self.kin_flush_delay = SDS_CHECK_TIME self.kin_flush_delay = SDS_CHECK_TIME
# Register handlers # Register handlers
printer.register_event_handler("klippy:shutdown", self._handle_shutdown) printer.register_event_handler("klippy:shutdown", self._handle_shutdown)
@ -118,8 +119,6 @@ class PrinterMotionQueuing:
def lookup_trapq_append(self): def lookup_trapq_append(self):
ffi_main, ffi_lib = chelper.get_ffi() ffi_main, ffi_lib = chelper.get_ffi()
return ffi_lib.trapq_append return ffi_lib.trapq_append
def set_step_generate_scan_time(self, delay):
self.kin_flush_delay = delay
def stats(self, eventtime): def stats(self, eventtime):
# Hack to globally invoke mcu check_active() # Hack to globally invoke mcu check_active()
for m in self.all_mcus: for m in self.all_mcus:
@ -128,6 +127,24 @@ class PrinterMotionQueuing:
est_print_time = self.mcu.estimated_print_time(eventtime) est_print_time = self.mcu.estimated_print_time(eventtime)
self.clear_history_time = est_print_time - MOVE_HISTORY_EXPIRE self.clear_history_time = est_print_time - MOVE_HISTORY_EXPIRE
return False, "" 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 # Flush tracking
def _handle_shutdown(self): def _handle_shutdown(self):
self.can_pause = False self.can_pause = False
@ -137,6 +154,7 @@ class PrinterMotionQueuing:
if target_time is None: if target_time is None:
# This is a full flush # This is a full flush
target_time = self.need_step_gen_time target_time = self.need_step_gen_time
self.need_calc_kin_flush_delay = True
want_flush_time = want_step_gen_time = target_time want_flush_time = want_step_gen_time = target_time
if lazy_target: if lazy_target:
# Account for step gen scan windows and optimize step compression # Account for step gen scan windows and optimize step compression
@ -162,6 +180,8 @@ class PrinterMotionQueuing:
if flush_time >= want_flush_time: if flush_time >= want_flush_time:
break break
def calc_step_gen_restart(self, est_print_time): 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) kin_time = max(est_print_time + MIN_KIN_TIME, self.last_step_gen_time)
return kin_time + self.kin_flush_delay return kin_time + self.kin_flush_delay
def _flush_handler(self, eventtime): def _flush_handler(self, eventtime):

View File

@ -69,14 +69,16 @@ class ExtruderStepper:
if not pressure_advance: if not pressure_advance:
new_smooth_time = 0. new_smooth_time = 0.
toolhead = self.printer.lookup_object("toolhead") 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() ffi_main, ffi_lib = chelper.get_ffi()
espa = ffi_lib.extruder_set_pressure_advance espa = ffi_lib.extruder_set_pressure_advance
toolhead.register_lookahead_callback( if new_smooth_time != old_smooth_time:
lambda print_time: espa(self.sk_extruder, print_time, # Need full kinematic flush to change the smooth time
pressure_advance, new_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))
self.pressure_advance = pressure_advance self.pressure_advance = pressure_advance
self.pressure_advance_smooth_time = smooth_time self.pressure_advance_smooth_time = smooth_time
cmd_SET_PRESSURE_ADVANCE_help = "Set pressure advance parameters" cmd_SET_PRESSURE_ADVANCE_help = "Set pressure advance parameters"

View File

@ -193,7 +193,6 @@ class LookAheadQueue:
BUFFER_TIME_LOW = 1.0 BUFFER_TIME_LOW = 1.0
BUFFER_TIME_HIGH = 2.0 BUFFER_TIME_HIGH = 2.0
BUFFER_TIME_START = 0.250 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 # Main code to track events (and their timing) on the printer toolhead
class ToolHead: class ToolHead:
@ -225,9 +224,6 @@ class ToolHead:
self.print_time = 0. self.print_time = 0.
self.special_queuing_state = "NeedPrime" self.special_queuing_state = "NeedPrime"
self.priming_timer = None 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 # Setup for generating moves
self.motion_queuing = self.printer.load_object(config, 'motion_queuing') self.motion_queuing = self.printer.load_object(config, 'motion_queuing')
self.motion_queuing.setup_lookahead_flush_callback( self.motion_queuing.setup_lookahead_flush_callback(
@ -469,7 +465,8 @@ class ToolHead:
if move.move_d: if move.move_d:
self.kin.check_move(move) self.kin.check_move(move)
# Make sure stepper movement doesn't start before nominal start time # 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 # Transmit move in "drip" mode
self._process_lookahead() self._process_lookahead()
start_time, end_time = self._drip_load_trapq(move) start_time, end_time = self._drip_load_trapq(move)
@ -510,15 +507,6 @@ class ToolHead:
return self.kin return self.kin
def get_trapq(self): def get_trapq(self):
return self.trapq 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): def register_lookahead_callback(self, callback):
last_move = self.lookahead.get_last() last_move = self.lookahead.get_last()
if last_move is None: if last_move is None: