Gcode-->quene_step
一、klippy.py入口,注意###处
#klippy.py
class Printer:
config_error = configfile.error
command_error = gcode.CommandError
def __init__(self, main_reactor, bglogger, start_args ):
self.bglogger = bglogger
self.start_args = start_args
self.reactor = main_reactor
self.reactor.register_callback(self._connect)
self.state_message = message_startup
self.in_shutdown_state = False
self.run_result = None
self.event_handlers = {}
self.objects = collections.OrderedDict() ###1
# Init printer components that must be setup prior to config
for m in [gcode, webhooks]: ####1
m.add_early_printer_objects(self) ####1
二、gcode.py
# Support reading gcode from a pseudo-tty interface
class GCodeIO:
def __init__(self, printer):
self.printer = printer
printer.register_event_handler("klippy:ready", self._handle_ready)
printer.register_event_handler("klippy:shutdown", self._handle_shutdown)
self.gcode = printer.lookup_object('gcode')
self.gcode_mutex = self.gcode.get_mutex()
self.fd = printer.get_start_args().get("gcode_fd")
self.reactor = printer.get_reactor()
self.is_printer_ready = False
self.is_processing_data = False
self.is_fileinput = not not printer.get_start_args().get("debuginput")
self.pipe_is_active = True
self.fd_handle = None
if not self.is_fileinput:
self.gcode.register_output_handler(self._respond_raw)
self.fd_handle = self.reactor.register_fd(self.fd, self._process_data) ###2
self.partial_input = ""
self.pending_commands = []
self.bytes_read = 0
self.input_log = collections.deque([], 50)
m112_r = re.compile(r'^(?:[nN][0-9]+)?\s*[mM]112(?:\s|$)')
def _process_data(self, eventtime): ###3
# Read input, separate by newline, and add to pending_commands
try:
data = str(os.read(self.fd, 4096).decode())
except (os.error, UnicodeDecodeError):
logging.exception("Read g-code")
return
self.input_log.append((eventtime, data))
self.bytes_read += len(data)
lines = data.split('\n')
lines[0] = self.partial_input + lines[0]
self.partial_input = lines.pop()
pending_commands = self.pending_commands
pending_commands.extend(lines)
self.pipe_is_active = True
# Special handling for debug file input EOF
if not data and self.is_fileinput:
if not self.is_processing_data:
self.reactor.unregister_fd(self.fd_handle)
self.fd_handle = None
self.gcode.request_restart('exit')
pending_commands.append("")
# Handle case where multiple commands pending
if self.is_processing_data or len(pending_commands) > 1:
if len(pending_commands) < 20:
# Check for M112 out-of-order
for line in lines:
if self.m112_r.match(line) is not None:
self.gcode.cmd_M112(None)
if self.is_processing_data:
if len(pending_commands) >= 20:
# Stop reading input
self.reactor.unregister_fd(self.fd_handle)
self.fd_handle = None
return
# Process commands
self.is_processing_data = True
while pending_commands:
self.pending_commands = []
with self.gcode_mutex:
self.gcode._process_commands(pending_commands) ###4
pending_commands = self.pending_commands
self.is_processing_data = False
if self.fd_handle is None:
self.fd_handle = self.reactor.register_fd(self.fd,
self._process_data)
def _respond_raw(self, msg):
if self.pipe_is_active:
try:
os.write(self.fd, (msg+"\n").encode())
except os.error:
logging.exception("Write g-code response")
self.pipe_is_active = False
def stats(self, eventtime):
return False, "gcodein=%d" % (self.bytes_read,)
args_r = re.compile('([A-Z_]+|[A-Z*])')
def _process_commands(self, commands, need_ack=True): ###5
for line in commands:
# Ignore comments and leading/trailing spaces
line = origline = line.strip()
cpos = line.find(';')
if cpos >= 0:
line = line[:cpos]
# Break line into parts and determine command
parts = self.args_r.split(line.upper())
if ''.join(parts[:2]) == 'N':
# Skip line number at start of command
cmd = ''.join(parts[3:5]).strip()
else:
cmd = ''.join(parts[:3]).strip()
# Build gcode "params" dictionary
params = { parts[i]: parts[i+1].strip()
for i in range(1, len(parts), 2) }
gcmd = GCodeCommand(self, cmd, origline, params, need_ack)
# Invoke handler for command
handler = self.gcode_handlers.get(cmd, self.cmd_default)
try:
handler(gcmd)
except self.error as e:
self._respond_error(str(e))
self.printer.send_event("gcode:command_error")
if not need_ack:
raise
except:
msg = 'Internal error on command:"%s"' % (cmd,)
logging.exception(msg)
self.printer.invoke_shutdown(msg)
self._respond_error(msg)
if not need_ack:
raise
gcmd.ack()
def add_early_printer_objects(printer): ###
printer.add_object('gcode', GCodeDispatch(printer))###
printer.add_object('gcode_io', GCodeIO(printer))###
三、cmd_G1命令在toolhead注册
class Printer:
config_error = configfile.error
command_error = gcode.CommandError
def __init__(self, main_reactor, bglogger, start_args ):
self.bglogger = bglogger
self.start_args = start_args
self.reactor = main_reactor
self.reactor.register_callback(self._connect)###
self.state_message = message_startup
self.in_shutdown_state = False
self.run_result = None
self.event_handlers = {}
self.objects = collections.OrderedDict()
# Init printer components that must be setup prior to config
for m in [gcode, webhooks]:
m.add_early_printer_objects(self)
def _connect(self, eventtime):###
try:
self._read_config() ###
self.send_event("klippy:mcu_identify")
for cb in self.event_handlers.get("klippy:connect", []):
if self.state_message is not message_startup:
return
cb()
except (self.config_error, pins.error) as e:
logging.exception("Config error")
self._set_state("%s\n%s" % (str(e), message_restart))
return
except msgproto.error as e:
msg = "Protocol error"
logging.exception(msg)
self._set_state(msg)
self.send_event("klippy:notify_mcu_error", msg, {"error": str(e)})
util.dump_mcu_build()
return
except mcu.error as e:
msg = "MCU error during connect"
logging.exception(msg)
self._set_state(msg)
self.send_event("klippy:notify_mcu_error", msg, {"error": str(e)})
util.dump_mcu_build()
return
except Exception as e:
logging.exception("Unhandled exception during connect")
self._set_state("Internal error during connect: %s\n%s"
% (str(e), message_restart,))
return
try:
self._set_state(message_ready)
for cb in self.event_handlers.get("klippy:ready", []):
if self.state_message is not message_ready:
return
cb()
except Exception as e:
logging.exception("Unhandled exception during ready callback")
self.invoke_shutdown("Internal error during ready callback: %s"
% (str(e),))
def _read_config(self):###
self.objects['configfile'] = pconfig = configfile.PrinterConfig(self)
config = pconfig.read_main_config()
if self.bglogger is not None:
pconfig.log_config(config)
# Create printer components
for m in [pins, mcu]:
m.add_printer_objects(config)
for section_config in config.get_prefix_sections(''):
self.load_object(config, section_config.get_name(), None)
for m in [toolhead]:###
m.add_printer_objects(config)###
# Validate that there are no undefined parameters in the config file
pconfig.check_unused_options(config)
class ToolHead:
def __init__(self, config):
self.printer = config.get_printer()
self.reactor = self.printer.get_reactor()
self.all_mcus = [
m for n, m in self.printer.lookup_objects(module='mcu')]
self.mcu = self.all_mcus[0]
self.lookahead = LookAheadQueue()
self.lookahead.set_flush_time(BUFFER_TIME_HIGH)
self.commanded_pos = [0., 0., 0., 0.]
# Velocity and acceleration control
self.max_velocity = config.getfloat('max_velocity', above=0.)
self.max_accel = config.getfloat('max_accel', above=0.)
self.min_cruise_ratio = config.getfloat('minimum_cruise_ratio',
0.5, below=1., minval=0.)
self.square_corner_velocity = config.getfloat(
'square_corner_velocity', 5., minval=0.)
self.junction_deviation = self.max_accel_to_decel = 0.
self._calc_junction_deviation()
# Input stall detection
self.check_stall_time = 0.
self.print_stall = 0
# Input pause tracking
self.can_pause = True
if self.mcu.is_fileoutput():
self.can_pause = False
self.need_check_pause = -1.
# Print time tracking
self.print_time = 0.
self.special_queuing_state = "NeedPrime"
self.priming_timer = None
# Flush tracking
self.flush_timer = self.reactor.register_timer(self._flush_handler)
self.do_kick_flush_timer = True
self.last_flush_time = self.min_restart_time = 0.
self.need_flush_time = self.step_gen_time = self.clear_history_time = 0.
# Kinematic step generation scan window time tracking
self.kin_flush_delay = SDS_CHECK_TIME
self.kin_flush_times = []
# Setup iterative solver
ffi_main, ffi_lib = chelper.get_ffi()
self.trapq = ffi_main.gc(ffi_lib.trapq_alloc(), ffi_lib.trapq_free)
self.trapq_append = ffi_lib.trapq_append
self.trapq_finalize_moves = ffi_lib.trapq_finalize_moves
# Motion flushing
self.step_generators = []
self.flush_trapqs = [self.trapq]
# Create kinematics class
gcode = self.printer.lookup_object('gcode')
self.Coord = gcode.Coord
extruder = kinematics.extruder.DummyExtruder(self.printer)
self.extra_axes = [extruder]
kin_name = config.get('kinematics')
try:
mod = importlib.import_module('kinematics.' + kin_name)
self.kin = mod.load_kinematics(self, config)
except config.error as e:
raise
except self.printer.lookup_object('pins').error as e:
raise
except:
msg = "Error loading kinematics '%s'" % (kin_name,)
logging.exception(msg)
raise config.error(msg)
# Register commands
gcode.register_command('G4', self.cmd_G4)
gcode.register_command('M400', self.cmd_M400)
gcode.register_command('SET_VELOCITY_LIMIT',
self.cmd_SET_VELOCITY_LIMIT,
desc=self.cmd_SET_VELOCITY_LIMIT_help)
gcode.register_command('M204', self.cmd_M204)
self.printer.register_event_handler("klippy:shutdown",
self._handle_shutdown)
# Load some default modules ###
modules = ["gcode_move", "homing", "idle_timeout", "statistics",
"manual_probe", "tuning_tower", "garbage_collection"]
for module_name in modules:
self.printer.load_object(config, module_name)###
def add_printer_objects(config):###
config.get_printer().add_object('toolhead', ToolHead(config))
kinematics.extruder.add_printer_objects(config)
四、gcode_move.py
class GCodeMove:
def __init__(self, config):
self.printer = printer = config.get_printer()
printer.register_event_handler("klippy:ready", self._handle_ready)
printer.register_event_handler("klippy:shutdown", self._handle_shutdown)
printer.register_event_handler("toolhead:set_position",
self.reset_last_position)
printer.register_event_handler("toolhead:manual_move",
self.reset_last_position)
printer.register_event_handler("toolhead:update_extra_axes",
self._update_extra_axes)
printer.register_event_handler("gcode:command_error",
self.reset_last_position)
printer.register_event_handler("extruder:activate_extruder",
self._handle_activate_extruder)
printer.register_event_handler("homing:home_rails_end",
self._handle_home_rails_end)
self.is_printer_ready = False
# Register g-code commands
gcode = printer.lookup_object('gcode')
handlers = [
'G1', 'G20', 'G21',
'M82', 'M83', 'G90', 'G91', 'G92', 'M220', 'M221',
'SET_GCODE_OFFSET', 'SAVE_GCODE_STATE', 'RESTORE_GCODE_STATE',
]
for cmd in handlers:
func = getattr(self, 'cmd_' + cmd)
desc = getattr(self, 'cmd_' + cmd + '_help', None)
gcode.register_command(cmd, func, False, desc)
gcode.register_command('G0', self.cmd_G1)
gcode.register_command('M114', self.cmd_M114, True)
gcode.register_command('GET_POSITION', self.cmd_GET_POSITION, True,
desc=self.cmd_GET_POSITION_help)
self.Coord = gcode.Coord
# G-Code coordinate manipulation
self.absolute_coord = self.absolute_extrude = True
self.base_position = [0.0, 0.0, 0.0, 0.0]
self.last_position = [0.0, 0.0, 0.0, 0.0]
self.homing_position = [0.0, 0.0, 0.0, 0.0]
self.axis_map = {'X':0, 'Y': 1, 'Z': 2, 'E': 3}
self.speed = 25.
self.speed_factor = 1. / 60.
self.extrude_factor = 1.
# G-Code state
self.saved_states = {}
self.move_transform = self.move_with_transform = None
self.position_with_transform = (lambda: [0., 0., 0., 0.])
# G-Code movement commands
def cmd_G1(self, gcmd):
# Move
params = gcmd.get_command_parameters()
try:
for axis, pos in self.axis_map.items():
if axis in params:
v = float(params[axis])
absolute_coord = self.absolute_coord
if axis == 'E':
v *= self.extrude_factor
if not self.absolute_extrude:
absolute_coord = False
if not absolute_coord:
# value relative to position of last move
self.last_position[pos] += v
else:
# value relative to base coordinate position
self.last_position[pos] = v + self.base_position[pos]
if 'F' in params:
gcode_speed = float(params['F'])
if gcode_speed <= 0.:
raise gcmd.error("Invalid speed in '%s'"
% (gcmd.get_commandline(),))
self.speed = gcode_speed * self.speed_factor
except ValueError as e:
raise gcmd.error("Unable to parse move '%s'"
% (gcmd.get_commandline(),))
self.move_with_transform(self.last_position, self.speed)
2161

被折叠的 条评论
为什么被折叠?



