toolhead: Keep stepcompress move history relative to current time (#6439)
Expire history relative to current time rather than last move in history queue Signed-off-by: Francois Chagnon <fc@francoischagnon.net>
This commit is contained in:
parent
b502558052
commit
d7f6348ae6
|
@ -60,7 +60,8 @@ defs_stepcompress = """
|
||||||
void steppersync_free(struct steppersync *ss);
|
void steppersync_free(struct steppersync *ss);
|
||||||
void steppersync_set_time(struct steppersync *ss
|
void steppersync_set_time(struct steppersync *ss
|
||||||
, double time_offset, double mcu_freq);
|
, double time_offset, double mcu_freq);
|
||||||
int steppersync_flush(struct steppersync *ss, uint64_t move_clock);
|
int steppersync_flush(struct steppersync *ss, uint64_t move_clock
|
||||||
|
, uint64_t clear_history_clock);
|
||||||
"""
|
"""
|
||||||
|
|
||||||
defs_itersolve = """
|
defs_itersolve = """
|
||||||
|
@ -94,7 +95,8 @@ defs_trapq = """
|
||||||
, double start_pos_x, double start_pos_y, double start_pos_z
|
, double start_pos_x, double start_pos_y, double start_pos_z
|
||||||
, double axes_r_x, double axes_r_y, double axes_r_z
|
, double axes_r_x, double axes_r_y, double axes_r_z
|
||||||
, double start_v, double cruise_v, double accel);
|
, double start_v, double cruise_v, double accel);
|
||||||
void trapq_finalize_moves(struct trapq *tq, double print_time);
|
void trapq_finalize_moves(struct trapq *tq, double print_time
|
||||||
|
, double clear_history_time);
|
||||||
void trapq_set_position(struct trapq *tq, double print_time
|
void trapq_set_position(struct trapq *tq, double print_time
|
||||||
, double pos_x, double pos_y, double pos_z);
|
, double pos_x, double pos_y, double pos_z);
|
||||||
int trapq_extract_old(struct trapq *tq, struct pull_move *p, int max
|
int trapq_extract_old(struct trapq *tq, struct pull_move *p, int max
|
||||||
|
|
|
@ -54,8 +54,6 @@ struct step_move {
|
||||||
int16_t add;
|
int16_t add;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HISTORY_EXPIRE (30.0)
|
|
||||||
|
|
||||||
struct history_steps {
|
struct history_steps {
|
||||||
struct list_node node;
|
struct list_node node;
|
||||||
uint64_t first_clock, last_clock;
|
uint64_t first_clock, last_clock;
|
||||||
|
@ -292,6 +290,13 @@ free_history(struct stepcompress *sc, uint64_t end_clock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expire the stepcompress history older than the given clock
|
||||||
|
static void
|
||||||
|
stepcompress_history_expire(struct stepcompress *sc, uint64_t end_clock)
|
||||||
|
{
|
||||||
|
free_history(sc, end_clock);
|
||||||
|
}
|
||||||
|
|
||||||
// Free memory associated with a 'stepcompress' object
|
// Free memory associated with a 'stepcompress' object
|
||||||
void __visible
|
void __visible
|
||||||
stepcompress_free(struct stepcompress *sc)
|
stepcompress_free(struct stepcompress *sc)
|
||||||
|
@ -322,9 +327,6 @@ calc_last_step_print_time(struct stepcompress *sc)
|
||||||
{
|
{
|
||||||
double lsc = sc->last_step_clock;
|
double lsc = sc->last_step_clock;
|
||||||
sc->last_step_print_time = sc->mcu_time_offset + (lsc - .5) / sc->mcu_freq;
|
sc->last_step_print_time = sc->mcu_time_offset + (lsc - .5) / sc->mcu_freq;
|
||||||
|
|
||||||
if (lsc > sc->mcu_freq * HISTORY_EXPIRE)
|
|
||||||
free_history(sc, lsc - sc->mcu_freq * HISTORY_EXPIRE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the conversion rate of 'print_time' to mcu clock
|
// Set the conversion rate of 'print_time' to mcu clock
|
||||||
|
@ -731,6 +733,18 @@ steppersync_set_time(struct steppersync *ss, double time_offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expire the stepcompress history before the given clock time
|
||||||
|
static void
|
||||||
|
steppersync_history_expire(struct steppersync *ss, uint64_t end_clock)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ss->sc_num; i++)
|
||||||
|
{
|
||||||
|
struct stepcompress *sc = ss->sc_list[i];
|
||||||
|
stepcompress_history_expire(sc, end_clock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Implement a binary heap algorithm to track when the next available
|
// Implement a binary heap algorithm to track when the next available
|
||||||
// 'struct move' in the mcu will be available
|
// 'struct move' in the mcu will be available
|
||||||
static void
|
static void
|
||||||
|
@ -758,7 +772,8 @@ heap_replace(struct steppersync *ss, uint64_t req_clock)
|
||||||
|
|
||||||
// Find and transmit any scheduled steps prior to the given 'move_clock'
|
// Find and transmit any scheduled steps prior to the given 'move_clock'
|
||||||
int __visible
|
int __visible
|
||||||
steppersync_flush(struct steppersync *ss, uint64_t move_clock)
|
steppersync_flush(struct steppersync *ss, uint64_t move_clock
|
||||||
|
, uint64_t clear_history_clock)
|
||||||
{
|
{
|
||||||
// Flush each stepcompress to the specified move_clock
|
// Flush each stepcompress to the specified move_clock
|
||||||
int i;
|
int i;
|
||||||
|
@ -806,5 +821,7 @@ steppersync_flush(struct steppersync *ss, uint64_t move_clock)
|
||||||
// Transmit commands
|
// Transmit commands
|
||||||
if (!list_empty(&msgs))
|
if (!list_empty(&msgs))
|
||||||
serialqueue_send_batch(ss->sq, ss->cq, &msgs);
|
serialqueue_send_batch(ss->sq, ss->cq, &msgs);
|
||||||
|
|
||||||
|
steppersync_history_expire(ss, clear_history_clock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct steppersync *steppersync_alloc(
|
||||||
void steppersync_free(struct steppersync *ss);
|
void steppersync_free(struct steppersync *ss);
|
||||||
void steppersync_set_time(struct steppersync *ss, double time_offset
|
void steppersync_set_time(struct steppersync *ss, double time_offset
|
||||||
, double mcu_freq);
|
, double mcu_freq);
|
||||||
int steppersync_flush(struct steppersync *ss, uint64_t move_clock);
|
int steppersync_flush(struct steppersync *ss, uint64_t move_clock
|
||||||
|
, uint64_t clear_history_clock);
|
||||||
|
|
||||||
#endif // stepcompress.h
|
#endif // stepcompress.h
|
||||||
|
|
|
@ -163,11 +163,10 @@ trapq_append(struct trapq *tq, double print_time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HISTORY_EXPIRE (30.0)
|
|
||||||
|
|
||||||
// Expire any moves older than `print_time` from the trapezoid velocity queue
|
// Expire any moves older than `print_time` from the trapezoid velocity queue
|
||||||
void __visible
|
void __visible
|
||||||
trapq_finalize_moves(struct trapq *tq, double print_time)
|
trapq_finalize_moves(struct trapq *tq, double print_time
|
||||||
|
, double clear_history_time)
|
||||||
{
|
{
|
||||||
struct move *head_sentinel = list_first_entry(&tq->moves, struct move,node);
|
struct move *head_sentinel = list_first_entry(&tq->moves, struct move,node);
|
||||||
struct move *tail_sentinel = list_last_entry(&tq->moves, struct move, node);
|
struct move *tail_sentinel = list_last_entry(&tq->moves, struct move, node);
|
||||||
|
@ -190,10 +189,9 @@ trapq_finalize_moves(struct trapq *tq, double print_time)
|
||||||
if (list_empty(&tq->history))
|
if (list_empty(&tq->history))
|
||||||
return;
|
return;
|
||||||
struct move *latest = list_first_entry(&tq->history, struct move, node);
|
struct move *latest = list_first_entry(&tq->history, struct move, node);
|
||||||
double expire_time = latest->print_time + latest->move_t - HISTORY_EXPIRE;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct move *m = list_last_entry(&tq->history, struct move, node);
|
struct move *m = list_last_entry(&tq->history, struct move, node);
|
||||||
if (m == latest || m->print_time + m->move_t > expire_time)
|
if (m == latest || m->print_time + m->move_t > clear_history_time)
|
||||||
break;
|
break;
|
||||||
list_del(&m->node);
|
list_del(&m->node);
|
||||||
free(m);
|
free(m);
|
||||||
|
@ -206,7 +204,7 @@ trapq_set_position(struct trapq *tq, double print_time
|
||||||
, double pos_x, double pos_y, double pos_z)
|
, double pos_x, double pos_y, double pos_z)
|
||||||
{
|
{
|
||||||
// Flush all moves from trapq
|
// Flush all moves from trapq
|
||||||
trapq_finalize_moves(tq, NEVER_TIME);
|
trapq_finalize_moves(tq, NEVER_TIME, 0);
|
||||||
|
|
||||||
// Prune any moves in the trapq history that were interrupted
|
// Prune any moves in the trapq history that were interrupted
|
||||||
while (!list_empty(&tq->history)) {
|
while (!list_empty(&tq->history)) {
|
||||||
|
|
|
@ -43,7 +43,8 @@ void trapq_append(struct trapq *tq, double print_time
|
||||||
, double start_pos_x, double start_pos_y, double start_pos_z
|
, double start_pos_x, double start_pos_y, double start_pos_z
|
||||||
, double axes_r_x, double axes_r_y, double axes_r_z
|
, double axes_r_x, double axes_r_y, double axes_r_z
|
||||||
, double start_v, double cruise_v, double accel);
|
, double start_v, double cruise_v, double accel);
|
||||||
void trapq_finalize_moves(struct trapq *tq, double print_time);
|
void trapq_finalize_moves(struct trapq *tq, double print_time
|
||||||
|
, double clear_history_time);
|
||||||
void trapq_set_position(struct trapq *tq, double print_time
|
void trapq_set_position(struct trapq *tq, double print_time
|
||||||
, double pos_x, double pos_y, double pos_z);
|
, double pos_x, double pos_y, double pos_z);
|
||||||
int trapq_extract_old(struct trapq *tq, struct pull_move *p, int max
|
int trapq_extract_old(struct trapq *tq, struct pull_move *p, int max
|
||||||
|
|
|
@ -86,7 +86,8 @@ class ForceMove:
|
||||||
0., 0., 0., axis_r, 0., 0., 0., cruise_v, accel)
|
0., 0., 0., axis_r, 0., 0., 0., cruise_v, accel)
|
||||||
print_time = print_time + accel_t + cruise_t + accel_t
|
print_time = print_time + accel_t + cruise_t + accel_t
|
||||||
stepper.generate_steps(print_time)
|
stepper.generate_steps(print_time)
|
||||||
self.trapq_finalize_moves(self.trapq, print_time + 99999.9)
|
self.trapq_finalize_moves(self.trapq, print_time + 99999.9,
|
||||||
|
print_time + 99999.9)
|
||||||
stepper.set_trapq(prev_trapq)
|
stepper.set_trapq(prev_trapq)
|
||||||
stepper.set_stepper_kinematics(prev_sk)
|
stepper.set_stepper_kinematics(prev_sk)
|
||||||
toolhead.note_kinematic_activity(print_time)
|
toolhead.note_kinematic_activity(print_time)
|
||||||
|
|
|
@ -67,7 +67,8 @@ class ManualStepper:
|
||||||
0., cruise_v, accel)
|
0., cruise_v, accel)
|
||||||
self.next_cmd_time = self.next_cmd_time + accel_t + cruise_t + accel_t
|
self.next_cmd_time = self.next_cmd_time + accel_t + cruise_t + accel_t
|
||||||
self.rail.generate_steps(self.next_cmd_time)
|
self.rail.generate_steps(self.next_cmd_time)
|
||||||
self.trapq_finalize_moves(self.trapq, self.next_cmd_time + 99999.9)
|
self.trapq_finalize_moves(self.trapq, self.next_cmd_time + 99999.9,
|
||||||
|
self.next_cmd_time + 99999.9)
|
||||||
toolhead = self.printer.lookup_object('toolhead')
|
toolhead = self.printer.lookup_object('toolhead')
|
||||||
toolhead.note_kinematic_activity(self.next_cmd_time)
|
toolhead.note_kinematic_activity(self.next_cmd_time)
|
||||||
if sync:
|
if sync:
|
||||||
|
|
|
@ -211,8 +211,8 @@ class PrinterExtruder:
|
||||||
gcode.register_mux_command("ACTIVATE_EXTRUDER", "EXTRUDER",
|
gcode.register_mux_command("ACTIVATE_EXTRUDER", "EXTRUDER",
|
||||||
self.name, self.cmd_ACTIVATE_EXTRUDER,
|
self.name, self.cmd_ACTIVATE_EXTRUDER,
|
||||||
desc=self.cmd_ACTIVATE_EXTRUDER_help)
|
desc=self.cmd_ACTIVATE_EXTRUDER_help)
|
||||||
def update_move_time(self, flush_time):
|
def update_move_time(self, flush_time, clear_history_time):
|
||||||
self.trapq_finalize_moves(self.trapq, flush_time)
|
self.trapq_finalize_moves(self.trapq, flush_time, clear_history_time)
|
||||||
def get_status(self, eventtime):
|
def get_status(self, eventtime):
|
||||||
sts = self.heater.get_status(eventtime)
|
sts = self.heater.get_status(eventtime)
|
||||||
sts['can_extrude'] = self.heater.can_extrude
|
sts['can_extrude'] = self.heater.can_extrude
|
||||||
|
@ -313,7 +313,7 @@ class PrinterExtruder:
|
||||||
class DummyExtruder:
|
class DummyExtruder:
|
||||||
def __init__(self, printer):
|
def __init__(self, printer):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
def update_move_time(self, flush_time):
|
def update_move_time(self, flush_time, clear_history_time):
|
||||||
pass
|
pass
|
||||||
def check_move(self, move):
|
def check_move(self, move):
|
||||||
raise move.move_error("Extrude when no extruder present")
|
raise move.move_error("Extrude when no extruder present")
|
||||||
|
|
|
@ -955,7 +955,7 @@ class MCU:
|
||||||
self._reserved_move_slots += 1
|
self._reserved_move_slots += 1
|
||||||
def register_flush_callback(self, callback):
|
def register_flush_callback(self, callback):
|
||||||
self._flush_callbacks.append(callback)
|
self._flush_callbacks.append(callback)
|
||||||
def flush_moves(self, print_time):
|
def flush_moves(self, print_time, clear_history_time):
|
||||||
if self._steppersync is None:
|
if self._steppersync is None:
|
||||||
return
|
return
|
||||||
clock = self.print_time_to_clock(print_time)
|
clock = self.print_time_to_clock(print_time)
|
||||||
|
@ -963,7 +963,10 @@ class MCU:
|
||||||
return
|
return
|
||||||
for cb in self._flush_callbacks:
|
for cb in self._flush_callbacks:
|
||||||
cb(print_time, clock)
|
cb(print_time, clock)
|
||||||
ret = self._ffi_lib.steppersync_flush(self._steppersync, clock)
|
clear_history_clock = \
|
||||||
|
max(0, self.print_time_to_clock(clear_history_time))
|
||||||
|
ret = self._ffi_lib.steppersync_flush(self._steppersync, clock,
|
||||||
|
clear_history_clock)
|
||||||
if ret:
|
if ret:
|
||||||
raise error("Internal error in MCU '%s' stepcompress"
|
raise error("Internal error in MCU '%s' stepcompress"
|
||||||
% (self._name,))
|
% (self._name,))
|
||||||
|
|
|
@ -195,6 +195,7 @@ MIN_KIN_TIME = 0.100
|
||||||
MOVE_BATCH_TIME = 0.500
|
MOVE_BATCH_TIME = 0.500
|
||||||
STEPCOMPRESS_FLUSH_TIME = 0.050
|
STEPCOMPRESS_FLUSH_TIME = 0.050
|
||||||
SDS_CHECK_TIME = 0.001 # step+dir+step filter in stepcompress.c
|
SDS_CHECK_TIME = 0.001 # step+dir+step filter in stepcompress.c
|
||||||
|
MOVE_HISTORY_EXPIRE = 30.
|
||||||
|
|
||||||
DRIP_SEGMENT_TIME = 0.050
|
DRIP_SEGMENT_TIME = 0.050
|
||||||
DRIP_TIME = 0.100
|
DRIP_TIME = 0.100
|
||||||
|
@ -289,13 +290,15 @@ class ToolHead:
|
||||||
for sg in self.step_generators:
|
for sg in self.step_generators:
|
||||||
sg(sg_flush_time)
|
sg(sg_flush_time)
|
||||||
self.last_sg_flush_time = sg_flush_time
|
self.last_sg_flush_time = sg_flush_time
|
||||||
|
clear_history_time = self.mcu.estimated_print_time(
|
||||||
|
self.reactor.monotonic() - MOVE_HISTORY_EXPIRE)
|
||||||
# Free trapq entries that are no longer needed
|
# Free trapq entries that are no longer needed
|
||||||
free_time = sg_flush_time - self.kin_flush_delay
|
free_time = sg_flush_time - self.kin_flush_delay
|
||||||
self.trapq_finalize_moves(self.trapq, free_time)
|
self.trapq_finalize_moves(self.trapq, free_time, clear_history_time)
|
||||||
self.extruder.update_move_time(free_time)
|
self.extruder.update_move_time(free_time, clear_history_time)
|
||||||
# Flush stepcompress and mcu steppersync
|
# Flush stepcompress and mcu steppersync
|
||||||
for m in self.all_mcus:
|
for m in self.all_mcus:
|
||||||
m.flush_moves(flush_time)
|
m.flush_moves(flush_time, clear_history_time)
|
||||||
self.last_flush_time = flush_time
|
self.last_flush_time = flush_time
|
||||||
def _advance_move_time(self, next_print_time):
|
def _advance_move_time(self, next_print_time):
|
||||||
pt_delay = self.kin_flush_delay + STEPCOMPRESS_FLUSH_TIME
|
pt_delay = self.kin_flush_delay + STEPCOMPRESS_FLUSH_TIME
|
||||||
|
@ -522,7 +525,7 @@ class ToolHead:
|
||||||
self.move_queue.flush()
|
self.move_queue.flush()
|
||||||
except DripModeEndSignal as e:
|
except DripModeEndSignal as e:
|
||||||
self.move_queue.reset()
|
self.move_queue.reset()
|
||||||
self.trapq_finalize_moves(self.trapq, self.reactor.NEVER)
|
self.trapq_finalize_moves(self.trapq, self.reactor.NEVER, 0)
|
||||||
# Exit "Drip" state
|
# Exit "Drip" state
|
||||||
self.reactor.update_timer(self.flush_timer, self.reactor.NOW)
|
self.reactor.update_timer(self.flush_timer, self.reactor.NOW)
|
||||||
self.flush_step_generation()
|
self.flush_step_generation()
|
||||||
|
|
Loading…
Reference in New Issue