Source code for gcode_reader.emulate.machines.small_scale_am
importrefrom..machineimportMachinefrom..extrudersimportStepperExtruder,Extruderfrom..operationsimportAdditiveOperationfrom..importmachine_optionsfrom..importcommandsfrom..registryimportregister# PrusaSlicer embeds machine limits as "; key = value" lines between these markers._PRUSA_FOOTER_BEGIN="prusaslicer_config = begin"_PRUSA_FOOTER_END="prusaslicer_config = end"_PRUSA_LIMIT_KEYS={"machine_max_feedrate_x":"max_feedrate",# mm/s"machine_max_acceleration_x":"max_acceleration",# mm/s²"machine_max_jerk_x":"max_jerk",# mm/s}_PRUSA_FOOTER_RE=re.compile(r"^;\s*([\w]+)\s*=\s*([\d.]+)")
[docs]@register("desktop",aliases=["desktopam"])classDesktopAM(Machine):"""Base class for desktop AM machines with Marlin Firmware"""def__init__(self,extrusion_type=machine_options.REL_EXTRUSION,**kwargs):super().__init__(tools=(StepperExtruder()),extrusion_type=extrusion_type,**kwargs)# Motion limits from explicit kwargs (e.g. DesktopAM(machine_max_feedrate_x=350)).# Values from PrusaSlicer config are in mm/s and mm/s²; no unit conversion needed.options=self.options.all_optionsif"machine_max_feedrate_x"inoptions:self.options.max_feedrate=float(options["machine_max_feedrate_x"])if"machine_max_acceleration_x"inoptions:self.options.max_acceleration=float(options["machine_max_acceleration_x"])if"machine_max_jerk_x"inoptions:self.options.max_jerk=float(options["machine_max_jerk_x"])@propertydefrelative_extrusion(self)->bool:# NOTE: This returns True if all extruders are in relative mode. If there were ever multiple extruders with different relative/absolute states, we would need to do something different.extruders=[tfortinself.toolsifisinstance(t,Extruder)]ifnotextruders:returnFalsereturnall(e.relative_extrusionforeinextruders)@relative_extrusion.setterdefrelative_extrusion(self,val):fortoolinself.tools:ifisinstance(tool,Extruder):tool.relative_extrusion=valdef_load_prusa_machine_limits(self,filepath:str)->None:"""Read machine kinematic limits from a PrusaSlicer gcode file footer. PrusaSlicer embeds full machine config between ``prusaslicer_config = begin`` and ``prusaslicer_config = end`` comment lines. This scans that section for the three limits we need (feedrate, acceleration, jerk in X) and populates ``self.options`` so ``get_motion_limits()`` can apply them to the motion profile. Values are stored in mm/s / mm/s² — no conversion needed. """found={}in_footer=Falsetry:withopen(filepath,"r",encoding="utf-8",errors="replace")asf:forlineinf:low=line.lower()if_PRUSA_FOOTER_BEGINinlow:in_footer=Truecontinueif_PRUSA_FOOTER_ENDinlow:breakifnotin_footer:continuem=_PRUSA_FOOTER_RE.match(line)ifmandm.group(1)in_PRUSA_LIMIT_KEYS:found[_PRUSA_LIMIT_KEYS[m.group(1)]]=float(m.group(2))except(FileNotFoundError,PermissionError):returnif"max_feedrate"infound:self.options.max_feedrate=found["max_feedrate"]if"max_acceleration"infound:self.options.max_acceleration=found["max_acceleration"]if"max_jerk"infound:self.options.max_jerk=found["max_jerk"]
def_config(self,command,process_data):# These are Marlin codesifisinstance(command,commands.M):ifcommand.code==82:self.relative_extrusion=Falseelifcommand.code==83:self.relative_extrusion=Truereturnsuper()._config(command,process_data)