From af2f5b244f0cc6913f0dd246376ea4ee74391dc2 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 30 Oct 2018 01:17:56 +0100 Subject: [PATCH] Workarea origin parameter in hoop settings setup. --- control_app/app.py | 50 ++++++++++++++++++++++++++++--------- control_app/path_preview.py | 31 +++++++++++++---------- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/control_app/app.py b/control_app/app.py index 65bcdb9..ddb2136 100644 --- a/control_app/app.py +++ b/control_app/app.py @@ -31,6 +31,7 @@ class ControlAppGUI: savemenu.add_command(label="CSV", command=self.SaveCsvFile) filemenu.add_cascade(label='Open...', menu=openmenu, underline=0) filemenu.add_cascade(label="Save...", menu=savemenu, underline=0) + #filemenu.add_command(label="Reload current file", command=None) filemenu.add_command(label="Set color", command=self.AskColor) filemenu.add_separator() def updatePortList(): @@ -77,13 +78,13 @@ class ControlAppGUI: self.homeButton.grid(row=2,column=0) testNavigation = Frame(tab1) - leftButton = Button(testNavigation, text="<", command=lambda: serial.queue_command("G91\nG0 Y-2\nG90\n"), state=DISABLED) + leftButton = Button(testNavigation, text="<", command=lambda: serial.queue_command("G91\nG0 X-2\nG90\n"), state=DISABLED) leftButton.grid(row=1,column=0) - rightButton = Button(testNavigation, text=">", command=lambda: serial.queue_command("G91\nG0 Y2\nG90\n"), state=DISABLED) + rightButton = Button(testNavigation, text=">", command=lambda: serial.queue_command("G91\nG0 X2\nG90\n"), state=DISABLED) rightButton.grid(row=1,column=2) - upButton = Button(testNavigation, text="/\\", command=lambda: serial.queue_command("G91\nG0 X2\nG90\n"), state=DISABLED) + upButton = Button(testNavigation, text="/\\", command=lambda: serial.queue_command("G91\nG0 Y2\nG90\n"), state=DISABLED) upButton.grid(row=0,column=1) - downButton = Button(testNavigation, text="\\/", command=lambda: serial.queue_command("G91\nG0 X-2\nG90\n"), state=DISABLED) + downButton = Button(testNavigation, text="\\/", command=lambda: serial.queue_command("G91\nG0 Y-2\nG90\n"), state=DISABLED) downButton.grid(row=2,column=1) testNavigation.grid(row=3,column=0) self.navigationButtons = [leftButton, rightButton, upButton, downButton] @@ -177,10 +178,12 @@ class ControlAppGUI: self.distanceTraveled = 0 self.positionResponseRegex = re.compile("X:(\-?\d+\.\d+),Y:(\-?\d+\.\d+)") self.workAreaSize = [100,100] + self.workAreaOrigin = [0,0] # LOAD SOME SETTIGS self.loadSettings() self.canvas.setArea(self.workAreaSize[0], self.workAreaSize[1]) + self.canvas.setOrigin(self.workAreaOrigin[0], self.workAreaOrigin[1]) # UI LOGIC def Quit(self): @@ -227,11 +230,11 @@ class ControlAppGUI: self.testButton.config(state=NORMAL) self.startButton.config(state=NORMAL) # center loaded path - rectangle = toolpath_border_points(self.commands[1:]) + rectangle = toolpath_border_points(self.commands) rwidth = rectangle[2][0] - rectangle[0][0] rheight = rectangle[2][1] - rectangle[0][1] center = (rectangle[2][0] - (rwidth)/2, rectangle[2][1] - (rheight)/2) - transform = (self.workAreaSize[0]/2 - center[0], self.workAreaSize[1]/2 - center[1]) + transform = (self.workAreaSize[0]/2 - center[0] + self.workAreaOrigin[0], self.workAreaSize[1]/2 - center[1] + self.workAreaOrigin[1]) self.commands = translate_toolpath(self.commands, transform) # check if design is bigger than available workarea if(rwidth > self.workAreaSize[0] or rheight > self.workAreaSize[1]): @@ -268,34 +271,57 @@ class ControlAppGUI: workareaHeight.delete(0, END) workareaHeight.insert(0, str(self.workAreaSize[1])) + hoopFrame = LabelFrame(frame, text="Machine hoop origin (mm)", relief=RIDGE) + hoopFrame.grid() + Label(hoopFrame, text="X " ).grid(row=0, column=0, sticky=N) + workareaOriginX = Entry(hoopFrame, text="3") + workareaOriginX.grid(row=0,column=1) + workareaOriginX.delete(0, END) + workareaOriginX.insert(0, str(self.workAreaOrigin[0])) + Label(hoopFrame, text="Y " ).grid(row=2, column=0, sticky=N) + workareaOriginY = Entry(hoopFrame, text="4") + workareaOriginY.grid(row=2,column=1) + workareaOriginY.delete(0, END) + workareaOriginY.insert(0, str(self.workAreaOrigin[1])) + Label(hoopFrame, text="Setup name " ).grid(row=3, column=0, sticky=N) + setupName = Entry(hoopFrame, text="Setup1") + setupName.grid(row=3,column=1) + + ttk.Combobox(frame, values=["A", "B"]).grid(row=2, column=0) + addSetupButton = Button(frame, relief=RAISED, command=None, text="Add setup").grid(row=2, column=1) + rmSetupButton = Button(frame, relief=RAISED, command=None, text="Remove setup").grid(row=2, column=2) + def saveSettings(): try: self.workAreaSize = (int(workareaWidth.get()), int(workareaHeight.get())) + self.workAreaOrigin = (int(workareaOriginX.get()), int(workareaOriginY.get())) except: messagebox.showerror("Invalid numeric values","Please provide correct workarea values!") return self.canvas.setArea(self.workAreaSize[0], self.workAreaSize[1]) + self.canvas.setOrigin(self.workAreaOrigin[0], self.workAreaOrigin[1]) self.storeSettings() TmpDim = namedtuple('TmpDim', 'width height') tmp = TmpDim(self.canvas.width, self.canvas.height) self.canvas.on_resize(tmp) - Button(frame, text="Save", command=saveSettings, width=10).grid(row=2, column=3) - Button(frame, text="Cancel", command=lambda: tl.destroy(), width=10).grid(row=2, column=2) + Button(frame, text="Save", command=saveSettings, width=10).grid(row=3, column=3) + Button(frame, text="Cancel", command=lambda: tl.destroy(), width=10).grid(row=3, column=2) def loadSettings(self): try: with open(self.SETTINGSFNAME, "rb") as f: data = pickle.load(f) self.workAreaSize = data["workAreaSize"] + self.workAreaOrigin = data["workAreaOrigin"] except Exception as e: print ("Unable to restore program settings:", str(e)) def storeSettings(self): with open(self.SETTINGSFNAME, "wb") as f: try: - data = {"workAreaSize": self.workAreaSize} + data = {"workAreaSize": self.workAreaSize, "workAreaOrigin": self.workAreaOrigin} pickle.dump(data, f) except Exception as e: print ("Error while saving settings:", str(e)) @@ -322,7 +348,7 @@ class ControlAppGUI: self.GetPositionTimerTaks() def TestBorder(self): - rectangle = toolpath_border_points(self.commands[1:]) + rectangle = toolpath_border_points(self.commands) for point in rectangle: serial.queue_command("G0 X%f Y%f F5000\n" % point) @@ -451,7 +477,7 @@ class ControlAppGUI: self.scaleButton.config(relief=RAISED) if self.isJobRunning: return - self.commands = reflect_toolpath(self.commands, self.workAreaSize[0]/2) + self.commands = reflect_toolpath(self.commands, self.workAreaSize[0]/2 + self.workAreaOrigin[0]) self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())]) def ToggleScale(self): self.panButton.config(relief=RAISED) @@ -533,7 +559,7 @@ class ControlAppGUI: # rotate event if self.rotateButton.config('relief')[-1] == SUNKEN: angle = math.atan2(vect[0], vect[1]) # atan2(y, x) or atan2(sin, cos) - self.commands = rotate_toolpath(self.commands, (self.workAreaSize[0]/2,self.workAreaSize[1]/2), -(self.transform-angle)) + self.commands = rotate_toolpath(self.commands, (self.workAreaSize[0]/2 + self.workAreaOrigin[0],self.workAreaSize[1]/2 + self.workAreaOrigin[1]), -(self.transform-angle)) self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())]) self.transform = angle # scale event diff --git a/control_app/path_preview.py b/control_app/path_preview.py index 0021df3..fc7e2af 100644 --- a/control_app/path_preview.py +++ b/control_app/path_preview.py @@ -12,6 +12,8 @@ class ResizingCanvas(Canvas): self.width = self.winfo_reqwidth() self.setArea(area_width, area_height) self.pointer = self.create_oval(0, 0, 4, 4) + self.origin_x = 0 + self.origin_y = 0 def setArea(self, area_width, area_height): self.aspect_ratio = area_width / area_height @@ -21,7 +23,9 @@ class ResizingCanvas(Canvas): self.height_ratio = self.height / self.area_height self.width_ratio = self.width / self.area_width - + def setOrigin(self, origin_x, origin_y): + self.origin_x = origin_x + self.origin_y = origin_y def on_resize(self,event): # start by using the width as the controlling dimension @@ -56,33 +60,35 @@ class ResizingCanvas(Canvas): # gcode coordinates into canvas coords # takes tuple (x1, y1, x2, y2) def calc_coords(self, coords): - x1 = coords[0]*self.width_ratio - y1 = self.height - coords[1]*self.height_ratio - x2 = coords[2]*self.width_ratio - y2 = self.height - coords[3]*self.height_ratio + x1 = (coords[0] - self.origin_x) * self.width_ratio + y1 = self.height - (coords[1] - self.origin_y)*self.height_ratio + x2 = (coords[2] - self.origin_x) * self.width_ratio + y2 = self.height - (coords[3] - self.origin_y) * self.height_ratio return int(x1), int(y1), int(x2), int(y2) def canvas_vector_to_machine(self, point): return (-point[0]/self.width_ratio, point[1]/self.height_ratio) def canvas_point_to_machine(self, point): - return (point[0]/self.width_ratio, (self.height - point[1])/self.height_ratio) + return (point[0]/self.width_ratio + self.origin_x, (self.height - point[1])/self.height_ratio + self.origin_y) def machine_point_to_canvas(self, point): - return (point[0]*self.width_ratio, self.height - point[1]*self.height_ratio) - # coords is a 2 element tuple (x1, y1) + return ((point[0]-self.origin_x) * self.width_ratio, self.height - (point[1] - self.origin_y) * self.height_ratio) + def move_pointer(self, point): + ''' Moves the circle which indicates current machine position. + Coords is a 2 element tuple (x1, y1)''' x1, y1 = self.machine_point_to_canvas(point) self.coords(self.pointer, (x1-2, y1-2, x1+2, y1+2)) # change coordinates - # takes a list of points as tuples: (x,y,color) def draw_toolpath(self, points): + ''' Takes a list of points as tuples: (text_command, x,y) ''' self.clear() if(len(points) < 2): return last_point = points[0] current_color = "black" color = current_color - for point in points[1:]: + for point in points: if "G0" == point[0]: color = "snow2" elif "M6" == point[0]: @@ -180,7 +186,7 @@ def load_csv_file(csvfile, offset=(0,0)): #reader = csv.reader(csvfile, dialect) reader = csv.reader(csvfile, delimiter=',') command = "G0" - commands = [("G28",0,0)] + commands = [] colors = [] last_color = None current_color = None @@ -269,6 +275,5 @@ def save_gcode_file(f, commands): f.close() def _from_rgb(rgb): - """translates an rgb tuple of int to a tkinter friendly color code - """ + """Translates an rgb tuple of int to a tkinter friendly color code """ return "#%02x%02x%02x" % rgb