class Position(object): def __init__(self, octolapseSettings, octoprintPrinterProfile, g90InfluencesExtruder): self.Settings = octolapseSettings self.Printer = self.Settings.CurrentPrinter() self.OctoprintPrinterProfile = octoprintPrinterProfile self.Origin = { "X": self.Printer.origin_x, "Y": self.Printer.origin_y, "Z": self.Printer.origin_z } self.BoundingBox = utility.GetBoundingBox(self.Printer, octoprintPrinterProfile) self.PrinterTolerance = self.Printer.printer_position_confirmation_tolerance self.Positions = [] self.Reset() self.Extruder = Extruder(octolapseSettings) self.G90InfluencesExtruder = g90InfluencesExtruder if (self.Printer.z_hop is None): self.Printer.z_hop = 0 self.Commands = Commands() def Reset(self): # todo: This reset function doesn't seem to reset everything. self.Positions = [] self.SavedPosition = None def UpdatePosition(self, x=None, y=None, z=None, e=None, f=None, force=False, calculateChanges=False): numPositions = len(self.Positions) if (numPositions == 0): return pos = self.Positions[0] pos.UpdatePosition(self.BoundingBox, x, y, z, e, f, force) if (calculateChanges and numPositions > 1): previousPos = self.Positions[1] pos.HasPositionChanged = not pos.IsPositionEqual( previousPos, self.PrinterTolerance) pos.HasStateChanged = not pos.IsStateEqual(previousPos, self.PrinterTolerance) def SavePosition(self, x=None, y=None, z=None, e=None, f=None, force=False): if (len(self.Positions) == 0): return self.SavedPosition = Pos(self.Positions[0]) def ToDict(self): positionDict = None if (len(self.Positions) > 0): previousPos = self.Positions[0] return previousPos.ToDict() return None def ToPositionDict(self): positionDict = None if (len(self.Positions) > 0): previousPos = self.Positions[0] return previousPos.ToPositionDict() return None def ToStateDict(self): positionDict = None if (len(self.Positions) > 0): previousPos = self.Positions[0] return previousPos.ToStateDict() return None def ZDelta(self, pos): if (len(self.Positions) > 0): previousPos = self.Positions[0] # calculate ZDelta if (pos.Height is not None): if (previousPos.Height is None): return pos.Height else: return pos.Height - previousPos.Height return 0 def HasStateChanged(self, index=0): if (len(self.Positions) > index): return self.Positions[index].HasStateChanged return None def HasPositionChanged(self, index=0): if (len(self.Positions) > index): return self.Positions[index].HasPositionChanged return None def HasPositionError(self, index=0): if (len(self.Positions) > index): return self.Positions[index].HasPositionError return None def DistanceToZLift(self, index=0): if (len(self.Positions) > index): pos = self.Positions[index] currentLift = utility.round_to(pos.Z - pos.Height, self.PrinterTolerance) if (currentLift < self.Printer.z_hop): return self.Printer.z_hop - currentLift return 0 return None def PositionError(self, index=0): if (len(self.Positions) > index): return self.Positions[index].PositionError return None def X(self, index=0): if (len(self.Positions) > index): return self.Positions[index].X return None def Y(self, index=0): if (len(self.Positions) > index): return self.Positions[index].Y return None def Z(self, index=0): if (len(self.Positions) > index): return self.Positions[index].Z return None def E(self, index=0): if (len(self.Positions) > index): return self.Positions[index].E return None def F(self, index=0): if (len(self.Positions) > index): return self.Positions[index].F return None def IsZHop(self, index=0): if (len(self.Positions) > index): return self.Positions[index].IsZHop return None def IsLayerChange(self, index=0): if (len(self.Positions) > index): return self.Positions[index].IsLayerChange return None def Layer(self, index=0): if (len(self.Positions) > index): return self.Positions[index].Layer return None def Height(self, index=0): if (len(self.Positions) > index): return self.Positions[index].Height return None def IsRelative(self, index=0): if (len(self.Positions) > index): return self.Positions[index].IsRelative return None def IsExtruderRelative(self, index=0): if (len(self.Positions) > index): return self.Positions[index].IsExtruderRelative return None def HasReceivedHomeCommand(self, index=0): if (len(self.Positions) > index): return self.Positions[ index].HasReceivedHomeCommand and self.HasHomedAxis(index) return False def UndoUpdate(self): if (len(self.Positions) > 0): del self.Positions[0] self.Extruder.UndoUpdate() def Update(self, gcode): command = self.Commands.GetCommand(gcode) # a new position pos = None previousPos = None numPositions = len(self.Positions) if (numPositions > 0): pos = Pos(self.OctoprintPrinterProfile, self.Positions[0]) if (numPositions > 1): previousPos = Pos(self.OctoprintPrinterProfile, self.Positions[1]) if (pos is None): pos = Pos(self.OctoprintPrinterProfile) if (previousPos is None): previousPos = Pos(self.OctoprintPrinterProfile) # reset the current position state (copied from the previous position, or a new position) pos.ResetState() # set the pos gcode command pos.GCode = gcode # apply the command to the position tracker if (command is not None): # I'm currently too lazy to keep this DRY # TODO: Make DRY if (command.Command in ["G0", "G1"]): #Movement if (command.Parse()): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived("Received {0}".format( command.Name)) x = command.Parameters["X"].Value y = command.Parameters["Y"].Value z = command.Parameters["Z"].Value e = command.Parameters["E"].Value f = command.Parameters["F"].Value if (x is not None or y is not None or z is not None or f is not None): if (pos.HasPositionError and not pos.IsRelative): pos.HasPositionError = False pos.PositionError = "" pos.UpdatePosition(self.BoundingBox, x, y, z, e=None, f=f) if (e is not None): if (pos.IsExtruderRelative is not None): if (pos.HasPositionError and not pos.IsExtruderRelative): pos.HasPositionError = False pos.PositionError = "" pos.UpdatePosition(self.BoundingBox, x=None, y=None, z=None, e=e, f=None) else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to update the extruder position, no extruder coordinate system has been selected (absolute/relative)." ) message = "Position Change - {0} - {1} Move From(X:{2},Y:{3},Z:{4},E:{5}) - To(X:{6},Y:{7},Z:{8},E:{9})" if (previousPos is None): message = message.format( gcode, "Relative" if pos.IsRelative else "Absolute", "None", "None", "None", "None", pos.X, pos.Y, pos.Z, pos.E) else: message = message.format( gcode, "Relative" if pos.IsRelative else "Absolute", previousPos.X, previousPos.Y, previousPos.Z, previousPos.E, pos.X, pos.Y, pos.Z, pos.E) self.Settings.CurrentDebugProfile().LogPositionChange( message) else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to parse the gcode command: {0}". format(gcode)) elif (command.Command == "G28"): # Home if (command.Parse()): pos.HasReceivedHomeCommand = True x = command.Parameters["X"].Value y = command.Parameters["Y"].Value z = command.Parameters["Z"].Value xHomed = False yHomed = False zHomed = False if (x is not None): xHomed = True if (y is not None): yHomed = True if (z is not None): zHomed = True if (x is None and y is None and z is None): xHomed = True yHomed = True zHomed = True homeStrings = [] if (xHomed): pos.XHomed = True pos.X = self.Origin[ "X"] if not self.Printer.auto_detect_origin else None if (pos.X is None): homeStrings.append("Homing X to Unknown Origin.") else: homeStrings.append("Homing X to {0}.".format( GetFormattedCoordinate(pos.X))) zHomedString = "" if (yHomed): pos.YHomed = True pos.Y = self.Origin[ "Y"] if not self.Printer.auto_detect_origin else None if (pos.Y is None): homeStrings.append("Homing Y to Unknown Origin.") else: homeStrings.append("Homing Y to {0}.".format( GetFormattedCoordinate(pos.Y))) xHomedString = "" if (zHomed): pos.ZHomed = True pos.Z = self.Origin[ "Z"] if not self.Printer.auto_detect_origin else None if (pos.Z is None): homeStrings.append("Homing Z to Unknown Origin.") else: homeStrings.append("Homing Z to {0}.".format( GetFormattedCoordinate(pos.Z))) self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived("Received G28 - ".format( " ".join(homeStrings))) pos.HasPositionError = False pos.PositionError = None else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to parse the Gcode:{0}".format( gcode)) elif (command.Command == "G90"): # change x,y,z to absolute if (pos.IsRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Switching to absolute x,y,z coordinates." ) pos.IsRelative = False else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Already using absolute x,y,z coordinates." ) # for some firmwares we need to switch the extruder to absolute coordinates as well if (self.G90InfluencesExtruder): if (pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Switching to absolute extruder coordinates" ) pos.IsExtruderRelative = False else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Already using absolute extruder coordinates" ) elif (command.Command == "G91"): # change x,y,z to relative if (not pos.IsRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Switching to relative x,y,z coordinates" ) pos.IsRelative = True else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Already using relative x,y,z coordinates" ) # for some firmwares we need to switch the extruder to absolute coordinates as well if (self.G90InfluencesExtruder): if (not pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Switching to relative extruder coordinates" ) pos.IsExtruderRelative = True else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Already using relative extruder coordinates" ) elif (command.Command == "M83"): # Extruder - Set Relative if (pos.IsExtruderRelative is None or not pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received M83 - Switching Extruder to Relative Coordinates" ) pos.IsExtruderRelative = True elif (command.Command == "M82"): # Extruder - Set Absolute if (pos.IsExtruderRelative is None or pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received M82 - Switching Extruder to Absolute Coordinates" ) pos.IsExtruderRelative = False elif (command.Command == "G92"): # Set Position (offset) if (command.Parse()): previousRelativeValue = pos.IsRelative previousExtruderRelativeValue = pos.IsExtruderRelative x = command.Parameters["X"].Value y = command.Parameters["Y"].Value z = command.Parameters["Z"].Value e = command.Parameters["E"].Value resetAll = False if (x is None and y is None and z is None and e is None): pos.XOffset = pos.X pos.YOffset = pos.Y pos.ZOffset = pos.Z pos.EOffset = pos.E # set the offsets if they are provided if (x is not None and pos.X is not None and pos.XHomed): pos.XOffset = pos.X - utility.getfloat(x, 0) if (y is not None and pos.Y is not None and pos.YHomed): pos.YOffset = pos.Y - utility.getfloat(y, 0) if (z is not None and pos.Z is not None and pos.ZHomed): pos.ZOffset = pos.Z - utility.getfloat(z, 0) if (e is not None and pos.E is not None): pos.EOffset = pos.E - utility.getfloat(e, 0) self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G92 - Set Position. Command:{0}, XOffset:{1}, YOffset:{2}, ZOffset:{3}, EOffset:{4}" .format(gcode, pos.XOffset, pos.YOffset, pos.ZOffset, pos.EOffset)) else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to parse the Gcode:{0}".format( gcode)) ######################################## # Update the extruder monitor. self.Extruder.Update(self.ERelative(pos)) ######################################## # If we have a homed axis, detect changes. ######################################## hasExtruderChanged = self.Extruder.HasChanged() pos.HasPositionChanged = not pos.IsPositionEqual( previousPos, self.PrinterTolerance) pos.HasStateChanged = not pos.IsStateEqual(previousPos, self.PrinterTolerance) if (self.HasHomedPosition()): if (hasExtruderChanged or pos.HasPositionChanged): # calculate LastExtrusionHeight and Height if (self.Extruder.IsExtruding()): pos.LastExtrusionHeight = pos.Z if (pos.Height is None or utility.round_to(pos.Z, self.PrinterTolerance) > previousPos.Height): pos.Height = utility.round_to( pos.Z, self.PrinterTolerance) self.Settings.CurrentDebugProfile( ).LogPositionHeightChange( "Position - Reached New Height:{0}.".format( pos.Height)) # calculate layer change if (utility.round_to(self.ZDelta(pos), self.PrinterTolerance) > 0 or pos.Layer == 0): pos.IsLayerChange = True pos.Layer += 1 self.Settings.CurrentDebugProfile( ).LogPositionLayerChange( "Position - Layer:{0}.".format(pos.Layer)) else: pos.IsLayerChange = False # Calculate ZHop based on last extrusion height if (pos.LastExtrusionHeight is not None): # calculate lift, taking into account floating point rounding lift = utility.round_to( pos.Z - pos.LastExtrusionHeight, self.PrinterTolerance) if (lift >= self.Printer.z_hop): lift = self.Printer.z_hop isLifted = self.Printer.z_hop > 0.0 and lift >= self.Printer.z_hop and ( not self.Extruder.IsExtruding() or self.Extruder.IsExtrudingStart()) if (isLifted): pos.IsZHop = True if (pos.IsZHop): self.Settings.CurrentDebugProfile().LogPositionZHop( "Position - Zhop:{0}".format(self.Printer.z_hop)) # Add the current position, remove positions if we have more than 5 from the end self.Positions.insert(0, pos) while (len(self.Positions) > 5): del self.Positions[5] def HasHomedPosition(self, index=0): if (len(self.Positions) <= index): return None pos = self.Positions[index] return (self.HasHomedAxis(index) and pos.X is not None and pos.Y is not None and pos.Z is not None) def HasHomedAxis(self, index=0): if (len(self.Positions) <= index): return None pos = self.Positions[index] return (pos.XHomed and pos.YHomed and pos.ZHomed) def XRelative(self): if (len(self.Positions) < 2): return None pos = self.Positions[0] prevoiusPos = self.Positions[1] return pos.X - previousPos.X def YRelative(self): if (len(self.Positions) < 2): return None pos = self.Positions[0] prevoiusPos = self.Positions[1] return pos.Y - previousPos.Y def ZRelative(self): if (len(self.Positions) < 2): return None pos = self.Positions[0] prevoiusPos = self.Positions[1] return pos.Z - previousPos.Z def ERelative(self, pos): if (len(self.Positions) < 1): return None previousPos = self.Positions[0] return pos.E - previousPos.E def IsAtPosition(self, x, y, z, pos, tolerance, applyOffset): if (applyOffset): x = x + pos.XOffset y = y + pos.YOffset if (z is not None): z = z + pos.ZOffset if ((pos.X is None or utility.isclose(pos.X, x, abs_tol=tolerance)) and (pos.Y is None or utility.isclose(pos.Y, y, abs_tol=tolerance)) and (z is None or pos.Z is None or utility.isclose(pos.Z, z, abs_tol=tolerance))): return True return False def IsAtPreviousPosition(self, x, y, z=None, applyOffset=True): if (len(self.Positions) < 2): return False return self.IsAtPosition( x, y, z, self.Positions[1], self.Printer.printer_position_confirmation_tolerance, True) def IsAtCurrentPosition(self, x, y, z=None, applyOffset=True): if (len(self.Positions) < 1): return False return self.IsAtPosition( x, y, z, self.Positions[0], self.Printer.printer_position_confirmation_tolerance, True) def IsAtSavedPosition(self, x, y, z=None, applyOffset=True): if (self.SavedPosition is None): return False return self.IsAtPosition( x, y, z, self.SavedPosition, self.Printer.printer_position_confirmation_tolerance, True)
class Position(object): def __init__(self, octolapseSettings, octoprintPrinterProfile, g90InfluencesExtruder): self.Settings = octolapseSettings self.Printer = self.Settings.CurrentPrinter() self.OctoprintPrinterProfile = octoprintPrinterProfile self.PrinterTolerance = self.Printer.printer_position_confirmation_tolerance self.Positions = [] self.Reset() self.Extruder = Extruder(octolapseSettings) self.G90InfluencesExtruder = g90InfluencesExtruder if (self.Printer.z_hop is None): self.Printer.z_hop = 0 self.Commands = Commands() def Reset(self): self.Positions = [] self.HasPositionError = False self.PositionError = None self.IsLayerChange = False self.HasPositionChanged = False self.Layer = 0 self.Height = 0 self.SavedPosition = None def UpdatePosition(self, x=None, y=None, z=None, e=None, f=None, force=False): if (len(self.Positions) == 0): return pos = self.Positions[0] pos.UpdatePosition(x, y, z, e, f, force) def SavePosition(self, x=None, y=None, z=None, e=None, f=None, force=False): if (len(self.Positions) == 0): return self.SavedPosition = Pos(self.Positions[0]) def ZDelta(self, pos): if (len(self.Positions) > 0): previousPos = self.Positions[0] # calculate ZDelta if (pos.Height is not None): if (previousPos.Height is None): return pos.Height else: return pos.Height - previousPos.Height return 0 def X(self): if (len(self.Positions) > 0): return self.Positions[0].X return None def Y(self): if (len(self.Positions) > 0): return self.Positions[0].Y return None def Z(self): if (len(self.Positions) > 0): return self.Positions[0].Z return None def E(self): if (len(self.Positions) > 0): return self.Positions[0].E return None def F(self): if (len(self.Positions) > 0): return self.Positions[0].F return None def IsZHop(self): if (len(self.Positions) > 0): return self.Positions[0].IsZHop return None def IsRelative(self): if (len(self.Positions) > 0): return self.Positions[0].IsRelative return None def IsExtruderRelative(self): if (len(self.Positions) > 0): return self.Positions[0].IsExtruderRelative return None def UndoUpdate(self): if (len(self.Positions) > 0): del self.Positions[0] self.Extruder.UndoUpdate() def Update(self, gcode): # reset state variables self.IsLayerChange = False self.HasPositionChanged = False command = self.Commands.GetCommand(gcode) # a new position pos = None previousPos = None numPositions = len(self.Positions) if (numPositions > 0): pos = Pos(self.OctoprintPrinterProfile, self.Positions[0]) if (numPositions > 1): previousPos = Pos(self.OctoprintPrinterProfile, self.Positions[1]) if (pos is None): pos = Pos(self.OctoprintPrinterProfile) if (previousPos is None): previousPos = Pos(self.OctoprintPrinterProfile) # Movement detected, set the previous values # disect the gcode and use it to update our position if (pos.IsZHopStart): pos.IsZHop = True elif (pos.IsZHopCompleting): pos.IsZHop = False pos.IsZHopCompleting = False pos.IsZHopStart = False # apply the command to the position tracker if (command is not None): if (command.Command in ["G0", "G1"]): #Movement if (command.Parse()): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived("Received {0}".format( command.Name)) x = command.Parameters["X"].Value y = command.Parameters["Y"].Value z = command.Parameters["Z"].Value e = command.Parameters["E"].Value f = command.Parameters["F"].Value if (x is not None or y is not None or z is not None or f is not None): if (self.HasPositionError and not pos.IsRelative): self.HasPositionError = False self.PositionError = "" pos.UpdatePosition(x, y, z, e=None, f=f) if (e is not None): if (pos.IsExtruderRelative is not None): if (self.HasPositionError and not pos.IsExtruderRelative): self.HasPositionError = False self.PositionError = "" pos.UpdatePosition(x=None, y=None, z=None, e=e, f=None) else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to update the extruder position, no extruder coordinate system has been selected (absolute/relative)." ) message = "Position Change - {0} - {1} Move From(X:{2},Y:{3},Z:{4},E:{5}) - To(X:{6},Y:{7},Z:{8},E:{9})" if (previousPos is None): message = message.format( gcode, "Relative" if pos.IsRelative else "Absolute", "None", "None", "None", "None", pos.X, pos.Y, pos.Z, pos.E) else: message = message.format( gcode, "Relative" if pos.IsRelative else "Absolute", previousPos.X, previousPos.Y, previousPos.Z, previousPos.E, pos.X, pos.Y, pos.Z, pos.E) self.Settings.CurrentDebugProfile().LogPositionChange( message) else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to parse the gcode command: {0}". format(gcode)) # If we've not yet homed the axis ######################################################### elif (command.Command == "G28"): # test homing of only X,Y or Z if (command.Parse()): x = command.Parameters["X"].Value y = command.Parameters["Y"].Value z = command.Parameters["Z"].Value if (x is not None): pos.XHomed = True if (y is not None): pos.YHomed = True if (z is not None): pos.ZHomed = True if (x is None and y is None and z is None): pos.XHomed = True pos.YHomed = True pos.ZHomed = True self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G28 - Homing to {0}".format( GetFormattedCoordinates(x, y, z, pos.E))) self.HasPositionError = False self.PositionError = None else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to parse the Gcode:{0}".format( gcode)) elif (command.Command == "G90"): # change x,y,z to absolute if (pos.IsRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Switching to absolute x,y,z coordinates." ) pos.IsRelative = False else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Already using absolute x,y,z coordinates." ) # for some firmwares we need to switch the extruder to absolute coordinates as well if (self.G90InfluencesExtruder): if (pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Switching to absolute extruder coordinates" ) pos.IsExtruderRelative = False else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G90 - Already using absolute extruder coordinates" ) elif (command.Command == "G91"): # change x,y,z to relative if (not pos.IsRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Switching to relative x,y,z coordinates" ) pos.IsRelative = True else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Already using relative x,y,z coordinates" ) # for some firmwares we need to switch the extruder to absolute coordinates as well if (self.G90InfluencesExtruder): if (not pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Switching to relative extruder coordinates" ) pos.IsExtruderRelative = True else: self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G91 - Already using relative extruder coordinates" ) elif (command.Command == "M83"): if (pos.IsExtruderRelative is None or not pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received M83 - Switching Extruder to Relative Coordinates" ) pos.IsExtruderRelative = True elif (command.Command == "M82"): if (pos.IsExtruderRelative is None or pos.IsExtruderRelative): self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received M82 - Switching Extruder to Absolute Coordinates" ) pos.IsExtruderRelative = False elif (command.Command == "G92"): if (command.Parse()): previousRelativeValue = self.IsRelative previousExtruderRelativeValue = self.IsExtruderRelative x = command.Parameters["X"].Value y = command.Parameters["Y"].Value z = command.Parameters["Z"].Value e = command.Parameters["E"].Value resetAll = False if (x is None and y is None and z is None and e is None): pos.XOffset = pos.X pos.YOffset = pos.Y pos.ZOffset = pos.Z pos.EOffset = pos.E # set the offsets if they are provided if (x is not None and pos.X is not None and pos.XHomed): pos.XOffset = pos.X - utility.getfloat(x, 0) if (y is not None and pos.Y is not None and pos.YHomed): pos.YOffset = pos.Y - utility.getfloat(y, 0) if (z is not None and pos.Z is not None and pos.ZHomed): pos.ZOffset = pos.Z - utility.getfloat(z, 0) if (e is not None and pos.E is not None): pos.EOffset = pos.E - utility.getfloat(e, 0) self.Settings.CurrentDebugProfile( ).LogPositionCommandReceived( "Received G92 - Set Position. Command:{0}, XOffset:{1}, YOffset:{2}, ZOffset:{3}, EOffset:{4}" .format(gcode, pos.XOffset, pos.YOffset, pos.ZOffset, pos.EOffset)) else: self.Settings.CurrentDebugProfile().LogError( "Position - Unable to parse the Gcode:{0}".format( gcode)) ######################################################### # Update the extruder monitor if there was movement self.Extruder.Update(self.ERelative(pos)) if (self.HasHomedAxis()): hasExtruderChanged = (utility.round_to( self.ERelative(pos), self.PrinterTolerance) != 0) hasXYZChanged = ( utility.round_to(pos.X, self.PrinterTolerance) != utility.round_to(previousPos.X, self.PrinterTolerance) or utility.round_to(pos.Y, self.PrinterTolerance) != utility.round_to(previousPos.Y, self.PrinterTolerance) or utility.round_to(pos.Z, self.PrinterTolerance) != utility.round_to(previousPos.Z, self.PrinterTolerance)) if (hasExtruderChanged or hasXYZChanged): self.HasPositionChanged = True # calculate LastExtrusionHeight and Height if (self.Extruder.IsExtruding() or self.Extruder.IsExtrudingStart()): pos.LastExtrusionHeight = pos.Z if (pos.Height is None or utility.round_to( pos.Z, self.PrinterTolerance) > self.Height): self.Height = utility.round_to( pos.Z, self.PrinterTolerance) pos.Height = self.Height self.Settings.CurrentDebugProfile( ).LogPositionHeightChange( "Position - Reached New Height:{0}.".format( pos.Height)) # calculate layer change if (utility.round_to(self.ZDelta(pos), self.PrinterTolerance) > 0 or self.Layer == 0): self.IsLayerChange = True self.Layer += 1 self.Settings.CurrentDebugProfile( ).LogPositionLayerChange( "Position - Layer:{0}.".format(self.Layer)) else: self.IsLayerChange = False # Calculate ZHop based on last extrusion height if (pos.LastExtrusionHeight is not None): # calculate lift, taking into account floating point rounding lift = utility.round_to( pos.Z - pos.LastExtrusionHeight, self.PrinterTolerance) if (lift >= self.Printer.z_hop): lift = self.Printer.z_hop isLifted = self.Printer.z_hop > 0.0 and lift >= self.Printer.z_hop and ( not self.Extruder.IsExtruding() or self.Extruder.IsExtrudingStart()) if (isLifted): if (not pos.IsZHop): pos.IsZHopStart = True else: if (pos.IsZHop): pos.IsZHopCompleting = True if (pos.IsZHopStart): self.Settings.CurrentDebugProfile().LogPositionZHop( "Position - ZhopStart:{0}".format( self.Printer.z_hop)) if (pos.IsZHop): self.Settings.CurrentDebugProfile().LogPositionZHop( "Position - Zhop:{0}".format(self.Printer.z_hop)) if (pos.IsZHopCompleting): self.Settings.CurrentDebugProfile().LogPositionZHop( "Position - IsZHopCompleting:{0}".format( self.Printer.z_hop)) # Add the current position, remove positions if we have more than 5 from the end self.Positions.insert(0, pos) while (len(self.Positions) > 5): del self.Positions[5] def HasHomedAxis(self): if (len(self.Positions) < 2): return False pos = self.Positions[0] previousPos = self.Positions[1] return (pos.XHomed and pos.YHomed and pos.ZHomed and pos.X is not None and pos.Y is not None and pos.Z is not None and previousPos.X is not None and previousPos.Y is not None and previousPos.Z is not None) def XRelative(self): if (len(self.Positions) < 2): return None pos = self.Positions[0] prevoiusPos = self.Positions[1] return pos.X - previousPos.X def YRelative(self): if (len(self.Positions) < 2): return None pos = self.Positions[0] prevoiusPos = self.Positions[1] return pos.Y - previousPos.Y def ZRelative(self): if (len(self.Positions) < 2): return None pos = self.Positions[0] prevoiusPos = self.Positions[1] return pos.Z - previousPos.Z def ERelative(self, pos): if (len(self.Positions) < 1): return None previousPos = self.Positions[0] return pos.E - previousPos.E def IsAtPosition(self, x, y, z, pos, tolerance, applyOffset): if (applyOffset): x = x + pos.XOffset y = y + pos.YOffset if (z is not None): z = z + pos.ZOffset if ((pos.X is None or utility.isclose(pos.X, x, abs_tol=tolerance)) and (pos.Y is None or utility.isclose(pos.Y, y, abs_tol=tolerance)) and (z is None or pos.Z is None or utility.isclose(pos.Z, z, abs_tol=tolerance))): return True return False def IsAtPreviousPosition(self, x, y, z=None, applyOffset=True): if (len(self.Positions) < 2): return False return self.IsAtPosition( x, y, z, self.Positions[1], self.Printer.printer_position_confirmation_tolerance, True) def IsAtCurrentPosition(self, x, y, z=None, applyOffset=True): if (len(self.Positions) < 1): return False return self.IsAtPosition( x, y, z, self.Positions[0], self.Printer.printer_position_confirmation_tolerance, True) def IsAtSavedPosition(self, x, y, z=None, applyOffset=True): if (self.SavedPosition is None): return False return self.IsAtPosition( x, y, z, self.SavedPosition, self.Printer.printer_position_confirmation_tolerance, True)