예제 #1
0
def FDL(k, fName):
    """Infitie loop function which constantly runs the display given
    the file name of the sequences and an initial k"""

    global kInput
    #Gets the initial de Bruijn Graph
    fdlNodes, minSeqLen = getFDLNodes(k, fName)
    #Sets up kInput to the appriate scale (3 to the shortest length - 1 ) to ensure
    #   all sequence reads are always included
    if not kInput:
        minSeqLen -= 1
        kInput = Scale(root,
                       from_=3,
                       to=minSeqLen,
                       orient=HORIZONTAL,
                       label="K",
                       relief=FLAT)
        kInput.set(k)  #sets the initial k value
        kInput.pack(side=LEFT, padx=50, pady=10)

    #generates all lines from the initial graph
    lines = addLines(fdlNodes)
    #starts inifinite recursive loop for redraw function
    move_nodes(fdlNodes, kInput.get(), kInput.get(), lines, root, fName)
    #starts display
    root.mainloop()
예제 #2
0
 def draw_game_info_grid(self):
     '''
     Draw control and inform part of game to right side of the window.
     '''
     self.info = Canvas(self.root, height=self.h - self.gridh, width=self.w - self.gridw)
     self.info.pack(side="left")
     
     label_stones = Label(self.info, text="Current stones:", font=("Helvetica", 10))
     label_stones.grid(row=1, column=0)
     label_max_time = Label(self.info, text="Max time:", font=("Helvetica", 10))
     label_max_time.grid(row=2, column=0)
     
     label_scale = Label(self.info, text='Game speed [ms]:', font=("Helvetica", 10), foreground='black')
     label_scale.grid(row=5, column=0)
   
     helv36 = font.Font(family="helvetica", size=16, weight='bold')
     self.scale_var = IntVar()
     scale = Scale(self.info, variable=self.scale_var, command=self.sleep_time_change_handler, from_=0, to=1000, resolution=10, width="15", orient=HORIZONTAL, length="225")
     scale.set(200)
     scale.grid(row=5, column=1, columnspan=3)
     
     self.button = Button(self.info, text="Play", width="20", height="2", command=self.play_button_click_handler)
     self.button['font'] = helv36
     self.button.grid(row=6, column=0, columnspan=4)
     
     # labels for num stones, max time of move, etc
     self.label_player_stones = [-1, -1]
     self.label_player_max_time = [-1, -1]
     self.labels_inform = [-1, -1]
     self.labels_player_name = [-1, -1]
     self.option_menus = [-1, -1]
     self.option_menus_vars = [-1, -1]
     
     for i in range(2):
         self.label_player_stones[i] = Label(self.info, text='2', font=("Helvetica", 10), foreground=self.colors[i])
         self.label_player_stones[i].grid(row=1, column=2 * (i + 1) - 1, columnspan=2)
     
         self.label_player_max_time[i] = Label(self.info, text="%.2f [ms]" % 0.0, font=("Helvetica", 10), foreground=self.colors[i])
         self.label_player_max_time[i].grid(row=2, column=2 * (i + 1) - 1, columnspan=2)
     
         self.labels_inform[i] = Label(self.info, text='', font=("Helvetica", 10), foreground='black')
         self.labels_inform[i].grid(row=i + 3, column=0, columnspan=4)  
     
         self.labels_player_name[i] = Label(self.info, text="Player%d:" % (i), font=("Helvetica", 12), foreground=self.colors[i])
         self.labels_player_name[i].grid(row=0, column=2 * i)    
         
         self.option_menus_vars[i] = StringVar(self.root)
         self.option_menus_vars[i].set(self.interractivePlayerName)
         self.option_menus[i] = OptionMenu(self.info, self.option_menus_vars[i], *self.possiblePlayers)
         self.option_menus[i].grid(row=0, column=2 * i + 1)
class JoystickFrame(LabelFrame):
    def __init__(self, master, tracker, text="Joystick", **options):
        LabelFrame.__init__(self, master, text=text, **options)
        self.tracker = tracker

        self.width = 400
        self.height = 400
        self.canvas = Canvas(self, height=self.height, width=self.width)
        self.canvas.grid()
        self.canvas.create_oval((self.width/2 - 3, self.height/2 - 3,
                                 self.width/2 + 3, self.height/2 + 3))
        self.canvas.bind("<Button-1>",
                         bg_caller(lambda event: self.move_tracker(event)))
        self.canvas.bind("<Motion>", self.update_label)

        self.motion_label = Label(self, text="",
                                  font=tkFont.Font(family="Courier"))
        self.motion_label.grid()

        f = LabelFrame(self, text="Sensitivity")
        self.sensitivity_scale = Scale(f, from_=0, to=10,
                                       resolution=0.01,
                                       orient=HORIZONTAL,
                                       length=self.width)
        self.sensitivity_scale.set(5)
        self.sensitivity_scale.grid()
        f.grid()

    @property
    def sensitivity(self):
        return self.sensitivity_scale.get() / 2000.

    def get_delta(self, event):
        dx = event.x - int(self.canvas['width'])/2.
        dy = event.y - int(self.canvas['height'])/2.
        dx_rad = dx*self.sensitivity
        dy_rad = dy*self.sensitivity
        dtheta = dy_rad
        dphi = -dx_rad
        return (dtheta, dphi)

    def update_label(self, event):
        dtheta, dphi = self.get_delta(event)
        self.motion_label.configure(text="<{:8.5f}, {:8.5f}>".format(dtheta,
                                                                     dphi))

    def move_tracker(self, event):
        dtheta, dphi = self.get_delta(event)
        self.tracker.move(0, dtheta, dphi)
        logger.info("Moved tracker by ({}, {})".format(dtheta, dphi))
예제 #4
0
 def create_scale(self, region):
     """ Create scale for this parameter"""
     if self._is_int:
         resolution = 1
     else:
         resolution = 0.001
     frame = Frame(region)
     label = Label(frame, text=self._label)
     label.pack()
     scale = Scale(frame,
                   from_=self._top,
                   to=self._bottom,
                   command=self.update_value,
                   resolution=resolution)
     scale.set(self._value)
     scale.pack()
     frame.pack(side=LEFT)
예제 #5
0
 def create_controls(self):
     canvas = self.area.get_canvas()
     start = Button(self, text="Start", command=self.start)
     scale = Scale(self,
                   length=250,
                   orient="horizontal",
                   label='Rayon :',
                   troughcolor='dark grey',
                   sliderlength=20,
                   showvalue=0,
                   from_=0,
                   to=100,
                   tickinterval=25,
                   command=self.update_circle)
     scale.set(50)
     canvas.create_window(50, 200, window=start)
     canvas.create_window(250, 200, window=scale)
     return start, scale
예제 #6
0
def FDL(k,fName):
    """Infitie loop function which constantly runs the display given
    the file name of the sequences and an initial k"""

    global kInput
    #Gets the initial de Bruijn Graph
    fdlNodes,minSeqLen = getFDLNodes(k,fName)  
    #Sets up kInput to the appriate scale (3 to the shortest length - 1 ) to ensure
    #   all sequence reads are always included
    if not kInput:
        minSeqLen -= 1 
        kInput = Scale(root, from_=3, to=minSeqLen,orient=HORIZONTAL,label="K",relief = FLAT)
        kInput.set(k) #sets the initial k value
        kInput.pack(side=LEFT, padx=50, pady=10)

    #generates all lines from the initial graph    
    lines = addLines(fdlNodes)
    #starts inifinite recursive loop for redraw function
    move_nodes(fdlNodes, kInput.get(), kInput.get(), lines, root,fName)
    #starts display
    root.mainloop()
예제 #7
0
    def __init__(self, master):
        super(GUI, self).__init__(master)
        row1, row2, row3, row4 = self.set_rows(4)
        desc = Label(row1,
                     text="Unify Walk Lengths by mean-Binning the Time Series")
        desc.pack(fill=tk.X, ipadx=10, ipady=10, side=tk.TOP)
        dirbutton = Button(row1, text="Select Folder", command=self.define_dir)
        dirbutton.pack(side=tk.LEFT, expand=True)
        o = Label(row1, text="or")
        o.pack(side=tk.LEFT, padx=20, expand=True)
        filebutton = Button(row1,
                            text="Select Specific File",
                            command=self.define_file)
        filebutton.pack(side=tk.LEFT, expand=True)

        self.show_chosen = Label(row2,
                                 textvariable=self.chosen,
                                 background='white')
        self.show_chosen.pack(fill=tk.X,
                              side=tk.LEFT,
                              pady=10,
                              ipady=5,
                              ipadx=5,
                              expand=True)

        nb = Label(row3, text="Number of Bins:", pady=10)
        nb.pack(side=tk.LEFT)

        scale = Scale(row3, from_=0, to=150, orient=tk.HORIZONTAL)
        scale.set(100)
        scale.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.scale = scale

        row4.pack(fill=tk.NONE)
        self.go_button = Button(row4, text="GO")
        self.go_button.pack(side=tk.LEFT, padx=10)

        self.close_button = Button(row4, text="Close", command=master.destroy)
        self.close_button.pack(side=tk.RIGHT, padx=10)
예제 #8
0
class EktaproGUI(Tk):
    """
    Constructs the main program window
    and interfaces with the EktaproController
    and the TimerController to access the slide
    projectors.  
    """
    
    def __init__(self):
        self.controller = EktaproController()
        self.controller.initDevices()
      
        Tk.__init__(self)
        self.protocol('WM_DELETE_WINDOW', self.onQuit)
        self.wm_title("EktaproGUI")

        self.bind("<Prior>", self.priorPressed)
        self.bind("<Next>", self.nextPressed)
        
      
        self.brightness = 0
        self.slide = 1
        self.timerController = TimerController(self.controller, self)


        self.controlPanel = Frame(self)
        self.manualPanel = Frame(self)

        
        self.projektorList = Listbox(self, selectmode=SINGLE)

        for i in range(len(self.controller.devices)):            
            self.projektorList.insert(END, \
                                  "[" + str(i) + "] " + str(self.controller.devices[i]))

               
        if self.projektorList.size >= 1:          
            self.projektorList.selection_set(0)
            
        self.projektorList.bind("<ButtonRelease>", \
                                self.projektorSelectionChanged)
        self.projektorList.config(width=50)

        self.initButton = Button(self.controlPanel, \
                                 text="init", \
                                 command=self.initButtonPressed)
        self.nextButton = Button(self.controlPanel, \
                                 text="next slide", \
                                 command=self.nextSlidePressed)
        self.nextButton.config(state=DISABLED)
        self.prevButton = Button(self.controlPanel, \
                                 text="previous slide", \
                                 command=self.prevSlidePressed)
        self.prevButton.config(state=DISABLED)

        self.startButton = Button(self.controlPanel, \
                                  text="start timer", \
                                  command=self.startTimer)
        self.startButton.config(state=DISABLED)
        self.pauseButton = Button(self.controlPanel, \
                                  text="pause", \
                                  command=self.pauseTimer)        
        self.stopButton = Button(self.controlPanel, \
                                  text="stop", \
                                  command=self.stopTimer)
        self.stopButton.config(state=DISABLED)
        self.timerLabel = Label(self.controlPanel, \
                                text="delay:")        
        self.timerInput = Entry(self.controlPanel, \
                                width=3)
        self.timerInput.insert(0, "5")        
        self.timerInput.config(state=DISABLED)
        self.timerInput.bind("<KeyPress-Return>", self.inputValuesChanged)
        self.timerInput.bind("<ButtonRelease>", self.updateGUI)


        
        self.fadeLabel = Label(self.controlPanel, \
                                text="fade:")        
        self.fadeInput = Entry(self.controlPanel, \
                                width=3)
        self.fadeInput.insert(0, "1")
        self.fadeInput.config(state=DISABLED)
        self.fadeInput.bind("<KeyPress-Return>", self.inputValuesChanged)                        
        self.fadeInput.bind("<ButtonRelease>", self.updateGUI)
                         



        self.standbyButton = Button(self.controlPanel, \
                                    text="standby", \
                                    command=self.toggleStandby)
        self.standbyButton.config(state=DISABLED)
        self.syncButton = Button(self.controlPanel, \
                                 text="sync", \
                                 command=self.sync)
        self.syncButton.config(state=DISABLED)
        self.reconnectButton = Button(self.controlPanel, \
                                      text="reconnect", \
                                      command=self.reconnect)        
                                 

        self.cycle = IntVar()
        self.cycleButton = Checkbutton(self.controlPanel, \
                                       text="use all projectors", \
                                       variable=self.cycle, \
                                       command=self.cycleToggled)        

        self.brightnessScale = Scale(self.manualPanel, from_=0, to=100, resolution=1, \
                                     label="brightness")
        self.brightnessScale.set(self.brightness)
        self.brightnessScale.bind("<ButtonRelease>", self.brightnessChanged)
        self.brightnessScale.config(state=DISABLED)
        self.brightnessScale.config(orient=HORIZONTAL)
        self.brightnessScale.config(length=400)
        
    


        self.gotoSlideScale = Scale(self.manualPanel, \
                                    from_=0, to=self.controller.maxTray, \
                                    label="goto slide")
        self.gotoSlideScale.set(1)
        self.gotoSlideScale.bind("<ButtonRelease>", self.gotoSlideChanged)
        self.gotoSlideScale.config(state=DISABLED)
        self.gotoSlideScale.config(orient=HORIZONTAL)
        self.gotoSlideScale.config(length=400)
        
        

        self.controlPanel.pack(side=BOTTOM, anchor=W, fill=X)
        self.projektorList.pack(side=LEFT, fill=BOTH)
        self.manualPanel.pack(side=RIGHT, expand=1, fill=BOTH)
        
        self.initButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        
        self.prevButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.nextButton.pack(side=LEFT, anchor=N, padx=4, pady=4)        
        self.cycleButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.startButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.pauseButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.stopButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.timerLabel.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.timerInput.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.fadeLabel.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.fadeInput.pack(side=LEFT, anchor=N, padx=4, pady=4)
        
        

        
        self.syncButton.pack(side=RIGHT, anchor=N, padx=4, pady=4)
        self.standbyButton.pack(side=RIGHT, anchor=N, padx=4, pady=4)
        self.reconnectButton.pack(side=RIGHT, anchor=N, padx=4, pady=4)
        self.brightnessScale.pack(side=TOP, anchor=W, expand=1, fill=X)
        self.gotoSlideScale.pack(side=TOP, anchor=W , expand=1, fill=X)


        self.menubar = Menu(self)
        
        self.toolsmenu = Menu(self.menubar)
        self.helpmenu = Menu(self.menubar)
        self.filemenu = Menu(self.menubar)
         
        self.toolsmenu.add_command(label="Interpret HEX Sequence", \
                                   command=self.interpretHEXDialog)
       
        self.helpmenu.add_command(label="About EktaproGUI", \
                                  command=lambda:tkMessageBox.showinfo("About EktaproGUI", \
                                                                       "EktaproGUI 1.0 (C)opyright Julian Hoch 2010"))

        self.filemenu.add_command(label="Exit", command=self.onQuit)

        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.menubar.add_cascade(label="Tools", menu=self.toolsmenu)
        self.menubar.add_cascade(label="Help", menu=self.helpmenu)


        self.configure(menu=self.menubar)


    def initButtonPressed(self):
        self.controller.resetDevices()
        self.updateGUI()
        self.brightnessScale.config(state=NORMAL)
        self.gotoSlideScale.config(state=NORMAL)
        self.nextButton.config(state=NORMAL)
        self.prevButton.config(state=NORMAL)
        self.startButton.config(state=NORMAL)        
        self.timerInput.config(state=NORMAL)
        self.fadeInput.config(state=NORMAL)
        self.syncButton.config(state=NORMAL)
        self.standbyButton.config(state=NORMAL)


    def inputValuesChanged(self, event):        
        try:
            fadeDelay = int(self.fadeInput.get())
            slideshowDelay = int(self.timerInput.get())            
            if fadeDelay in range(0, 60):
                self.timerController.fadeDelay = fadeDelay
            if slideshowDelay in range(1, 60):                
                self.timerController.slideshowDelay = slideshowDelay            
        except Exception:
            pass
        self.updateGUI()
    

    def sync(self):
        self.controller.syncDevices()
        self.updateGUI()            


    def reconnect(self):
        self.controller.cleanUp()
        self.controller.initDevices()
        self.updateGUI()
        
        self.projektorList.delete(0, END)
        for i in range(len(self.controller.devices)):            
            self.projektorList.insert(END, \
                                  "[" + str(i) + "] " + str(self.controller.devices[i]))
               
        if self.projektorList.size >= 1:          
            self.projektorList.selection_set(0)


    def projektorSelectionChanged(self, event):
        items = map(int, self.projektorList.curselection())        
        if self.controller.setActiveDevice(items):
            self.updateGUI()


    def updateGUI(self, event=None):
        if self.controller.activeDevice == None:
            return
        
        self.brightness = self.controller.activeDevice.brightness
        self.brightnessScale.set(self.brightness)

        self.slide = self.controller.activeDevice.slide
        self.gotoSlideScale.set(self.slide)

        for i in range(self.projektorList.size()):
            if i == self.controller.activeIndex:
                self.projektorList.selection_set(i)
            else:
                self.projektorList.selection_clear(i)


    def brightnessChanged(self, event):
        newBrightness = self.brightnessScale.get()
        if not self.brightness == newBrightness \
           and not self.controller.activeDevice == None:
            self.controller.activeDevice.setBrightness(newBrightness)
            self.brightness = self.brightnessScale.get()


    def gotoSlideChanged(self, event):
        if self.controller.activeDevice is None:
            return
        newSlide = self.gotoSlideScale.get()
        if not self.slide == newSlide:
            self.controller.activeDevice.gotoSlide(newSlide)
            self.slide = newSlide

  
    def nextSlidePressed(self):
        if self.controller.activeDevice is None:
            return
        self.timerController.fadePaused = False
        self.timerController.nextSlide()
        self.updateGUI()

        
    def prevSlidePressed(self):
        if self.controller.activeDevice is None:
            return
        self.timerController.fadePaused = False
        self.timerController.previousSlide()
        self.updateGUI()


    def startTimer(self):        
        self.stopButton.config(state=NORMAL)
        self.startButton.config(state=DISABLED)
        self.timerController.startSlideshow()        
            

    def pauseTimer(self):
        if self.timerController.fadePaused or self.timerController.slideshowPaused:
            self.pauseButton.config(text="pause")
            self.timerController.resume()
            self.updateGUI()            
        else:
            self.pauseButton.config(text="resume")
            self.timerController.pause()
            self.updateGUI()
        
        

    def stopTimer(self):        
        self.pauseButton.config(text="pause")
        self.stopButton.config(state=DISABLED)
        self.startButton.config(state=NORMAL)
        self.timerController.stopSlideshow()
        self.updateGUI()


    def cycleToggled(self):
        self.timerController.cycle = True if self.cycle.get() == 1 else False


    def interpretHEXDialog(self):        
        interpretDialog = InterpretHEXDialog(self) #@UnusedVariable


    def toggleStandby(self):
        if self.pauseButton.config()["text"][4] == "pause" \
           and self.pauseButton.config()["state"][4] == "normal":           
            self.pauseTimer()
        self.controller.toggleStandby()


    def nextPressed(self, event):
        if self.startButton.config()["state"][4] == "disabled":
            self.pauseTimer()            
        else:
            self.nextSlidePressed()
            

    def priorPressed(self, event):
        if self.startButton.config()["state"][4] == "disabled":        
            self.toggleStandby()
        else:      
            self.prevSlidePressed()


    def onQuit(self):
        self.controller.cleanUp()
        self.destroy()
예제 #9
0
class ObjectDialog(Dialog):
    """
    A custom dialog that allows the user to configure placing objects in the virtual environment
    """
    def __init__(self, parent, x=None, y=None, populator=None):
        """
        Construct the instance of the object dialog

        :param parent:          The parent tk instance that spawns the dialog
        """
        self._entries = {
            "x_coordinate"   : None,
            "y_coordinate"   : None,
            "name"      : None,
            "mesh"      : None,
            "scale"     : None
        }
        self._scale_text = StringVar()
        self._scale_text.set(str(1))

        Dialog.__init__(self, parent, "ObjectBuilder", True, x, y, populator)

    def body(self, parent):
        """
        Define the custom body of the dialog
        :param parent:          The parent instance of the dialog
        """
        # Define the labels of all of the sub widgets that are to be used
        Label(parent, text="Name:").grid(row=0, column=0, sticky=W)
        Label(parent, text="X-Coord:").grid(row=1, column=0, sticky=W)
        Label(parent, text="Y-Coord:").grid(row=1, column=2, sticky=W)
        Label(parent, text="Mesh:").grid(row=2, column=0, sticky=W)
        Label(parent, text="Scale:").grid(row=3, column=0, sticky=W)
        Label(parent, textvariable=self._scale_text, bg="grey").grid(row=3, column=1, sticky=W)

        #Define the text entry widgets
        self._object_name = Label(parent, text=self._entries["name"])
        self._object_name.grid(column=1, row=0, sticky=W)
        self._x_coord = Label(parent, text=self._entries["x_coordinate"])
        self._x_coord.grid(column=1, row=1, sticky=W)
        self._y_coord = Label(parent, text=self._entries["y_coordinate"])
        self._y_coord.grid(column=3, row=1, stick=W)
        self._mesh = Entry(parent, width=15, text=self._entries["mesh"])
        if self._entries["mesh"] is None:
            self._mesh.insert(0, "No mesh loaded")
        else:
            self._mesh.insert(0, self._entries["mesh"])
        self._mesh.grid(column=1, row=2, columnspan=2, sticky=W)
        Button(parent, text="Load", width=5, command=self._load_mesh, default=ACTIVE).grid(column=3, row=2)

        self._scale = Scale(parent, from_=1, to=100, orient=HORIZONTAL, length=140, variable=self._scale_text, showvalue=0)
        if self._entries["scale"] is not None:
            self._scale.set(self._entries["scale"])
            self._scale_text.set(str(self._entries["scale"]))
        self._scale.grid(row=3, column=2, columnspan=2, sticky=W)

    def validate(self):
        (result, message) = DataValidator.validate(DataStore.EVENT.OBJECT_EDIT,
            {
                "name"  :   self._entries["name"],
                "mesh"  :   self._mesh.get()
            })
        if result is not True:
            tkMessageBox.showerror("Input Error", message)
        return result

    def apply(self):
        self._entries["scale"] = self._scale.get()
        self._entries["mesh"] = self._mesh.get()

    def _load_mesh(self):
        """
        Open a file dialog to load a mesh filepath
        :return:
        """
        Debug.printi("Load Mesh called", Debug.Level.INFO)
        types = \
            [
                ("DirectX", "*.x")
            ]
        dialog = tkFileDialog.Open(self, filetypes=types)
        file_path = dialog.show()

        file_path = self._move_img(file_path)

        self._mesh.delete(0, END)
        self._mesh.insert(0, str(file_path))
        Debug.printi("Mesh Filepath:" + file_path, Debug.Level.INFO)

    def _move_img(self, file_path):
        """
        Move the DirectX file to the Data folder automagically
        :param file_path:           The file path of the file to be moved
        :return:
        """
        try:
            src = file_path
            file_name = self._scrub_name(file_path)
            dest = os.path.dirname(os.path.realpath(__file__)) + "/" + file_name
            shutil.copy(src, dest)
            Debug.printi("Moving file " + file_path + " to location "
                         + os.path.dirname(os.path.realpath(__file__))
                         + "/" + file_name, Debug.Level.INFO)
            return file_name
        # eg. src and dest are the same file
        except shutil.Error as e:
            print('Error: %s' % e + " " + dest)
            return file_name
        # eg. source or destination doesn't exist
        except IOError as e:
            print('Error: %s' % e.strerror + " " + dest)
            return file_name

    def _scrub_name(self, file_path):
        """
        Scrubs the file name so taht it is /really/long/abs/path/fil.x
        to
        Data/file.x
        """
        split = file_path.split("/")
        f_name = "Data/" + split[-1]
        return f_name

    def populate(self, manager):
        self._entries["x_coordinate"]   = manager.x_coordinate
        self._entries["y_coordinate"]   = manager.y_coordinate
        self._entries["name"]           = manager.name
        self._entries["mesh"]           = manager.mesh
        self._entries["scale"]          = manager.scale

    def auto_populate(self):
        self._mesh.delete(0, END)
        self._mesh.insert(0, Defaults.Object.MESH)
        self._scale.set(Defaults.Object.SCALE)
예제 #10
0
class ToolBar(Frame):
	def __init__(self, root, printer, settings, logger, *arg):
		self.app = root
		self.printer = printer
		self.settings = settings
		self.logger = logger
		
		self.app.printing = False
		self.app.connected = False
		self.app.paused = False
		
		Frame.__init__(self, root, *arg)
		topBar = Frame(self)
		topBar.grid(row=1, column=1, columnspan=3, sticky=W)
		speedBar = Frame(self)
		speedBar.grid(row=1, column=5, sticky=E)
		bottomBar = Frame(self)
		bottomBar.grid(row=2, column=1, columnspan=6, sticky=W+E)
		
		self.bPort = Button(topBar, text="Port", width=BWIDTH, command=self.doPort)
		self.bPort.pack(side=LEFT, padx=2, pady=2)
		ports = self.scanSerial()
		self.spPort = Spinbox(topBar, values=ports, state="readonly")
		self.spPort.pack(side=LEFT, padx=2, pady=2)
		l = Label(topBar, text=" @ ")
		l.pack(side=LEFT, padx=2, pady=2)
		self.spBaud = Spinbox(topBar, values=baudChoices)
		self.spBaud.pack(side=LEFT, padx=2, pady=2)
		self.spBaud.delete(0, END)
		self.spBaud.insert(0, 115200)
		self.spBaud.config(state="readonly")

		self.bConnectMode = CM_CONNECT
		self.bConnect = Button(topBar, text=connectText[CM_CONNECT], width=BWIDTH, command=self.doConnect)
		self.bConnect.pack(side=LEFT, padx=2, pady=2)
		if len(ports) == 0:
			self.bConnect.config(state=DISABLED)
		else:
			self.bConnect.config(state=NORMAL)


		self.bReset = Button(topBar, text="Reset", width=BWIDTH, command=self.doReset, state=DISABLED)
		self.bReset.pack(side=LEFT, padx=2, pady=2)
		
		l = Label(speedBar, text="Speed:", justify=RIGHT)
		l.grid(row=1, column=1, sticky=E)

		self._speedJob = None		
		self.currentSpeed = self.app.FeedMultiply
		self.scSpeed = Scale(speedBar, from_=MINSPEED, to=MAXSPEED, orient=HORIZONTAL, command=self.updateSpeedCommand)
		self.scSpeed.grid(row=1, column=2)
		self.scSpeed.set(self.currentSpeed);

		l = Label(speedBar, text="Fan:", width=10, anchor=E, justify=RIGHT)
		l.grid(row=1, column=3, sticky=E)
		
		self._fanJob = None		
		self.currentFanSpeed = self.app.FanSpeed
		self.scFan = Scale(speedBar, from_=0, to=255, orient=HORIZONTAL, command=self.updateFanSpeedCommand)
		self.scFan.grid(row=1, column=4)
		self.scFan.set(self.currentFanSpeed);

		if self.settings.speedcommand is not None:
			self.cbvAssertFan = IntVar()
			if self.settings.forcefanspeed:
				self.cbvAssertFan.set(1)
			else:
				self.cbvAssertFan.set(0)
			self.cbAssertFan = Checkbutton(speedBar, text="Force", variable=self.cbvAssertFan,
				command=self.clickAssertFan)
			self.cbAssertFan.grid(row=1, column=5)

		self.bSliceMode = SM_SLICE
		self.bSlice = Button(bottomBar, text=sliceText[SM_SLICE], width=BWIDTH*2, command=self.doSlice)
		self.bSlice.pack(side=LEFT, padx=2, pady=2)
		
		self.bLoad = Button(bottomBar, text="Load GCode", width=BWIDTH, command=self.doLoad)
		self.bLoad.pack(side=LEFT, padx=2, pady=2)
		self.setSliceText()
		
		self.bSD = Button(bottomBar, text="SD", width=BWIDTH, command=self.doSD, state=DISABLED)
		self.bSD.pack(side=LEFT, padx=2, pady=2)
		
		self.bPrintMode = PR_PRINT		
		self.bPrint = Button(bottomBar, text=printText[PR_PRINT], width=BWIDTH, command=self.doPrint, state=DISABLED)
		self.bPrint.pack(side=LEFT, padx=2, pady=2)
		
		self.bPauseMode = PM_PAUSE
		self.bPause = Button(bottomBar, text=pauseText[PM_PAUSE], width=BWIDTH, command=self.doPause, state=DISABLED)
		self.bPause.pack(side=LEFT, padx=2, pady=2)

		self.bAbandon = Button(bottomBar, text="Abandon SD Print", width=BWIDTH+8, command=self.doAbandon, state=DISABLED)
		self.bAbandon.pack(side=LEFT, padx=2, pady=2)
		
		self.cbvLiftOnPause = IntVar()
		if self.settings.liftonpause:
			self.cbvLiftOnPause.set(1)
		else:
			self.cbvLiftOnPause.set(0)
		self.cbLiftOnPause = Checkbutton(bottomBar, text="Lift Head/Retract on Pause", variable=self.cbvLiftOnPause,
			command=self.clickLiftOnPause)
		self.cbLiftOnPause.pack(side=LEFT, padx=2)

		self.cbvResumeAtPause = IntVar()
		if self.settings.resumeatpausepoint:
			self.cbvResumeAtPause.set(1)
		else:
			self.cbvResumeAtPause.set(0)
		self.cbResumeAtPause = Checkbutton(bottomBar, text="Resume print at pause point", variable=self.cbvResumeAtPause,
			command=self.clickResumeAtPause)
		self.cbResumeAtPause.pack(side=LEFT, padx=2)
		
	def clickAssertFan(self):
		if self.cbvAssertFan.get() == 1:
			self.settings.forcefanspeed = True
			self.settings.setModified()
		else:
			self.settings.forcefanspeed = False
			self.settings.setModified()
		
	def clickLiftOnPause(self):
		if self.cbvLiftOnPause.get() == 1:
			self.settings.liftonpause = True
			self.settings.setModified()
		else:
			self.settings.liftonpause = False
			self.settings.setModified()
		
	def clickResumeAtPause(self):
		if self.cbvResumeAtPause.get() == 1:
			self.settings.resumeatpausepoint = True
			self.settings.setModified()
		else:
			self.settings.resumeatpausepoint = False
			self.settings.setModified()
	
	def setSliceText(self):
		if self.settings.slicer == SLIC3R:
			sl = "slic3r:%s" % self.app.slic3r.getProfile()
		else:
			sl = "skeinforge:%s" % self.app.skeinforge.getProfile()
		sliceText[SM_SLICE] = "Slice (%s)" % sl
		if self.bSliceMode == SM_SLICE:
			self.bLoad.config(state=NORMAL)
			self.app.allowLoadGCodeMenu(True)
			lt = len(sliceText[SM_SLICE])+2
			if lt < BWIDTH:
				lt = BWIDTH
			self.bSlice.config(text=sliceText[SM_SLICE], width=lt)
		
	def updateSpeedCommand(self, *arg):
		if self._speedJob:
			self.app.master.after_cancel(self._speedJob)
			
		self._speedJob = self.app.master.after(500, self.updateSpeed)

	def updateSpeed(self, *arg):
		v = self.scSpeed.get()
		self.setSpeed(v)
		
	def setSpeed(self, v):
		if v < MINSPEED or v > MAXSPEED:
			self.logger.logMsg("Attempt to change speed outside of allowable range (%d-%d)" % (MINSPEED, MAXSPEED))
		elif int(v) != self.currentSpeed:
			if self.app.connected:
				self.currentSpeed = int(v)
				self.logger.logMsg("changing speed percentage to %d%%" % self.currentSpeed)
				cmd = "M220 S%d" % self.currentSpeed
				self.printer.send_now(cmd)
			else:
				self.logger.logMsg("Printer is off-line")

		self.scSpeed.set(self.currentSpeed)
		
	def updateFanSpeedCommand(self, *arg):
		if self._fanJob:
			self.app.master.after_cancel(self._fanJob)
			
		self._fanJob = self.app.master.after(500, self.updateFanSpeed)
		
	def updateFanSpeed(self, *arg):
		v = self.scFan.get()
		self.setFanSpeed(v)
		self.app.FanSpeed = v

	def forceFanSpeed(self, v):
		self.currentFanSpeed = -1
		self.setFanSpeed(v)

	def setFanSpeed(self, v):
		if int(v) != self.currentFanSpeed:
			if self.app.connected:
				self.currentFanSpeed = int(v)
				cmd = "M106 S%d" % self.currentFanSpeed
				self.printer.send_now(cmd)
			else:
				self.logger.logMsg("Printer is off-line")
		self.scFan.set(self.currentFanSpeed)
		
	def syncSpeeds(self):
		self.currentSpeed = self.app.FeedMultiply
		self.scSpeed.set(self.currentSpeed)
		self.currentFanSpeed = self.app.FanSpeed
		self.scFan.set(self.currentFanSpeed)
		
	def initializeToolbar(self):
		self.bReset.config(state=DISABLED)
		self.bSliceMode = SM_SLICE
		self.bSlice.config(text=sliceText[SM_SLICE])
		self.bLoad.config(state=NORMAL)
		self.app.allowLoadGCodeMenu(True)
		if not self.app.sdprinting and not self.app.sdpaused:
			self.bPrintMode = PR_PRINT
			self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
			self.bPauseMode = PM_PAUSE
			self.bPause.config(text=pauseText[PM_PAUSE], state=DISABLED)
		
	def setSDPrint(self):
		self.bPause.config(text=pauseText[PM_PAUSE], state=NORMAL)
		self.bPauseMode = PM_PAUSE
		self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
		self.bPrintMode = PR_PRINT
		self.bAbandon.config(state=NORMAL)
		
	def clearSDPrint(self):
		self.bPause.config(text=pauseText[PM_PAUSE], state=DISABLED)
		self.bPauseMode = PM_PAUSE
		self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
		self.bPrintMode = PR_PRINT
		self.bAbandon.config(state=DISABLED)
		self.checkAllowPrint()
		
	def setCancelMode(self):
		self.bSliceMode = SM_CANCEL
		self.bSlice.config(text=sliceText[SM_CANCEL], width=BWIDTH)
		self.bLoad.config(state=DISABLED)
		self.app.allowLoadGCodeMenu(False)
		self.app.allowSliceMenu(False)

	def setLoading(self, flag):
		if flag:
			self.bLoad.config(state=DISABLED)
			self.bSlice.config(state=DISABLED)
			self.app.allowLoadGCodeMenu(False)
			self.app.allowSliceMenu(False)
		else:
			self.bLoad.config(state=NORMAL)
			self.bSlice.config(state=NORMAL)
			self.app.allowLoadGCodeMenu(True)
			self.app.allowSliceMenu(True)
		
	def clearCancelMode(self):
		self.bSliceMode = SM_SLICE
		lt = len(sliceText[SM_SLICE])+2
		if lt < BWIDTH:
			lt = BWIDTH
		self.bSlice.config(text=sliceText[SM_SLICE], width=lt)
		self.bLoad.config(state=NORMAL)
		self.app.allowLoadGCodeMenu(True)
		self.app.allowSliceMenu(True)
		
	def doConnect(self):
		if self.bConnectMode == CM_CONNECT:
			port = self.spPort.get()
			baud = int(self.spBaud.get())
			self.printer.onlinecb = self.onlinecb
			try:
				self.printer.connect(port, baud)
			except SerialException:
				self.logger.logMsg("Unable to open printer port %s" % port)
		else:
			if self.app.printing:
				self.logger.logMsg("Please wait until printing has finished or is paused")
			else:
				self.printer.disconnect()
				self.printer.onlinecb = None
				self.app.printerConnected(False)
#				self.app.connected = False
				self.bConnectMode = CM_CONNECT
				self.bConnect.config(text=connectText[CM_CONNECT])
				self.bReset.config(state=DISABLED)
				self.bSD.config(state=DISABLED)
				if self.app.paused:
					self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
					self.bPrintMode = PR_PRINT
					self.bPause.config(text=pauseText[PM_PAUSE], state=DISABLED)
					self.bPauseMode = PM_PAUSE
					self.app.printing = False
					self.app.paused = False
					
	def doReset(self):
		if tkMessageBox.askyesno("Reset?", "Are you sure you want to reset the printer?", parent=self.app):
			self.printer.reset()
			self.printer.printing = 0
			self.app.printing = False
			self.bSlice.config(state=NORMAL)
			self.bLoad.config(state=NORMAL)
			self.app.allowLoadGCodeMenu(True)
			self.app.allowSliceMenu(True)

			self.bPrintMode = PR_PRINT
			self.bPrint.config(text=printText[PR_PRINT], state=NORMAL)
			if self.app.paused:
				self.printer.paused = 0
				self.bPause.config(text=pauseText[PM_PAUSE], state=DISABLED)
				self.bPauseMode = PM_PAUSE
				self.app.paused = False

	def onlinecb(self):
		self.logger.logMsg("Printer is on-line")
		self.app.printerConnected(True)
#		self.app.connected = True
		self.bConnectMode = CM_DISCONNECT
		self.bConnect.config(text=connectText[CM_DISCONNECT])
		self.bReset.config(state=NORMAL)
		self.bSD.config(state=NORMAL)
		self.checkAllowPrint()
	
	def checkAllowPrint(self):
		if self.app.connected and len(self.app.gcode) != 0 and not self.app.printing and not self.app.sdprinting:
			self.bPrint.config(text=printText[PR_PRINT], state=NORMAL)
			self.bPrintMode = PR_PRINT
			
	def printComplete(self):
		self.app.endTime = time.time()
		self.app.elapsedTime = self.app.endTime - self.app.startTime
		self.logger.logMsg("Printing completed at %s" % time.strftime('%H:%M:%S', time.localtime()))
		self.logger.logMsg("Total elapsed time: %s" % formatElapsed(self.app.elapsedTime))
		self.bPrintMode = PR_PRINT
		self.bPrint.config(text=printText[PR_PRINT], state=NORMAL)
		
		self.bPauseMode = PM_PAUSE
		self.bPause.config(text=pauseText[PM_PAUSE], state=DISABLED)
		
		self.app.printing = False
		self.bSlice.config(state=NORMAL)
		self.bLoad.config(state=NORMAL)
		self.app.allowLoadGCodeMenu(True)
		self.app.allowSliceMenu(True)
		self.app.paused = False
		self.app.gc.updatePrintProgress(0)
		self.app.closeAllReports()
		if self.settings.endprintmacro is not None:
			self.app.doMacro(name=self.settings.endprintmacro, silent=True)

		
	def doPause(self):
		if self.bPauseMode == PM_PAUSE:
			if self.app.printing:
				self.app.paused = True
				self.printer.pause()
			elif self.app.sdprinting:
				self.app.sdpaused = True
				self.printer.send_now("M25")
				self.app.sdprinting = False
				self.bPause.config(text=pauseText[PM_RESUME])
				self.bPauseMode = PM_RESUME
				self.bPrint.config(text=printText[PR_RESTART], state=NORMAL)
				self.bPrintMode = PR_RESTART
		else:
			if self.app.sdpaused:
				self.printer.send_now("M24")
				self.app.sdpaused = False
				self.app.sdprinting = True
				self.bPause.config(text=pauseText[PM_PAUSE])
				self.bPauseMode = PM_PAUSE
				self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
				self.bPrintMode = PR_PRINT
			else:
				self.hitPrint = False
				if self.settings.resumeatpausepoint:
					self.printer.send_now("G1 X%s Y%s F%s" % (self.app.pausePoint[XAxis], self.app.pausePoint[YAxis], self.settings.xyfeed))
					self.printer.send_now("G1 Z%s F%s" % (self.app.pausePoint[ZAxis], self.settings.zfeed))
					self.printer.send_now("G92 E%s" % self.app.pausePoint[EAxis])
					self.printer.send_now("G1 F%s" % self.settings.xyfeed)
				self.printer.startcb = self.startcb
				self.printer.resume()
				
	def doAbandon(self):
		self.printer.send_now("M25")
		self.app.sdpaused = False
		self.app.sdprinting = False
		self.clearSDPrint()

	def doSlice(self):
		if self.bSliceMode == SM_SLICE:
			self.bLoad.config(state=DISABLED)
			self.app.allowLoadGCodeMenu(False)
			self.app.openSTLFile()
		else:
			self.app.slicerCancel = True
			self.bLoad.config(state=NORMAL)
			self.app.allowLoadGCodeMenu(True)
			
	def doLoad(self):
		self.app.openGCodeFile()
	
	def doPrint(self):
		if self.app.sdpaused:
			self.printer.send_now("M26 S0")
			self.printer.send_now("M24")
			self.app.sdpaused = False
			self.app.sdprinting = True
			self.bPause.config(text=pauseText[PM_PAUSE])
			self.bPauseMode = PM_PAUSE
			self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
			self.bPrintMode = PR_PRINT
		else:
			if len(self.app.gcode) == 0:
				self.logger.logMsg("Nothing to print")
			else:
				#if not self.app.paused:
				self.app.gc.updatePrintProgress(0, restart=True)
	
				self.bPauseMode = PM_PAUSE
				self.bPause.config(text=pauseText[PM_PAUSE], state=NORMAL)
				self.hitPrint = True
				self.printer.startcb = self.startcb
				self.printer.startprint(self.app.gcode)
			
	def startcb(self):
		self.printer.startcb = None
		if not self.app.paused:
			self.app.startTime = time.time()
			self.logger.logMsg("Printing Started at %s" % time.strftime('%H:%M:%S', time.localtime(self.app.startTime)))
			self.app.printing = True
			
			self.bSlice.config(state=DISABLED)
			self.bLoad.config(state=DISABLED)
			self.app.allowLoadGCodeMenu(False)
			self.app.allowSliceMenu(False)

			self.bPrint.config(text=printText[PR_RESTART], state=DISABLED)
			self.bPrintMode = PR_RESTART
			self.printer.endcb = self.endcb
		else:
			if self.hitPrint:
				self.app.startTime = time.time()
				self.logger.logMsg("Printing restarted at %s" % time.strftime('%H:%M:%S', time.localtime()))
			else:
				self.logger.logMsg("Printing resumed at %s" % time.strftime('%H:%M:%S', time.localtime()))
			self.bPause.config(text=pauseText[PM_PAUSE])
			self.bPauseMode = PM_PAUSE
			self.app.printing = True
			
			self.bSlice.config(state=DISABLED)
			self.bLoad.config(state=DISABLED)
			self.app.allowLoadGCodeMenu(False)
			self.app.allowSliceMenu(False)


			self.app.paused = False
			self.bPrint.config(state=DISABLED)
			self.printer.endcb = self.endcb
		
	def endcb(self):
		self.printer.endcb = None
		if not self.app.paused:
			self.printComplete()
			if self.app.sduploading:
				self.app.sduploading = False
				self.printer.send_now("M29")
		else:
			self.app.event_generate(MWM_REQUESTPOSITIONREPORT)
			# record the current printer position and how many intervals were willing to wait fo the response
			self.maxWait114 = MAXWAIT114;
			self.waitPos = self.printer.queueindex
			self.check114Response()
		
	def check114Response(self) :
		# tick off 1 interval, and make sure we haven't either received the report or we've waited max intervals
		self.maxWait114 -= 1
		if self.app.m114count == 0 or self.maxWait114 <= 0:
			# one way or the other we're done waiting here
			if self.maxWait114 <= 0:
				self.app.m114count = 0
				self.logger.logMsg("Location report not received - proceeding")
				
			self.app.pausePoint[XAxis] = self.app.location[XAxis]
			self.app.pausePoint[YAxis] = self.app.location[YAxis]
			self.app.pausePoint[ZAxis] = self.app.location[ZAxis]
			self.app.pausePoint[EAxis] = self.app.location[EAxis]

			self.logger.logMsg("Pause location: X:%f Y:%f Z:%f E:%f" %
				(self.app.pausePoint[XAxis], self.app.pausePoint[YAxis], self.app.pausePoint[ZAxis], self.app.pausePoint[EAxis]))
			
			if self.settings.liftonpause:
				self.printer.send_now("G1 E%s F%s" % (self.app.pausePoint[EAxis]-2, self.settings.efeed))
				self.printer.send_now("G1 Z%s F%s" % (self.app.pausePoint[ZAxis]+10, self.settings.zfeed))

			self.bPause.config(text=pauseText[PM_RESUME])
			self.bPauseMode = PM_RESUME
			self.app.printing = False
			
			self.bSlice.config(state=NORMAL)
			self.bLoad.config(state=NORMAL)
			self.app.allowLoadGCodeMenu(True)
			self.app.allowSliceMenu(True)


			if self.app.sduploading:
				self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
				self.bPrintMode = PR_PRINT
			else:
				self.bPrint.config(text=printText[PR_RESTART], state=NORMAL)
				self.bPrintMode = PR_RESTART
		else:
			# we still are waiting for the report, but reset everything if the printer is still moving
			if self.waitPos != self.printer.queueindex:
				self.waitPos = self.printer.queueindex
				self.maxWait114 = MAXWAIT114
				
			self.app.master.after(500, self.check114Response)
	
	def doPort(self):
		l = self.scanSerial()
		self.spPort.config(values=l)
		if len(l) == 0:
			self.bConnect.config(state=DISABLED)
		else:
			self.bConnect.config(state=NORMAL)
	
	def scanSerial(self):
		"""scan for available ports. return a list of device names."""
		baselist=[]
		if os.name=="nt":
			try:
				key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
				i=0
				while(1):
					baselist+=[_winreg.EnumValue(key,i)[1]]
					i+=1
			except:
				pass
		return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') +glob.glob("/dev/tty.*")+glob.glob("/dev/cu.*")+glob.glob("/dev/rfcomm*")
	
	def doSD(self):
		self.app.doSD()
예제 #11
0
class GUI:
    def __init__(self, model, title='PyCX Simulator', interval=0, stepSize=1,
            param_gui_names=None):
        self.model = model
        self.titleText = title
        self.timeInterval = interval
        self.stepSize = stepSize
        self.param_gui_names = param_gui_names
        if param_gui_names is None:
            self.param_gui_names = {}
        self.param_entries = {}
        self.statusStr = ""
        self.running = False
        self.modelFigure = None
        self.currentStep = 0

        self.initGUI()

    def initGUI(self):
        #create root window
        self.rootWindow = Tk()
        self.statusText = StringVar(value=self.statusStr)
        self.setStatusStr("Simulation not yet started")

        self.rootWindow.wm_title(self.titleText)
        self.rootWindow.protocol('WM_DELETE_WINDOW', self.quitGUI)
        self.rootWindow.geometry('550x700')
        self.rootWindow.columnconfigure(0, weight=1)
        self.rootWindow.rowconfigure(0, weight=1)

        self.frameSim = Frame(self.rootWindow)

        self.frameSim.pack(expand=YES, fill=BOTH, padx=5, pady=5, side=TOP)
        self.status = Label(self.rootWindow, width=40, height=3, relief=SUNKEN,
                            bd=1, textvariable=self.statusText)
        self.status.pack(side=TOP, fill=X, padx=1, pady=1, expand=NO)

        self.runPauseString = StringVar()
        self.runPauseString.set("Run")
        self.buttonRun = Button(self.frameSim, width=30, height=2,
                                textvariable=self.runPauseString,
                                command=self.runEvent)
        self.buttonRun.pack(side=TOP, padx=5, pady=5)

        self.showHelp(self.buttonRun,
                      "Runs the simulation (or pauses the running simulation)")
        self.buttonStep = Button(self.frameSim, width=30, height=2,
                                 text="Step Once", command=self.stepOnce)
        self.buttonStep.pack(side=TOP, padx=5, pady=5)
        self.showHelp(self.buttonStep, "Steps the simulation only once")
        self.buttonReset = Button(self.frameSim, width=30, height=2,
                                  text="Reset", command=self.resetModel)
        self.buttonReset.pack(side=TOP, padx=5, pady=5)
        self.showHelp(self.buttonReset, "Resets the simulation")

        for param in self.model.params:
            var_text = self.param_gui_names.get(param, param)
            can = Canvas(self.frameSim)
            lab = Label(can, width=25, height=1 + var_text.count('\n'),
                        text=var_text, anchor=W, takefocus=0)
            lab.pack(side='left')
            ent = Entry(can, width=11)
            val = getattr(self.model, param)
            if isinstance(val, bool):
                val = int(val)  # Show 0/1 which can convert back to bool
            ent.insert(0, str(val))
            ent.pack(side='left')
            can.pack(side='top')
            self.param_entries[param] = ent
        if self.param_entries:
            self.buttonSaveParameters = Button(self.frameSim, width=50,
                    height=1, command=self.saveParametersCmd,
                    text="Save parameters to the running model", state=DISABLED)
            self.showHelp(self.buttonSaveParameters,
                    "Saves the parameter values.\n" +
                    "Not all values may take effect on a running model\n" +
                    "A model reset might be required.")
            self.buttonSaveParameters.pack(side='top', padx=5, pady=5)
            self.buttonSaveParametersAndReset = Button(self.frameSim, width=50,
                    height=1, command=self.saveParametersAndResetCmd,
                    text="Save parameters to the model and reset the model")
            self.showHelp(self.buttonSaveParametersAndReset,
                    "Saves the given parameter values and resets the model")
            self.buttonSaveParametersAndReset.pack(side='top', padx=5, pady=5)

        can = Canvas(self.frameSim)
        lab = Label(can, width=25, height=1, text="Step size ", justify=LEFT,
                anchor=W, takefocus=0)
        lab.pack(side='left')
        self.stepScale = Scale(can, from_=1, to=500, resolution=1,
                               command=self.changeStepSize, orient=HORIZONTAL,
                               width=25, length=150)
        self.stepScale.set(self.stepSize)
        self.showHelp(self.stepScale,
                "Skips model redraw during every [n] simulation steps\n" +
                "Results in a faster model run.")
        self.stepScale.pack(side='left')
        can.pack(side='top')

        can = Canvas(self.frameSim)
        lab = Label(can, width=25, height=1,
                    text="Step visualization delay in ms ", justify=LEFT,
                    anchor=W, takefocus=0)
        lab.pack(side='left')
        self.stepDelay = Scale(can, from_=0, to=max(2000, self.timeInterval),
                               resolution=10, command=self.changeStepDelay,
                               orient=HORIZONTAL, width=25, length=150)
        self.stepDelay.set(self.timeInterval)
        self.showHelp(self.stepDelay, "The visualization of each step is " +
                                      "delays by the given number of " +
                                      "milliseconds.")
        self.stepDelay.pack(side='left')
        can.pack(side='top')

    def setStatusStr(self, newStatus):
        self.statusStr = newStatus
        self.statusText.set(self.statusStr)

    #model control functions
    def changeStepSize(self, val):
        self.stepSize = int(val)

    def changeStepDelay(self, val):
        self.timeInterval = int(val)

    def saveParametersCmd(self):
        for param, entry in self.param_entries.items():
            val = entry.get()
            if isinstance(getattr(self.model, param), bool):
                val = bool(int(val))
            setattr(self.model, param, val)
            # See if the model changed the value (e.g. clipping)
            new_val = getattr(self.model, param)
            if isinstance(new_val, bool):
                new_val = int(new_val)
            entry.delete(0, END)
            entry.insert(0, str(new_val))
        self.setStatusStr("New parameter values have been set")

    def saveParametersAndResetCmd(self):
        self.saveParametersCmd()
        self.resetModel()

    def runEvent(self):
        if not self.running:
            self.running = True
            self.rootWindow.after(self.timeInterval, self.stepModel)
            self.runPauseString.set("Pause")
            self.buttonStep.configure(state=DISABLED)
            if self.param_entries:
                self.buttonSaveParameters.configure(state=NORMAL)
                self.buttonSaveParametersAndReset.configure(state=DISABLED)
        else:
            self.stopRunning()

    def stopRunning(self):
        self.running = False
        self.runPauseString.set("Continue Run")
        self.buttonStep.configure(state=NORMAL)
        self.drawModel()
        if self.param_entries:
            self.buttonSaveParameters.configure(state=NORMAL)
            self.buttonSaveParametersAndReset.configure(state=NORMAL)

    def stepModel(self):
        if self.running:
            if self.model.step() is True:
                self.stopRunning()
            self.currentStep += 1
            self.setStatusStr("Step " + str(self.currentStep))
            self.status.configure(foreground='black')
            if (self.currentStep) % self.stepSize == 0:
                self.drawModel()
            self.rootWindow.after(int(self.timeInterval * 1.0 / self.stepSize),
                                  self.stepModel)

    def stepOnce(self):
        self.running = False
        self.runPauseString.set("Continue Run")
        self.model.step()
        self.currentStep += 1
        self.setStatusStr("Step " + str(self.currentStep))
        self.drawModel()
        if self.param_entries:
            self.buttonSaveParameters.configure(state=NORMAL)

    def resetModel(self):
        self.running = False
        self.runPauseString.set("Run")
        self.model.reset()
        self.currentStep = 0
        self.setStatusStr("Model has been reset")
        self.drawModel()

    def drawModel(self):
        if self.modelFigure is None:
            self.modelFigure = plt.figure()
            plt.ion()
        self.model.draw()

        # Tell matplotlib to redraw too. The darwin-version works with more
        # types of matplotlib backends, but seems to fail on some Linux
        # machines. Hence we use the TkAgg specific method when available.
        if sys.platform == 'darwin':
            self.modelFigure.canvas.manager.show()
        else:
            self.modelFigure.canvas.manager.window.update()

    def start(self):
        if self.model.step.__doc__:
            self.showHelp(self.buttonStep, self.model.step.__doc__.strip())

        self.model.reset()
        self.drawModel()
        self.rootWindow.mainloop()

    def quitGUI(self):
        plt.close('all')
        self.rootWindow.quit()
        self.rootWindow.destroy()

    def showHelp(self, widget, text):
        def setText(self):
            self.statusText.set(text)
            self.status.configure(foreground='blue')

        def showHelpLeave(self):
            self.statusText.set(self.statusStr)
            self.status.configure(foreground='black')
        widget.bind("<Enter>", lambda e: setText(self))
        widget.bind("<Leave>", lambda e: showHelpLeave(self))
예제 #12
0
class GUI:
    def __init__(self,
                 model,
                 title='PyCX Simulator',
                 interval=0,
                 step_size=1,
                 param_gui_names=None):
        self.model = model
        self.titleText = title
        self.timeInterval = interval
        self.stepSize = step_size
        self.param_gui_names = param_gui_names
        if param_gui_names is None:
            self.param_gui_names = {}
        self.param_entries = {}
        self.statusStr = ""
        self.running = False
        self.modelFigure = None
        self.currentStep = 0

        self.init_gui()

    def init_gui(self):
        # create root window
        self.rootWindow = Tk()
        self.statusText = StringVar(value=self.statusStr)
        self.set_status_str("Simulation not yet started")

        self.rootWindow.wm_title(self.titleText)
        self.rootWindow.protocol('WM_DELETE_WINDOW', self.quit_gui)
        self.rootWindow.geometry('550x700')
        self.rootWindow.columnconfigure(0, weight=1)
        self.rootWindow.rowconfigure(0, weight=1)

        self.frameSim = Frame(self.rootWindow)

        self.frameSim.pack(expand=YES, fill=BOTH, padx=5, pady=5, side=TOP)
        self.status = Label(self.rootWindow,
                            width=40,
                            height=3,
                            relief=SUNKEN,
                            bd=1,
                            textvariable=self.statusText)
        self.status.pack(side=TOP, fill=X, padx=1, pady=1, expand=NO)

        self.runPauseString = StringVar()
        self.runPauseString.set("Run")
        self.buttonRun = Button(self.frameSim,
                                width=30,
                                height=2,
                                textvariable=self.runPauseString,
                                command=self.run_event)
        self.buttonRun.pack(side=TOP, padx=5, pady=5)

        self.show_help(
            self.buttonRun,
            "Runs the simulation (or pauses the running simulation)")
        self.buttonStep = Button(self.frameSim,
                                 width=30,
                                 height=2,
                                 text="Step Once",
                                 command=self.step_once)
        self.buttonStep.pack(side=TOP, padx=5, pady=5)
        self.show_help(self.buttonStep, "Steps the simulation only once")
        self.buttonReset = Button(self.frameSim,
                                  width=30,
                                  height=2,
                                  text="Reset",
                                  command=self.reset_model)
        self.buttonReset.pack(side=TOP, padx=5, pady=5)
        self.show_help(self.buttonReset, "Resets the simulation")

        for param in self.model.params:
            var_text = self.param_gui_names.get(param, param)
            can = Canvas(self.frameSim)
            lab = Label(can,
                        width=25,
                        height=1 + var_text.count('\n'),
                        text=var_text,
                        anchor=W,
                        takefocus=0)
            lab.pack(side='left')
            ent = Entry(can, width=11)
            val = getattr(self.model, param)
            if isinstance(val, bool):
                val = int(val)  # Show 0/1 which can convert back to bool
            ent.insert(0, str(val))
            ent.pack(side='left')
            can.pack(side='top')
            self.param_entries[param] = ent
        if self.param_entries:
            self.buttonSaveParameters = Button(
                self.frameSim,
                width=50,
                height=1,
                command=self.save_parameters_cmd,
                text="Save parameters to the running model",
                state=DISABLED)
            self.show_help(
                self.buttonSaveParameters,
                "Saves the parameter values.\n Not all values may take effect "
                "on a running model\n A model reset might be required.")
            self.buttonSaveParameters.pack(side='top', padx=5, pady=5)
            self.buttonSaveParametersAndReset = Button(
                self.frameSim,
                width=50,
                height=1,
                command=self.save_parameters_and_reset_cmd,
                text="Save parameters to the model and reset the model")
            self.show_help(
                self.buttonSaveParametersAndReset,
                "Saves the given parameter values and resets the model")
            self.buttonSaveParametersAndReset.pack(side='top', padx=5, pady=5)

        can = Canvas(self.frameSim)
        lab = Label(can,
                    width=25,
                    height=1,
                    text="Step size ",
                    justify=LEFT,
                    anchor=W,
                    takefocus=0)
        lab.pack(side='left')
        self.stepScale = Scale(can,
                               from_=1,
                               to=500,
                               resolution=1,
                               command=self.change_step_size,
                               orient=HORIZONTAL,
                               width=25,
                               length=150)
        self.stepScale.set(self.stepSize)
        self.show_help(
            self.stepScale,
            "Skips model redraw during every [n] simulation steps\n" +
            " Results in a faster model run.")
        self.stepScale.pack(side='left')
        can.pack(side='top')

        can = Canvas(self.frameSim)
        lab = Label(can,
                    width=25,
                    height=1,
                    text="Step visualization delay in ms ",
                    justify=LEFT,
                    anchor=W,
                    takefocus=0)
        lab.pack(side='left')
        self.stepDelay = Scale(can,
                               from_=0,
                               to=max(2000, self.timeInterval),
                               resolution=10,
                               command=self.change_step_delay,
                               orient=HORIZONTAL,
                               width=25,
                               length=150)
        self.stepDelay.set(self.timeInterval)
        self.show_help(
            self.stepDelay, "The visualization of each step is " +
            "delays by the given number of " + "milliseconds.")
        self.stepDelay.pack(side='left')
        can.pack(side='top')

    def set_status_str(self, new_status):
        self.statusStr = new_status
        self.statusText.set(self.statusStr)

    # model control functions
    def change_step_size(self, val):
        self.stepSize = int(val)

    def change_step_delay(self, val):
        self.timeInterval = int(val)

    def save_parameters_cmd(self):
        for param, entry in self.param_entries.items():
            val = entry.get()
            if isinstance(getattr(self.model, param), bool):
                val = bool(int(val))
            setattr(self.model, param, val)
            # See if the model changed the value (e.g. clipping)
            new_val = getattr(self.model, param)
            if isinstance(new_val, bool):
                new_val = int(new_val)
            entry.delete(0, END)
            entry.insert(0, str(new_val))
        self.set_status_str("New parameter values have been set")

    def save_parameters_and_reset_cmd(self):
        self.save_parameters_cmd()
        self.reset_model()

    def run_event(self):
        if not self.running:
            self.running = True
            self.rootWindow.after(self.timeInterval, self.step_model)
            self.runPauseString.set("Pause")
            self.buttonStep.configure(state=DISABLED)
            if self.param_entries:
                self.buttonSaveParameters.configure(state=NORMAL)
                self.buttonSaveParametersAndReset.configure(state=DISABLED)
        else:
            self.stop_running()

    def stop_running(self):
        self.running = False
        self.runPauseString.set("Continue Run")
        self.buttonStep.configure(state=NORMAL)
        self.draw_model()
        if self.param_entries:
            self.buttonSaveParameters.configure(state=NORMAL)
            self.buttonSaveParametersAndReset.configure(state=NORMAL)

    def step_model(self):
        if self.running:
            if self.model.step() is True:
                self.stop_running()
            self.currentStep += 1
            self.set_status_str("Step " + str(self.currentStep))
            self.status.configure(foreground='black')
            if self.currentStep % self.stepSize == 0:
                self.draw_model()
            self.rootWindow.after(int(self.timeInterval * 1.0 / self.stepSize),
                                  self.step_model)

    def step_once(self):
        self.running = False
        self.runPauseString.set("Continue Run")
        self.model.step()
        self.currentStep += 1
        self.set_status_str("Step " + str(self.currentStep))
        self.draw_model()
        if self.param_entries:
            self.buttonSaveParameters.configure(state=NORMAL)
        self.currentStep += 1

    def reset_model(self):
        self.running = False
        self.runPauseString.set("Run")
        self.model.reset()
        self.currentStep = 0
        self.set_status_str("Model has been reset")
        self.draw_model()

    def get_point_color(self, data):
        point_colors = []
        for i in data:
            point_colors.append([0, 0, 0, i / self.model.k])
        return point_colors

    def draw_model(self):

        if self.modelFigure is None:
            self.modelFigure = plt.figure()

            ax = self.modelFigure.add_subplot(111)
            xax = ax.xaxis
            xax.tick_top()

            points = self.init_values()

            ax.axis([0, len(points[0]) + 1, 0, 100])
            ax.invert_yaxis()

            plt.scatter(points[0],
                        points[1],
                        c=self.get_point_color(points[2]),
                        s=5,
                        marker='s')
            plt.gray()
            plt.ion()
            dpi = self.modelFigure.get_dpi()
            self.modelFigure.set_size_inches(550.0 / float(dpi),
                                             550.0 / float(dpi))
            self.modelFigure.canvas.manager.window.resizable("false", "false")
            plt.show()

        if sys.platform == 'darwin':
            self.modelFigure.canvas.manager.show()
        else:
            points = self.init_values()
            plt.scatter(points[0],
                        points[1],
                        c=self.get_point_color(points[2]),
                        s=5,
                        marker='s')
            self.modelFigure.canvas.manager.window.update()

    def init_values(self):
        data = self.model.draw()
        x = []
        point_value = 1
        for _ in data:
            x.append(point_value)
            point_value += 1

        t = np.empty(len(x))
        t.fill(self.currentStep)
        return [x, t, data]

    def start(self):
        if self.model.step.__doc__:
            self.show_help(self.buttonStep, self.model.step.__doc__.strip())

        self.model.reset()
        self.draw_model()
        self.rootWindow.mainloop()

    def quit_gui(self):
        plt.close('all')
        self.rootWindow.quit()
        self.rootWindow.destroy()

    def show_help(self, widget, text):
        def set_text(self):
            self.statusText.set(text)
            self.status.configure(foreground='blue')

        def show_help_leave(self):
            self.statusText.set(self.statusStr)
            self.status.configure(foreground='black')

        widget.bind("<Enter>", lambda e: set_text(self))
        widget.bind("<Leave>", lambda e: show_help_leave(self))
예제 #13
0
파일: lightsim.py 프로젝트: shakaran/light9
root.bind("<Key-plus>", lambda ev: changescale(0.15))
root.bind("<Key-minus>", lambda ev: changescale(-0.15))

amountvars = {}  # each light name maps to a Tkinter.DoubleVar object which the Scale adjusts


def redraw(*args):
    global l, amountvars, update
    # read the value out of each Scale
    amounts = dict([(k, v.get()) for k, v in amountvars.items()])
    mix.setamounts(amounts)


for x in mix.lightnames():
    # the Scale sets this; the redraw() callback reads it
    amountvars[x] = DoubleVar()

    # a new frame for each slider row
    f = Frame(root, bd=1, relief="groove")
    f.pack(fill="x", expand=1)
    # title
    Label(f, text=x, width=10, anchor="e").pack(side="left")
    # slider
    s = Scale(f, from_=0, to=1, res=0.01, orient="horiz", variable=amountvars[x], command=redraw)
    s.pack(side="left", fill="x", expand=1)
    if x == "ambient":  # the 'ambient' level (if present) starts at 1
        s.set(1)

root.mainloop()
예제 #14
0
파일: logplayer.py 프로젝트: robotika/eduro
class Logplayer(Frame):
    def __init__(self, root, logfn, viewer, analyzator=None, logdir=None, **kwargs):
        self.root=root
        self.logdir = logdir
        self.analyzator = analyzator
        if not self.logdir:
            self.logdir=os.path.join(os.path.dirname(os.path.dirname(__file__)),'log')
        Frame.__init__(self, **kwargs)
        self.view=viewer(self, x=800, y=600, onLeft=self.clickL, onRight=self.clickR)
        self.createWidgets()
        self.bind_all("<Left>", self.prev)
        self.bind_all("<Right>", self.next)

        self.view.redraw()
        self.root.update()
        if not logfn:
            logfn = self.logSelectDialog()
        self.dirname, self.filename = os.path.split(logfn)
        self.startRun(logfn,0)
        self.view.redraw()
        self.root.after(10,self.view.zoomExtens)
        self.running=False

    def logSelectDialog(self):
            self.root.update()
            timestamps, dirs, fns = zip(*sorted(listdir(self.logdir), reverse=True))
            o=SelcectDialog(self.root, "select log", timestamps)
            self.root.wait_window(o.top)
            index=timestamps.index(o.option)
            return os.path.join(dirs[index], fns[index])

    def createWidgets(self):
        self.controlFrame=Frame(self)
        self.posScale = Scale(self.controlFrame, orient='horizontal',
                           length=210,
                           from_=0, tickinterval=0,
                           command=self.pos_callback,
                           showvalue=0,sliderlength=10, resolution=1)
        #self.posScale.bind('<Button-1>',self.pos_start_drag)
        #self.posScale.bind('<ButtonRelease-1>', self.pos_set)

        self.playB=Button(self.controlFrame, text="play", command=self.playToggle)
        self.nextB=Button(self.controlFrame, text="next", command=self.nextRun)
        self.prevB=Button(self.controlFrame, text="prev", command=self.prevRun)
        self.camera=tkimg(self, width=640, height=512)
        self.controlFrame.grid(row=0,column=1, sticky="nw")
        self.view.grid(row=1, column=1, sticky="nsew")
        self.grid_columnconfigure(1,weight=1)
        self.grid_rowconfigure(1,weight=1)
        self.camera.grid(row = 1, column = 2, sticky = 'ne')
        self.playB.grid(row=0, column=1)
        self.prevB.grid(row=0, column=2)
        self.nextB.grid(row=0, column=3)
        self.posScale.grid(row=0, column=0)


    def playToggle(self, *args):
        if self.running:
            self.root.after_cancel(self.cycleId)
        else:
            self.cycleId=self.root.after(20, self.showrun)
        self.running=not self.running

    def nextRun(self, *args):
        self.changeRun(1)

    def prevRun(self, *args):
        self.changeRun(-1)

    def changeRun(self, step):
        if self.running:
            self.root.after_cancel(self.cycleId)
            self.running=False
        run=self.loggenerator.run+step
        if run >= len(self.loggenerator.runconfig) or run<0:
            timestamps, dirs, fns = zip(*sorted(listdir(self.logdir)))
            index=fns.index(self.filename)+step
            if 0<=index<len(fns):
                run = 0 if step==1 else -1
                self.startRun(os.path.join(dirs[index], fns[index]), run)
        else:
            self.startRun(os.path.join(self.dirname, self.filename), run)




    def restart(self, keeppostion=True, startposition=None):
        self.loggenerator.startrun(self.loggenerator.run, startposition=startposition)
        self.data=list(self.loggenerator)
        if not keeppostion:
            self.position=0
        self.posScale.set(self.position)
        self.showData(self.position)

    def startRun(self, fn, run, keeppostion=False):
        self.dirname, self.filename = os.path.split(fn)
        print("starting log %s run %i"%(fn,run))
        self.loggenerator=EduroMaxiReader(fn)
        self.loggenerator.startrun(run)
        self.root.title("%s %s run %i"%(self.dirname,self.filename, self.loggenerator.run+1))
        self.data=list(self.loggenerator)
        if not keeppostion:
            self.position=0
        self.posScale.set(self.position)
        self.showData(self.position)
        self.posScale.configure(to_= len(self.data)-1)
        self.view.reset()
        self.camera.clear()

    def showData(self,position):
        self.position=position
        self.posScale.set(position)
        time, pose, msgs = self.data[position]
        self.view.MsgListener(time, pose, msgs)
        #if self.analyzator:
        #    self.analyzator(time, pose, msgs)
        self.view.robot.update(*pose)
        self.view.redraw_lasers()
        self.view.robot.redraw(self.view)
        if msgs['CAMERALOG']:
            _, shot = msgs['CAMERALOG']
            if shot:
                shot = os.path.join(self.dirname, shot.split('/')[-1])
                self.camera.showImg(shot)

    def clickL(self, x, y):
        #self.loggenerator.correction=Position(self.loggenerator.correction.x+x-self.view.robot.x, self.loggenerator.correction.y+y-self.view.robot.y, self.loggenerator.correction.a)
        #print(self.loggenerator.correction)
        A=self.data[self.position][1]
        S=self.data[0][1]
        #self.restart(keeppostion=True, startposition=Position(S.x+x-A.x, S.y+y-A.y, S.a))
        print("left", x,y)

    def clickR(self, x, y):
        #try to modify start position so that actual position heading is in direction of this click

        #actual position
        A=self.data[self.position][1]
        #start position
        S=self.data[0][1]
        #polar vector from actual to start
        dist=((A.x-S.x)**2+(A.y-S.y)**2)**0.5
        if S.x==A.x:#when x distance is 0 then angle +-90 (when y dist is 0 then it doesnt matter
            beta=-pi/2 if S.y>=A.y else pi/2
        else:
            beta=atan((A.y-S.y)/(A.x-S.x))
        #angle difference from actual position to click
        #TODO solve +-90 same as above
        delta=A.a-atan((A.y-y)/(A.x-x))

        newStart = Position(A.x+cos(beta+delta)*dist, A.y+sin(beta+delta)*dist, S.a-delta)
        #self.restart(keeppostion=True, startposition=newStart)
        print("right", x, y)

    def showrun(self):
        pos=self.position+1
        if pos<len(self.data):
            self.showData(pos)
            self.cycleId=self.root.after(20, self.showrun)
        else:
            self.running=False

    def next(self, event):
        pos=self.position+1
        if pos<len(self.data):
            self.posScale.set(pos)

    def prev(self, event):
        pos=self.position-1
        if pos>=0:
            self.posScale.set(pos)

    def pos_callback(self, pos, *args):
        if not self.running:
            self.showData(int(pos))
예제 #15
0
파일: tkhello.py 프로젝트: xiahei/TOTAL
#!/usr/bin/env python
#coding=utf-8
from Tkinter import (Tk, Scale, Button, Label, Y, HORIZONTAL, X, mainloop)
from time import ctime
#

def resize(ev=None):
    label.config(font='Helvetica -%d bold' % scale.get())

top = Tk()
# top.geometry('250 X 150')
txt = ctime()
label = Label(top, text=txt, font='Consolas -12 bold')
label.pack(fill=Y, expand=1)

scale = Scale(top, from_=10, to=40, orient=HORIZONTAL, command=resize)
scale.set(12)
scale.pack(fill=X, expand=1)

quit=Button(top, text='QUIT', command=top.quit, activeforeground='white', activebackground='red')

quit.pack()

mainloop()
class ResolverInterface:

	def __init__(self):

		self.window_width = 800
		self.window_height = 10*40

		self.root = Tk()

		self.colourSetter = ColourSetter(self)

		self.draw(init=True)

		self.root.mainloop()

		return

	def draw(self, init=False):


		self.root.geometry("%dx%d" % (self.window_width, self.window_height))
		self.root.title("RandomImageResolver")

		# set colours
		self.root.configure(background="black")

		self.tk_iters_scale = Scale(self.root)
		self.tk_iters_scale_label = Label(self.root, text="Iters")

		self.tk_width_scale = Scale(self.root, command=self.handleGridSizeChange)
		self.tk_width_scale_label = Label(self.root, text="Width")

		self.tk_height_scale = Scale(self.root, command=self.handleGridSizeChange)
		self.tk_height_scale_label = Label(self.root, text="Height")

		self.tk_hueStd_scale = Scale(self.root)
		self.tk_hueStd_scale_label = Label(self.root, text="HueStd")

		self.tk_saturStd_scale = Scale(self.root)
		self.tk_saturStd_scale_label = Label(self.root, text="SaturStd")

		self.tk_valueStd_scale = Scale(self.root)
		self.tk_valueStd_scale_label = Label(self.root, text="ValueStd")

		self.tk_stdDecay_scale = Scale(self.root)
		self.tk_stdDecay_scale_label = Label(self.root, text="StdDecay")

		self.tk_parentNoise_scale = Scale(self.root)
		self.tk_parentNoise_scale_label = Label(self.root, text="ParentPosNoise")

		self.tk_parentNoiseDecay_scale = Scale(self.root)
		self.tk_parentNoiseDecay_scale_label = Label(self.root, text="ParentPosNoiseDecay")

		# start width, start height, hue shift std, saturation std, value std

		self.tk_randomize = Button(self.root, text="Randomize", command=self.handleRandomize)
		self.tk_generate = Button(self.root, text="Generate", command=self.handleGenerate)
		self.tk_expand = Button(self.root, text="Expand", command=self.handleExpand)
		self.tk_save = Button(self.root, text="Save", command=self.handleSave)

		self.tk_iters_scale.configure(bd=0, from_=1, to=10, orient=HORIZONTAL, sliderrelief=FLAT, resolution=1)
		self.tk_iters_scale.set(8)

		self.tk_width_scale.configure(bd=0, from_=1, to=10, orient=HORIZONTAL, sliderrelief=FLAT, resolution=1)
		self.tk_width_scale.set(2)

		self.tk_height_scale.configure(bd=0, from_=1, to=10, orient=HORIZONTAL, sliderrelief=FLAT, resolution=1)
		self.tk_height_scale.set(2)

		self.tk_hueStd_scale.configure(bd=0, from_=0, to=0.1, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.005)
		self.tk_hueStd_scale.set(0.01)

		self.tk_saturStd_scale.configure(bd=0, from_=0, to=0.4, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.01)
		self.tk_saturStd_scale.set(0.07)

		self.tk_valueStd_scale.configure(bd=0, from_=0, to=0.4, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.01)
		self.tk_valueStd_scale.set(0.07)

		self.tk_stdDecay_scale.configure(bd=0, from_=0, to=1., orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.1)
		self.tk_stdDecay_scale.set(0.)

		self.tk_parentNoise_scale.configure(bd=0, from_=0, to=1, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.05)
		self.tk_parentNoise_scale.set(0.15)

		self.tk_parentNoiseDecay_scale.configure(bd=0, from_=0, to=1, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.1)
		self.tk_parentNoiseDecay_scale.set(0.)

		self.root.bind("<Configure>", self.resize)


		# make sure colourSetter size is synced to default
		self.colourSetter.setGridSize((self.tk_width_scale.get(), self.tk_height_scale.get()))
		self.colourSetter.randomize()

		return

	def handleRandomize(self, event=[]):

		# generate a new random set of colours
		start_width = self.tk_width_scale.get()
		start_height = self.tk_height_scale.get()

		self.colourSetter.setGridSize((start_width, start_height))
		self.colourSetter.randomize()		

		return

	def handleGenerate(self, event=[]):

		'''
		iters = self.tk_iters_scale.get()
		start_width = self.tk_width_scale.get()
		start_height = self.tk_height_scale.get()
		hueStd = self.tk_hueStd_scale.get()
		staurStd = self.tk_saturStd_scale.get()
		valueStd = self.tk_valueStd_scale.get()
		std_decay = self.tk_stdDecay_scale.get()
		parent_pos_noise = self.tk_parentNoise_scale.get()

		self.IMGS = newImage(start_size=(start_width, start_height), iters=iters, hsv_std = (hueStd, staurStd, valueStd), std_decay=std_decay, parent_pos_noise=parent_pos_noise)
		self.IMGS[-1].show()
		'''

		iters = self.tk_iters_scale.get()
		hueStd = self.tk_hueStd_scale.get()
		staurStd = self.tk_saturStd_scale.get()
		valueStd = self.tk_valueStd_scale.get()
		std_decay = self.tk_stdDecay_scale.get()
		parent_pos_noise = self.tk_parentNoise_scale.get()
		parent_pos_noise_decay = self.tk_parentNoiseDecay_scale.get()
		seed = self.colourSetter.getSeed()

		self.IMGS = newImage(seed=seed, iters=iters, hsv_std = (hueStd, staurStd, valueStd), std_decay=std_decay, parent_pos_noise=parent_pos_noise, parent_pos_noise_decay=parent_pos_noise_decay)
		self.IMGS[-1].show()

		return

	def handleExpand(self, event=[]):

		hueStd = self.tk_hueStd_scale.get()
		staurStd = self.tk_saturStd_scale.get()
		valueStd = self.tk_valueStd_scale.get()
		std_decay = self.tk_stdDecay_scale.get()
		parent_pos_noise = self.tk_parentNoise_scale.get()
		parent_pos_noise_decay = self.tk_parentNoiseDecay_scale.get()

		new_imgs = newImage(seed=self.IMGS[-1], iters=1, hsv_std = (hueStd, staurStd, valueStd), std_decay=std_decay, parent_pos_noise=parent_pos_noise, parent_pos_noise_decay=parent_pos_noise_decay, inum_offset=len(self.IMGS))
		self.IMGS.append(new_imgs[-1])
		self.IMGS[-1].show()
 
		return

	def handleSave(self, event=[]):
		# save the current image with prompt for name

		#self.tk_entry.focus()

		d = MyDialog(self.root)
		self.root.wait_window(d.top)
		#print("You said: ", d.value)
		fname = d.value.strip()

		try:
			if '.png' not in fname:
				fname = fname+".png"
			self.IMGS[-1].save(fname)
			print("Saved.")
		except:
			#print("Error: Have not generated image yet.")
			print("Error: Nothing saved")

	def handleGridSizeChange(self, event=[]):

		self.colourSetter.setGridSize((self.tk_width_scale.get(), self.tk_height_scale.get()))

		return



	def resize(self, event=[]):
		pixelX=self.root.winfo_width()
		pixelY=self.root.winfo_height()

		self.window_width = pixelX
		self.window_height = pixelY

		nb_scales = 9

		colourSetterWidth = 200
		label_width = 150
		button_width = 75
		scale_height = self.window_height/nb_scales

		cur_height = 0
		scale_width = self.window_width - label_width - button_width - colourSetterWidth
		scale_x = label_width+colourSetterWidth
		self.tk_iters_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_iters_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)
		
		cur_height += scale_height
		self.tk_width_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_width_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_height_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_height_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_hueStd_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_hueStd_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_saturStd_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_saturStd_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_valueStd_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_valueStd_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_stdDecay_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_stdDecay_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_parentNoise_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_parentNoise_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)

		cur_height += scale_height
		self.tk_parentNoiseDecay_scale.place(x=scale_x, y=cur_height, width = scale_width, height = scale_height)
		self.tk_parentNoiseDecay_scale_label.place(x=colourSetterWidth, y=cur_height, width = label_width, height = scale_height)


		randomize_height = int(round(self.window_height*0.3))
		generate_height = int(round(self.window_height*0.3))
		expand_height = int(round(self.window_height*0.2))
		save_height = int(round(self.window_height*0.2))

		button_cur_ypos = 0.
		self.tk_randomize.place(x=self.window_width-button_width, y=button_cur_ypos, width=button_width, height=randomize_height)
		button_cur_ypos += randomize_height

		self.tk_generate.place(x=self.window_width-button_width, y=button_cur_ypos, width=button_width, height=generate_height)
		button_cur_ypos += generate_height

		self.tk_expand.place(x=self.window_width-button_width, y=button_cur_ypos, width=button_width, height= expand_height)
		button_cur_ypos += expand_height

		self.tk_save.place(x=self.window_width-button_width, y=button_cur_ypos, width=button_width, height= save_height)
		button_cur_ypos += save_height

		self.colourSetter.place(x=0, y=0, width = colourSetterWidth, height = self.window_height)
예제 #17
0
class FrameScale(object):
    # TODO Bugs: When the scale bar is dragged to overlap the other the values does not update correctly
    # TODO The histogram should be updated when scale is changed
    def __init__(self, a, frame, view):
        self.view = view
        amin = np.amin(a)
        amax = np.amax(a)

        # Image min and max values
        self.min_var = IntVar(value=amin)
        self.max_var = IntVar(value=amax)

        self.min_label = Label(frame, text="Min.")
        self.max_label = Label(frame, text="Max.")

        self.min_entry = Entry(frame, textvariable=self.min_var)
        self.max_entry = Entry(frame, textvariable=self.max_var)

        self.min_entry.bind(
            "<Return>", lambda event: self.min_entry_change(
                self.min_scale, self.min_var.get()))
        self.max_entry.bind(
            "<Return>", lambda event: self.max_entry_change(
                self.max_scale, self.max_var.get()))

        self.min_scale = Scale(frame,
                               orient=HORIZONTAL,
                               from_=amin,
                               to=amax - 1,
                               length=150,
                               command=self.min_change)
        self.max_scale = Scale(frame,
                               orient=HORIZONTAL,
                               from_=amin + 1,
                               to=amax,
                               length=150,
                               command=self.max_change)

        self.min_scale.set(amin)
        self.max_scale.set(amax)

        self.min_label.grid(row=0, column=0, sticky='w')
        self.max_label.grid(row=1, column=0, sticky='w')
        self.min_entry.grid(row=0, column=1, ipady=2)
        self.max_entry.grid(row=1, column=1, ipady=2)
        self.min_scale.grid(row=0, column=2, sticky='e', padx=10)
        self.max_scale.grid(row=1, column=2, sticky='e', padx=10)

    #Scale bar
    def min_change(self, val):
        val = int(val)
        temp = self.max_var.get()
        if (val < temp):
            self.min_var.set(val)
            self.view.change_clim(val, temp)
        else:
            self.min_var.set(temp - 1)
            self.view.change_clim(temp - 1, temp)

    #Scale bar
    def max_change(self, val):
        val = int(val)
        temp = self.min_var.get()
        if (val > temp):
            self.max_var.set(val)
            self.view.change_clim(temp, val)
        else:
            self.min_var.set(temp + 1)
            self.view.change_clim(temp, temp + 1)

    #Entry
    #TODO: only allow numbers as input. Use nbr_check from FrameFormat.
    def min_entry_change(self, scale, value):
        if (value < int(self.max_var.get())):
            scale.configure(from_=value - 20, to=value + 20)
            scale.set(value)
        else:
            scale.configure(from_=value - 20, to=value + 20)
            scale.set(int(self.max_var.get()) - 1)

    #Entry
    #TODO: only allow numbers as input. Use nbr_check from FrameFormat.
    def max_entry_change(self, scale, value):
        if (value > int(self.min_var.get())):
            scale.configure(from_=value - 20, to=value + 20)
            scale.set(value)
        else:
            scale.configure(from_=value - 20, to=value + 20)
            scale.set(int(self.min_var.get()) + 1)

    def update_limit(self, a):
        self.min_change(np.amin(a))
        self.max_change(np.amax(a))
        self.min_entry_change(self.min_scale, np.amin(a))
        self.max_entry_change(self.max_scale, np.amax(a))
예제 #18
0
class OfflineVisualiser(Visualiser):
    """A VTK-powered offline visualiser which runs in its own thread.
    In addition to the functions provided by the standard visualiser,
    the following additional functions are provided:

    precache_height_quantities() - Precache all the vtkpoints
    structures for any dynamic height based quantities to render.
    """
    def __init__(self, source, frameDelay=100, frameStep=1):
        """The source parameter is assumed to be a NetCDF sww file.
        The frameDelay parameter is the number of milliseconds waited between frames.
        """
        Visualiser.__init__(self, source)

        self.frameNumber = 0
        fin = NetCDFFile(self.source, 'r')
        self.maxFrameNumber = fin.variables['time'].shape[0] - 1
        fin.close()
        
        #self.frameNumberTkVariable = StringVar()
        #self.frameNumberTkVariable.set('Frame - %05g'%self.framNumber)

        self.frameDelay = frameDelay

        self.xmin = None
        self.xmax = None
        self.ymin = None
        self.ymax = None
        self.zmin = None
        self.zmax = None

        self.frameStep= frameStep 

        self.vtk_heightQuantityCache = []
        for i in range(self.maxFrameNumber + 1): # maxFrameNumber is zero indexed.
            self.vtk_heightQuantityCache.append({})

        self.paused = False
        self.movie = False
        
    def setup_grid(self):
        fin = NetCDFFile(self.source, 'r')
        self.vtk_cells = vtkCellArray()
        N_tri = fin.variables['volumes'].shape[0]
        for v in range(N_tri):
            self.vtk_cells.InsertNextCell(3)
            for i in range(3):
                self.vtk_cells.InsertCellPoint(fin.variables['volumes'][v][i])
        fin.close()
        
    def update_height_quantity(self, quantityName, dynamic=True):
        polydata = self.vtk_polyData[quantityName] = vtkPolyData()
        if dynamic is True:
            #print ' - Frame',self.frameNumber,'of',self.maxFrameNumber
            if not self.vtk_heightQuantityCache[self.frameNumber].has_key(quantityName):
                self.vtk_heightQuantityCache[self.frameNumber][quantityName]\
                    = self.read_height_quantity(quantityName, True, self.frameNumber);
            polydata.SetPoints(self.vtk_heightQuantityCache[self.frameNumber][quantityName])
        else:
            polydata.SetPoints(self.read_height_quantity(quantityName, False))
        polydata.SetPolys(self.vtk_cells)

    def get_3d_bounds(self):
        return [self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax]
            
    def read_height_quantity(self, quantityName, dynamic=True, frameNumber=0):
        """Read in a height based quantity from the NetCDF source file
        and return a vtkPoints object. frameNumber is ignored if
        dynamic is false."""
        fin = NetCDFFile(self.source, 'r')
        points = vtkPoints()
        if dynamic is True:
            N_vert = fin.variables[quantityName].shape[1]
        else:
            N_vert = len(fin.variables[quantityName])
        x = num.ravel(num.array(fin.variables['x'], num.float))
        y = num.ravel(num.array(fin.variables['y'], num.float))
        if dynamic is True:
            q = num.array(fin.variables[quantityName][frameNumber], num.float)
        else:
            q = num.ravel(num.array(fin.variables[quantityName], num.float))

        q *= self.height_zScales[quantityName]
        q += self.height_offset[quantityName]

        for v in range(N_vert):
            points.InsertNextPoint(x[v], y[v], q[v])
            if self.xmin == None or self.xmin > x[v]:
                self.xmin = x[v]
            if self.xmax == None or self.xmax < x[v]:
                self.xmax = x[v]
            if self.ymin == None or self.ymin > y[v]:
                self.ymin = y[v]
            if self.ymax == None or self.ymax < y[v]:
                self.ymax = y[v]
            if self.zmin == None or self.zmin > q[v]:
                self.zmin = q[v]
            if self.zmax == None or self.zmax < q[v]:
                self.zmax = q[v]
        fin.close()
        return points

    def precache_height_quantities(self):
        """Precache any height-based quantities. Call before rendering
        beigns."""
        for q in self.height_quantities:
            if self.height_dynamic[q] is True:
                print 'Precaching %s' % q
                for i in range(self.maxFrameNumber + 1): # maxFrameNumber is zero-indexed
                    print ' - Frame %d of %d' % (i, self.maxFrameNumber)
                    self.vtk_heightQuantityCache[i][q]\
                        = self.read_height_quantity(q, True, i)

    def build_quantity_dict(self):
        quantities = {}
        fin = NetCDFFile(self.source, 'r')
        for q in filter(lambda n:n != 'x' and n != 'y' and n != 'z' and n != 'time' and n != 'volumes', fin.variables.keys()):
            if len(fin.variables[q].shape) == 1: # Not a time-varying quantity
                quantities[q] = num.ravel(num.array(fin.variables[q], num.float))
            else: # Time-varying, get the current timestep data
                quantities[q] = num.array(fin.variables[q][self.frameNumber], num.float)
        fin.close()
        return quantities

    def setup_gui(self):
        Visualiser.setup_gui(self)
        self.tk_quit.grid(row=0, column=0, sticky=W+E)
        self.tk_movie_toggle = Button(self.tk_controlFrame, text="Movie off", command=self.movie_toggle)
        self.tk_movie_toggle.grid(row=0, column=6,  sticky=W+E)
        
                
        self.tk_restart = Button(self.tk_controlFrame, text="<<<", command=self.restart, width=5)
        self.tk_restart.grid(row=1, column=0, sticky=W+E)
        self.tk_back10 = Button(self.tk_controlFrame, text="<<", command=self.back10, width=5)
        self.tk_back10.grid(row=1, column=1, sticky=W+E)
        self.tk_back = Button(self.tk_controlFrame, text="<", command=self.back, width=5)
        self.tk_back.grid(row=1, column=2, sticky=W+E)
        self.tk_pauseResume = Button(self.tk_controlFrame, text="Pause", command=self.pauseResume, width=15)
        self.tk_pauseResume.grid(row=1, column=3, sticky=W+E)
        self.tk_forward = Button(self.tk_controlFrame, text=">", command=self.forward, width=5)
        self.tk_forward.grid(row=1, column=4, sticky=W+E)
        self.tk_forward10 = Button(self.tk_controlFrame, text=">>", command=self.forward10, width=5)
        self.tk_forward10.grid(row=1, column=5, sticky=W+E)
        self.tk_forwardEnd = Button(self.tk_controlFrame, text=">>>", command=self.forwardEnd, width=5)
        self.tk_forwardEnd.grid(row=1, column=6, sticky=W+E)
        

        self.tk_frameNumber = Label(self.tk_controlFrame, text='Frame')
        self.tk_frameNumber.grid(row=2, column=0, sticky=W+E)
        self.tk_gotoFrame = Scale(self.tk_controlFrame, from_=0, to=self.maxFrameNumber, orient=HORIZONTAL)
        self.tk_gotoFrame.grid(row=2, column=1, columnspan=2, sticky=W+E)
        self.tk_stepLabel = Label(self.tk_controlFrame, text='Step')
        self.tk_stepLabel.grid(row=2, column=4, sticky=W+E)        
        self.tk_frameStep = Scale(self.tk_controlFrame, from_=0, to=self.maxFrameNumber, orient=HORIZONTAL)
        self.tk_frameStep.grid(row=2, column=5, columnspan=2, sticky=W+E)
        
        # Make the buttons stretch to fill all available space
        for i in range(7):
            self.tk_controlFrame.grid_columnconfigure(i, weight=1)

    def run(self):
        self.alter_tkroot(Tk.after, (self.frameDelay, self.animateForward))
        Visualiser.run(self)

    def restart(self):
        self.frameNumber = 0
        self.redraw_quantities()
        self.update_labels()
        self.pause()
        
        if self.movie:
            self.save_image()
 
    def forwardEnd(self):
        self.frameNumber = self.maxFrameNumber
        self.redraw_quantities()
        self.update_labels()
        self.pause()
                
    def movie_toggle(self):
        if self.movie == True:
            self.movie = False
            self.tk_movie_toggle.config(text='Movie off')
        else:
            self.movie = True
            self.tk_movie_toggle.config(text='Movie on ')
            
            
        
        
    def save_image(self):
        
        from vtk import vtkJPEGWriter, vtkJPEGWriter, vtkPNGWriter
        from vtk import vtkPNMWriter, vtkWindowToImageFilter
        from os import path
         
        sourcebase, _ = path.splitext(self.source)
        fname = sourcebase+'%05g.png' % self.frameNumber
        #print fname
        
        extmap = {'.jpg' : vtkJPEGWriter,
                  '.jpeg' : vtkJPEGWriter,
                  '.png' : vtkPNGWriter,
                  '.pnm' : vtkPNMWriter,
                  }
        basename, ext = path.splitext(fname)
        try: Writer = extmap[ext.lower()]
        except KeyError:
            error_msg("Don't know how to handle %s files" % ext, parent=self)
            return
    
        renWin = self.vtk_renderer.GetRenderWindow()
        w2i = vtkWindowToImageFilter()
        writer = Writer()
        w2i.SetInput(renWin)
        w2i.Update()
        writer.SetInput(w2i.GetOutput())
        writer.SetFileName(fname)
        renWin.Render()
        writer.Write()        
    
    def back10(self):
        if self.frameNumber - 10 >= 0:
            self.frameNumber -= 10
        else:
            self.frameNumber = 0
        self.redraw_quantities()
        self.update_labels()
        self.pause()

    def back(self):
        if self.frameNumber > 0:
            self.frameNumber -= 1
            self.redraw_quantities()
            self.update_labels()
            self.pause()

    def pauseResume(self):
        if self.paused is True:
            self.resume()
        else:
            self.pause()

    def pause(self):
        self.paused = True
        self.tk_pauseResume.config(text="Resume")

    def resume(self):
        self.paused = False
        self.tk_pauseResume.config(text="Pause")
        self.frameNumber = self.tk_gotoFrame.get()
        self.frameStep = self.tk_frameStep.get()
        self.tk_root.after(self.frameDelay, self.animateForward)

    def forward(self):
        if self.frameNumber < self.maxFrameNumber:
            self.frameNumber += 1
            self.redraw_quantities()
            self.update_labels()
            self.pause()
            
    def forward_step(self):
        if self.frameNumber + self.frameStep <= self.maxFrameNumber:
            self.frameNumber += self.frameStep
            self.redraw_quantities()
            self.update_labels()
        else:
            self.frameNumber = self.maxFrameNumber            
            self.redraw_quantities()
            self.update_labels()    
            self.pause()
         
        if self.movie:
             self.save_image()
                

    def forward10(self):
        if self.frameNumber + 10 <= self.maxFrameNumber:
            self.frameNumber += 10
        else:
            self.frameNumber = self.maxFrameNumber
        self.redraw_quantities()
        self.update_labels()
        self.pause()

    def animateForward(self):
        if self.paused is not True:
            self.forward_step()
            self.tk_root.after(self.frameDelay, self.animateForward)
            
    def update_labels(self): 
        #self.tk_frameNumber.config(text='%05g of %05g'%(self.frameNumber,self.maxFrameNumber))
        self.tk_gotoFrame.set(self.frameNumber)
        self.tk_frameStep.set(self.frameStep)
               
    def shutdown(self):
        #self.pause()
        self.tk_root.withdraw()
        self.tk_root.destroy()
예제 #19
0
파일: cockpit.py 프로젝트: dpm76/eaglebone
class Cockpit(ttkFrame):
    '''
    Remote device GUI 
    '''
    
    #TODO: 20160415 DPM - Set these values from configuration file
    #--- config
    THROTTLE_BY_USER = True
    THROTTLE_RESOLUTION = 0.1
    
    # Joystick enabled or not, if any
    JOYSTICK_ENABLED = True 

    DEFAULT_DRONE_IP = "192.168.1.130"
    DEFAULT_DRONE_PORT = 2121
    #--- end config
    

    KEY_ANG_SPEED = "ang-speed"
    KEY_ANGLES = "angles"
    KEY_ACCEL = "accel"
    
    PID_KEYS = ["P", "I", "D"]

    DIR_NONE = 0
    DIR_VERTICAL = 1
    DIR_HORIZONTAL = 2
    
    def __init__(self, parent, isDummy = False, droneIp = DEFAULT_DRONE_IP, dronePort = DEFAULT_DRONE_PORT):
        '''
        Constructor
        '''
        ttkFrame.__init__(self, parent)
        
        self._target = [0.0] * 4        
        
        self._selectedPidConstats = "--"
        self._pidConstants = {
                              Cockpit.KEY_ANG_SPEED:{
                                           "X":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Y":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Z":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                }
                                           },
                               Cockpit.KEY_ANGLES: {
                                          "X":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Y":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                }
                                          },
                               Cockpit.KEY_ACCEL:{
                                           "X":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Y":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                            "Z":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                 }
                                          }
                              }
        
        self.parent = parent

        self.initUI()

        self._controlKeysLocked = False

        if not isDummy:
            self._link = INetLink(droneIp, dronePort)
        else:
            self._link = ConsoleLink()
            
        self._link.open()

        self._updateInfoThread = Thread(target=self._updateInfo)
        self._updateInfoThreadRunning = False
        self._readingState = False

        self._start()
        
            
    def initUI(self):
        
        self.parent.title("Drone control")
        self.style = Style()
        self.style.theme_use("default")
        
        self.pack(fill=BOTH, expand=1)
        
        self.parent.bind_all("<Key>", self._keyDown)
        self.parent.bind_all("<KeyRelease>", self._keyUp)

        if system() == "Linux":
            self.parent.bind_all("<Button-4>", self._onMouseWheelUp)
            self.parent.bind_all("<Button-5>", self._onMouseWheelDown)

        else:
            #case of Windows
            self.parent.bind_all("<MouseWheel>", self._onMouseWheel)
        
        #Commands        
        commandsFrame = tkFrame(self)
        commandsFrame.grid(column=0, row=0, sticky="WE")
        
        self._started = IntVar()
        self._startedCB = Checkbutton(commandsFrame, text="On", variable=self._started, command=self._startedCBChanged)
        self._startedCB.pack(side=LEFT, padx=4)
        
#         self._integralsCB = Checkbutton(commandsFrame, text="Int.", variable=self._integralsEnabled, \
#                                         command=self._integralsCBChanged, state=DISABLED)
#         self._integralsCB.pack(side=LEFT, padx=4)
        
        self._quitButton = Button(commandsFrame, text="Quit", command=self.exit)
        self._quitButton.pack(side=LEFT, padx=2, pady=2)
        
#         self._angleLbl = Label(commandsFrame, text="Angle")
#         self._angleLbl.pack(side=LEFT, padx=4)
#         
#         self._angleEntry = Entry(commandsFrame, state=DISABLED)
#         self._angleEntry.pack(side=LEFT)
        
        #Info
        infoFrame = tkFrame(self)
        infoFrame.grid(column=1, row=1, sticky="NE", padx=4)
        
        #Throttle
        Label(infoFrame, text="Throttle").grid(column=0, row=0, sticky="WE")        
        self._throttleTexts = [StringVar(),StringVar(),StringVar(),StringVar()]
        Entry(infoFrame, textvariable=self._throttleTexts[3], state=DISABLED, width=5).grid(column=0, row=1)                
        Entry(infoFrame, textvariable=self._throttleTexts[0], state=DISABLED, width=5).grid(column=1, row=1)
        Entry(infoFrame, textvariable=self._throttleTexts[2], state=DISABLED, width=5).grid(column=0, row=2)
        Entry(infoFrame, textvariable=self._throttleTexts[1], state=DISABLED, width=5).grid(column=1, row=2)
        
        #Angles
        Label(infoFrame, text="Angles").grid(column=0, row=3, sticky="WE")        
        self._angleTexts = [StringVar(),StringVar(),StringVar()]
        for index in range(3):
            Entry(infoFrame, textvariable=self._angleTexts[index], state=DISABLED, width=5).grid(column=index, row=4)
               
        #Accels
        Label(infoFrame, text="Accels").grid(column=0, row=5, sticky="WE")
        self._accelTexts = [StringVar(),StringVar(),StringVar()]
        for index in range(3):
            Entry(infoFrame, textvariable=self._accelTexts[index], state=DISABLED, width=5).grid(column=index, row=6)
        
        #Speeds
        Label(infoFrame, text="Speeds").grid(column=0, row=7, sticky="WE")
        self._speedTexts = [StringVar(),StringVar(),StringVar()]
        for index in range(3):
            Entry(infoFrame, textvariable=self._speedTexts[index], state=DISABLED, width=5).grid(column=index, row=8)
        
        #Height
        Label(infoFrame, text="Height").grid(column=0, row=9, sticky="E")
        self._heightText = StringVar()
        Entry(infoFrame, textvariable=self._heightText, state=DISABLED, width=5).grid(column=1, row=9)
        
        #Loop rate
        Label(infoFrame, text="Loop @").grid(column=0, row=10, sticky="E")
        self._loopRateText = StringVar()
        Entry(infoFrame, textvariable=self._loopRateText, state=DISABLED, width=5).grid(column=1, row=10)
        Label(infoFrame, text="Hz").grid(column=2, row=10, sticky="W")
        
        #control
        
        controlFrame = tkFrame(self)
        controlFrame.grid(column=0, row=1, sticky="W")
        
        self._throttle = DoubleVar()
        
        if Cockpit.THROTTLE_BY_USER:

            self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=0.0, \
                                tickinterval=0, variable=self._throttle, resolution=Cockpit.THROTTLE_RESOLUTION, \
                                length=200, showvalue=1, \
                                state=DISABLED,
                                command=self._onThrustScaleChanged)

        else:
        
            self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=-100.0, \
                                tickinterval=0, variable=self._throttle, \
                                length=200, showvalue=1, \
                                state=DISABLED,
                                command=self._onThrustScaleChanged)

        self._thrustScale.bind("<Double-Button-1>", self._onThrustScaleDoubleButton1, "+")
        self._thrustScale.grid(column=0)
        
        self._shiftCanvas = Canvas(controlFrame, bg="white", height=400, width=400, \
                             relief=SUNKEN)
        self._shiftCanvas.bind("<Button-1>", self._onMouseButton1)
        #self._shiftCanvas.bind("<ButtonRelease-1>", self._onMouseButtonRelease1)
        self._shiftCanvas.bind("<B1-Motion>", self._onMouseButton1Motion)
        self._shiftCanvas.bind("<Double-Button-1>", self._onMouseDoubleButton1)

        self._shiftCanvas.bind("<Button-3>", self._onMouseButton3)
        #self._shiftCanvas.bind("<ButtonRelease-3>", self._onMouseButtonRelease3)
        self._shiftCanvas.bind("<B3-Motion>", self._onMouseButton3Motion)

        self._shiftCanvas.grid(row=0,column=1, padx=2, pady=2)
        self._shiftCanvas.create_oval(1, 1, 400, 400, outline="#ff0000")
        self._shiftCanvas.create_line(200, 2, 200, 400, fill="#ff0000")
        self._shiftCanvas.create_line(2, 200, 400, 200, fill="#ff0000")
        self._shiftMarker = self._shiftCanvas.create_oval(196, 196, 204, 204, outline="#0000ff", fill="#0000ff")
        
        self._yaw = DoubleVar()
        self._yawScale = Scale(controlFrame, orient=HORIZONTAL, from_=-100.0, to=100.0, \
                            tickinterval=0, variable=self._yaw, \
                            length=200, showvalue=1, \
                            command=self._onYawScaleChanged)
        self._yawScale.bind("<Double-Button-1>", self._onYawScaleDoubleButton1, "+")
        self._yawScale.grid(row=1, column=1)
        
        self._controlKeyActive = False
        

        #PID calibration

        pidCalibrationFrame = tkFrame(self)
        pidCalibrationFrame.grid(column=0, row=2, sticky="WE");

        self._pidSelected = StringVar()
        self._pidSelected.set("--")
        self._pidListBox = OptionMenu(pidCalibrationFrame, self._pidSelected, "--", \
                                      Cockpit.KEY_ANG_SPEED, Cockpit.KEY_ANGLES, Cockpit.KEY_ACCEL, \
                                       command=self._onPidListBoxChanged)
        self._pidListBox.pack(side=LEFT, padx=2)
        self._pidListBox.config(width=10)
        
        self._axisSelected = StringVar()
        self._axisSelected.set("--")
        self._axisListBox = OptionMenu(pidCalibrationFrame, self._axisSelected, "--", "X", "Y", "Z", \
                                       command=self._onAxisListBoxChanged)
        self._axisListBox.pack(side=LEFT, padx=2)
        self._axisListBox.config(state=DISABLED)

        Label(pidCalibrationFrame, text="P").pack(side=LEFT, padx=(14, 2))

        self._pidPString = StringVar()
        self._pidPString.set("0.00")
        self._pidPSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidPString, command=self._onPidSpinboxChanged)
        self._pidPSpinbox.pack(side=LEFT, padx=2)

        Label(pidCalibrationFrame, text="I").pack(side=LEFT, padx=(14, 2))

        self._pidIString = StringVar()
        self._pidIString.set("0.00")
        self._pidISpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidIString, command=self._onPidSpinboxChanged)
        self._pidISpinbox.pack(side=LEFT, padx=2)
        
        Label(pidCalibrationFrame, text="D").pack(side=LEFT, padx=(14, 2))
        
        self._pidDString = StringVar()
        self._pidDString.set("0.00")
        self._pidDSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidDString, command=self._onPidSpinboxChanged)
        self._pidDSpinbox.pack(side=LEFT, padx=2)
        
        #debug
        debugFrame = tkFrame(self)
        debugFrame.grid(column=0, row=3, sticky="WE")
        
        self._debugMsg = Message(debugFrame, anchor="nw", justify=LEFT, relief=SUNKEN, width=300)
        self._debugMsg.pack(fill=BOTH, expand=1)



    def _start(self):

        self._readDroneConfig()
        
        if Cockpit.JOYSTICK_ENABLED:
            self._joystickManager = JoystickManager.getInstance()
            self._joystickManager.start()
            
            joysticks = self._joystickManager.getJoysticks()
            if len(joysticks) != 0:
                self._joystick = joysticks[0]
                self._joystick.onAxisChanged += self._onJoystickAxisChanged
                self._joystick.onButtonPressed += self._onJoystickButtonPressed
            else:
                self._joystick = None     
        
        
    def _onJoystickAxisChanged(self, sender, index):
        
        if self._started.get() and sender == self._joystick:
            
            axisValue = self._joystick.getAxisValue(index) 
            
            if index == 0:
                
                self._yaw.set(axisValue)
                self._updateTarget()
            
            elif index == 1 and not Cockpit.THROTTLE_BY_USER:
            
                thrust = -axisValue
                self._throttle.set(thrust)            
                self._updateTarget()

            elif index == 2 and Cockpit.THROTTLE_BY_USER:            
            
                rowThrottle = (axisValue + 100.0)/2.0 
                if rowThrottle < 10.0:
                    throttle = rowThrottle * 6.0
                elif rowThrottle < 90.0:
                    throttle = 60.0 + ((rowThrottle - 10.0) / 8.0)
                else:
                    throttle = 70.0 + (rowThrottle - 90.0) * 3.0
                self._throttle.set(throttle)
                self._sendThrottle()
                
            elif index == 3:
                
                x = 196 + axisValue * 2                
                lastCoords = self._shiftCanvas.coords(self._shiftMarker)
                coords = (x, lastCoords[1])                 
                self._plotShiftCanvasMarker(coords)
                
            elif index == 4:
                
                y = 196 + axisValue * 2 
                lastCoords = self._shiftCanvas.coords(self._shiftMarker)
                coords = (lastCoords[0], y)                 
                self._plotShiftCanvasMarker(coords)


    def _onJoystickButtonPressed(self, sender, index):
        
        if sender == self._joystick and index == 7:
            
            if self._started.get() == 0:
                self._startedCB.select()
            else:
                self._startedCB.deselect()
                
            # Tkinter's widgets seem not to be calling the event-handler
            # when they are changed programmatically. Therefore, the 
            # even-handler is called explicitly here.
            self._startedCBChanged()
        
    
    def exit(self):
        
        self._link.send({"key": "close", "data": None})
        
        self._stopUpdateInfoThread()
        
        self._link.close()

        if Cockpit.JOYSTICK_ENABLED:
            self._joystickManager.stop()
        
        self.quit()


    def _updateTarget(self):
        
        markerCoords = self._shiftCanvas.coords(self._shiftMarker)
        coords = ((markerCoords[0] + markerCoords[2]) / 2, (markerCoords[1] + markerCoords[3]) / 2)
        
        self._target[0] = float(coords[1] - 200) / 2.0 # X-axis angle / X-axis acceleration
        self._target[1] = float(coords[0] - 200) / 2.0 # Y-axis angle / Y-axis acceleration
        #Remote control uses clockwise angle, but the drone's referece system uses counter-clockwise angle
        self._target[2] = -self._yaw.get() # Z-axis angular speed
        
        # Z-axis acceleration (thrust). Only when the motor throttle is not controlled by user directly
        if Cockpit.THROTTLE_BY_USER:
            self._target[3] = 0.0
        else:        
            self._target[3] = self._throttle.get()
        
        self._sendTarget() 
    
        
    def _keyDown(self, event):

        if event.keysym == "Escape":            
            self._throttle.set(0)
            self._started.set(0)
            self._thrustScale.config(state=DISABLED)
            self._stopUpdateInfoThread()
            self._sendIsStarted()
            
        elif event.keysym.startswith("Control"):            
            self._controlKeyActive = True
            
        elif not self._controlKeysLocked and self._controlKeyActive:
            
            if event.keysym == "Up":
                self._thrustScaleUp()
                
            elif event.keysym == "Down":
                self._thrustScaleDown()
                
            elif event.keysym == "Left":
                self._yawLeft()
                
            elif event.keysym == "Right":
                self._yawRight()
                
            elif event.keysym == "space":
                self._yawReset()
                if not Cockpit.THROTTLE_BY_USER:
                    self._thrustReset()
                
        elif not self._controlKeysLocked and not self._controlKeyActive:
            
            if event.keysym == "Up":
                self._moveShiftCanvasMarker((0,-5))
                
            elif event.keysym == "Down":
                self._moveShiftCanvasMarker((0,5))
                
            elif event.keysym == "Left":
                self._moveShiftCanvasMarker((-5,0))
                
            elif event.keysym == "Right":
                self._moveShiftCanvasMarker((5,0))
                
            elif event.keysym == "space":
                self._resetShiftCanvasMarker()                
    
    
    def _keyUp(self, eventArgs):
        
        if eventArgs.keysym.startswith("Control"):
            self._controlKeyActive = False
            
    
    def _onMouseButton1(self, eventArgs):

        self._lastMouseCoords = (eventArgs.x, eventArgs.y)

        
    def _onMouseButtonRelease1(self, eventArgs):

        self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204)

    
    def _limitCoordsToSize(self, coords, size, width):
        
        maxSize = size-(width/2.0)
        minSize = -(width/2.0)
        
        if coords[0] > maxSize:
            x = maxSize
        
        elif coords[0] < minSize:
            x = minSize
            
        else:
            x = coords[0]
            
            
        if coords[1] > maxSize:
            y = maxSize
            
        elif coords[1] < minSize:
            y = minSize
            
        else:
            y = coords[1]
            
        
        return (x,y)
    
    
    def _plotShiftCanvasMarker(self, coords):
        
        coords = self._limitCoordsToSize(coords, 400, 8)
        self._shiftCanvas.coords(self._shiftMarker, coords[0], coords[1], coords[0] + 8, coords[1] + 8)
        self._updateTarget()

    
    def _moveShiftCanvasMarker(self, shift):

        lastCoords = self._shiftCanvas.coords(self._shiftMarker)
        newCoords = (lastCoords[0] + shift[0], lastCoords[1] + shift[1])        
        self._plotShiftCanvasMarker(newCoords)
    
    
    def _resetShiftCanvasMarker(self):
    
        self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204)
        self._updateTarget()
        
    
    def _onMouseButton1Motion(self, eventArgs):

        deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1])
        self._moveShiftCanvasMarker(deltaCoords)
        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
  
      
    def _onMouseDoubleButton1(self, eventArgs):
        
        self._resetShiftCanvasMarker()        
            

    def _onMouseButton3(self, eventArgs):

        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
        self._mouseDirection = Cockpit.DIR_NONE

        
    def _onMouseButtonRelease3(self, eventArgs):

        self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204)

        
    def _onMouseButton3Motion(self, eventArgs):

        deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1])

        if self._mouseDirection == Cockpit.DIR_NONE:
            if abs(deltaCoords[0]) > abs(deltaCoords[1]):
                self._mouseDirection = Cockpit.DIR_HORIZONTAL
            else:
                self._mouseDirection = Cockpit.DIR_VERTICAL

        if self._mouseDirection == Cockpit.DIR_HORIZONTAL:
            deltaCoords = (deltaCoords[0], 0)
        else:
            deltaCoords = (0, deltaCoords[1])

        self._moveShiftCanvasMarker(deltaCoords)
        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
        
    
    def _thrustScaleUp(self):

        #TODO: 20160526 DPM: El valor de incremento de aceleración (1.0) puede ser muy alto
        if self._started.get(): 
            newValue = self._thrustScale.get() \
                + (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0)
            self._thrustScale.set(newValue)
            
            self._updateTarget()
    
    
    def _thrustScaleDown(self):
        
        #TODO: 20160526 DPM: El valor de decremento de aceleración (1.0) puede ser muy alto
        if self._started.get():
            newValue = self._thrustScale.get() \
                - (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0)
            self._thrustScale.set(newValue)
            
            self._updateTarget()
            
    
    def _thrustReset(self):
        
        if self._started.get():
            self._thrustScale.set(0.0)
            
            self._updateTarget()
            
            
    def _onThrustScaleDoubleButton1(self, eventArgs):
        
        self._thrustReset()
        
        return "break"
        
    
    def _yawRight(self):
        
        newValue = self._yaw.get() + 1
        self._yaw.set(newValue)
        self._updateTarget()
            

    def _yawLeft(self):
        
        newValue = self._yaw.get() - 1
        self._yaw.set(newValue)
        self._updateTarget()
        
        
    def _yawReset(self):
        
        self._yaw.set(0)
        self._updateTarget()
        
        
    def _onMouseWheelUp(self, eventArgs):
        
        if not self._controlKeyActive:
            self._thrustScaleUp()
            
        else:
            self._yawRight()
            

    def _onMouseWheelDown(self, eventArgs):

        if not self._controlKeyActive:
            self._thrustScaleDown()
            
        else:
            self._yawLeft()
    

    def _onMouseWheel(self, eventArgs):

        factor = eventArgs.delta/(1200.0 if Cockpit.THROTTLE_BY_USER and not self._controlKeyActive else 120.0)

        if not self._controlKeyActive:
        
            if self._started.get():
                newValue = self._thrustScale.get() + factor 
                self._thrustScale.set(newValue)
                
                self._updateTarget()
        else:
            newValue = self._yaw.get() + factor
            self._yaw.set(newValue)
            self._updateTarget()

    
    def _onYawScaleChanged(self, eventArgs):
        
        self._updateTarget()
    
    
    def _onYawScaleDoubleButton1(self, eventArgs):
        
        self._yawReset()
        
        return "break"
        
    
    def _startedCBChanged(self):
        
        if not self._started.get():
            self._throttle.set(0)
            self._thrustScale.config(state=DISABLED)            
            #self._integralsCB.config(state=DISABLED)
            self._stopUpdateInfoThread()
        else:
            self._thrustScale.config(state="normal")            
            #self._integralsCB.config(state="normal")
            self._startUpdateInfoThread()
            
        self._sendIsStarted()
     
    
#     def _integralsCBChanged(self):
#     
#         self._link.send({"key": "integrals", "data":self._integralsEnabled.get() != 0})
#             
    
     
    def _onThrustScaleChanged(self, eventArgs):
        
        if Cockpit.THROTTLE_BY_USER:
            
            self._sendThrottle()
        
        else:
        
            self._updateTarget()


    def _sendThrottle(self):
        
        self._link.send({"key": "throttle", "data": self._throttle.get()})
    

    def _sendTarget(self):
        
        self._link.send({"key": "target", "data": self._target})
        
        
    def _sendIsStarted(self):
        
        isStarted = self._started.get() != 0        
        self._link.send({"key": "is-started", "data": isStarted})
        

    def _sendPidCalibrationData(self):

        if self._pidSelected.get() != "--" and self._axisSelected.get() != "--":

            pidData = {
                "pid": self._pidSelected.get(),
                "axis": self._axisSelected.get(), 
                "p": float(self._pidPSpinbox.get()),
                "i": float(self._pidISpinbox.get()),
                "d": float(self._pidDSpinbox.get())}
        
            self._link.send({"key": "pid-calibration", "data": pidData})


    def _updatePidCalibrationData(self):

        pid = self._pidSelected.get()
        axis = self._axisSelected.get()

        if pid != "--" and axis != "--":
             
            self._pidConstants[pid][axis]["P"] = float(self._pidPSpinbox.get())
            self._pidConstants[pid][axis]["I"] = float(self._pidISpinbox.get())
            self._pidConstants[pid][axis]["D"] = float(self._pidDSpinbox.get())
            

    def _readDroneConfig(self):

        self._link.send({"key": "read-drone-config", "data": None}, self._onDroneConfigRead)


    def _readDroneState(self):
        
        if not self._readingState:
            self._readingState = True
            self._link.send({"key": "read-drone-state", "data": None}, self._onDroneStateRead)


    def _readPidConfigItem(self, message, cockpitKey, axises, configKeys):
        
        for i in range(len(axises)):
            for j in range(len(Cockpit.PID_KEYS)):
                self._pidConstants[cockpitKey][axises[i]][Cockpit.PID_KEYS[j]] = message[configKeys[j]][i]
                

    def _onDroneConfigRead(self, message):

        #TODO Show current configuration within the GUI (at least relevant settings)
        if message:
            
            #Angle-speeds
            self._readPidConfigItem(message, Cockpit.KEY_ANG_SPEED, ["X", "Y", "Z"], \
                                    [Configuration.PID_ANGLES_SPEED_KP, \
                                     Configuration.PID_ANGLES_SPEED_KI, \
                                     Configuration.PID_ANGLES_SPEED_KD])
            
            #Angles
            self._readPidConfigItem(message, Cockpit.KEY_ANGLES, ["X", "Y"], \
                                    [Configuration.PID_ANGLES_KP, \
                                     Configuration.PID_ANGLES_KI, \
                                     Configuration.PID_ANGLES_KD])
                        
            #Accels
            self._readPidConfigItem(message, Cockpit.KEY_ACCEL, ["X", "Y", "Z"], \
                                    [Configuration.PID_ACCEL_KP, \
                                     Configuration.PID_ACCEL_KI, \
                                     Configuration.PID_ACCEL_KD])
        

    def _onDroneStateRead(self, state):
        
        if state:
            
            for index in range(4):
                self._throttleTexts[index].set("{0:.3f}".format(state["_throttles"][index]))
                
            for index in range(3):
                self._accelTexts[index].set("{0:.3f}".format(state["_accels"][index]))
                self._angleTexts[index].set("{0:.3f}".format(state["_angles"][index]))
                
            currentPeriod = state["_currentPeriod"]
            if currentPeriod > 0.0:
                
                freq = 1.0/currentPeriod                
                self._loopRateText.set("{0:.3f}".format(freq))
                
            else:
                self._loopRateText.set("--")
                
        else:
            self._stopUpdateInfoThread()
            
        self._readingState = False
   

    def _onPidSpinboxChanged(self):

        self._updatePidCalibrationData()
        self._sendPidCalibrationData()

    
    def _onPidListBoxChanged(self, pid):
        
        self._axisSelected.set("--")
        
        self._pidPString.set("--")
        self._pidIString.set("--")
        self._pidDString.set("--")

        self._pidPSpinbox.config(state=DISABLED)
        self._pidISpinbox.config(state=DISABLED)
        self._pidDSpinbox.config(state=DISABLED)

        self._selectedPidConstats = pid

        if pid == "--":
            self._axisListBox.config(state=DISABLED)
            self._controlKeysLocked = False
                       
        else:
            self._axisListBox.config(state="normal")
            self._controlKeysLocked = True


    def _onAxisListBoxChanged(self, axis):
        
        if axis == "--" or (self._selectedPidConstats == Cockpit.KEY_ANGLES and axis == "Z"):
            
            self._pidPString.set("--")
            self._pidIString.set("--")
            self._pidDString.set("--")
            
            self._pidPSpinbox.config(state=DISABLED)
            self._pidISpinbox.config(state=DISABLED)
            self._pidDSpinbox.config(state=DISABLED)
            
            self._controlKeysLocked = axis != "--"
            
        else:
            
            self._pidPString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["P"]))
            self._pidIString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["I"]))
            self._pidDString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["D"]))
            
            self._pidPSpinbox.config(state="normal")
            self._pidISpinbox.config(state="normal")
            self._pidDSpinbox.config(state="normal")
            
            self._controlKeysLocked = True

            
    def _updateInfo(self):
        
        while self._updateInfoThreadRunning:
            
            self._readDroneState()
            
            time.sleep(1.0)
            

    def _startUpdateInfoThread(self):
        
        self._updateInfoThreadRunning = True
        if not self._updateInfoThread.isAlive():                
            self._updateInfoThread.start()
        
            
    def _stopUpdateInfoThread(self):
        
        self._updateInfoThreadRunning = False
        if self._updateInfoThread.isAlive():
            self._updateInfoThread.join()
예제 #20
0
class EktaproGUI(Tk):
    """
    Constructs the main program window
    and interfaces with the EktaproController
    and the TimerController to access the slide
    projectors.  
    """

    def __init__(self):
        self.controller = EktaproController()
        self.controller.initDevices()

        Tk.__init__(self)
        self.protocol("WM_DELETE_WINDOW", self.onQuit)
        self.wm_title("EktaproGUI")

        self.bind("<Prior>", self.priorPressed)
        self.bind("<Next>", self.nextPressed)

        self.brightness = 0
        self.slide = 1
        self.timerController = TimerController(self.controller, self)

        self.controlPanel = Frame(self)
        self.manualPanel = Frame(self)

        self.projektorList = Listbox(self, selectmode=SINGLE)

        for i in range(len(self.controller.devices)):
            self.projektorList.insert(END, "[" + str(i) + "] " + str(self.controller.devices[i]))

        if self.projektorList.size >= 1:
            self.projektorList.selection_set(0)

        self.projektorList.bind("<ButtonRelease>", self.projektorSelectionChanged)
        self.projektorList.config(width=50)

        self.initButton = Button(self.controlPanel, text="init", command=self.initButtonPressed)
        self.nextButton = Button(self.controlPanel, text="next slide", command=self.nextSlidePressed)
        self.nextButton.config(state=DISABLED)
        self.prevButton = Button(self.controlPanel, text="previous slide", command=self.prevSlidePressed)
        self.prevButton.config(state=DISABLED)

        self.startButton = Button(self.controlPanel, text="start timer", command=self.startTimer)
        self.startButton.config(state=DISABLED)
        self.pauseButton = Button(self.controlPanel, text="pause", command=self.pauseTimer)
        self.stopButton = Button(self.controlPanel, text="stop", command=self.stopTimer)
        self.stopButton.config(state=DISABLED)
        self.timerLabel = Label(self.controlPanel, text="delay:")
        self.timerInput = Entry(self.controlPanel, width=3)
        self.timerInput.insert(0, "5")
        self.timerInput.config(state=DISABLED)
        self.timerInput.bind("<KeyPress-Return>", self.inputValuesChanged)
        self.timerInput.bind("<ButtonRelease>", self.updateGUI)

        self.fadeLabel = Label(self.controlPanel, text="fade:")
        self.fadeInput = Entry(self.controlPanel, width=3)
        self.fadeInput.insert(0, "1")
        self.fadeInput.config(state=DISABLED)
        self.fadeInput.bind("<KeyPress-Return>", self.inputValuesChanged)
        self.fadeInput.bind("<ButtonRelease>", self.updateGUI)

        self.standbyButton = Button(self.controlPanel, text="standby", command=self.toggleStandby)
        self.standbyButton.config(state=DISABLED)
        self.syncButton = Button(self.controlPanel, text="sync", command=self.sync)
        self.syncButton.config(state=DISABLED)
        self.reconnectButton = Button(self.controlPanel, text="reconnect", command=self.reconnect)

        self.cycle = IntVar()
        self.cycleButton = Checkbutton(
            self.controlPanel, text="use all projectors", variable=self.cycle, command=self.cycleToggled
        )

        self.brightnessScale = Scale(self.manualPanel, from_=0, to=100, resolution=1, label="brightness")
        self.brightnessScale.set(self.brightness)
        self.brightnessScale.bind("<ButtonRelease>", self.brightnessChanged)
        self.brightnessScale.config(state=DISABLED)
        self.brightnessScale.config(orient=HORIZONTAL)
        self.brightnessScale.config(length=400)

        self.gotoSlideScale = Scale(self.manualPanel, from_=0, to=self.controller.maxTray, label="goto slide")
        self.gotoSlideScale.set(1)
        self.gotoSlideScale.bind("<ButtonRelease>", self.gotoSlideChanged)
        self.gotoSlideScale.config(state=DISABLED)
        self.gotoSlideScale.config(orient=HORIZONTAL)
        self.gotoSlideScale.config(length=400)

        self.controlPanel.pack(side=BOTTOM, anchor=W, fill=X)
        self.projektorList.pack(side=LEFT, fill=BOTH)
        self.manualPanel.pack(side=RIGHT, expand=1, fill=BOTH)

        self.initButton.pack(side=LEFT, anchor=N, padx=4, pady=4)

        self.prevButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.nextButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.cycleButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.startButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.pauseButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.stopButton.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.timerLabel.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.timerInput.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.fadeLabel.pack(side=LEFT, anchor=N, padx=4, pady=4)
        self.fadeInput.pack(side=LEFT, anchor=N, padx=4, pady=4)

        self.syncButton.pack(side=RIGHT, anchor=N, padx=4, pady=4)
        self.standbyButton.pack(side=RIGHT, anchor=N, padx=4, pady=4)
        self.reconnectButton.pack(side=RIGHT, anchor=N, padx=4, pady=4)
        self.brightnessScale.pack(side=TOP, anchor=W, expand=1, fill=X)
        self.gotoSlideScale.pack(side=TOP, anchor=W, expand=1, fill=X)

        self.menubar = Menu(self)

        self.toolsmenu = Menu(self.menubar)
        self.helpmenu = Menu(self.menubar)
        self.filemenu = Menu(self.menubar)

        self.toolsmenu.add_command(label="Interpret HEX Sequence", command=self.interpretHEXDialog)

        self.helpmenu.add_command(
            label="About EktaproGUI",
            command=lambda: tkMessageBox.showinfo("About EktaproGUI", "EktaproGUI 1.0 (C)opyright Julian Hoch 2010"),
        )

        self.filemenu.add_command(label="Exit", command=self.onQuit)

        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.menubar.add_cascade(label="Tools", menu=self.toolsmenu)
        self.menubar.add_cascade(label="Help", menu=self.helpmenu)

        self.configure(menu=self.menubar)

    def initButtonPressed(self):
        self.controller.resetDevices()
        self.updateGUI()
        self.brightnessScale.config(state=NORMAL)
        self.gotoSlideScale.config(state=NORMAL)
        self.nextButton.config(state=NORMAL)
        self.prevButton.config(state=NORMAL)
        self.startButton.config(state=NORMAL)
        self.timerInput.config(state=NORMAL)
        self.fadeInput.config(state=NORMAL)
        self.syncButton.config(state=NORMAL)
        self.standbyButton.config(state=NORMAL)

    def inputValuesChanged(self, event):
        try:
            fadeDelay = int(self.fadeInput.get())
            slideshowDelay = int(self.timerInput.get())
            if fadeDelay in range(0, 60):
                self.timerController.fadeDelay = fadeDelay
            if slideshowDelay in range(1, 60):
                self.timerController.slideshowDelay = slideshowDelay
        except Exception:
            pass
        self.updateGUI()

    def sync(self):
        self.controller.syncDevices()
        self.updateGUI()

    def reconnect(self):
        self.controller.cleanUp()
        self.controller.initDevices()
        self.updateGUI()

        self.projektorList.delete(0, END)
        for i in range(len(self.controller.devices)):
            self.projektorList.insert(END, "[" + str(i) + "] " + str(self.controller.devices[i]))

        if self.projektorList.size >= 1:
            self.projektorList.selection_set(0)

    def projektorSelectionChanged(self, event):
        items = map(int, self.projektorList.curselection())
        if self.controller.setActiveDevice(items):
            self.updateGUI()

    def updateGUI(self, event=None):
        if self.controller.activeDevice == None:
            return

        self.brightness = self.controller.activeDevice.brightness
        self.brightnessScale.set(self.brightness)

        self.slide = self.controller.activeDevice.slide
        self.gotoSlideScale.set(self.slide)

        for i in range(self.projektorList.size()):
            if i == self.controller.activeIndex:
                self.projektorList.selection_set(i)
            else:
                self.projektorList.selection_clear(i)

    def brightnessChanged(self, event):
        newBrightness = self.brightnessScale.get()
        if not self.brightness == newBrightness and not self.controller.activeDevice == None:
            self.controller.activeDevice.setBrightness(newBrightness)
            self.brightness = self.brightnessScale.get()

    def gotoSlideChanged(self, event):
        if self.controller.activeDevice is None:
            return
        newSlide = self.gotoSlideScale.get()
        if not self.slide == newSlide:
            self.controller.activeDevice.gotoSlide(newSlide)
            self.slide = newSlide

    def nextSlidePressed(self):
        if self.controller.activeDevice is None:
            return
        self.timerController.fadePaused = False
        self.timerController.nextSlide()
        self.updateGUI()

    def prevSlidePressed(self):
        if self.controller.activeDevice is None:
            return
        self.timerController.fadePaused = False
        self.timerController.previousSlide()
        self.updateGUI()

    def startTimer(self):
        self.stopButton.config(state=NORMAL)
        self.startButton.config(state=DISABLED)
        self.timerController.startSlideshow()

    def pauseTimer(self):
        if self.timerController.fadePaused or self.timerController.slideshowPaused:
            self.pauseButton.config(text="pause")
            self.timerController.resume()
            self.updateGUI()
        else:
            self.pauseButton.config(text="resume")
            self.timerController.pause()
            self.updateGUI()

    def stopTimer(self):
        self.pauseButton.config(text="pause")
        self.stopButton.config(state=DISABLED)
        self.startButton.config(state=NORMAL)
        self.timerController.stopSlideshow()
        self.updateGUI()

    def cycleToggled(self):
        self.timerController.cycle = True if self.cycle.get() == 1 else False

    def interpretHEXDialog(self):
        interpretDialog = InterpretHEXDialog(self)  # @UnusedVariable

    def toggleStandby(self):
        if self.pauseButton.config()["text"][4] == "pause" and self.pauseButton.config()["state"][4] == "normal":
            self.pauseTimer()
        self.controller.toggleStandby()

    def nextPressed(self, event):
        if self.startButton.config()["state"][4] == "disabled":
            self.pauseTimer()
        else:
            self.nextSlidePressed()

    def priorPressed(self, event):
        if self.startButton.config()["state"][4] == "disabled":
            self.toggleStandby()
        else:
            self.prevSlidePressed()

    def onQuit(self):
        self.controller.cleanUp()
        self.destroy()
예제 #21
0
파일: cockpit.py 프로젝트: hisie/eaglebone
class Cockpit(ttkFrame):
    '''
    Remote controller GUI 
    '''
    
    KEY_ANG_SPEED = "ang-speed"
    KEY_ANGLES = "angles"
    KEY_ACCEL = "accel"
    
    PID_KEYS = ["P", "I", "D"]

    DEFAULT_DRONE_IP = "192.168.1.130"
    DEFAULT_DRONE_PORT = 2121

    DIR_NONE = 0
    DIR_VERTICAL = 1
    DIR_HORIZONTAL = 2
    
    MAX_ACCEL = 10.0 #TODO angles. Replace by m/s²
    MAX_ACCEL_Z = 0.1 #m/s²
    MAX_ANGLE_SPEED = 50.0 #º/s

    def __init__(self, parent, isDummy = False, droneIp = DEFAULT_DRONE_IP, dronePort = DEFAULT_DRONE_PORT):
        '''
        Constructor
        '''
        ttkFrame.__init__(self, parent)
        
        self._started = IntVar()
        self._integralsEnabled = IntVar()
        self._target = [0.0] * 4        
        
        self._selectedPidConstats = "--"
        self._pidConstants = {
                              Cockpit.KEY_ANG_SPEED:{
                                           "X":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Y":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Z":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                }
                                           },
                               Cockpit.KEY_ANGLES: {
                                          "X":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Y":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                }
                                          },
                               Cockpit.KEY_ACCEL:{
                                           "X":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                           "Y":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                },
                                            "Z":{
                                                "P": 0.0,
                                                "I": 0.0,
                                                "D": 0.0
                                                 }
                                          }
                              }
        
        self.parent = parent

        self.initUI()

        self._controlKeysLocked = False

        if not isDummy:
            self._link = INetLink(droneIp, dronePort)
        else:
            self._link = ConsoleLink()
            
        self._link.open()

        self._updateInfoThread = Thread(target=self._updateInfo)
        self._updateInfoThreadRunning = False
        self._readingState = False

        self._start()
        
            
    def initUI(self):
        
        self.parent.title("Drone control")
        self.style = Style()
        self.style.theme_use("default")
        
        self.pack(fill=BOTH, expand=1)
        
        self.parent.bind_all("<Key>", self._keyDown)
        self.parent.bind_all("<KeyRelease>", self._keyUp)

        if system() == "Linux":
            self.parent.bind_all("<Button-4>", self._onMouseWheelUp)
            self.parent.bind_all("<Button-5>", self._onMouseWheelDown)

        else:
            #case of Windows
            self.parent.bind_all("<MouseWheel>", self._onMouseWheel)
        
        #Commands        
        commandsFrame = tkFrame(self)
        commandsFrame.grid(column=0, row=0, sticky="WE")
        
        self._startedCB = Checkbutton(commandsFrame, text="On", variable=self._started, command=self._startedCBChanged)
        self._startedCB.pack(side=LEFT, padx=4)
        
        self._integralsCB = Checkbutton(commandsFrame, text="Int.", variable=self._integralsEnabled, \
                                        command=self._integralsCBChanged, state=DISABLED)
        self._integralsCB.pack(side=LEFT, padx=4)
        
        self._quitButton = Button(commandsFrame, text="Quit", command=self.exit)
        self._quitButton.pack(side=LEFT, padx=2, pady=2)
        
#         self._angleLbl = Label(commandsFrame, text="Angle")
#         self._angleLbl.pack(side=LEFT, padx=4)
#         
#         self._angleEntry = Entry(commandsFrame, state=DISABLED)
#         self._angleEntry.pack(side=LEFT)
        
        #Info
        infoFrame = tkFrame(self)
        infoFrame.grid(column=1, row=1, sticky="E", padx=4)
        
        #Throttle
        Label(infoFrame, text="Throttle").grid(column=0, row=0, sticky="WE")        
        self._throttleTexts = [StringVar(),StringVar(),StringVar(),StringVar()]
        Entry(infoFrame, textvariable=self._throttleTexts[3], state=DISABLED, width=5).grid(column=0, row=1)                
        Entry(infoFrame, textvariable=self._throttleTexts[0], state=DISABLED, width=5).grid(column=1, row=1)
        Entry(infoFrame, textvariable=self._throttleTexts[2], state=DISABLED, width=5).grid(column=0, row=2)
        Entry(infoFrame, textvariable=self._throttleTexts[1], state=DISABLED, width=5).grid(column=1, row=2)
        
        #Angles
        Label(infoFrame, text="Angles").grid(column=0, row=3, sticky="WE")        
        self._angleTexts = [StringVar(),StringVar(),StringVar()]
        for index in range(3):
            Entry(infoFrame, textvariable=self._angleTexts[index], state=DISABLED, width=5).grid(column=index, row=4)
               
        #Accels
        Label(infoFrame, text="Accels").grid(column=0, row=5, sticky="WE")
        self._accelTexts = [StringVar(),StringVar(),StringVar()]
        for index in range(3):
            Entry(infoFrame, textvariable=self._accelTexts[index], state=DISABLED, width=5).grid(column=index, row=6)
        
        #Speeds
        Label(infoFrame, text="Speeds").grid(column=0, row=7, sticky="WE")
        self._speedTexts = [StringVar(),StringVar(),StringVar()]
        for index in range(3):
            Entry(infoFrame, textvariable=self._speedTexts[index], state=DISABLED, width=5).grid(column=index, row=8)
        
        #Height
        Label(infoFrame, text="Height").grid(column=0, row=9, sticky="W")
        self._heightText = StringVar()
        Entry(infoFrame, state=DISABLED, width=5).grid(column=1, row=9)
        
        #control
        
        controlFrame = tkFrame(self)
        controlFrame.grid(column=0, row=1, sticky="W")
        
        self._throttle = DoubleVar()
        self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=-100.0, \
                            tickinterval=0, variable=self._throttle, \
                            length=200, showvalue=1, \
                            state=DISABLED,
                            command=self._onThrustScaleChanged)
        self._thrustScale.bind("<Double-Button-1>", self._onThrustScaleDoubleButton1, "+")
        self._thrustScale.grid(column=0)
        
        self._shiftCanvas = Canvas(controlFrame, bg="white", height=400, width=400, \
                             relief=SUNKEN)
        self._shiftCanvas.bind("<Button-1>", self._onMouseButton1)
        #self._shiftCanvas.bind("<ButtonRelease-1>", self._onMouseButtonRelease1)
        self._shiftCanvas.bind("<B1-Motion>", self._onMouseButton1Motion)
        self._shiftCanvas.bind("<Double-Button-1>", self._onMouseDoubleButton1)

        self._shiftCanvas.bind("<Button-3>", self._onMouseButton3)
        #self._shiftCanvas.bind("<ButtonRelease-3>", self._onMouseButtonRelease3)
        self._shiftCanvas.bind("<B3-Motion>", self._onMouseButton3Motion)

        self._shiftCanvas.grid(row=0,column=1, padx=2, pady=2)
        self._shiftCanvas.create_oval(2, 2, 400, 400, outline="#ff0000")
        self._shiftCanvas.create_line(201, 2, 201, 400, fill="#ff0000")
        self._shiftCanvas.create_line(2, 201, 400, 201, fill="#ff0000")
        self._shiftMarker = self._shiftCanvas.create_oval(197, 197, 205, 205, outline="#0000ff", fill="#0000ff")
        
        self._yaw = DoubleVar()
        self._yawScale = Scale(controlFrame, orient=HORIZONTAL, from_=-100.0, to=100.0, \
                            tickinterval=0, variable=self._yaw, \
                            length=200, showvalue=1, \
                            command=self._onYawScaleChanged)
        self._yawScale.bind("<Double-Button-1>", self._onYawScaleDoubleButton1, "+")
        self._yawScale.grid(row=1, column=1)
        
        self._controlKeyActive = False
        

        #PID calibration

        pidCalibrationFrame = tkFrame(self)
        pidCalibrationFrame.grid(column=0, row=2, sticky="WE");

        self._pidSelected = StringVar()
        self._pidSelected.set("--")
        self._pidListBox = OptionMenu(pidCalibrationFrame, self._pidSelected, "--", \
                                      Cockpit.KEY_ANG_SPEED, Cockpit.KEY_ANGLES, Cockpit.KEY_ACCEL, \
                                       command=self._onPidListBoxChanged)
        self._pidListBox.pack(side=LEFT, padx=2)
        self._pidListBox.config(width=10)
        
        self._axisSelected = StringVar()
        self._axisSelected.set("--")
        self._axisListBox = OptionMenu(pidCalibrationFrame, self._axisSelected, "--", "X", "Y", "Z", \
                                       command=self._onAxisListBoxChanged)
        self._axisListBox.pack(side=LEFT, padx=2)
        self._axisListBox.config(state=DISABLED)

        Label(pidCalibrationFrame, text="P").pack(side=LEFT, padx=(14, 2))

        self._pidPString = StringVar()
        self._pidPString.set("0.00")
        self._pidPSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=100.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidPString, command=self._onPidSpinboxChanged)
        self._pidPSpinbox.pack(side=LEFT, padx=2)

        Label(pidCalibrationFrame, text="I").pack(side=LEFT, padx=(14, 2))

        self._pidIString = StringVar()
        self._pidIString.set("0.00")
        self._pidISpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=100.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidIString, command=self._onPidSpinboxChanged)
        self._pidISpinbox.pack(side=LEFT, padx=2)
        
        Label(pidCalibrationFrame, text="D").pack(side=LEFT, padx=(14, 2))
        
        self._pidDString = StringVar()
        self._pidDString.set("0.00")
        self._pidDSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=100.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidDString, command=self._onPidSpinboxChanged)
        self._pidDSpinbox.pack(side=LEFT, padx=2)
        
        #debug
        debugFrame = tkFrame(self)
        debugFrame.grid(column=0, row=3, sticky="WE")
        
        self._debugMsg = Message(debugFrame, anchor="nw", justify=LEFT, relief=SUNKEN, width=300)
        self._debugMsg.pack(fill=BOTH, expand=1)



    def _start(self):

        self._readDroneConfig()
        
    
    def exit(self):
        
        self._link.send({"key": "close", "data": None})
        
        self._stopUpdateInfoThread()
        
        self._link.close()

        self.quit()


    def _updateTarget(self):
        
        markerCoords = self._shiftCanvas.coords(self._shiftMarker)
        coords = ((markerCoords[0] + markerCoords[2]) / 2, (markerCoords[1] + markerCoords[3]) / 2)
        
        self._target[1] = float(coords[0] - 201) * Cockpit.MAX_ACCEL / 200.0
        self._target[0] = float(coords[1] - 201) * Cockpit.MAX_ACCEL / 200.0      
        #Remote control uses clockwise angle, but the drone's referece system uses counter-clockwise angle
        self._target[2] = -self._yaw.get() * Cockpit.MAX_ANGLE_SPEED / 100.0
        
        self._target[3] = self._throttle.get() * Cockpit.MAX_ACCEL_Z / 100.0
        
        self._sendTarget() 
    
        
    def _keyDown(self, event):

        if event.keysym == "Escape":            
            self._throttle.set(0)
            self._started.set(0)
            self._thrustScale.config(state=DISABLED)
            self._stopUpdateInfoThread()
            self._sendIsStarted()
            
        elif event.keysym.startswith("Control"):            
            self._controlKeyActive = True
            
        elif not self._controlKeysLocked and self._controlKeyActive:
            
            if event.keysym == "Up":
                self._thrustScaleUp()
                
            elif event.keysym == "Down":
                self._thrustScaleDown()
                
            elif event.keysym == "Left":
                self._yawLeft()
                
            elif event.keysym == "Right":
                self._yawRight()
                
            elif event.keysym == "space":
                self._yawReset()
                self._thrustReset()
                
        elif not self._controlKeysLocked and not self._controlKeyActive:
            
            if event.keysym == "Up":
                self._moveShiftCanvasMarker((0,-5))
                
            elif event.keysym == "Down":
                self._moveShiftCanvasMarker((0,5))
                
            elif event.keysym == "Left":
                self._moveShiftCanvasMarker((-5,0))
                
            elif event.keysym == "Right":
                self._moveShiftCanvasMarker((5,0))
                
            elif event.keysym == "space":
                self._resetShiftCanvasMarker()                
    
    
    def _keyUp(self, eventArgs):
        
        if eventArgs.keysym.startswith("Control"):
            self._controlKeyActive = False
            
    
    def _onMouseButton1(self, eventArgs):

        self._lastMouseCoords = (eventArgs.x, eventArgs.y)

        
    def _onMouseButtonRelease1(self, eventArgs):

        self._shiftCanvas.coords(self._shiftMarker, 197, 197, 205, 205)

    
    def _limitCoordsToSize(self, coords, size):
        
        if coords[0] > size:
            x = size
        
        elif coords[0] < 0:
            x = 0
            
        else:
            x = coords[0]
            
            
        if coords[1] > size:
            y = size
            
        elif coords[1] < 0:
            y = 0
            
        else:
            y = coords[1]
            
        
        return (x,y)
    
    
    def _moveShiftCanvasMarker(self, shift):

        lastCoords = self._shiftCanvas.coords(self._shiftMarker)
        newCoords = (lastCoords[0] + shift[0], lastCoords[1] + shift[1])        
        newCoords = self._limitCoordsToSize(newCoords, 400)
    
        self._shiftCanvas.coords(self._shiftMarker, newCoords[0], newCoords[1], newCoords[0] + 8, newCoords[1] + 8)
        self._updateTarget()
    
    
    def _resetShiftCanvasMarker(self):
    
        self._shiftCanvas.coords(self._shiftMarker, 197, 197, 205, 205)
        self._updateTarget()
        
    
    def _onMouseButton1Motion(self, eventArgs):

        deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1])
        self._moveShiftCanvasMarker(deltaCoords)
        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
  
      
    def _onMouseDoubleButton1(self, eventArgs):
        
        self._resetShiftCanvasMarker()        
            

    def _onMouseButton3(self, eventArgs):

        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
        self._mouseDirection = Cockpit.DIR_NONE

        
    def _onMouseButtonRelease3(self, eventArgs):

        self._shiftCanvas.coords(self._shiftMarker, 197, 197, 205, 205)

        
    def _onMouseButton3Motion(self, eventArgs):

        deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1])

        if self._mouseDirection == Cockpit.DIR_NONE:
            if abs(deltaCoords[0]) > abs(deltaCoords[1]):
                self._mouseDirection = Cockpit.DIR_HORIZONTAL
            else:
                self._mouseDirection = Cockpit.DIR_VERTICAL

        if self._mouseDirection == Cockpit.DIR_HORIZONTAL:
            deltaCoords = (deltaCoords[0], 0)
        else:
            deltaCoords = (0, deltaCoords[1])

        self._moveShiftCanvasMarker(deltaCoords)
        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
        
    
    def _thrustScaleUp(self):

        if self._started.get(): 
            newValue = self._thrustScale.get() + 1
            self._thrustScale.set(newValue)
            
            self._updateTarget()
    
    
    def _thrustScaleDown(self):
        
        if self._started.get():
            newValue = self._thrustScale.get() - 1
            self._thrustScale.set(newValue)
            
            self._updateTarget()
            
    
    def _thrustReset(self):
        
        if self._started.get():
            self._thrustScale.set(0.0)
            
            self._updateTarget()
            
            
    def _onThrustScaleDoubleButton1(self, eventArgs):
        
        self._thrustReset()
        
        return "break"
        
    
    def _yawRight(self):
        
        newValue = self._yaw.get() + 1
        self._yaw.set(newValue)
        self._updateTarget()
            

    def _yawLeft(self):
        
        newValue = self._yaw.get() - 1
        self._yaw.set(newValue)
        self._updateTarget()
        
        
    def _yawReset(self):
        
        self._yaw.set(0)
        self._updateTarget()
        
        
    def _onMouseWheelUp(self, eventArgs):
        
        if not self._controlKeyActive:
            self._thrustScaleUp()
            
        else:
            self._yawRight()
            

    def _onMouseWheelDown(self, eventArgs):

        if not self._controlKeyActive:
            self._thrustScaleDown()
            
        else:
            self._yawLeft()
    

    def _onMouseWheel(self, eventArgs):

        factor = int(eventArgs.delta/120)

        if not self._controlKeyActive:
        
            if self._started.get():
                newValue = self._thrustScale.get() + factor
                self._thrustScale.set(newValue)
                
                self._updateTarget()
        else:
            newValue = self._yaw.get() + factor
            self._yaw.set(newValue)
            self._updateTarget()

    
    def _onYawScaleChanged(self, eventArgs):
        
        self._updateTarget()
    
    
    def _onYawScaleDoubleButton1(self, eventArgs):
        
        self._yawReset()
        
        return "break"
        
    
    def _startedCBChanged(self):
        
        if not self._started.get():
            self._throttle.set(0)
            self._thrustScale.config(state=DISABLED)            
            self._integralsCB.config(state=DISABLED)
            self._stopUpdateInfoThread()
        else:
            self._thrustScale.config(state="normal")            
            self._integralsCB.config(state="normal")
            self._startUpdateInfoThread()
            
        self._sendIsStarted()
     
    
    def _integralsCBChanged(self):
    
        self._link.send({"key": "integrals", "data":self._integralsEnabled.get() != 0})
            
     
    def _onThrustScaleChanged(self, eventArgs):
        
        self._updateTarget()
    

    def _sendTarget(self):
        
        self._link.send({"key": "target", "data": self._target})
        
        
    def _sendIsStarted(self):
        
        isStarted = self._started.get() != 0        
        self._link.send({"key": "is-started", "data": isStarted})
        

    def _sendPidCalibrationData(self):

        if self._pidSelected.get() != "--" and self._axisSelected.get() != "--":

            pidData = {
                "pid": self._pidSelected.get(),
                "axis": self._axisSelected.get(), 
                "p": float(self._pidPSpinbox.get()),
                "i": float(self._pidISpinbox.get()),
                "d": float(self._pidDSpinbox.get())}
        
            self._link.send({"key": "pid-calibration", "data": pidData})


    def _updatePidCalibrationData(self):

        pid = self._pidSelected.get()
        axis = self._axisSelected.get()

        if pid != "--" and axis != "--":
             
            self._pidConstants[pid][axis]["P"] = float(self._pidPSpinbox.get())
            self._pidConstants[pid][axis]["I"] = float(self._pidISpinbox.get())
            self._pidConstants[pid][axis]["D"] = float(self._pidDSpinbox.get())
            

    def _readDroneConfig(self):

        self._link.send({"key": "read-drone-config", "data": None}, self._onDroneConfigRead)


    def _readDroneState(self):
        
        if not self._readingState:
            self._readingState = True
            self._link.send({"key": "read-drone-state", "data": None}, self._onDroneStateRead)


    def _readPidConfigItem(self, message, cockpitKey, axises, configKeys):
        
        for i in range(len(axises)):
            for j in range(len(Cockpit.PID_KEYS)):
                self._pidConstants[cockpitKey][axises[i]][Cockpit.PID_KEYS[j]] = message[configKeys[j]][i]
                

    def _onDroneConfigRead(self, message):

        #TODO Show current configuration within the GUI (at least relevant settings)
        if message:
            
            #Angle-speeds
            self._readPidConfigItem(message, Cockpit.KEY_ANG_SPEED, ["X", "Y", "Z"], \
                                    [Configuration.PID_ANGLES_SPEED_KP, \
                                     Configuration.PID_ANGLES_SPEED_KI, \
                                     Configuration.PID_ANGLES_SPEED_KD])
            
            #Angles
            self._readPidConfigItem(message, Cockpit.KEY_ANGLES, ["X", "Y"], \
                                    [Configuration.PID_ANGLES_KP, \
                                     Configuration.PID_ANGLES_KI, \
                                     Configuration.PID_ANGLES_KD])
                        
            #Accels
            self._readPidConfigItem(message, Cockpit.KEY_ACCEL, ["X", "Y", "Z"], \
                                    [Configuration.PID_ACCEL_KP, \
                                     Configuration.PID_ACCEL_KI, \
                                     Configuration.PID_ACCEL_KD])
        

    def _onDroneStateRead(self, state):
        
        if state:
            for index in range(4):
                self._throttleTexts[index].set("{0:.3f}".format(state["_throttles"][index]))
                
            for index in range(3):
                self._accelTexts[index].set("{0:.3f}".format(state["_accels"][index]))
                self._angleTexts[index].set("{0:.3f}".format(state["_angles"][index]))
                
        else:
            self._stopUpdateInfoThread()
            
        self._readingState = False
   

    def _onPidSpinboxChanged(self):

        self._updatePidCalibrationData()
        self._sendPidCalibrationData()

    
    def _onPidListBoxChanged(self, pid):
        
        self._axisSelected.set("--")
        
        self._pidPString.set("--")
        self._pidIString.set("--")
        self._pidDString.set("--")

        self._pidPSpinbox.config(state=DISABLED)
        self._pidISpinbox.config(state=DISABLED)
        self._pidDSpinbox.config(state=DISABLED)

        self._selectedPidConstats = pid

        if pid == "--":
            self._axisListBox.config(state=DISABLED)
            self._controlKeysLocked = False
                       
        else:
            self._axisListBox.config(state="normal")
            self._controlKeysLocked = True


    def _onAxisListBoxChanged(self, axis):
        
        if axis == "--" or (self._selectedPidConstats == Cockpit.KEY_ANGLES and axis == "Z"):
            
            self._pidPString.set("--")
            self._pidIString.set("--")
            self._pidDString.set("--")
            
            self._pidPSpinbox.config(state=DISABLED)
            self._pidISpinbox.config(state=DISABLED)
            self._pidDSpinbox.config(state=DISABLED)
            
            self._controlKeysLocked = axis != "--"
            
        else:
            
            self._pidPString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["P"]))
            self._pidIString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["I"]))
            self._pidDString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["D"]))
            
            self._pidPSpinbox.config(state="normal")
            self._pidISpinbox.config(state="normal")
            self._pidDSpinbox.config(state="normal")
            
            self._controlKeysLocked = True

            
    def _updateInfo(self):
        
        while self._updateInfoThreadRunning:
            
            self._readDroneState()
            
            time.sleep(1.0)
            

    def _startUpdateInfoThread(self):
        
        self._updateInfoThreadRunning = True
        if not self._updateInfoThread.isAlive():                
            self._updateInfoThread.start()
        
            
    def _stopUpdateInfoThread(self):
        
        self._updateInfoThreadRunning = False
        if self._updateInfoThread.isAlive():
            self._updateInfoThread.join()
예제 #22
0
class TelloUI:
    """Wrapper class to enable the GUI."""
    def __init__(self, tello, outputpath):
        """
        Initial all the element of the GUI,support by Tkinter

        :param tello: class interacts with the Tello drone.

        Raises:
            RuntimeError: If the Tello rejects the attempt to enter command mode.
        """

        self.tello = tello  # videostream device
        self.outputPath = outputpath  # the path that save pictures created by clicking the takeSnapshot button
        self.frame = None  # frame read from h264decoder and used for pose recognition
        self.thread = None  # thread of the Tkinter mainloop
        self.stopEvent = None
        # control variables
        self.distance = 0.3  # default distance for :sad'move' cmd
        self.degree = 30  # default degree for 'cw' or 'ccw' cmd

        # if the flag is TRUE,the auto-takeoff thread will stop waiting for the response from tello
        self.quit_waiting_flag = False

        # initialize the root window and image panel
        self.root = tki.Tk()
        self.panel = None

        # create buttons

        self.btn_tracking = tki.Button(self.root,
                                       text="Tracking",
                                       relief="raised",
                                       command=self.Tracking)
        self.btn_tracking.pack(side="bottom",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

        # self.btn_tracking = tki.Button(self.root, text="Tracking!",
        #                                command=self.Tracking)
        # self.tracking.pack(side="bottom", fill="both",
        #                        expand="yes", padx=10, pady=5)

        self.btn_snapshot = tki.Button(self.root,
                                       text="Snapshot!",
                                       command=self.takeSnapshot)
        self.btn_snapshot.pack(side="bottom",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

        # self.btn_pause = tki.Button(self.root, text="Pause", relief="raised", command=self.pauseVideo)
        # self.btn_pause.pack(side="bottom", fill="both",
        #                     expand="yes", padx=10, pady=5)

        self.btn_landing = tki.Button(self.root,
                                      text="Open Command Panel",
                                      relief="raised",
                                      command=self.openCmdWindow)
        self.btn_landing.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

    def _updateGUIImage(self, image):
        """
        Main operation to initial the object of image,and update the GUI panel 
        """
        image = ImageTk.PhotoImage(image)
        # if the panel none ,we need to initial it
        if self.panel is None:
            self.panel = tki.Label(image=image)
            self.panel.image = image
            self.panel.pack(side="left", padx=10, pady=10)
        # otherwise, simply update the panel
        else:
            self.panel.configure(image=image)
            self.panel.image = image

    def _sendingCommand(self):
        """
        start a while loop that sends 'command' to tello every 5 second
        """

        while True:
            self.tello.send_command('command')
            time.sleep(5)

    def _setQuitWaitingFlag(self):
        """
        set the variable as TRUE,it will stop computer waiting for response from tello  
        """
        self.quit_waiting_flag = True

    def Tracking(self):
        # start a thread that constantly pools the video sensor for
        # the most recently read frame
        self.stopEvent = threading.Event()
        self.thread = threading.Thread(target=self.videoLoop, args=())
        self.thread.start()

        # set a callback to handle when the window is closed
        self.root.wm_title("TELLO Controller")
        self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose)

        # the sending_command will send command to tello every 5 seconds
        self.sending_command_thread = threading.Thread(
            target=self._sendingCommand)

    def videoLoop(self):
        """
        The mainloop thread of Tkinter
        Raises:
            RuntimeError: To get around a RunTime error that Tkinter throws due to threading.
        """

        try:
            # start the thread that get GUI image and drwa skeleton
            time.sleep(0.5)
            self.sending_command_thread.start()
            while not self.stopEvent.is_set():
                system = platform.system()

                # read the frame for GUI show
                self.frame = self.tello.read()
                if self.frame is None or self.frame.size == 0:
                    continue

                integral_y = 0
                integral_x = 0
                previous_error_y = 0
                start_time = time.time()
                hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
                low_red = np.array([120, 150, 50], np.uint8)
                high_red = np.array([150, 255, 255], np.uint8)
                mask = cv2.inRange(hsv, low_red, high_red)
                # median = cv2.medianBlur(mask, 15)
                font = cv2.FONT_HERSHEY_COMPLEX
                ret, contorno, hierarchy = cv2.findContours(
                    mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
                mensaje2 = "Bateria =" + str(self.tellobateria()) + "%"
                # mensaje3 = "Altura =" + str(self.telloheight()) + "cm"
                # cv2.putText(self.frame, mensaje3, (10, 130), font, 1, (255, 0, 0), 1, cv2.LINE_AA)
                if self.tellobateria() > 50:
                    cv2.putText(self.frame, mensaje2, (10, 100), font, 1,
                                (0, 255, 0), 1, cv2.LINE_AA)
                else:
                    cv2.putText(self.frame, mensaje2, (10, 100), font, 1,
                                (255, 0, 0), 1, cv2.LINE_AA)

                SET_POINT_X = 960 / 2
                SET_POINT_Y = 720 / 2

                cv2.putText(self.frame, '{},{}'.format(SET_POINT_X,
                                                       SET_POINT_Y),
                            (SET_POINT_X, SET_POINT_Y), font, 0.75,
                            (255, 255, 255), 1, cv2.LINE_AA)
                for cnt in contorno:
                    area = cv2.contourArea(cnt)
                    approx = cv2.approxPolyDP(cnt,
                                              0.03 * cv2.arcLength(cnt, True),
                                              True)
                    if area > 2000:
                        # start_time = time.time()
                        M = cv2.moments(cnt)
                        if (M["m00"] == 0): M["m00"] = 1
                        x = int(M["m10"] / M["m00"])
                        y = int(M['m01'] / M['m00'])
                        nuevoContorno = cv2.convexHull(cnt)
                        cv2.circle(self.frame, (x, y), 7, (0, 0, 255), -1)
                        cv2.drawContours(self.frame, [nuevoContorno], -1,
                                         (0, 255, 0), 5)
                        # start_time = time.time()

                        if len(approx) == 4:
                            delay_pid = time.time() - start_time
                            # start_time = time.time()
                            # tiempo_transcurrido = time.clock() - tiempo_inicial
                            # elapsed_time = time() - start_time
                            mensaje80 = "tiempo =" + str(delay_pid)
                            cv2.putText(self.frame, mensaje80, (10, 90), font,
                                        1, (255, 255, 255), 1, cv2.LINE_AA)
                            kpy = 0.0022
                            kiy = 0.0008
                            # kdy = 0.02

                            kpx = 0.0022
                            kix = 0.0008

                            # kpx = 0.0022
                            w = 17
                            medidas = cv2.minAreaRect(nuevoContorno)
                            p = medidas[1][0]
                            f = 1000
                            # distancia = (w * f)/p
                            errorx = x - SET_POINT_X
                            errory = y - SET_POINT_Y
                            # mensaje = "Distancia =" + str(round(distancia, 2)) + " cm"
                            # erroryn = errory * kp
                            derivative_y = (errory -
                                            previous_error_y) / delay_pid
                            # integral_y = integral_y + errory * delay_pid
                            # pi = kpy * errory + kiy*integral_y
                            integral_y = integral_y + errory * delay_pid
                            integral_x = integral_x + errorx * delay_pid
                            piy = kpy * errory + kiy * integral_y
                            pix = kpx * errorx + kix * integral_x
                            # pi = kp * errory + ki + errory * delay_pid
                            # pid = kpy * errory + kiy * integral_y + kdy * derivative_y
                            mensaje90 = "value pi =" + str(piy)
                            cv2.putText(self.frame, mensaje90, (10, 130), font,
                                        1, (255, 255, 255), 1, cv2.LINE_AA)
                            # pid = kp * errory + ki + errory * delay_pid + kd * errory / derivative_y

                            if piy >= 0:
                                self.telloDown(piy)
                                previous_error_y = errory
                            else:
                                errory2n = piy * (-1)
                                self.telloUp(errory2n)
                            if pix >= 0:
                                self.telloMoveRight(pix)
                            else:
                                errorx2n = pix * (-1)
                                self.telloMoveLeft(errorx2n)
                            # cv2.putText(self.frame, mensaje, (10, 70), font, 1, (255, 255, 255), 1, cv2.LINE_AA)
                            # cv2.putText(self.frame, '{},{}'.format(x, y), (x-60, y+45), font, 0.75, (0, 255, 0), 1,
                            #             cv2.LINE_AA)
                            # if distancia > 100:
                            #     distancia2 = distancia - 100
                            #     self.telloMoveForward(distancia2/100)
                            # elif distancia < 80:
                            #     distancia3 = 100 - distancia
                            #     self.telloMoveBackward(distancia3/100)
                image = Image.fromarray(self.frame)
                if system == "Windows" or system == "Linux":

                    self._updateGUIImage(image)

                else:
                    thread_tmp = threading.Thread(target=self._updateGUIImage,
                                                  args=(image))
                    thread_tmp.start()
                    time.sleep(0.03)
        except RuntimeError as e:
            print("[INFO] caught a RuntimeError")

    def openCmdWindow(self):
        """
        open the cmd window and initial all the button and text
        """
        panel = Toplevel(self.root)
        panel.wm_title("Command Panel")

        # create text input entry
        text0 = tki.Label(
            panel,
            text=
            'This Controller map keyboard inputs to Tello control commands\n'
            'Adjust the trackbar to reset distance and degree parameter',
            font='Helvetica 10 bold')
        text0.pack(side='top')

        text1 = tki.Label(
            panel,
            text='W - Move Tello Up\t\t\tArrow Up - Move Tello Forward\n'
            'S - Move Tello Down\t\t\tArrow Down - Move Tello Backward\n'
            'A - Rotate Tello Counter-Clockwise\tArrow Left - Move Tello Left\n'
            'D - Rotate Tello Clockwise\t\tArrow Right - Move Tello Right',
            justify="left")
        text1.pack(side="top")

        self.btn_landing = tki.Button(panel,
                                      text="Land",
                                      relief="raised",
                                      command=self.telloLanding)
        self.btn_landing.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        self.btn_takeoff = tki.Button(panel,
                                      text="Takeoff",
                                      relief="raised",
                                      command=self.telloTakeOff)
        self.btn_takeoff.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        # binding arrow keys to drone control
        self.tmp_f = tki.Frame(panel, width=100, height=2)
        self.tmp_f.bind('<KeyPress-w>', self.on_keypress_w)
        self.tmp_f.bind('<KeyPress-s>', self.on_keypress_s)
        self.tmp_f.bind('<KeyPress-a>', self.on_keypress_a)
        self.tmp_f.bind('<KeyPress-d>', self.on_keypress_d)
        self.tmp_f.bind('<KeyPress-Up>', self.on_keypress_up)
        self.tmp_f.bind('<KeyPress-Down>', self.on_keypress_down)
        self.tmp_f.bind('<KeyPress-Left>', self.on_keypress_left)
        self.tmp_f.bind('<KeyPress-Right>', self.on_keypress_right)
        self.tmp_f.pack(side="bottom")
        self.tmp_f.focus_set()

        self.btn_landing = tki.Button(panel,
                                      text="Flip",
                                      relief="raised",
                                      command=self.openFlipWindow)
        self.btn_landing.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        self.distance_bar = Scale(panel,
                                  from_=0.02,
                                  to=5,
                                  tickinterval=0.01,
                                  digits=3,
                                  label='Distance(m)',
                                  resolution=0.01)
        self.distance_bar.set(0.2)
        self.distance_bar.pack(side="left")

        self.btn_distance = tki.Button(
            panel,
            text="Reset Distance",
            relief="raised",
            command=self.updateDistancebar,
        )
        self.btn_distance.pack(side="left",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

        self.degree_bar = Scale(panel,
                                from_=1,
                                to=360,
                                tickinterval=10,
                                label='Degree')
        self.degree_bar.set(30)
        self.degree_bar.pack(side="right")

        self.btn_distance = tki.Button(
            panel,
            text="Reset Degreejustin bieber love yourself",
            relief="raised",
            command=self.updateDegreebar)
        self.btn_distance.pack(side="right",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

    def openFlipWindow(self):
        """
        open the flip window and initial all the button and text
        """
        panel = Toplevel(self.root)
        panel.wm_title("Gesture Recognition")

        self.btn_flipl = tki.Button(panel,
                                    text="Flip Left",
                                    relief="raised",
                                    command=self.telloFlip_l)
        self.btn_flipl.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_flipr = tki.Button(panel,
                                    text="Flip Right",
                                    relief="raised",
                                    command=self.telloFlip_r)
        self.btn_flipr.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_flipf = tki.Button(panel,
                                    text="Flip Forward",
                                    relief="raised",
                                    command=self.telloFlip_f)
        self.btn_flipf.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_flipb = tki.Button(panel,
                                    text="Flip Backward",
                                    relief="raised",
                                    command=self.telloFlip_b)
        self.btn_flipb.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

    def takeSnapshot(self):
        """
        save the current frame of the video as a jpg file and put it into outputpath
        """
        # grab the current timestamp and use it to construct the filename
        ts = datetime.datetime.now()
        filename = "{}.jpg".format(ts.strftime("%Y-%m-%d_%H-%M-%S"))

        p = os.path.sep.join((self.outputPath, filename))

        # save the file
        cv2.imshow("gray", self.frame)
        cv2.imwrite(p, cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR))
        print("[INFO] saved {}".format(filename))

    # def Tracking(self):

    def tellobateria(self):
        return self.tello.get_battery()

    def telloheight(self):
        return self.tello.get_height()

    def telloTakeOff(self):
        return self.tello.takeoff()

    def telloLanding(self):
        return self.tello.land()

    def telloFlip_l(self):
        return self.tello.flip('l')

    def telloFlip_r(self):
        return self.tello.flip('r')

    def telloFlip_f(self):
        return self.tello.flip('f')

    def telloFlip_b(self):
        return self.tello.flip('b')

    def telloCW(self, degree):
        return self.tello.rotate_cw(degree)

    def telloCCW(self, degree):
        return self.tello.rotate_ccw(degree)

    def telloMoveForward(self, distance):
        return self.tello.move_forward(distance)

    def telloMoveBackward(self, distance):
        return self.tello.move_backward(distance)

    def telloMoveLeft(self, distance):
        return self.tello.move_left(distance)

    def telloMoveRight(self, distance):
        return self.tello.move_right(distance)

    def telloUp(self, dist):
        return self.tello.move_up(dist)

    def telloDown(self, dist):
        return self.tello.move_down(dist)

    def updateTrackBar(self):
        self.my_tello_hand.setThr(self.hand_thr_bar.get())

    def updateDistancebar(self):
        self.distance = self.distance_bar.get()
        print 'reset distance to %.1f' % self.distance

    def updateDegreebar(self):
        self.degree = self.degree_bar.get()
        print 'reset distance to %d' % self.degree

    def on_keypress_w(self, event):
        print "up %d m" % self.distance
        self.telloUp(self.distance)

    def on_keypress_s(self, event):
        print "down %d m" % self.distance
        self.telloDown(self.distance)

    def on_keypress_a(self, event):
        print "ccw %d degree" % self.degree
        self.tello.rotate_ccw(self.degree)

    def on_keypress_d(self, event):
        print "cw %d m" % self.degree
        self.tello.rotate_cw(self.degree)

    def on_keypress_up(self, event):
        print "forward %d m" % self.distance
        self.telloMoveForward(self.distance)

    def on_keypress_down(self, event):
        print "backward %d m" % self.distance
        self.telloMoveBackward(self.distance)

    def on_keypress_left(self, event):
        print "left %d m" % self.distance
        self.telloMoveLeft(self.distance)

    def on_keypress_right(self, event):
        print "right %d m" % self.distance
        self.telloMoveRight(self.distance)

    def on_keypress_enter(self, event):
        if self.frame is not None:
            self.registerFace()
        self.tmp_f.focus_set()

    def onClose(self):
        """
        set the stop event, cleanup the camera, and allow the rest of
        
        the quit process to continue
        """
        print("[INFO] closing...")
        self.stopEvent.set()
        del self.tello
        self.root.quit()
예제 #23
0
파일: generator.py 프로젝트: Akanoa/CAI2014
class Generator(Frame):
    """calcul d'une vibration harmonique du type : e=a*sin(2*pi*f*t+p)

    scale_A : controleur d'amplitude
    """
    def __init__(self, parent, name="X",color="red"):
        """ initialisation

        parent : un oscilloscope
        name : nom du signal
        """
        Frame.__init__(self)
        self.configure(bd=1, relief="sunken", background = color)
        self.parent = parent
        self.name = name
        self.color = color
        self.scale_A = Scale(self, length=300, orient="horizontal",
                label=name + " Amplitude", showvalue=1, from_=0, to=10,
                tickinterval=1, command=self.update_signal)

        self.scale_P = Scale(self, length=300, orient="horizontal",
                label=name + " Phase", showvalue=1, from_=0, to=90,
                tickinterval=20, command=self.update_signal)

        self.scale_F = Scale(self, length=300, orient="horizontal",
                label=name + " Fréquence", showvalue=1, from_=0, to=100,
                tickinterval=10, command=self.update_signal)

        self.scale_A.pack(expand="yes", fill="both")
        self.scale_P.pack(expand="yes", fill="both")
        self.scale_F.pack(expand="yes", fill="both")

    def update_signal(self, event):
        """mise a jour de courbe si modifications (amplitude, frequence, phase)."""
        #print("Vibration.update_signal()")
        #print("Amplitude :", self.scale_A.get())
        scaling=0.05
        amp = scaling*self.scale_A.get()
        fre = scaling*self.scale_F.get()
        pha = scaling*self.scale_P.get()
        signal = self.generate_signal(a=amp, f=fre, p=pha)
        if not isinstance(self.parent, Tk):
            self.parent.set_signal(self.name, signal, self.color)
        return signal

    def generate_signal(self, a=1.0, f=2.0, p=0):
        """Calcul de l'elongation, amplitude, frequence et phase sur une periode."""
        signal = []
        samples = 100
        for t in range(0, samples):
            samples = float(samples)
            e = a * sin((2*pi*f*(t/samples)) - p)
            signal.append((t/samples,e))
        return signal

    def get_parameter(self):
        """
        Récupère les valeurs des paramètres de la courbe et les renvoie sous forme d'un tuple
        """
        return [str(self.scale_A.get()), str(self.scale_F.get()), str(self.scale_P.get())]

    def set_parameter(self, amp=1.0, freq=2.0, phase=0):
        """
        Modifie les valeurs des paramètres de la courbe
        """
        self.scale_A.set(amp)
        self.scale_F.set(freq)
        self.scale_P.set(phase)
예제 #24
0
파일: arm.py 프로젝트: maxvitek/robotic_arm
    def gui(self):
        from Tkinter import Tk, Scale, HORIZONTAL
        root = Tk()
        x = Scale(root, from_=0, to=self.HUMERUS + self.ULNA + 2, resolution=0.1,
                orient = HORIZONTAL, length = 400,
                command=lambda i: self.dump_target_position(
                    float(i), y.get(), z.get(), g.get(), wa.get(), wr.get())
                )
        x.pack()
        x.set(8)
        
        y = Scale(root, from_=0, to=self.HUMERUS + self.ULNA + 2, resolution=0.1,
                orient = HORIZONTAL, length = 400,
                command=lambda i: self.dump_target_position(
                    x.get(), float(i), z.get(), g.get(), wa.get(), wr.get())
                )
        y.pack()
        y.set(6)
        
        z = Scale(root, from_=0, to=175,
                orient = HORIZONTAL, length = 400,
                command=lambda i: self.dump_target_position(
                    x.get(), y.get(), float(i), g.get(), wa.get(), wr.get())
                )
        z.pack()
        z.set(90)
        
        g = Scale(root, from_=0, to=175,
                orient = HORIZONTAL, length = 400,
                command=lambda i: self.dump_target_position(
                    x.get(), y.get(), z.get(), float(i), wa.get(), wr.get())
                )
        g.pack()
        g.set(90)
        
        wa = Scale(root, from_=-85, to=85,
                orient = HORIZONTAL, length = 400,
                command=lambda i: self.dump_target_position(
                    x.get(), y.get(), z.get(), g.get(), float(i), wr.get())
                )
        wa.pack()
        wa.set(0)
        
        wr = Scale(root, from_=0, to=175,
                orient = HORIZONTAL, length = 400,
                command=lambda i: self.dump_target_position(
                    x.get(), y.get(), z.get(), g.get(), wa.get(), float(i))
                )
        wr.pack()
        wr.set(90)

        root.mainloop()
예제 #25
0
class Equilibrium_GUI(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent

        self.manager = Equilibrium_manager()
        # Slider setting the animation pace, in ms/frame
        self.slider = None
        self.diameter = None
        # Variables making sure data is properly set before rendering
        # associated with checkboxes to give user feedback
        self.configured = IntVar()
        self.configured.set(0)
        self.configured_box = None
        self.loaded = IntVar()
        self.configured.set(0)
        self.loaded_box = None
        self.init_UI(self.parent)
        self.test_auto_conf()
        #self.plot_figure(self.parent)

    def init_UI(self, frame):
        frame.title("Pegasus system")

        b_import = Button(master=frame,
                          text='Importer',
                          command=self.open_data_file)
        b_import.grid(row=1, column=0)
        b_export = Button(master=frame,
                          text='Exporter',
                          command=self.export_data)
        b_export.grid(row=1, column=1)
        b_play = Button(master=frame, text='Play', command=self.render)
        b_play.grid(row=1, column=2)
        b_display = Button(master=frame, text='Afficher', command=self.display)
        b_display.grid(row=1, column=3)
        b_import = Button(master=frame,
                          text='Séparer pas/trot',
                          command=self.open_split_file_popup)
        b_import.grid(row=1, column=5)
        b_config = Button(master=frame,
                          text='Configurer',
                          command=self.open_conf_file)
        b_config.grid(row=1, column=6)
        b_quit = Button(master=frame, text='Quitter', command=self._quit)
        b_quit.grid(row=1, column=7)

        slider_label_fast = Label(master=frame, text="Rapide")
        slider_label_fast.grid(row=2, column=2)
        slider_label_slow = Label(master=frame, text="Lent")
        slider_label_slow.grid(row=2, column=0)
        self.slider = Scale(master=frame,
                            from_=150,
                            to=15,
                            orient=HORIZONTAL,
                            length=100)
        self.slider.set(25)
        self.slider.grid(row=2, column=1)

        slider_label_large = Label(master=frame, text="Large")
        slider_label_large.grid(row=2, column=6)
        slider_label_tiny = Label(master=frame, text="Réduit")
        slider_label_tiny.grid(row=2, column=4)
        self.diameter = Scale(master=frame,
                              from_=1,
                              to=35,
                              resolution=0.1,
                              orient=HORIZONTAL,
                              length=100)
        self.diameter.set(35)
        self.diameter.grid(row=2, column=5)

        self.configured_box = Checkbutton(master=frame,
                                          text="Configuré",
                                          variable=self.configured,
                                          state=DISABLED)
        self.configured_box.grid(row=3, column=0)

        self.loaded_box = Checkbutton(master=frame,
                                      text="Données chargées",
                                      variable=self.loaded,
                                      state=DISABLED)
        self.loaded_box.grid(row=3, column=1)

    def test_auto_conf(self):
        onlyfiles = [f for f in listdir(".") if isfile(join(".", f))]
        if ("equi_librium.conf" in onlyfiles):
            self.manager.read_config_file("equi_librium.conf")
            self.configured.set(1)

    def open_data_file(self):
        if (self.configured.get() == 1):
            ftypes = [('All files', '*')]
            dlg = tkFileDialog.Open(self, filetypes=ftypes)
            fl = dlg.show()
            if fl != '':
                self.manager.read_data_file(fl)
                self.loaded.set(1)
        else:
            tkMessageBox.showwarning(
                "Configuration non effectuee",
                "Il faut configurer avant d'importer les données")

    def open_split_file_popup(self):
        w = popupWindow(self.master, self.manager)
        self.master.wait_window(w.top)

    def open_conf_file(self):
        ftypes = [('conf files', '*.conf'), ('All files', '*')]
        dlg = tkFileDialog.Open(self, filetypes=ftypes)
        fl = dlg.show()
        if fl != '':
            self.manager.read_config_file(fl)
            self.configured.set(1)

    def export_data(self):
        ftypes = [('All files', '*')]
        dlg = tkFileDialog.SaveAs(self, filetypes=ftypes)
        fl = dlg.show()
        if fl != '':
            self.manager.set_diameter(self.diameter.get())
            self.manager.export_chart(fl + ".csv")

    def display(self):
        self.manager.set_diameter(self.diameter.get())
        self.manager.display_data()

    def render(self):
        self.manager.render_animation(self.slider.get())
        #self.plot_figure(self.parent)

    def plot_figure(self, frame):
        f = Figure(figsize=(5, 4), dpi=100)
        #f = self.manager.render_animation()
        #a = f.add_subplot(111)
        #t = arange(0.0,3.0,0.01)
        #s = sin(2*pi*t)

        #a.plot(t,s)
        canvas = FigureCanvasTkAgg(f, master=frame)
        canvas.show()
        canvas.get_tk_widget().grid(row=0, columnspan=5)
        # canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

        # toolbar = NavigationToolbar2TkAgg( canvas, root )
        # toolbar.update()
        # canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
        canvas._tkcanvas.grid(row=0, columnspan=5)

        def on_key_event(event):
            print('you pressed %s' % event.key)
            key_press_handler(event, canvas)  #, toolbar)

        canvas.mpl_connect('key_press_event', on_key_event)

    def _quit(self):
        self.quit()  # stops mainloop
        self.destroy()  # this is necessary on Windows to prevent
예제 #26
0
파일: scraper.py 프로젝트: protobuf/dsbot
class Scraper():

    def __init__(self, img_filename='snap.png'):
        self.canvas = Canvas()
        self.scales = []
        self.canvas.pack()
        self._current_image = None
        self._original_image = None
        
        self.root = self._load_gui()
        self.open_image(img_filename)
        self.repaint()
        self.root.mainloop()

    @property
    def image(self):
        return self._current_image

    @image.setter
    def image(self, value):
        self._current_image = value

    @property
    def original_image(self):
        return self._original_image

    @image.setter
    def image(self, value):
        self._original_image = value

    def open_image(self, filename):
        self.original_image = Image.open(filename).copy()
        self.image = self.original_image

    def repaint(self):
        rgb_min = (self.scale_red_min.get(), self.scale_green_min.get(), self.scale_blue_min.get())
        rgb_max = (self.scale_red_max.get(), self.scale_green_max.get(), self.scale_blue_max.get())
        print "repainting", rgb_min, rgb_max
        self.image = strip_colors(self.original_image, rgb_min, rgb_max)
        self._paint(self.image)

    def _paint(self, image):
        if image is not None:
            # check if we need to resize the canvas, based on the size of the image being painted
            image_width, image_height = image.size
            if self.canvas.winfo_width() != image_width or self.canvas.winfo_height() != image_height:
                self.canvas.config(width=image_width, height=image_height)

            # paint the image to the canvas
            self._img_tk = ImageTk.PhotoImage(image)
            self.canvas.create_image(0, 0, image=self._img_tk, anchor=NW)
        else:
            print 'there is no image to paint'
            return -1
 
    def _load_gui(self):
        root = Tk()
        root.title("Scraper")
        main_frame = Frame(root)
        main_frame.grid(column=0, row=0, sticky=(N, W, E, S))
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(0, weight=1)
        main_frame.pack()
        
        self.scale_red_min = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_red_min)
        self.scale_red_min.grid(column=1, row=1)
       
        self.scale_red_max = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_red_max)
        self.scale_red_max.grid(column=2, row=1)
        self.scale_red_max.set(255)
        
        self.scale_green_min = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_green_min)
        self.scale_green_min.grid(column=1, row=2)

        self.scale_green_max = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_green_max)
        self.scale_green_max.grid(column=2, row=2)
        self.scale_green_max.set(255)

        self.scale_blue_min = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_blue_min)
        self.scale_blue_min.grid(column=1, row=3)
        
        self.scale_blue_max = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_blue_max)
        self.scale_blue_max.grid(column=2, row=3)
        self.scale_blue_max.set(255)
        return root

    def _update_red_min(self, value):
        print 'updating red min to %s' % value
        if self.scale_red_min.get() > self.scale_red_max.get():
            self.scale_red_max.set(self.scale_red_min.get())
        self.repaint()

    def _update_red_max(self, value):
        print 'updating red max to %s' % value
        if self.scale_red_max.get() < self.scale_red_min.get():
            self.scale_red_min.set(self.scale_red_max.get())
        self.repaint()

    def _update_green_min(self, value):
        print 'updating green min to %s' % value
        if self.scale_green_min.get() > self.scale_green_max.get():
            self.scale_green_max.set(self.scale_green_min.get())
        self.repaint()

    def _update_green_max(self, value):
        print 'updating green max to  %s' % value
        if self.scale_green_max.get() < self.scale_green_min.get():
            self.scale_green_min.set(self.scale_green_max.get())
        self.repaint()

    def _update_blue_min(self, value):
        print 'updating blue min to %s' % value
        if self.scale_blue_min.get() > self.scale_blue_max.get():
            self.scale_blue_max.set(self.scale_blue_min.get())
        self.repaint()

    def _update_blue_max(self, value):
        print 'updating blue max to %s' % value
        if self.scale_blue_max.get() < self.scale_blue_min.get():
            self.scale_blue_min.set(self.scale_blue_max.get())
        self.repaint()
예제 #27
0
#!/usr/bin/python
import commands
from Tkinter import Tk, IntVar, Scale


def adjustVol(vol):
    commands.getoutput("/usr/sbin/mixer vol " + vol)
    return


root = Tk()
root.geometry('50x100+80+620')
vol = IntVar()
scale = Scale(root, variable=vol, from_=100, to=0, command=adjustVol)
scale.set(commands.getoutput('/usr/sbin/mixer -S').split(':')[1])
scale.pack()
root.mainloop()
예제 #28
0
class TelloUI:
    """Wrapper class to enable the GUI."""
    def __init__(self, tello, outputpath):
        """
        Initial all the element of the GUI,support by Tkinter

        :param tello: class interacts with the Tello drone.

        Raises:
            RuntimeError: If the Tello rejects the attempt to enter command mode.
        """
        self.tello = tello  # videostream device
        self.outputPath = outputpath  # the path that save pictures created by clicking the takeSnapshot button
        self.frame = None  # frame read from h264decoder and used for pose recognition
        self.thread = None  # thread of the Tkinter mainloop
        self.stopEvent = None

        # control variables
        self.distance = 0.1  # default distance for 'move' cmd
        self.degree = 10  # default degree for 'cw' or 'ccw' cmd
        # if the pose recognition mode is opened
        self.pose_mode = False
        # if the flag is TRUE,the auto-takeoff thread will stop waiting for the response from tello
        self.quit_waiting_flag = False
        # if the flag is TRUE,the pose recognition skeleton will be drawn on the GUI picture
        self.draw_skeleton_flag = False
        # pose recognition
        self.my_tello_pose = Tello_Pose()

        # record the coordinates of the nodes in the pose recognition skeleton
        self.points = []
        # list of all the possible connections between skeleton nodes
        self.POSE_PAIRS = [[0, 1], [1, 2], [2, 3], [3, 4], [1, 5], [5, 6],
                           [6, 7], [1, 14], [14, 8], [8, 9], [9, 10], [14, 11],
                           [11, 12], [12, 13]]

        # initialize the root window and image panel
        self.root = tki.Tk()
        self.panel = None
        # self.panel_for_pose_handle_show = None

        # create buttons
        self.btn_snapshot = tki.Button(self.root,
                                       text="Snapshot!",
                                       command=self.takeSnapshot)
        self.btn_snapshot.pack(side="bottom",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

        self.btn_pose = tki.Button(self.root,
                                   text="Pose Recognition Status: Off",
                                   command=self.setPoseMode)
        self.btn_pose.pack(side="bottom",
                           fill="both",
                           expand="yes",
                           padx=10,
                           pady=5)

        self.btn_pause = tki.Button(self.root,
                                    text="Pause",
                                    relief="raised",
                                    command=self.pauseVideo)
        self.btn_pause.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_landing = tki.Button(self.root,
                                      text="Open Command Panel",
                                      relief="raised",
                                      command=self.openCmdWindow)
        self.btn_landing.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        # start a thread that constantly pools the video sensor for
        # the most recently read frame
        self.stopEvent = threading.Event()
        self.thread = threading.Thread(target=self.videoLoop, args=())
        self.thread.start()

        # set a callback to handle when the window is closed
        self.root.wm_title("TELLO Controller")
        self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose)

        # the auto-takeoff thread will start if the 'takeoff' button on command window is clicked
        self.auto_takeoff_thread = threading.Thread(target=self._autoTakeoff)
        # the sending_command will send command to tello every 5 seconds
        self.sending_command_thread = threading.Thread(
            target=self._sendingCommand)
        self.get_GUI_Image_thread = threading.Thread(target=self._getGUIImage)

    def videoLoop(self):
        """
        The mainloop thread of Tkinter 
        Raises:
            RuntimeError: To get around a RunTime error that Tkinter throws due to threading.
        """
        try:
            # start the thread that get GUI image and drwa skeleton
            # todo adjust 1: 采集图像时间间隔为2s (识别时间平均0.05s)
            time.sleep(2)
            self.get_GUI_Image_thread.start()
            while not self.stopEvent.is_set():
                # read the frame for pose recognition
                self.frame = self.tello.read()
                if self.frame is None or self.frame.size == 0:
                    continue

                # smoothing filter---nparray
                self.frame = cv2.bilateralFilter(self.frame, 5, 50, 100)

                # PIL image
                # self.frame=Image.fromarray(self.frame)
                # img.show()

                # cv2 image
                # self.frame = cv2.cvtColor(np.asarray(self.frame), cv2.COLOR_RGB2BGR)
                # every 2 second
                # time.sleep(2)

                cmd = ''
                self.points.append(None)
                # process pose-recognition
                if self.pose_mode:
                    # cmd, self.draw_skeleton_flag, self.points = self.my_tello_pose.detect(self.frame)
                    cmd = self.my_tello_pose.detect_v1(self.frame)

                # todo adjust 2: 根据返回的识别结果发送相应的指令
                # 移动距离
                dis = 0.4
                # 间隔时间
                slp = 5
                # 老虎
                if cmd == 'tiger' or cmd == 'tabby':
                    self.takeSnapshot()
                    time.sleep(slp)
                    self.telloMoveLeft(dis)
                # 豹
                elif cmd == 'leopard':
                    self.takeSnapshot()
                    time.sleep(slp)
                    self.telloMoveLeft(dis)
                # 小熊猫
                elif cmd == 'lesser panda' or cmd == 'West Highland white terrier' or cmd == 'polecat':
                    self.takeSnapshot()
                    time.sleep(slp)
                    self.telloMoveLeft(dis)
                # 非洲大鳄鱼
                elif cmd == 'African crocodile' or cmd == 'American alligator':
                    # self.takeSnapshot()
                    time.sleep(slp)
                    self.telloMoveLeft(dis)
                # 蝎子
                elif cmd == 'scorpion':
                    # self.takeSnapshot()
                    time.sleep(slp)
                    self.telloMoveLeft(dis)
                # 蛇
                elif cmd == 'green snake' or cmd == 'green mamba' or cmd == 'eel' or cmd == 'cucumber':
                    # self.takeSnapshot()
                    time.sleep(slp)
                    self.telloFlip_b()
                    time.sleep(slp)
                    self.telloLanding()
                elif cmd=='nematode' or cmd == 'envelope' or cmd=='binder' or cmd =='book jacket' or cmd=='window screen'\
                        or cmd=='paper towel':
                    time.sleep(slp)
                    self.telloMoveLeft(0.2)
                    # time.sleep(slp)

                # if cmd=='show time':#检测到时机向后飞 0.3m,然后降落
                #     self.telloMoveBackward(0.3)
                #     time.sleep(3)
                #     self.telloLanding()
                # elif cmd=='bucket':
                #     self.telloMoveForward(1.0)
                #     time.sleep(3)
                #     self.telloLanding()

                # process command - map your motion to whatever Tello movement you want!
                # if cmd == 'moveback':
                #     self.telloMoveBackward(0.30)
                # elif cmd == 'moveforward':
                #     self.telloMoveForward(0.30)
                # elif cmd == 'land':
                #     self.telloLanding()

        except RuntimeError:
            print("[INFO] caught a RuntimeError")

    def _getGUIImage(self):
        """
        Main operation to read frames from h264decoder and draw skeleton on 
        frames if the pose mode is opened
        """
        # read the system of your computer
        system = platform.system()
        while not self.stopEvent.is_set():
            # read the frame for GUI show
            frame = self.tello.read()
            if frame is None or frame.size == 0:
                continue
            if self.pose_mode:
                # Draw the detected skeleton points
                for i in range(15):
                    if self.draw_skeleton_flag == True:
                        cv2.circle(frame,
                                   self.points[i],
                                   8, (0, 255, 255),
                                   thickness=-1,
                                   lineType=cv2.FILLED)
                        cv2.putText(frame,
                                    "{}".format(i),
                                    self.points[i],
                                    cv2.FONT_HERSHEY_SIMPLEX,
                                    1, (0, 0, 255),
                                    2,
                                    lineType=cv2.LINE_AA)
                        # Draw Skeleton
                # for pair in self.POSE_PAIRS:
                #     partA = pair[0]
                #     partB = pair[1]
                #     if self.points[partA] and self.points[partB]:
                #         cv2.line(frame, self.points[partA], self.points[partB], (0, 255, 255), 2)
                #         cv2.circle(frame, self.points[partA], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)

            # transfer the format from frame to image
            image = Image.fromarray(frame)

            # we found compatibility problem between Tkinter,PIL and Macos,and it will
            # sometimes result the very long preriod of the "ImageTk.PhotoImage" function,
            # so for Macos,we start a new thread to execute the _updateGUIImage function.
            if system == "Windows" or system == "Linux":
                self._updateGUIImage(image)
                # time.sleep(0.5)

            else:
                thread_tmp = threading.Thread(target=self._updateGUIImage,
                                              args=(image, ))
                thread_tmp.start()
                time.sleep(0.03)

    def _updateGUIImage(self, image):
        """
        Main operation to initial the object of image,and update the GUI panel 
        """
        image = ImageTk.PhotoImage(image)
        # if the panel none ,we need to initial it
        if self.panel is None:
            self.panel = tki.Label(image=image)
            self.panel.image = image
            self.panel.pack(side="left", padx=10, pady=10)
        # otherwise, simply update the panel
        else:
            self.panel.configure(image=image)
            self.panel.image = image

    def _autoTakeoff(self):
        """
        Firstly,it will waiting for the response that will be sent by Tello if Tello 
        
        finish the takeoff command.If computer doesn't receive the response,it may be
        
        because tello doesn't takeoff normally,or because the UDP pack of response is
        
        lost.So in order to confirm the reason,computer will send 'height?'command to
        
        get several real-time height datas and get a average value.If the height is in
        
        normal range,tello will execute the moveup command.Otherwise,tello will land.
        
        Finally,the sending-command thread will start.
        """
        response = None
        height_tmp = 0  # temp variable to content value of height
        height_val = 0  # average value of height
        cnt = 0  # effective number of height reading
        # todo change 1: set max time out
        timeout = 8  # max waiting time of tello's response

        timer = threading.Timer(timeout, self._setQuitWaitingFlag)
        timer.start()

        # waiting for the response from tello
        while response != 'ok':
            if self.quit_waiting_flag is True:
                break
            response = self.tello.get_response()
            print
            "ack:%s" % response
        timer.cancel()

        # receive the correct response
        if response == 'ok':
            # self.tello.move_up(0.5)
            self.tello.move_up(0.1)

        # calculate the height of tello
        else:
            # todo change 2: calcute the ave height
            for i in range(0, 10):
                time.sleep(0.5)
                height_tmp = self.tello.get_height()
                try:
                    height_val = height_val + height_tmp
                    cnt = cnt + 1
                    print
                    height_tmp, cnt
                except:
                    height_val = height_val

            height_val = height_val / cnt

            # if the height value is in normal range
            if height_val == 9 or height_val == 10 or height_val == 11:
                # todo change 3: 成功起飞后的默认提升高度
                self.tello.move_up(0.2)
            else:
                self.tello.land()
        # start the sendingCmd thread
        self.sending_command_thread.start()

    def _sendingCommand(self):
        """
        start a while loop that sends 'command' to tello every 5 second
        """

        while True:
            self.tello.send_command('command')
            time.sleep(5)

    def _setQuitWaitingFlag(self):
        """
        set the variable as TRUE,it will stop computer waiting for response from tello  
        """
        self.quit_waiting_flag = True

    def openCmdWindow(self):
        """
        open the cmd window and initial all the button and text
        """
        panel = Toplevel(self.root)
        panel.wm_title("Command Panel")

        # create text input entry
        text0 = tki.Label(
            panel,
            text=
            'This Controller map keyboard inputs to Tello control commands\n'
            'Adjust the trackbar to reset distance and degree parameter',
            font='Helvetica 10 bold')
        text0.pack(side='top')

        text1 = tki.Label(
            panel,
            text='W - Move Tello Up\t\t\tArrow Up - Move Tello Forward\n'
            'S - Move Tello Down\t\t\tArrow Down - Move Tello Backward\n'
            'A - Rotate Tello Counter-Clockwise\tArrow Left - Move Tello Left\n'
            'D - Rotate Tello Clockwise\t\tArrow Right - Move Tello Right',
            justify="left")
        text1.pack(side="top")

        self.btn_landing = tki.Button(panel,
                                      text="Land",
                                      relief="raised",
                                      command=self.telloLanding)
        self.btn_landing.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        self.btn_takeoff = tki.Button(panel,
                                      text="Takeoff",
                                      relief="raised",
                                      command=self.telloTakeOff)
        self.btn_takeoff.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        # binding arrow keys to drone control
        self.tmp_f = tki.Frame(panel, width=100, height=2)
        self.tmp_f.bind('<KeyPress-w>', self.on_keypress_w)
        self.tmp_f.bind('<KeyPress-s>', self.on_keypress_s)
        self.tmp_f.bind('<KeyPress-a>', self.on_keypress_a)
        self.tmp_f.bind('<KeyPress-d>', self.on_keypress_d)
        self.tmp_f.bind('<KeyPress-Up>', self.on_keypress_up)
        self.tmp_f.bind('<KeyPress-Down>', self.on_keypress_down)
        self.tmp_f.bind('<KeyPress-Left>', self.on_keypress_left)
        self.tmp_f.bind('<KeyPress-Right>', self.on_keypress_right)
        self.tmp_f.pack(side="bottom")
        self.tmp_f.focus_set()

        self.btn_landing = tki.Button(panel,
                                      text="Flip",
                                      relief="raised",
                                      command=self.openFlipWindow)
        self.btn_landing.pack(side="bottom",
                              fill="both",
                              expand="yes",
                              padx=10,
                              pady=5)

        self.distance_bar = Scale(panel,
                                  from_=0.02,
                                  to=5,
                                  tickinterval=0.01,
                                  digits=3,
                                  label='Distance(m)',
                                  resolution=0.01)
        self.distance_bar.set(0.2)
        self.distance_bar.pack(side="left")

        self.btn_distance = tki.Button(
            panel,
            text="Reset Distance",
            relief="raised",
            command=self.updateDistancebar,
        )
        self.btn_distance.pack(side="left",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

        self.degree_bar = Scale(panel,
                                from_=1,
                                to=360,
                                tickinterval=10,
                                label='Degree')
        self.degree_bar.set(30)
        self.degree_bar.pack(side="right")

        self.btn_distance = tki.Button(panel,
                                       text="Reset Degree",
                                       relief="raised",
                                       command=self.updateDegreebar)
        self.btn_distance.pack(side="right",
                               fill="both",
                               expand="yes",
                               padx=10,
                               pady=5)

    def openFlipWindow(self):
        """
        open the flip window and initial all the button and text
        """

        panel = Toplevel(self.root)
        panel.wm_title("Gesture Recognition")

        self.btn_flipl = tki.Button(panel,
                                    text="Flip Left",
                                    relief="raised",
                                    command=self.telloFlip_l)
        self.btn_flipl.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_flipr = tki.Button(panel,
                                    text="Flip Right",
                                    relief="raised",
                                    command=self.telloFlip_r)
        self.btn_flipr.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_flipf = tki.Button(panel,
                                    text="Flip Forward",
                                    relief="raised",
                                    command=self.telloFlip_f)
        self.btn_flipf.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

        self.btn_flipb = tki.Button(panel,
                                    text="Flip Backward",
                                    relief="raised",
                                    command=self.telloFlip_b)
        self.btn_flipb.pack(side="bottom",
                            fill="both",
                            expand="yes",
                            padx=10,
                            pady=5)

    def takeSnapshot(self):
        """
        save the current frame of the video as a jpg file and put it into outputpath
        """

        # grab the current timestamp and use it to construct the filename
        ts = datetime.datetime.now()
        filename = "{}.jpg".format(ts.strftime("%Y-%m-%d_%H-%M-%S"))

        p = os.path.sep.join((self.outputPath, filename))

        # save the file
        cv2.imwrite(p, cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR))
        print("[INFO] saved {}".format(filename))

    def setPoseMode(self):
        """
        Toggle the open/close of pose recognition mode
        """
        if self.pose_mode is False:
            self.pose_mode = True
            self.btn_pose.config(text='Pose Recognition Status: On')
        else:
            self.pose_mode = False
            self.btn_pose.config(text='Pose Recognition Status: Off')

    def pauseVideo(self):
        """
        Toggle the freeze/unfreze of video
        """
        if self.btn_pause.config('relief')[-1] == 'sunken':
            self.btn_pause.config(relief="raised")
            self.tello.video_freeze(False)
        else:
            self.btn_pause.config(relief="sunken")
            self.tello.video_freeze(True)

    def telloTakeOff(self):
        """
        send the takeoff command to tello,and wait for the first response,
        
        if get the 'error'response,remind the "battery low" warning.Otherwise,
        
        start the auto-takeoff thread
        """
        takeoff_response = None

        self.tello.takeoff()
        time.sleep(0.2)

        takeoff_response = self.tello.get_response()

        if takeoff_response != 'error':
            self.auto_takeoff_thread.start()
        else:
            print
            "battery low,please repalce with a new one"

    def telloLanding(self):
        return self.tello.land()

    def telloFlip_l(self):
        return self.tello.flip('l')

    def telloFlip_r(self):
        return self.tello.flip('r')

    def telloFlip_f(self):
        return self.tello.flip('f')

    def telloFlip_b(self):
        return self.tello.flip('b')

    def telloCW(self, degree):
        return self.tello.rotate_cw(degree)

    def telloCCW(self, degree):
        return self.tello.rotate_ccw(degree)

    def telloMoveForward(self, distance):
        return self.tello.move_forward(distance)

    def telloMoveBackward(self, distance):
        return self.tello.move_backward(distance)

    def telloMoveLeft(self, distance):
        return self.tello.move_left(distance)

    def telloMoveRight(self, distance):
        return self.tello.move_right(distance)

    def telloUp(self, dist):
        return self.tello.move_up(dist)

    def telloDown(self, dist):
        return self.tello.move_down(dist)

    def updateTrackBar(self):
        self.my_tello_hand.setThr(self.hand_thr_bar.get())

    def updateDistancebar(self):
        self.distance = self.distance_bar.get()
        print
        'reset distance to %.1f' % self.distance

    def updateDegreebar(self):
        self.degree = self.degree_bar.get()
        print
        'reset distance to %d' % self.degree

    def on_keypress_w(self, event):
        print
        "up %d m" % self.distance
        self.telloUp(self.distance)

    def on_keypress_s(self, event):
        print
        "down %d m" % self.distance
        self.telloDown(self.distance)

    def on_keypress_a(self, event):
        print
        "ccw %d degree" % self.degree
        self.tello.rotate_ccw(self.degree)

    def on_keypress_d(self, event):
        print
        "cw %d m" % self.degree
        self.tello.rotate_cw(self.degree)

    def on_keypress_up(self, event):
        print
        "forward %d m" % self.distance
        self.telloMoveForward(self.distance)

    def on_keypress_down(self, event):
        print
        "backward %d m" % self.distance
        self.telloMoveBackward(self.distance)

    def on_keypress_left(self, event):
        print
        "left %d m" % self.distance
        self.telloMoveLeft(self.distance)

    def on_keypress_right(self, event):
        print
        "right %d m" % self.distance
        self.telloMoveRight(self.distance)

    def on_keypress_enter(self, event):
        if self.frame is not None:
            self.registerFace()
        self.tmp_f.focus_set()

    def onClose(self):
        """
        set the stop event, cleanup the camera, and allow the rest of
        
        the quit process to continue
        """
        print("[INFO] closing...")
        self.stopEvent.set()
        del self.tello
        self.root.quit()
예제 #29
0
class OfflineVisualiser(Visualiser):
    """A VTK-powered offline visualiser which runs in its own thread.
    In addition to the functions provided by the standard visualiser,
    the following additional functions are provided:

    precache_height_quantities() - Precache all the vtkpoints
    structures for any dynamic height based quantities to render.
    """
    def __init__(self, source, frameDelay=100, frameStep=1):
        """The source parameter is assumed to be a NetCDF sww file.
        The frameDelay parameter is the number of milliseconds waited between frames.
        """
        Visualiser.__init__(self, source)

        self.frameNumber = 0
        fin = NetCDFFile(self.source, 'r')
        self.maxFrameNumber = fin.variables['time'].shape[0] - 1
        fin.close()

        #self.frameNumberTkVariable = StringVar()
        #self.frameNumberTkVariable.set('Frame - %05g'%self.framNumber)

        self.frameDelay = frameDelay

        self.xmin = None
        self.xmax = None
        self.ymin = None
        self.ymax = None
        self.zmin = None
        self.zmax = None

        self.frameStep = frameStep

        self.vtk_heightQuantityCache = []
        for i in range(self.maxFrameNumber +
                       1):  # maxFrameNumber is zero indexed.
            self.vtk_heightQuantityCache.append({})

        self.paused = False
        self.movie = False

    def setup_grid(self):
        fin = NetCDFFile(self.source, 'r')
        self.vtk_cells = vtkCellArray()
        N_tri = fin.variables['volumes'].shape[0]
        for v in range(N_tri):
            self.vtk_cells.InsertNextCell(3)
            for i in range(3):
                self.vtk_cells.InsertCellPoint(fin.variables['volumes'][v][i])
        fin.close()

    def update_height_quantity(self, quantityName, dynamic=True):
        polydata = self.vtk_polyData[quantityName] = vtkPolyData()
        if dynamic is True:
            #print ' - Frame',self.frameNumber,'of',self.maxFrameNumber
            if not self.vtk_heightQuantityCache[self.frameNumber].has_key(
                    quantityName):
                self.vtk_heightQuantityCache[self.frameNumber][quantityName]\
                    = self.read_height_quantity(quantityName, True, self.frameNumber)
            polydata.SetPoints(
                self.vtk_heightQuantityCache[self.frameNumber][quantityName])
        else:
            polydata.SetPoints(self.read_height_quantity(quantityName, False))
        polydata.SetPolys(self.vtk_cells)

    def get_3d_bounds(self):
        return [
            self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax
        ]

    def read_height_quantity(self, quantityName, dynamic=True, frameNumber=0):
        """Read in a height based quantity from the NetCDF source file
        and return a vtkPoints object. frameNumber is ignored if
        dynamic is false."""
        fin = NetCDFFile(self.source, 'r')
        points = vtkPoints()
        if dynamic is True:
            N_vert = fin.variables[quantityName].shape[1]
        else:
            N_vert = len(fin.variables[quantityName])
        x = num.ravel(num.array(fin.variables['x'], num.float))
        y = num.ravel(num.array(fin.variables['y'], num.float))
        if dynamic is True:
            q = num.array(fin.variables[quantityName][frameNumber], num.float)
        else:
            q = num.ravel(num.array(fin.variables[quantityName], num.float))

        q *= self.height_zScales[quantityName]
        q += self.height_offset[quantityName]

        for v in range(N_vert):
            points.InsertNextPoint(x[v], y[v], q[v])
            if self.xmin is None or self.xmin > x[v]:
                self.xmin = x[v]
            if self.xmax is None or self.xmax < x[v]:
                self.xmax = x[v]
            if self.ymin is None or self.ymin > y[v]:
                self.ymin = y[v]
            if self.ymax is None or self.ymax < y[v]:
                self.ymax = y[v]
            if self.zmin is None or self.zmin > q[v]:
                self.zmin = q[v]
            if self.zmax is None or self.zmax < q[v]:
                self.zmax = q[v]
        fin.close()
        return points

    def precache_height_quantities(self):
        """Precache any height-based quantities. Call before rendering
        beigns."""
        for q in self.height_quantities:
            if self.height_dynamic[q] is True:
                print 'Precaching %s' % q
                for i in range(self.maxFrameNumber +
                               1):  # maxFrameNumber is zero-indexed
                    print ' - Frame %d of %d' % (i, self.maxFrameNumber)
                    self.vtk_heightQuantityCache[i][q]\
                        = self.read_height_quantity(q, True, i)

    def build_quantity_dict(self):
        quantities = {}
        fin = NetCDFFile(self.source, 'r')
        for q in filter(
                lambda n: n != 'x' and n != 'y' and n != 'z' and n != 'time'
                and n != 'volumes', fin.variables.keys()):
            if len(fin.variables[q].shape) == 1:  # Not a time-varying quantity
                quantities[q] = num.ravel(
                    num.array(fin.variables[q], num.float))
            else:  # Time-varying, get the current timestep data
                quantities[q] = num.array(fin.variables[q][self.frameNumber],
                                          num.float)
        fin.close()
        return quantities

    def setup_gui(self):
        Visualiser.setup_gui(self)
        self.tk_quit.grid(row=0, column=0, sticky=W + E)
        self.tk_movie_toggle = Button(self.tk_controlFrame,
                                      text="Movie off",
                                      command=self.movie_toggle)
        self.tk_movie_toggle.grid(row=0, column=6, sticky=W + E)

        self.tk_restart = Button(self.tk_controlFrame,
                                 text="<<<",
                                 command=self.restart,
                                 width=5)
        self.tk_restart.grid(row=1, column=0, sticky=W + E)
        self.tk_back10 = Button(self.tk_controlFrame,
                                text="<<",
                                command=self.back10,
                                width=5)
        self.tk_back10.grid(row=1, column=1, sticky=W + E)
        self.tk_back = Button(self.tk_controlFrame,
                              text="<",
                              command=self.back,
                              width=5)
        self.tk_back.grid(row=1, column=2, sticky=W + E)
        self.tk_pauseResume = Button(self.tk_controlFrame,
                                     text="Pause",
                                     command=self.pauseResume,
                                     width=15)
        self.tk_pauseResume.grid(row=1, column=3, sticky=W + E)
        self.tk_forward = Button(self.tk_controlFrame,
                                 text=">",
                                 command=self.forward,
                                 width=5)
        self.tk_forward.grid(row=1, column=4, sticky=W + E)
        self.tk_forward10 = Button(self.tk_controlFrame,
                                   text=">>",
                                   command=self.forward10,
                                   width=5)
        self.tk_forward10.grid(row=1, column=5, sticky=W + E)
        self.tk_forwardEnd = Button(self.tk_controlFrame,
                                    text=">>>",
                                    command=self.forwardEnd,
                                    width=5)
        self.tk_forwardEnd.grid(row=1, column=6, sticky=W + E)

        self.tk_frameNumber = Label(self.tk_controlFrame, text='Frame')
        self.tk_frameNumber.grid(row=2, column=0, sticky=W + E)
        self.tk_gotoFrame = Scale(self.tk_controlFrame,
                                  from_=0,
                                  to=self.maxFrameNumber,
                                  orient=HORIZONTAL)
        self.tk_gotoFrame.grid(row=2, column=1, columnspan=2, sticky=W + E)
        self.tk_stepLabel = Label(self.tk_controlFrame, text='Step')
        self.tk_stepLabel.grid(row=2, column=4, sticky=W + E)
        self.tk_frameStep = Scale(self.tk_controlFrame,
                                  from_=0,
                                  to=self.maxFrameNumber,
                                  orient=HORIZONTAL)
        self.tk_frameStep.grid(row=2, column=5, columnspan=2, sticky=W + E)

        # Make the buttons stretch to fill all available space
        for i in range(7):
            self.tk_controlFrame.grid_columnconfigure(i, weight=1)

    def run(self):
        self.alter_tkroot(Tk.after, (self.frameDelay, self.animateForward))
        Visualiser.run(self)

    def restart(self):
        self.frameNumber = 0
        self.redraw_quantities()
        self.update_labels()
        self.pause()

        if self.movie:
            self.save_image()

    def forwardEnd(self):
        self.frameNumber = self.maxFrameNumber
        self.redraw_quantities()
        self.update_labels()
        self.pause()

    def movie_toggle(self):
        if self.movie == True:
            self.movie = False
            self.tk_movie_toggle.config(text='Movie off')
        else:
            self.movie = True
            self.tk_movie_toggle.config(text='Movie on ')

    def save_image(self):

        from vtk import vtkJPEGWriter, vtkJPEGWriter, vtkPNGWriter
        from vtk import vtkPNMWriter, vtkWindowToImageFilter
        from os import path

        sourcebase, _ = path.splitext(self.source)
        fname = sourcebase + '%05g.png' % self.frameNumber
        #print fname

        extmap = {
            '.jpg': vtkJPEGWriter,
            '.jpeg': vtkJPEGWriter,
            '.png': vtkPNGWriter,
            '.pnm': vtkPNMWriter,
        }
        basename, ext = path.splitext(fname)
        try:
            Writer = extmap[ext.lower()]
        except KeyError:
            error_msg("Don't know how to handle %s files" % ext, parent=self)
            return

        renWin = self.vtk_renderer.GetRenderWindow()
        w2i = vtkWindowToImageFilter()
        writer = Writer()
        w2i.SetInput(renWin)
        w2i.Update()
        writer.SetInput(w2i.GetOutput())
        writer.SetFileName(fname)
        renWin.Render()
        writer.Write()

    def back10(self):
        if self.frameNumber - 10 >= 0:
            self.frameNumber -= 10
        else:
            self.frameNumber = 0
        self.redraw_quantities()
        self.update_labels()
        self.pause()

    def back(self):
        if self.frameNumber > 0:
            self.frameNumber -= 1
            self.redraw_quantities()
            self.update_labels()
            self.pause()

    def pauseResume(self):
        if self.paused is True:
            self.resume()
        else:
            self.pause()

    def pause(self):
        self.paused = True
        self.tk_pauseResume.config(text="Resume")

    def resume(self):
        self.paused = False
        self.tk_pauseResume.config(text="Pause")
        self.frameNumber = self.tk_gotoFrame.get()
        self.frameStep = self.tk_frameStep.get()
        self.tk_root.after(self.frameDelay, self.animateForward)

    def forward(self):
        if self.frameNumber < self.maxFrameNumber:
            self.frameNumber += 1
            self.redraw_quantities()
            self.update_labels()
            self.pause()

    def forward_step(self):
        if self.frameNumber + self.frameStep <= self.maxFrameNumber:
            self.frameNumber += self.frameStep
            self.redraw_quantities()
            self.update_labels()
        else:
            self.frameNumber = self.maxFrameNumber
            self.redraw_quantities()
            self.update_labels()
            self.pause()

        if self.movie:
            self.save_image()

    def forward10(self):
        if self.frameNumber + 10 <= self.maxFrameNumber:
            self.frameNumber += 10
        else:
            self.frameNumber = self.maxFrameNumber
        self.redraw_quantities()
        self.update_labels()
        self.pause()

    def animateForward(self):
        if self.paused is not True:
            self.forward_step()
            self.tk_root.after(self.frameDelay, self.animateForward)

    def update_labels(self):
        #self.tk_frameNumber.config(text='%05g of %05g'%(self.frameNumber,self.maxFrameNumber))
        self.tk_gotoFrame.set(self.frameNumber)
        self.tk_frameStep.set(self.frameStep)

    def shutdown(self):
        #self.pause()
        self.tk_root.withdraw()
        self.tk_root.destroy()
예제 #30
0
class SettingWindow(Toplevel):
    def __init__(self, master, max_num_features, num_frames, mser_image):
        Toplevel.__init__(self, master)

        self.protocol('WM_DELETE_WINDOW', self.withdraw)

        self.notebook = ttk.Notebook(self)
        frame_feats = ttk.Frame(self.notebook)
        frame_forest = ttk.Frame(self.notebook)
        frame_mser = ttk.Frame(self.notebook)
        frame_other = ttk.Frame(self.notebook)
        self.notebook.add(frame_feats, text="Features ")
        self.notebook.add(frame_forest, text=" Forest  ")
        self.notebook.add(frame_mser, text=" MSER  ")
        self.notebook.add(frame_other, text=" Other  ")

        self.max_num_feats = max_num_features
        self.selection = None

        self.mser_image = mser_image

        rand_row = random.randint(1, 512-200)
        rand_col = random.randint(1, 512-110)
        self.mser_area = mser_image[rand_row:rand_row+180, rand_col:rand_col+100]

        # read images from icons folder
        self.hf0_img = PhotoImage(file="./icons/hf0.gif")
        self.hf1_img = PhotoImage(file="./icons/hf1.gif")
        self.hf2_img = PhotoImage(file="./icons/hf2.gif")
        self.hf3_img = PhotoImage(file="./icons/hf3.gif")
        self.hf4_img = PhotoImage(file="./icons/hf4.gif")
        self.hf5_img = PhotoImage(file="./icons/hf5.gif")

        self.features_vars = list()
        for i in range(max_num_features):
            self.features_vars.append(IntVar())

        Label(frame_feats, text="Patch size (" + u"\N{GREEK SMALL LETTER PI}" + "):").grid(row=0, column=0, pady=5)
        self.patch_size_spinbox = Spinbox(frame_feats, from_=3, to=30, width=3)
        self.patch_size_spinbox.delete(0, END)
        self.patch_size_spinbox.insert(END, 10)
        self.patch_size_spinbox.grid(row=0, column=1, padx=5)

        f1 = ttk.Labelframe(frame_feats, text='Mean filter')
        f1.grid(row=1, columnspan=2)

        Label(f1, text=u"\N{GREEK SMALL LETTER PI}").grid(row=0, column=0)
        Checkbutton(f1, text="R", variable=self.features_vars[0]).grid(row=0, column=1)
        Checkbutton(f1, text="G", variable=self.features_vars[1]).grid(row=0, column=2)
        Checkbutton(f1, text="B", variable=self.features_vars[2]).grid(row=0, column=3)

        Label(f1, text=u"\N{GREEK SMALL LETTER PI}" + "/2").grid(row=1, column=0)
        Checkbutton(f1, text="R", variable=self.features_vars[3]).grid(row=1, column=1)
        Checkbutton(f1, text="G", variable=self.features_vars[4]).grid(row=1, column=2)
        Checkbutton(f1, text="B", variable=self.features_vars[5]).grid(row=1, column=3)

        f2 = ttk.Labelframe(frame_feats, text="Gaussian filter")
        f2.grid(row=2, columnspan=2)

        Label(f2, text=str(1.0)).grid(row=0, column=0)
        Checkbutton(f2, text="R", variable=self.features_vars[6]).grid(row=0, column=1)
        Checkbutton(f2, text="G", variable=self.features_vars[7]).grid(row=0, column=2)
        Checkbutton(f2, text="B", variable=self.features_vars[8]).grid(row=0, column=3)

        Label(f2, text=str(3.5)).grid(row=1, column=0)
        Checkbutton(f2, text="R", variable=self.features_vars[9]).grid(row=1, column=1)
        Checkbutton(f2, text="G", variable=self.features_vars[10]).grid(row=1, column=2)
        Checkbutton(f2, text="B", variable=self.features_vars[11]).grid(row=1, column=3)

        f3 = ttk.Labelframe(frame_feats, text="Laplacian of gaussian")
        f3.grid(row=3, columnspan=2)

        Label(f3, text=str(2.0)).grid(row=0, column=0)
        Checkbutton(f3, text="R", variable=self.features_vars[12]).grid(row=0, column=1)
        Checkbutton(f3, text="G", variable=self.features_vars[13]).grid(row=0, column=2)
        Checkbutton(f3, text="B", variable=self.features_vars[14]).grid(row=0, column=3)

        Label(f3, text=str(3.5)).grid(row=1, column=0)
        Checkbutton(f3, text="R", variable=self.features_vars[15]).grid(row=1, column=1)
        Checkbutton(f3, text="G", variable=self.features_vars[16]).grid(row=1, column=2)
        Checkbutton(f3, text="B", variable=self.features_vars[17]).grid(row=1, column=3)

        f4 = ttk.Labelframe(frame_feats, text="Haar-like features")
        f4.grid(row=1, rowspan=2, column=3, padx=5)

        Checkbutton(f4, image=self.hf0_img, variable=self.features_vars[18]).grid(row=0, column=0)
        Checkbutton(f4, image=self.hf1_img, variable=self.features_vars[19]).grid(row=0, column=1)
        Checkbutton(f4, image=self.hf2_img, variable=self.features_vars[20]).grid(row=1, column=0)
        Checkbutton(f4, image=self.hf3_img, variable=self.features_vars[21]).grid(row=1, column=1)
        Checkbutton(f4, image=self.hf4_img, variable=self.features_vars[22]).grid(row=2, column=0)
        Checkbutton(f4, image=self.hf5_img, variable=self.features_vars[23]).grid(row=2, column=1)

        buttons_paned_window = PanedWindow(frame_feats, orient=VERTICAL)
        buttons_paned_window.grid(row=3, column=3)

        self.select_all_button = Button(buttons_paned_window, text="Select all", command=self._select_all)
        buttons_paned_window.add(self.select_all_button)

        self.clear_selection_button = Button(buttons_paned_window, text="Clear selection", command=self._clear_selection)
        buttons_paned_window.add(self.clear_selection_button)

        # default values
        for j in [0, 1, 3, 6, 7, 9, 15, 21, 23]:
            self.features_vars[j].set(1)

        # FOREST FRAMES
        # number of trees
        f5 = ttk.Labelframe(frame_forest, text="Number of trees")
        f5.grid(row=0, columnspan=2, pady=5, padx=5)
        Label(f5, text="N").grid(row=1, column=0)
        self.num_trees_scale = Scale(f5, from_=5, to=500, resolution=5, orient=HORIZONTAL)
        self.num_trees_scale.set(300)
        self.num_trees_scale.grid(row=0, column=1, rowspan=2)

        # depth single tree
        f6 = ttk.Labelframe(frame_forest, text="Depth single tree")
        f6.grid(row=1, columnspan=2, pady=5, padx=5)
        Label(f6, text="d").grid(row=1, column=0)
        self.depth_tree_scale = Scale(f6, from_=2, to=20, orient=HORIZONTAL)
        self.depth_tree_scale.set(3)
        self.depth_tree_scale.grid(row=0, column=1, rowspan=2)

        # percentage number of features
        f7 = ttk.Labelframe(frame_forest, text="% subset of features")
        f7.grid(row=2, columnspan=2, pady=5, padx=5)
        Label(f7, text="m").grid(row=1, column=0)
        self.percentage_feats_scale = Scale(f7, from_=0.0, to=1, resolution=0.05, orient=HORIZONTAL)
        self.percentage_feats_scale.set(0.5)
        self.percentage_feats_scale.grid(row=0, column=1, rowspan=2)

        # mser frame
        # delta
        f8 = ttk.Labelframe(frame_mser, text="Delta")
        f8.grid(row=0, columnspan=2, pady=5, padx=5)
        Label(f8, text=u"\N{GREEK SMALL LETTER DELTA}").grid(row=1, column=0)
        self.delta_scale = Scale(f8, from_=1, to=10, resolution=1, orient=HORIZONTAL)
        self.delta_scale.set(2)
        self.delta_scale.grid(row=0, column=1, rowspan=2)

        # min area
        f9 = ttk.Labelframe(frame_mser, text="Minimum area")
        f9.grid(row=1, columnspan=2, pady=5, padx=5)
        Label(f9, text="m").grid(row=1, column=0)
        self.min_area_scale = Scale(f9, from_=2, to=200, orient=HORIZONTAL)
        self.min_area_scale.set(10)
        self.min_area_scale.grid(row=0, column=1, rowspan=2)

        # percentage number of features
        f10 = ttk.Labelframe(frame_mser, text="Maximum area")
        f10.grid(row=2, columnspan=2, pady=5, padx=5)
        Label(f10, text="M").grid(row=1, column=0)
        self.max_area_scale = Scale(f10, from_=50, to=1000, resolution=5, orient=HORIZONTAL)
        self.max_area_scale.set(350)
        self.max_area_scale.grid(row=0, column=1, rowspan=2)

        # mser image
        f11 = ttk.Labelframe(frame_mser)
        f11.grid(row=0, rowspan=3, column=2, padx=5)

        self.mser_img_array = Image.fromarray(self.mser_area, "RGB")
        self.mser_img = ImageTk.PhotoImage(self.mser_img_array)

        img_label = Label(f11, image=self.mser_img)
        img_label.grid(row=0, column=0)

        buttons_p_w_mser = PanedWindow(f11, orient=HORIZONTAL)
        try_button = Button(f11, text="Try", command=self.try_mser)
        buttons_p_w_mser.add(try_button)
        change_button = Button(f11, text="New img", command=self.change_mser)
        buttons_p_w_mser.add(change_button)
        buttons_p_w_mser.grid(row=1, column=0)

        # other frame
        f12 = ttk.Labelframe(frame_other, text="Refinement")
        f12.grid(row=0, columnspan=2, pady=5, padx=5)
        Label(f12, text=u"\N{GREEK CAPITAL LETTER PHI}_l").grid(row=1, column=0)
        self.low_thresh_scale = Scale(f12, from_=0, to=1, resolution=0.05, orient=HORIZONTAL, length=90)
        self.low_thresh_scale.set(0.45)
        self.low_thresh_scale.grid(row=0, column=1, rowspan=2)
        Label(f12, text=u"\N{GREEK CAPITAL LETTER PHI}_h").grid(row=3, column=0)
        self.high_thresh_scale = Scale(f12, from_=0, to=1, resolution=0.05, orient=HORIZONTAL, length=90)
        self.high_thresh_scale.set(0.65)
        self.high_thresh_scale.grid(row=2, column=1, rowspan=2)

        f13 = ttk.Labelframe(frame_other, text="Dots distance")
        f13.grid(row=1, columnspan=2, pady=5, padx=5)
        Label(f13, text=u"     \N{GREEK SMALL LETTER SIGMA}").grid(row=1, column=0)
        self.dots_distance_scale = Scale(f13, from_=1, to=20, resolution=1, orient=HORIZONTAL, length=90)
        self.dots_distance_scale.set(6)
        self.dots_distance_scale.grid(row=0, column=1, rowspan=2)

        f14 = ttk.Labelframe(frame_other, text="Tracks")
        f14.grid(row=0, column=3, pady=5, padx=5)
        Label(f14, text="N").grid(row=1, column=0)
        self.num_frames_tracks_spinbox = Spinbox(f14, from_=2, to=num_frames, width=10)
        self.num_frames_tracks_spinbox.delete(0, END)
        self.num_frames_tracks_spinbox.insert(END, num_frames)
        self.num_frames_tracks_spinbox.grid(row=0, column=1, rowspan=2)

        Label(f14, text=u"\N{GREEK SMALL LETTER TAU}").grid(row=3, column=0)
        self.gaps_scale = Scale(f14, from_=1, to=10, resolution=1, orient=HORIZONTAL, length=90)
        self.gaps_scale.set(2)
        self.gaps_scale.grid(row=2, column=1, rowspan=2)

        self.notebook.pack(padx=1, pady=1)

        save_button = Button(self, text=" Save and Close window ", command=self.withdraw)
        save_button.pack(pady=2)

    def _select_all(self):
        for i, var in enumerate(self.features_vars):
            var.set(1)

    def _clear_selection(self):
        for i, var in enumerate(self.features_vars):
            var.set(0)

    def change_mser(self):
        rand_row = random.randint(1, 512-200)
        rand_col = random.randint(1, 512-110)
        self.mser_area = self.mser_image[rand_row:rand_row+180, rand_col:rand_col+100]

        self.update_mser_image(self.mser_area)

    def try_mser(self):
        delta = self.delta_scale.get()
        min_area = self.min_area_scale.get()
        max_area = self.max_area_scale.get()

        image = self.mser_area
        red_c = image[:,:,0]
        red_c = cv2.equalizeHist(red_c)

        det_img = image.copy()

        mser = cv2.MSER(delta, _min_area=min_area, _max_area=max_area)
        regions = mser.detect(red_c)
        cp = list()
        new_c = np.zeros(self.mser_area.shape, dtype=np.uint8)
        for r in regions:
            for point in r:
                cp.append(point)
                det_img[point[1], point[0], 0] = 0
                det_img[point[1], point[0], 1] = 0
                det_img[point[1], point[0], 2] = 204
                #new_c[point[1], point[0]] = 255

        self.update_mser_image(det_img)

    def update_mser_image(self, new_image):
        self.mser_img_array = Image.fromarray(new_image)
        self.mser_img.paste(self.mser_img_array)

    def get_patch_size(self):
        patch_size = self.patch_size_spinbox.get()
        return int(patch_size)

    def get_num_frames_tracks(self):
        num_frames_tracks = self.num_frames_tracks_spinbox.get()
        return int(num_frames_tracks)

    def get_mser_opts(self):
        return [self.delta_scale.get(), self.min_area_scale.get(), self.max_area_scale.get()]

    def get_forest_opts(self):
        return [self.num_trees_scale.get(), self.depth_tree_scale.get(), self.percentage_feats_scale.get()]

    def get_low_thresh(self):
        return self.low_thresh_scale.get()

    def get_high_thresh(self):
        return self.high_thresh_scale.get()

    def get_dots_distance(self):
        return int(self.dots_distance_scale.get())

    def get_selection_mask(self):
        if self.selection is not None:
            return self.selection

        selection_mask = np.zeros((self.max_num_feats, ), dtype='bool')
        for i, var in enumerate(self.features_vars):
            selection_mask[i] = var.get()
        self.selection = selection_mask
        return selection_mask
예제 #31
0
                    relief=FLAT)
coulombInput = Scale(root,
                     from_=1,
                     to=1000,
                     orient=HORIZONTAL,
                     label="Coulomb",
                     relief=FLAT)
decayInput = Scale(root,
                   from_=0,
                   to=100,
                   orient=HORIZONTAL,
                   label="Decay",
                   relief=FLAT)

#Sets initial FDL constant values
timeInput.set(100)
springInput.set(250)
coulombInput.set(500)
decayInput.set(90)

#Initializes the canvas for animation
canvas = Canvas(width=width, height=height, bg="#f0f0f0")
canvas.pack(fill="both", expand=1, padx=50)

#Adds teh sliders to the tkinter frame after the canvas for positioning
timeInput.pack(side=LEFT, padx=50, pady=10)
springInput.pack(side=LEFT, padx=50, pady=10)
coulombInput.pack(side=LEFT, padx=50, pady=10)
decayInput.pack(side=LEFT, padx=50, pady=10)

#Smallest node size in pixels
spd = 50


def changeSpeed(ev=None):
    tmp = 'speed'
    global spd
    spd = speed.get()
    data = tmp + str(
        spd
    )  # Change the integers into strings and combine them with the string 'speed'.
    print 'sendData = %s' % data
    tcpCliSock.send(data)  # Send the speed data to the server(Raspberry Pi)


label = Label(top, text='Speed:', fg='red')  # Create a label
label.grid(row=6, column=0)  # Label layout

speed = Scale(top, from_=0, to=100, orient=HORIZONTAL,
              command=changeSpeed)  # Create a scale
speed.set(50)
speed.grid(row=6, column=1)


def main():
    top.mainloop()


if __name__ == '__main__':
    main()
예제 #33
0
class Cockpit(ttkFrame):
    '''
    Remote device GUI 
    '''

    #TODO: 20160415 DPM - Set these values from configuration file
    #--- config
    THROTTLE_BY_USER = True
    THROTTLE_RESOLUTION = 0.1

    # Joystick enabled or not, if any
    JOYSTICK_ENABLED = True

    DEFAULT_DRONE_IP = "192.168.1.130"
    DEFAULT_DRONE_PORT = 2121
    #--- end config

    KEY_ANG_SPEED = "ang-speed"
    KEY_ANGLES = "angles"
    KEY_ACCEL = "accel"

    PID_KEYS = ["P", "I", "D"]

    DIR_NONE = 0
    DIR_VERTICAL = 1
    DIR_HORIZONTAL = 2

    def __init__(self,
                 parent,
                 isDummy=False,
                 droneIp=DEFAULT_DRONE_IP,
                 dronePort=DEFAULT_DRONE_PORT):
        '''
        Constructor
        '''
        ttkFrame.__init__(self, parent)

        self._target = [0.0] * 4

        self._selectedPidConstats = "--"
        self._pidConstants = {
            Cockpit.KEY_ANG_SPEED: {
                "X": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                },
                "Y": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                },
                "Z": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                }
            },
            Cockpit.KEY_ANGLES: {
                "X": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                },
                "Y": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                }
            },
            Cockpit.KEY_ACCEL: {
                "X": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                },
                "Y": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                },
                "Z": {
                    "P": 0.0,
                    "I": 0.0,
                    "D": 0.0
                }
            }
        }

        self.parent = parent

        self.initUI()

        self._controlKeysLocked = False

        if not isDummy:
            self._link = INetLink(droneIp, dronePort)
        else:
            self._link = ConsoleLink()

        self._link.open()

        self._updateInfoThread = Thread(target=self._updateInfo)
        self._updateInfoThreadRunning = False
        self._readingState = False

        self._start()

    def initUI(self):

        self.parent.title("Drone control")
        self.style = Style()
        self.style.theme_use("default")

        self.pack(fill=BOTH, expand=1)

        self.parent.bind_all("<Key>", self._keyDown)
        self.parent.bind_all("<KeyRelease>", self._keyUp)

        if system() == "Linux":
            self.parent.bind_all("<Button-4>", self._onMouseWheelUp)
            self.parent.bind_all("<Button-5>", self._onMouseWheelDown)

        else:
            #case of Windows
            self.parent.bind_all("<MouseWheel>", self._onMouseWheel)

        #Commands
        commandsFrame = tkFrame(self)
        commandsFrame.grid(column=0, row=0, sticky="WE")

        self._started = IntVar()
        self._startedCB = Checkbutton(commandsFrame,
                                      text="On",
                                      variable=self._started,
                                      command=self._startedCBChanged)
        self._startedCB.pack(side=LEFT, padx=4)

        #         self._integralsCB = Checkbutton(commandsFrame, text="Int.", variable=self._integralsEnabled, \
        #                                         command=self._integralsCBChanged, state=DISABLED)
        #         self._integralsCB.pack(side=LEFT, padx=4)

        self._quitButton = Button(commandsFrame,
                                  text="Quit",
                                  command=self.exit)
        self._quitButton.pack(side=LEFT, padx=2, pady=2)

        #         self._angleLbl = Label(commandsFrame, text="Angle")
        #         self._angleLbl.pack(side=LEFT, padx=4)
        #
        #         self._angleEntry = Entry(commandsFrame, state=DISABLED)
        #         self._angleEntry.pack(side=LEFT)

        #Info
        infoFrame = tkFrame(self)
        infoFrame.grid(column=1, row=1, sticky="NE", padx=4)

        #Throttle
        Label(infoFrame, text="Throttle").grid(column=0, row=0, sticky="WE")
        self._throttleTexts = [
            StringVar(), StringVar(),
            StringVar(), StringVar()
        ]
        Entry(infoFrame,
              textvariable=self._throttleTexts[3],
              state=DISABLED,
              width=5).grid(column=0, row=1)
        Entry(infoFrame,
              textvariable=self._throttleTexts[0],
              state=DISABLED,
              width=5).grid(column=1, row=1)
        Entry(infoFrame,
              textvariable=self._throttleTexts[2],
              state=DISABLED,
              width=5).grid(column=0, row=2)
        Entry(infoFrame,
              textvariable=self._throttleTexts[1],
              state=DISABLED,
              width=5).grid(column=1, row=2)

        #Angles
        Label(infoFrame, text="Angles").grid(column=0, row=3, sticky="WE")
        self._angleTexts = [StringVar(), StringVar(), StringVar()]
        for index in range(3):
            Entry(infoFrame,
                  textvariable=self._angleTexts[index],
                  state=DISABLED,
                  width=5).grid(column=index, row=4)

        #Accels
        Label(infoFrame, text="Accels").grid(column=0, row=5, sticky="WE")
        self._accelTexts = [StringVar(), StringVar(), StringVar()]
        for index in range(3):
            Entry(infoFrame,
                  textvariable=self._accelTexts[index],
                  state=DISABLED,
                  width=5).grid(column=index, row=6)

        #Speeds
        Label(infoFrame, text="Speeds").grid(column=0, row=7, sticky="WE")
        self._speedTexts = [StringVar(), StringVar(), StringVar()]
        for index in range(3):
            Entry(infoFrame,
                  textvariable=self._speedTexts[index],
                  state=DISABLED,
                  width=5).grid(column=index, row=8)

        #Height
        Label(infoFrame, text="Height").grid(column=0, row=9, sticky="E")
        self._heightText = StringVar()
        Entry(infoFrame,
              textvariable=self._heightText,
              state=DISABLED,
              width=5).grid(column=1, row=9)

        #Loop rate
        Label(infoFrame, text="Loop @").grid(column=0, row=10, sticky="E")
        self._loopRateText = StringVar()
        Entry(infoFrame,
              textvariable=self._loopRateText,
              state=DISABLED,
              width=5).grid(column=1, row=10)
        Label(infoFrame, text="Hz").grid(column=2, row=10, sticky="W")

        #control

        controlFrame = tkFrame(self)
        controlFrame.grid(column=0, row=1, sticky="W")

        self._throttle = DoubleVar()

        if Cockpit.THROTTLE_BY_USER:

            self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=0.0, \
                                tickinterval=0, variable=self._throttle, resolution=Cockpit.THROTTLE_RESOLUTION, \
                                length=200, showvalue=1, \
                                state=DISABLED,
                                command=self._onThrustScaleChanged)

        else:

            self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=-100.0, \
                                tickinterval=0, variable=self._throttle, \
                                length=200, showvalue=1, \
                                state=DISABLED,
                                command=self._onThrustScaleChanged)

        self._thrustScale.bind("<Double-Button-1>",
                               self._onThrustScaleDoubleButton1, "+")
        self._thrustScale.grid(column=0)

        self._shiftCanvas = Canvas(controlFrame, bg="white", height=400, width=400, \
                             relief=SUNKEN)
        self._shiftCanvas.bind("<Button-1>", self._onMouseButton1)
        #self._shiftCanvas.bind("<ButtonRelease-1>", self._onMouseButtonRelease1)
        self._shiftCanvas.bind("<B1-Motion>", self._onMouseButton1Motion)
        self._shiftCanvas.bind("<Double-Button-1>", self._onMouseDoubleButton1)

        self._shiftCanvas.bind("<Button-3>", self._onMouseButton3)
        #self._shiftCanvas.bind("<ButtonRelease-3>", self._onMouseButtonRelease3)
        self._shiftCanvas.bind("<B3-Motion>", self._onMouseButton3Motion)

        self._shiftCanvas.grid(row=0, column=1, padx=2, pady=2)
        self._shiftCanvas.create_oval(1, 1, 400, 400, outline="#ff0000")
        self._shiftCanvas.create_line(200, 2, 200, 400, fill="#ff0000")
        self._shiftCanvas.create_line(2, 200, 400, 200, fill="#ff0000")
        self._shiftMarker = self._shiftCanvas.create_oval(196,
                                                          196,
                                                          204,
                                                          204,
                                                          outline="#0000ff",
                                                          fill="#0000ff")

        self._yaw = DoubleVar()
        self._yawScale = Scale(controlFrame, orient=HORIZONTAL, from_=-100.0, to=100.0, \
                            tickinterval=0, variable=self._yaw, \
                            length=200, showvalue=1, \
                            command=self._onYawScaleChanged)
        self._yawScale.bind("<Double-Button-1>", self._onYawScaleDoubleButton1,
                            "+")
        self._yawScale.grid(row=1, column=1)

        self._controlKeyActive = False

        #PID calibration

        pidCalibrationFrame = tkFrame(self)
        pidCalibrationFrame.grid(column=0, row=2, sticky="WE")

        self._pidSelected = StringVar()
        self._pidSelected.set("--")
        self._pidListBox = OptionMenu(pidCalibrationFrame, self._pidSelected, "--", \
                                      Cockpit.KEY_ANG_SPEED, Cockpit.KEY_ANGLES, Cockpit.KEY_ACCEL, \
                                       command=self._onPidListBoxChanged)
        self._pidListBox.pack(side=LEFT, padx=2)
        self._pidListBox.config(width=10)

        self._axisSelected = StringVar()
        self._axisSelected.set("--")
        self._axisListBox = OptionMenu(pidCalibrationFrame, self._axisSelected, "--", "X", "Y", "Z", \
                                       command=self._onAxisListBoxChanged)
        self._axisListBox.pack(side=LEFT, padx=2)
        self._axisListBox.config(state=DISABLED)

        Label(pidCalibrationFrame, text="P").pack(side=LEFT, padx=(14, 2))

        self._pidPString = StringVar()
        self._pidPString.set("0.00")
        self._pidPSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidPString, command=self._onPidSpinboxChanged)
        self._pidPSpinbox.pack(side=LEFT, padx=2)

        Label(pidCalibrationFrame, text="I").pack(side=LEFT, padx=(14, 2))

        self._pidIString = StringVar()
        self._pidIString.set("0.00")
        self._pidISpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidIString, command=self._onPidSpinboxChanged)
        self._pidISpinbox.pack(side=LEFT, padx=2)

        Label(pidCalibrationFrame, text="D").pack(side=LEFT, padx=(14, 2))

        self._pidDString = StringVar()
        self._pidDString.set("0.00")
        self._pidDSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \
                                         textvariable=self._pidDString, command=self._onPidSpinboxChanged)
        self._pidDSpinbox.pack(side=LEFT, padx=2)

        #debug
        debugFrame = tkFrame(self)
        debugFrame.grid(column=0, row=3, sticky="WE")

        self._debugMsg = Message(debugFrame,
                                 anchor="nw",
                                 justify=LEFT,
                                 relief=SUNKEN,
                                 width=300)
        self._debugMsg.pack(fill=BOTH, expand=1)

    def _start(self):

        self._readDroneConfig()

        if Cockpit.JOYSTICK_ENABLED:
            self._joystickManager = JoystickManager.getInstance()
            self._joystickManager.start()

            joysticks = self._joystickManager.getJoysticks()
            if len(joysticks) != 0:
                self._joystick = joysticks[0]
                self._joystick.onAxisChanged += self._onJoystickAxisChanged
                self._joystick.onButtonPressed += self._onJoystickButtonPressed
            else:
                self._joystick = None

    def _onJoystickAxisChanged(self, sender, index):

        if self._started.get() and sender == self._joystick:

            axisValue = self._joystick.getAxisValue(index)

            if index == 0:

                self._yaw.set(axisValue)
                self._updateTarget()

            elif index == 1 and not Cockpit.THROTTLE_BY_USER:

                thrust = -axisValue
                self._throttle.set(thrust)
                self._updateTarget()

            elif index == 2 and Cockpit.THROTTLE_BY_USER:

                rowThrottle = (axisValue + 100.0) / 2.0
                if rowThrottle < 10.0:
                    throttle = rowThrottle * 6.0
                elif rowThrottle < 90.0:
                    throttle = 60.0 + ((rowThrottle - 10.0) / 8.0)
                else:
                    throttle = 70.0 + (rowThrottle - 90.0) * 3.0
                self._throttle.set(throttle)
                self._sendThrottle()

            elif index == 3:

                x = 196 + axisValue * 2
                lastCoords = self._shiftCanvas.coords(self._shiftMarker)
                coords = (x, lastCoords[1])
                self._plotShiftCanvasMarker(coords)

            elif index == 4:

                y = 196 + axisValue * 2
                lastCoords = self._shiftCanvas.coords(self._shiftMarker)
                coords = (lastCoords[0], y)
                self._plotShiftCanvasMarker(coords)

    def _onJoystickButtonPressed(self, sender, index):

        if sender == self._joystick and index == 7:

            if self._started.get() == 0:
                self._startedCB.select()
            else:
                self._startedCB.deselect()

            # Tkinter's widgets seem not to be calling the event-handler
            # when they are changed programmatically. Therefore, the
            # even-handler is called explicitly here.
            self._startedCBChanged()

    def exit(self):

        self._link.send({"key": "close", "data": None})

        self._stopUpdateInfoThread()

        self._link.close()

        if Cockpit.JOYSTICK_ENABLED:
            self._joystickManager.stop()

        self.quit()

    def _updateTarget(self):

        markerCoords = self._shiftCanvas.coords(self._shiftMarker)
        coords = ((markerCoords[0] + markerCoords[2]) / 2,
                  (markerCoords[1] + markerCoords[3]) / 2)

        self._target[0] = float(
            coords[1] - 200) / 2.0  # X-axis angle / X-axis acceleration
        self._target[1] = float(
            coords[0] - 200) / 2.0  # Y-axis angle / Y-axis acceleration
        #Remote control uses clockwise angle, but the drone's referece system uses counter-clockwise angle
        self._target[2] = -self._yaw.get()  # Z-axis angular speed

        # Z-axis acceleration (thrust). Only when the motor throttle is not controlled by user directly
        if Cockpit.THROTTLE_BY_USER:
            self._target[3] = 0.0
        else:
            self._target[3] = self._throttle.get()

        self._sendTarget()

    def _keyDown(self, event):

        if event.keysym == "Escape":
            self._throttle.set(0)
            self._started.set(0)
            self._thrustScale.config(state=DISABLED)
            self._stopUpdateInfoThread()
            self._sendIsStarted()

        elif event.keysym.startswith("Control"):
            self._controlKeyActive = True

        elif not self._controlKeysLocked and self._controlKeyActive:

            if event.keysym == "Up":
                self._thrustScaleUp()

            elif event.keysym == "Down":
                self._thrustScaleDown()

            elif event.keysym == "Left":
                self._yawLeft()

            elif event.keysym == "Right":
                self._yawRight()

            elif event.keysym == "space":
                self._yawReset()
                if not Cockpit.THROTTLE_BY_USER:
                    self._thrustReset()

        elif not self._controlKeysLocked and not self._controlKeyActive:

            if event.keysym == "Up":
                self._moveShiftCanvasMarker((0, -5))

            elif event.keysym == "Down":
                self._moveShiftCanvasMarker((0, 5))

            elif event.keysym == "Left":
                self._moveShiftCanvasMarker((-5, 0))

            elif event.keysym == "Right":
                self._moveShiftCanvasMarker((5, 0))

            elif event.keysym == "space":
                self._resetShiftCanvasMarker()

    def _keyUp(self, eventArgs):

        if eventArgs.keysym.startswith("Control"):
            self._controlKeyActive = False

    def _onMouseButton1(self, eventArgs):

        self._lastMouseCoords = (eventArgs.x, eventArgs.y)

    def _onMouseButtonRelease1(self, eventArgs):

        self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204)

    def _limitCoordsToSize(self, coords, size, width):

        maxSize = size - (width / 2.0)
        minSize = -(width / 2.0)

        if coords[0] > maxSize:
            x = maxSize

        elif coords[0] < minSize:
            x = minSize

        else:
            x = coords[0]

        if coords[1] > maxSize:
            y = maxSize

        elif coords[1] < minSize:
            y = minSize

        else:
            y = coords[1]

        return (x, y)

    def _plotShiftCanvasMarker(self, coords):

        coords = self._limitCoordsToSize(coords, 400, 8)
        self._shiftCanvas.coords(self._shiftMarker, coords[0], coords[1],
                                 coords[0] + 8, coords[1] + 8)
        self._updateTarget()

    def _moveShiftCanvasMarker(self, shift):

        lastCoords = self._shiftCanvas.coords(self._shiftMarker)
        newCoords = (lastCoords[0] + shift[0], lastCoords[1] + shift[1])
        self._plotShiftCanvasMarker(newCoords)

    def _resetShiftCanvasMarker(self):

        self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204)
        self._updateTarget()

    def _onMouseButton1Motion(self, eventArgs):

        deltaCoords = (eventArgs.x - self._lastMouseCoords[0],
                       eventArgs.y - self._lastMouseCoords[1])
        self._moveShiftCanvasMarker(deltaCoords)
        self._lastMouseCoords = (eventArgs.x, eventArgs.y)

    def _onMouseDoubleButton1(self, eventArgs):

        self._resetShiftCanvasMarker()

    def _onMouseButton3(self, eventArgs):

        self._lastMouseCoords = (eventArgs.x, eventArgs.y)
        self._mouseDirection = Cockpit.DIR_NONE

    def _onMouseButtonRelease3(self, eventArgs):

        self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204)

    def _onMouseButton3Motion(self, eventArgs):

        deltaCoords = (eventArgs.x - self._lastMouseCoords[0],
                       eventArgs.y - self._lastMouseCoords[1])

        if self._mouseDirection == Cockpit.DIR_NONE:
            if abs(deltaCoords[0]) > abs(deltaCoords[1]):
                self._mouseDirection = Cockpit.DIR_HORIZONTAL
            else:
                self._mouseDirection = Cockpit.DIR_VERTICAL

        if self._mouseDirection == Cockpit.DIR_HORIZONTAL:
            deltaCoords = (deltaCoords[0], 0)
        else:
            deltaCoords = (0, deltaCoords[1])

        self._moveShiftCanvasMarker(deltaCoords)
        self._lastMouseCoords = (eventArgs.x, eventArgs.y)

    def _thrustScaleUp(self):

        #TODO: 20160526 DPM: El valor de incremento de aceleración (1.0) puede ser muy alto
        if self._started.get():
            newValue = self._thrustScale.get() \
                + (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0)
            self._thrustScale.set(newValue)

            self._updateTarget()

    def _thrustScaleDown(self):

        #TODO: 20160526 DPM: El valor de decremento de aceleración (1.0) puede ser muy alto
        if self._started.get():
            newValue = self._thrustScale.get() \
                - (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0)
            self._thrustScale.set(newValue)

            self._updateTarget()

    def _thrustReset(self):

        if self._started.get():
            self._thrustScale.set(0.0)

            self._updateTarget()

    def _onThrustScaleDoubleButton1(self, eventArgs):

        self._thrustReset()

        return "break"

    def _yawRight(self):

        newValue = self._yaw.get() + 1
        self._yaw.set(newValue)
        self._updateTarget()

    def _yawLeft(self):

        newValue = self._yaw.get() - 1
        self._yaw.set(newValue)
        self._updateTarget()

    def _yawReset(self):

        self._yaw.set(0)
        self._updateTarget()

    def _onMouseWheelUp(self, eventArgs):

        if not self._controlKeyActive:
            self._thrustScaleUp()

        else:
            self._yawRight()

    def _onMouseWheelDown(self, eventArgs):

        if not self._controlKeyActive:
            self._thrustScaleDown()

        else:
            self._yawLeft()

    def _onMouseWheel(self, eventArgs):

        factor = eventArgs.delta / (1200.0 if Cockpit.THROTTLE_BY_USER
                                    and not self._controlKeyActive else 120.0)

        if not self._controlKeyActive:

            if self._started.get():
                newValue = self._thrustScale.get() + factor
                self._thrustScale.set(newValue)

                self._updateTarget()
        else:
            newValue = self._yaw.get() + factor
            self._yaw.set(newValue)
            self._updateTarget()

    def _onYawScaleChanged(self, eventArgs):

        self._updateTarget()

    def _onYawScaleDoubleButton1(self, eventArgs):

        self._yawReset()

        return "break"

    def _startedCBChanged(self):

        if not self._started.get():
            self._throttle.set(0)
            self._thrustScale.config(state=DISABLED)
            #self._integralsCB.config(state=DISABLED)
            self._stopUpdateInfoThread()
        else:
            self._thrustScale.config(state="normal")
            #self._integralsCB.config(state="normal")
            self._startUpdateInfoThread()

        self._sendIsStarted()

#     def _integralsCBChanged(self):
#
#         self._link.send({"key": "integrals", "data":self._integralsEnabled.get() != 0})
#

    def _onThrustScaleChanged(self, eventArgs):

        if Cockpit.THROTTLE_BY_USER:

            self._sendThrottle()

        else:

            self._updateTarget()

    def _sendThrottle(self):

        self._link.send({"key": "throttle", "data": self._throttle.get()})

    def _sendTarget(self):

        self._link.send({"key": "target", "data": self._target})

    def _sendIsStarted(self):

        isStarted = self._started.get() != 0
        self._link.send({"key": "is-started", "data": isStarted})

    def _sendPidCalibrationData(self):

        if self._pidSelected.get() != "--" and self._axisSelected.get(
        ) != "--":

            pidData = {
                "pid": self._pidSelected.get(),
                "axis": self._axisSelected.get(),
                "p": float(self._pidPSpinbox.get()),
                "i": float(self._pidISpinbox.get()),
                "d": float(self._pidDSpinbox.get())
            }

            self._link.send({"key": "pid-calibration", "data": pidData})

    def _updatePidCalibrationData(self):

        pid = self._pidSelected.get()
        axis = self._axisSelected.get()

        if pid != "--" and axis != "--":

            self._pidConstants[pid][axis]["P"] = float(self._pidPSpinbox.get())
            self._pidConstants[pid][axis]["I"] = float(self._pidISpinbox.get())
            self._pidConstants[pid][axis]["D"] = float(self._pidDSpinbox.get())

    def _readDroneConfig(self):

        self._link.send({
            "key": "read-drone-config",
            "data": None
        }, self._onDroneConfigRead)

    def _readDroneState(self):

        if not self._readingState:
            self._readingState = True
            self._link.send({
                "key": "read-drone-state",
                "data": None
            }, self._onDroneStateRead)

    def _readPidConfigItem(self, message, cockpitKey, axises, configKeys):

        for i in range(len(axises)):
            for j in range(len(Cockpit.PID_KEYS)):
                self._pidConstants[cockpitKey][axises[i]][
                    Cockpit.PID_KEYS[j]] = message[configKeys[j]][i]

    def _onDroneConfigRead(self, message):

        #TODO Show current configuration within the GUI (at least relevant settings)
        if message:

            #Angle-speeds
            self._readPidConfigItem(message, Cockpit.KEY_ANG_SPEED, ["X", "Y", "Z"], \
                                    [Configuration.PID_ANGLES_SPEED_KP, \
                                     Configuration.PID_ANGLES_SPEED_KI, \
                                     Configuration.PID_ANGLES_SPEED_KD])

            #Angles
            self._readPidConfigItem(message, Cockpit.KEY_ANGLES, ["X", "Y"], \
                                    [Configuration.PID_ANGLES_KP, \
                                     Configuration.PID_ANGLES_KI, \
                                     Configuration.PID_ANGLES_KD])

            #Accels
            self._readPidConfigItem(message, Cockpit.KEY_ACCEL, ["X", "Y", "Z"], \
                                    [Configuration.PID_ACCEL_KP, \
                                     Configuration.PID_ACCEL_KI, \
                                     Configuration.PID_ACCEL_KD])

    def _onDroneStateRead(self, state):

        if state:

            for index in range(4):
                self._throttleTexts[index].set("{0:.3f}".format(
                    state["_throttles"][index]))

            for index in range(3):
                self._accelTexts[index].set("{0:.3f}".format(
                    state["_accels"][index]))
                self._angleTexts[index].set("{0:.3f}".format(
                    state["_angles"][index]))

            currentPeriod = state["_currentPeriod"]
            if currentPeriod > 0.0:

                freq = 1.0 / currentPeriod
                self._loopRateText.set("{0:.3f}".format(freq))

            else:
                self._loopRateText.set("--")

        else:
            self._stopUpdateInfoThread()

        self._readingState = False

    def _onPidSpinboxChanged(self):

        self._updatePidCalibrationData()
        self._sendPidCalibrationData()

    def _onPidListBoxChanged(self, pid):

        self._axisSelected.set("--")

        self._pidPString.set("--")
        self._pidIString.set("--")
        self._pidDString.set("--")

        self._pidPSpinbox.config(state=DISABLED)
        self._pidISpinbox.config(state=DISABLED)
        self._pidDSpinbox.config(state=DISABLED)

        self._selectedPidConstats = pid

        if pid == "--":
            self._axisListBox.config(state=DISABLED)
            self._controlKeysLocked = False

        else:
            self._axisListBox.config(state="normal")
            self._controlKeysLocked = True

    def _onAxisListBoxChanged(self, axis):

        if axis == "--" or (self._selectedPidConstats == Cockpit.KEY_ANGLES
                            and axis == "Z"):

            self._pidPString.set("--")
            self._pidIString.set("--")
            self._pidDString.set("--")

            self._pidPSpinbox.config(state=DISABLED)
            self._pidISpinbox.config(state=DISABLED)
            self._pidDSpinbox.config(state=DISABLED)

            self._controlKeysLocked = axis != "--"

        else:

            self._pidPString.set("{:.2f}".format(
                self._pidConstants[self._selectedPidConstats][axis]["P"]))
            self._pidIString.set("{:.2f}".format(
                self._pidConstants[self._selectedPidConstats][axis]["I"]))
            self._pidDString.set("{:.2f}".format(
                self._pidConstants[self._selectedPidConstats][axis]["D"]))

            self._pidPSpinbox.config(state="normal")
            self._pidISpinbox.config(state="normal")
            self._pidDSpinbox.config(state="normal")

            self._controlKeysLocked = True

    def _updateInfo(self):

        while self._updateInfoThreadRunning:

            self._readDroneState()

            time.sleep(1.0)

    def _startUpdateInfoThread(self):

        self._updateInfoThreadRunning = True
        if not self._updateInfoThread.isAlive():
            self._updateInfoThread.start()

    def _stopUpdateInfoThread(self):

        self._updateInfoThreadRunning = False
        if self._updateInfoThread.isAlive():
            self._updateInfoThread.join()
예제 #34
0
class VRConfigDialog(Dialog):
    """
    Defines a custom dialog for editing the Virtual Reality params
    """
    def __init__(self, parent, populator=None, manager=None):
        """
        Construct the dialog
        """
        self._entries = {
            "frame_angle"    : None,
            "distortion"     : False,
            "windowed"      : False,
            "eye_height"     : None,
            "minimum_dist_to_wall"  : None

        }
        self._win_var = IntVar(0)
        self._distortion_var = IntVar(0)
        Dialog.__init__(self, parent=parent, title="VRConfiguration", populator=populator, manager=manager)

    def body(self, parent):
        """
        Overridden method defining the body of the dialog
        :param parent:
        :return:
        """

        # Define all of the labels for our options
        Label(parent, text="Frame Angle:", padx=3, anchor=SW, height=2).grid(row=0, column=0, sticky=W)
        Label(parent, text="Eye Height:", padx=3, anchor=SW, height=2).grid(row=1, column=0, pady=2, sticky=W )
        Label(parent, text="MinDistToWall:", padx=3, anchor=SW, height=2).grid(row=2, column=0, pady=2,  sticky=W)
        Label(parent, text="Distortion:", padx=3).grid(row=3, column=0, pady=2, sticky=W)
        Label(parent, text="Windowed:", padx=3).grid(row=4, column=0, pady=2, sticky=W)

        # Define the sub-widgets that the labels are referring to
        self._frameAngle = Scale(parent, from_=-20, to=20, orient=HORIZONTAL)
        if self._entries["frame_angle"] is not None:
            self._frameAngle.set(self._entries["frame_angle"])
        else:
            self._frameAngle.set(-5)
        self._frameAngle.grid(row=0, column=1, padx=3)

        self._eyeHeight = Scale(parent, from_=0, to=500, orient=HORIZONTAL)
        if self._entries["eye_height"] is not None:
            self._eyeHeight.set( self._entries["eye_height"] )
        else:
            self._eyeHeight.set(50)
        self._eyeHeight.grid(row=1, column=1, padx=3)

        self._minDistToWall = Scale(parent, from_=1, to=300, orient=HORIZONTAL)
        if self._entries["minimum_dist_to_wall"] is not None:
            self._minDistToWall.set( self._entries["minimum_dist_to_wall"] )
        else:
            self._minDistToWall.set(20)
        self._minDistToWall.grid(row=2, column=1, padx=3)

        self._distortion = Checkbutton(parent, variable=self._distortion_var, offvalue=0, onvalue=1, text="Enable", command=self._toggle_distortion)
        self._distortion.grid(row=3, column=1, padx=3)

        self._windowed = Checkbutton(parent, variable=self._win_var, offvalue=0, onvalue=1, text="Enable", command=self._toggle_windowed)
        self._windowed.grid(row=4, column=1, padx=3)

    def _toggle_distortion(self):
        """
        Toggle the distortion flag
        :return:
        """
        self._distortion_var.set(0 if self._distortion_var.get() == 1 else 1)
        val = self._entries["distortion"]
        self._entries["distortion"] = not val
        Debug.printi("Distortion toggled to " + (str(not val)), Debug.Level.INFO)
        self._distortion.toggle()

    def _toggle_windowed(self):
        """
        Toggle the windowed flag
        :return:
        """
        self._win_var.set(0 if self._win_var.get() == 1 else 1)
        val = self._entries["windowed"]
        self._entries["windowed"] = not val
        Debug.printi("Windowing toggled to " + (str(not val)), Debug.Level.INFO)
        self._windowed.toggle()

    def populate(self, manager):
        self._entries["frame_angle"]            = manager.frame_angle
        self._entries["distortion"]             = manager.distortion
        self._entries["windowed"]               = manager.windowed
        self._entries["eye_height"]             = manager.eye_height
        self._entries["minimum_dist_to_wall"]   = manager.minimum_dist_to_wall
        self._win_var.set( 0 if manager.windowed is False else 1 )
        self._distortion_var.set( 0 if manager.distortion is False else 1 )

    def validate(self):
        (result, message) = DataValidator.validate(DataStore.EVENT.VR_EDIT, self._entries)
        if result is not True:
            tkMessageBox.showerror("Input Error", message)
        return result

    def apply(self):
        self._entries["frame_angle"] = self._frameAngle.get()
        self._entries["eye_height"] = self._eyeHeight.get()
        self._entries["minimum_dist_to_wall"] = self._minDistToWall.get()

        self._manager.inform(DataStore.EVENT.VR_EDIT, self._entries)

    def auto_populate(self):
        self._frameAngle.set(Defaults.VR.FRAME_ANGLE)
        self._eyeHeight.set(Defaults.VR.EYE_HEIGHT)
        self._minDistToWall.set(Defaults.VR.MIN_DIST_TO_WALL)
        self._distortion_var.set(Defaults.VR.DISTORTION)
        self._win_var.set(Defaults.VR.WINDOWED)
예제 #35
0
파일: GUI.py 프로젝트: NissankaW/Mariokart3
class SPIFrame(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)   
        self.parent = parent
        self.initialize()
        
    def initialize(self):
        self.grid()
        self.entryVariable = StringVar()
        self.entry = Entry(self, textvariable=self.entryVariable)
        self.entry.grid(column=0,row=0,sticky='EW')
        self.entry.bind("<Return>", self.OnPressEnter)

        button = Button(self,text="SPI send", command=self.OnButtonClick)
        button.grid(column=1,row=0)
        
        #ramp = Button(self,text="RAMP", command=self.setlabvar)
        #ramp.grid(column=1,row=1)        

        self.labelVariable = StringVar()
        label = Label(self,textvariable=self.labelVariable,
                              anchor="w",fg="white",bg="blue")
        label.grid(column=0,row=1,columnspan=1,sticky='EW')
        self.labelVariable.set("Start..")
        
        self.slider = Scale(self, from_=0, to=80, orient=HORIZONTAL, 
                            command=self.setlabvar)
        self.slider.grid(column=0, row=2, columnspan=3, sticky='EW')
        
        self.PID = PIDTune(self)
        self.PID.grid(column=0, row=3, columnspan=3, sticky='EW')
        
        self.grid_columnconfigure(0,weight=1)
        self.update()
        #self.geometry(self.geometry()) # caused busy wait?
        self.entry.focus_set()
        #self.entry.selection_range(0, Tkinter.END) # caused busy wait?
        

        
        
    def setlabvar(self, val):
        val = self.slider.get()
        speed.SetAcceleration(val)
        accel = val;
        self.labelVariable.set("Duty set: " + str(val) )       
        

    def OnButtonClick(self):
        accel = int(self.entryVariable.get())
        self.slider.set(accel)
        speed.SetAcceleration(accel)
        self.labelVariable.set("Duty set: " + str(accel) )
        self.entry.focus_set()
        self.entry.selection_range(0, END)
        
    def OnPressEnter(self,event):
        accel = int(self.entryVariable.get())
        self.slider.set(accel)
        speed.SetAcceleration(accel)
        self.labelVariable.set("Duty set: " + str(accel) )
        self.entry.focus_set()
        self.entry.selection_range(0, END)
예제 #36
0
class SettingWindow(Toplevel):
    def __init__(self, master, max_num_features, num_frames, mser_image):
        Toplevel.__init__(self, master)

        self.protocol('WM_DELETE_WINDOW', self.withdraw)

        self.notebook = ttk.Notebook(self)
        frame_feats = ttk.Frame(self.notebook)
        frame_forest = ttk.Frame(self.notebook)
        frame_mser = ttk.Frame(self.notebook)
        frame_other = ttk.Frame(self.notebook)
        self.notebook.add(frame_feats, text="Features ")
        self.notebook.add(frame_forest, text=" Forest  ")
        self.notebook.add(frame_mser, text=" MSER  ")
        self.notebook.add(frame_other, text=" Other  ")

        self.max_num_feats = max_num_features
        self.selection = None

        self.mser_image = mser_image

        rand_row = random.randint(1, 512 - 200)
        rand_col = random.randint(1, 512 - 110)
        self.mser_area = mser_image[rand_row:rand_row + 180,
                                    rand_col:rand_col + 100]

        # read images from icons folder
        self.hf0_img = PhotoImage(file="./icons/hf0.gif")
        self.hf1_img = PhotoImage(file="./icons/hf1.gif")
        self.hf2_img = PhotoImage(file="./icons/hf2.gif")
        self.hf3_img = PhotoImage(file="./icons/hf3.gif")
        self.hf4_img = PhotoImage(file="./icons/hf4.gif")
        self.hf5_img = PhotoImage(file="./icons/hf5.gif")

        self.features_vars = list()
        for i in range(max_num_features):
            self.features_vars.append(IntVar())

        Label(frame_feats,
              text="Patch size (" + u"\N{GREEK SMALL LETTER PI}" + "):").grid(
                  row=0, column=0, pady=5)
        self.patch_size_spinbox = Spinbox(frame_feats, from_=3, to=30, width=3)
        self.patch_size_spinbox.delete(0, END)
        self.patch_size_spinbox.insert(END, 10)
        self.patch_size_spinbox.grid(row=0, column=1, padx=5)

        f1 = ttk.Labelframe(frame_feats, text='Mean filter')
        f1.grid(row=1, columnspan=2)

        Label(f1, text=u"\N{GREEK SMALL LETTER PI}").grid(row=0, column=0)
        Checkbutton(f1, text="R",
                    variable=self.features_vars[0]).grid(row=0, column=1)
        Checkbutton(f1, text="G",
                    variable=self.features_vars[1]).grid(row=0, column=2)
        Checkbutton(f1, text="B",
                    variable=self.features_vars[2]).grid(row=0, column=3)

        Label(f1, text=u"\N{GREEK SMALL LETTER PI}" + "/2").grid(row=1,
                                                                 column=0)
        Checkbutton(f1, text="R",
                    variable=self.features_vars[3]).grid(row=1, column=1)
        Checkbutton(f1, text="G",
                    variable=self.features_vars[4]).grid(row=1, column=2)
        Checkbutton(f1, text="B",
                    variable=self.features_vars[5]).grid(row=1, column=3)

        f2 = ttk.Labelframe(frame_feats, text="Gaussian filter")
        f2.grid(row=2, columnspan=2)

        Label(f2, text=str(1.0)).grid(row=0, column=0)
        Checkbutton(f2, text="R",
                    variable=self.features_vars[6]).grid(row=0, column=1)
        Checkbutton(f2, text="G",
                    variable=self.features_vars[7]).grid(row=0, column=2)
        Checkbutton(f2, text="B",
                    variable=self.features_vars[8]).grid(row=0, column=3)

        Label(f2, text=str(3.5)).grid(row=1, column=0)
        Checkbutton(f2, text="R",
                    variable=self.features_vars[9]).grid(row=1, column=1)
        Checkbutton(f2, text="G",
                    variable=self.features_vars[10]).grid(row=1, column=2)
        Checkbutton(f2, text="B",
                    variable=self.features_vars[11]).grid(row=1, column=3)

        f3 = ttk.Labelframe(frame_feats, text="Laplacian of gaussian")
        f3.grid(row=3, columnspan=2)

        Label(f3, text=str(2.0)).grid(row=0, column=0)
        Checkbutton(f3, text="R",
                    variable=self.features_vars[12]).grid(row=0, column=1)
        Checkbutton(f3, text="G",
                    variable=self.features_vars[13]).grid(row=0, column=2)
        Checkbutton(f3, text="B",
                    variable=self.features_vars[14]).grid(row=0, column=3)

        Label(f3, text=str(3.5)).grid(row=1, column=0)
        Checkbutton(f3, text="R",
                    variable=self.features_vars[15]).grid(row=1, column=1)
        Checkbutton(f3, text="G",
                    variable=self.features_vars[16]).grid(row=1, column=2)
        Checkbutton(f3, text="B",
                    variable=self.features_vars[17]).grid(row=1, column=3)

        f4 = ttk.Labelframe(frame_feats, text="Haar-like features")
        f4.grid(row=1, rowspan=2, column=3, padx=5)

        Checkbutton(f4, image=self.hf0_img,
                    variable=self.features_vars[18]).grid(row=0, column=0)
        Checkbutton(f4, image=self.hf1_img,
                    variable=self.features_vars[19]).grid(row=0, column=1)
        Checkbutton(f4, image=self.hf2_img,
                    variable=self.features_vars[20]).grid(row=1, column=0)
        Checkbutton(f4, image=self.hf3_img,
                    variable=self.features_vars[21]).grid(row=1, column=1)
        Checkbutton(f4, image=self.hf4_img,
                    variable=self.features_vars[22]).grid(row=2, column=0)
        Checkbutton(f4, image=self.hf5_img,
                    variable=self.features_vars[23]).grid(row=2, column=1)

        buttons_paned_window = PanedWindow(frame_feats, orient=VERTICAL)
        buttons_paned_window.grid(row=3, column=3)

        self.select_all_button = Button(buttons_paned_window,
                                        text="Select all",
                                        command=self._select_all)
        buttons_paned_window.add(self.select_all_button)

        self.clear_selection_button = Button(buttons_paned_window,
                                             text="Clear selection",
                                             command=self._clear_selection)
        buttons_paned_window.add(self.clear_selection_button)

        # default values
        for j in [0, 1, 3, 6, 7, 9, 15, 21, 23]:
            self.features_vars[j].set(1)

        # FOREST FRAMES
        # number of trees
        f5 = ttk.Labelframe(frame_forest, text="Number of trees")
        f5.grid(row=0, columnspan=2, pady=5, padx=5)
        Label(f5, text="N").grid(row=1, column=0)
        self.num_trees_scale = Scale(f5,
                                     from_=5,
                                     to=500,
                                     resolution=5,
                                     orient=HORIZONTAL)
        self.num_trees_scale.set(300)
        self.num_trees_scale.grid(row=0, column=1, rowspan=2)

        # depth single tree
        f6 = ttk.Labelframe(frame_forest, text="Depth single tree")
        f6.grid(row=1, columnspan=2, pady=5, padx=5)
        Label(f6, text="d").grid(row=1, column=0)
        self.depth_tree_scale = Scale(f6, from_=2, to=20, orient=HORIZONTAL)
        self.depth_tree_scale.set(3)
        self.depth_tree_scale.grid(row=0, column=1, rowspan=2)

        # percentage number of features
        f7 = ttk.Labelframe(frame_forest, text="% subset of features")
        f7.grid(row=2, columnspan=2, pady=5, padx=5)
        Label(f7, text="m").grid(row=1, column=0)
        self.percentage_feats_scale = Scale(f7,
                                            from_=0.0,
                                            to=1,
                                            resolution=0.05,
                                            orient=HORIZONTAL)
        self.percentage_feats_scale.set(0.5)
        self.percentage_feats_scale.grid(row=0, column=1, rowspan=2)

        # mser frame
        # delta
        f8 = ttk.Labelframe(frame_mser, text="Delta")
        f8.grid(row=0, columnspan=2, pady=5, padx=5)
        Label(f8, text=u"\N{GREEK SMALL LETTER DELTA}").grid(row=1, column=0)
        self.delta_scale = Scale(f8,
                                 from_=1,
                                 to=10,
                                 resolution=1,
                                 orient=HORIZONTAL)
        self.delta_scale.set(2)
        self.delta_scale.grid(row=0, column=1, rowspan=2)

        # min area
        f9 = ttk.Labelframe(frame_mser, text="Minimum area")
        f9.grid(row=1, columnspan=2, pady=5, padx=5)
        Label(f9, text="m").grid(row=1, column=0)
        self.min_area_scale = Scale(f9, from_=2, to=200, orient=HORIZONTAL)
        self.min_area_scale.set(10)
        self.min_area_scale.grid(row=0, column=1, rowspan=2)

        # percentage number of features
        f10 = ttk.Labelframe(frame_mser, text="Maximum area")
        f10.grid(row=2, columnspan=2, pady=5, padx=5)
        Label(f10, text="M").grid(row=1, column=0)
        self.max_area_scale = Scale(f10,
                                    from_=50,
                                    to=1000,
                                    resolution=5,
                                    orient=HORIZONTAL)
        self.max_area_scale.set(350)
        self.max_area_scale.grid(row=0, column=1, rowspan=2)

        # mser image
        f11 = ttk.Labelframe(frame_mser)
        f11.grid(row=0, rowspan=3, column=2, padx=5)

        self.mser_img_array = Image.fromarray(self.mser_area, "RGB")
        self.mser_img = ImageTk.PhotoImage(self.mser_img_array)

        img_label = Label(f11, image=self.mser_img)
        img_label.grid(row=0, column=0)

        buttons_p_w_mser = PanedWindow(f11, orient=HORIZONTAL)
        try_button = Button(f11, text="Try", command=self.try_mser)
        buttons_p_w_mser.add(try_button)
        change_button = Button(f11, text="New img", command=self.change_mser)
        buttons_p_w_mser.add(change_button)
        buttons_p_w_mser.grid(row=1, column=0)

        # other frame
        f12 = ttk.Labelframe(frame_other, text="Refinement")
        f12.grid(row=0, columnspan=2, pady=5, padx=5)
        Label(f12, text=u"\N{GREEK CAPITAL LETTER PHI}_l").grid(row=1,
                                                                column=0)
        self.low_thresh_scale = Scale(f12,
                                      from_=0,
                                      to=1,
                                      resolution=0.05,
                                      orient=HORIZONTAL,
                                      length=90)
        self.low_thresh_scale.set(0.45)
        self.low_thresh_scale.grid(row=0, column=1, rowspan=2)
        Label(f12, text=u"\N{GREEK CAPITAL LETTER PHI}_h").grid(row=3,
                                                                column=0)
        self.high_thresh_scale = Scale(f12,
                                       from_=0,
                                       to=1,
                                       resolution=0.05,
                                       orient=HORIZONTAL,
                                       length=90)
        self.high_thresh_scale.set(0.65)
        self.high_thresh_scale.grid(row=2, column=1, rowspan=2)

        f13 = ttk.Labelframe(frame_other, text="Dots distance")
        f13.grid(row=1, columnspan=2, pady=5, padx=5)
        Label(f13, text=u"     \N{GREEK SMALL LETTER SIGMA}").grid(row=1,
                                                                   column=0)
        self.dots_distance_scale = Scale(f13,
                                         from_=1,
                                         to=20,
                                         resolution=1,
                                         orient=HORIZONTAL,
                                         length=90)
        self.dots_distance_scale.set(6)
        self.dots_distance_scale.grid(row=0, column=1, rowspan=2)

        f14 = ttk.Labelframe(frame_other, text="Tracks")
        f14.grid(row=0, column=3, pady=5, padx=5)
        Label(f14, text="N").grid(row=1, column=0)
        self.num_frames_tracks_spinbox = Spinbox(f14,
                                                 from_=2,
                                                 to=num_frames,
                                                 width=10)
        self.num_frames_tracks_spinbox.delete(0, END)
        self.num_frames_tracks_spinbox.insert(END, num_frames)
        self.num_frames_tracks_spinbox.grid(row=0, column=1, rowspan=2)

        Label(f14, text=u"\N{GREEK SMALL LETTER TAU}").grid(row=3, column=0)
        self.gaps_scale = Scale(f14,
                                from_=1,
                                to=10,
                                resolution=1,
                                orient=HORIZONTAL,
                                length=90)
        self.gaps_scale.set(2)
        self.gaps_scale.grid(row=2, column=1, rowspan=2)

        self.notebook.pack(padx=1, pady=1)

        save_button = Button(self,
                             text=" Save and Close window ",
                             command=self.withdraw)
        save_button.pack(pady=2)

    def _select_all(self):
        for i, var in enumerate(self.features_vars):
            var.set(1)

    def _clear_selection(self):
        for i, var in enumerate(self.features_vars):
            var.set(0)

    def change_mser(self):
        rand_row = random.randint(1, 512 - 200)
        rand_col = random.randint(1, 512 - 110)
        self.mser_area = self.mser_image[rand_row:rand_row + 180,
                                         rand_col:rand_col + 100]

        self.update_mser_image(self.mser_area)

    def try_mser(self):
        delta = self.delta_scale.get()
        min_area = self.min_area_scale.get()
        max_area = self.max_area_scale.get()

        image = self.mser_area
        red_c = image[:, :, 0]
        red_c = cv2.equalizeHist(red_c)

        det_img = image.copy()

        mser = cv2.MSER(delta, _min_area=min_area, _max_area=max_area)
        regions = mser.detect(red_c)
        cp = list()
        new_c = np.zeros(self.mser_area.shape, dtype=np.uint8)
        for r in regions:
            for point in r:
                cp.append(point)
                det_img[point[1], point[0], 0] = 0
                det_img[point[1], point[0], 1] = 0
                det_img[point[1], point[0], 2] = 204
                #new_c[point[1], point[0]] = 255

        self.update_mser_image(det_img)

    def update_mser_image(self, new_image):
        self.mser_img_array = Image.fromarray(new_image)
        self.mser_img.paste(self.mser_img_array)

    def get_patch_size(self):
        patch_size = self.patch_size_spinbox.get()
        return int(patch_size)

    def get_num_frames_tracks(self):
        num_frames_tracks = self.num_frames_tracks_spinbox.get()
        return int(num_frames_tracks)

    def get_mser_opts(self):
        return [
            self.delta_scale.get(),
            self.min_area_scale.get(),
            self.max_area_scale.get()
        ]

    def get_forest_opts(self):
        return [
            self.num_trees_scale.get(),
            self.depth_tree_scale.get(),
            self.percentage_feats_scale.get()
        ]

    def get_low_thresh(self):
        return self.low_thresh_scale.get()

    def get_high_thresh(self):
        return self.high_thresh_scale.get()

    def get_dots_distance(self):
        return int(self.dots_distance_scale.get())

    def get_selection_mask(self):
        if self.selection is not None:
            return self.selection

        selection_mask = np.zeros((self.max_num_feats, ), dtype='bool')
        for i, var in enumerate(self.features_vars):
            selection_mask[i] = var.get()
        self.selection = selection_mask
        return selection_mask
class TelloUI(threading.Thread):
    """Wrapper class to enable the GUI."""

    def __init__(self,tello,outputpath):
        """
        Initial all the element of the GUI,support by Tkinter

        :param tello: class interacts with the Tello drone.

        Raises:
            RuntimeError: If the Tello rejects the attempt to enter command mode.
        """        

        self.tello = tello # videostream device
        self.outputPath = outputpath # the path that save pictures created by clicking the takeSnapshot button 
        self.frame = None  # frame read from h264decoder and used for pose recognition
        self.thread = None # thread of the Tkinter mainloop
        self.stopEvent = None

        # control variables
        self.distance = 0.1  # default distance for 'move' cmd
        self.degree = 30  # default degree for 'cw' or 'ccw' cmd

        # *************place of cut

        
        # start a thread that constantly pools the video sensor for
        # the most recently read frame
        self.stopEvent = threading.Event()
        self.thread = threading.Thread(target=self.videoLoop, args=())
        self.thread.start()

        # *************place of cut


        '''
        #### start main loop
        print("before main loop")
        self.thread_tk_main = threading.Thread(target=self.root.mainloop(), args=())
        self.thread_tk_main.start()
        print("after main loop")
        '''
        threading.Thread.__init__(self)
        self.start()
        # the sending_command will send command to tello every 5 seconds
        # self.sending_command_thread = threading.Thread(target = self._sendingCommand)

    def run(self):
        # if the flag is TRUE,the auto-takeoff thread will stop waiting for the response from tello
        self.quit_waiting_flag = False

        # initialize the root window and image panel
        self.root = tki.Tk()

        self.panel = None

        # create buttons
        self.btn_snapshot = tki.Button(self.root, text="Snapshot!",
                                       command=self.takeSnapshot)
        self.btn_snapshot.pack(side="bottom", fill="both",
                               expand="yes", padx=10, pady=5)

        self.btn_pause = tki.Button(self.root, text="Pause", relief="raised", command=self.pauseVideo)
        self.btn_pause.pack(side="bottom", fill="both",
                            expand="yes", padx=10, pady=5)

        self.btn_landing = tki.Button(
            self.root, text="Open Command Panel", relief="raised", command=self.openCmdWindow)
        self.btn_landing.pack(side="bottom", fill="both",
                              expand="yes", padx=10, pady=5)


        #************************************************

        # set a callback to handle when the window is closed
        self.root.wm_title("TELLO Controller")
        self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose)


        print("before main loop")
        self.root.mainloop()

    def videoLoop(self):
        """
        The mainloop thread of Tkinter 
        Raises:
            RuntimeError: To get around a RunTime error that Tkinter throws due to threading.
        """
        try:
            # start the thread that get GUI image and drwa skeleton 
            time.sleep(0.5)
            # self.sending_command_thread.start()
            while not self.stopEvent.is_set():                
                system = platform.system()

            # read the frame for GUI show
                self.frame = self.tello.read()
                if self.frame is None or self.frame.size == 0:
                    continue 
            
            # transfer the format from frame to image         
                image = Image.fromarray(self.frame)

            # we found compatibility problem between Tkinter,PIL and Macos,and it will 
            # sometimes result the very long preriod of the "ImageTk.PhotoImage" function,
            # so for Macos,we start a new thread to execute the _updateGUIImage function.
                if system =="Windows" or system =="Linux":                
                    self._updateGUIImage(image)

                else:
                    thread_tmp = threading.Thread(target=self._updateGUIImage,args=(image,))
                    thread_tmp.start()
                    time.sleep(0.03)                                                            
        except RuntimeError as e:
            print("[INFO] caught a RuntimeError", e)

           
    def _updateGUIImage(self,image):
        """
        Main operation to initial the object of image,and update the GUI panel 
        """  
        image = ImageTk.PhotoImage(image)
        # if the panel none ,we need to initial it
        if self.panel is None:
            self.panel = tki.Label(image=image)
            self.panel.image = image
            self.panel.pack(side="left", padx=10, pady=10)
        # otherwise, simply update the panel
        else:
            self.panel.configure(image=image)
            self.panel.image = image

            
    def _sendingCommand(self):
        """
        start a while loop that sends 'command' to tello every 5 second
        """    

        while True:
            self.tello.send_command('command')        
            time.sleep(30)

    def _setQuitWaitingFlag(self):  
        """
        set the variable as TRUE,it will stop computer waiting for response from tello  
        """       
        self.quit_waiting_flag = True        
   
    def openCmdWindow(self):
        """
        open the cmd window and initial all the button and text
        """        
        panel = Toplevel(self.root)
        panel.wm_title("Command Panel")

        # create text input entry
        text0 = tki.Label(panel,
                          text='This Controller map keyboard inputs to Tello control commands\n'
                               'Adjust the trackbar to reset distance and degree parameter',
                          font='Helvetica 10 bold'
                          )
        text0.pack(side='top')

        text1 = tki.Label(panel, text=
                          'W - Move Tello Up\t\t\tArrow Up - Move Tello Forward\n'
                          'S - Move Tello Down\t\t\tArrow Down - Move Tello Backward\n'
                          'A - Rotate Tello Counter-Clockwise\tArrow Left - Move Tello Left\n'
                          'D - Rotate Tello Clockwise\t\tArrow Right - Move Tello Right',
                          justify="left")
        text1.pack(side="top")

        self.btn_landing = tki.Button(
            panel, text="Land", relief="raised", command=self.telloLanding)
        self.btn_landing.pack(side="bottom", fill="both",
                              expand="yes", padx=10, pady=5)

        self.btn_takeoff = tki.Button(
            panel, text="Takeoff", relief="raised", command=self.telloTakeOff)
        self.btn_takeoff.pack(side="bottom", fill="both",
                              expand="yes", padx=10, pady=5)

        # binding arrow keys to drone control
        self.tmp_f = tki.Frame(panel, width=100, height=2)
        self.tmp_f.bind('<KeyPress-w>', self.on_keypress_w)
        self.tmp_f.bind('<KeyPress-s>', self.on_keypress_s)
        self.tmp_f.bind('<KeyPress-a>', self.on_keypress_a)
        self.tmp_f.bind('<KeyPress-d>', self.on_keypress_d)
        self.tmp_f.bind('<KeyPress-Up>', self.on_keypress_up)
        self.tmp_f.bind('<KeyPress-Down>', self.on_keypress_down)
        self.tmp_f.bind('<KeyPress-Left>', self.on_keypress_left)
        self.tmp_f.bind('<KeyPress-Right>', self.on_keypress_right)
        self.tmp_f.pack(side="bottom")
        self.tmp_f.focus_set()

        self.btn_landing = tki.Button(
            panel, text="Flip", relief="raised", command=self.openFlipWindow)
        self.btn_landing.pack(side="bottom", fill="both",
                              expand="yes", padx=10, pady=5)

        self.distance_bar = Scale(panel, from_=0.02, to=5, tickinterval=0.01, digits=3, label='Distance(m)',
                                  resolution=0.01)
        self.distance_bar.set(0.2)
        self.distance_bar.pack(side="left")

        self.btn_distance = tki.Button(panel, text="Reset Distance", relief="raised",
                                       command=self.updateDistancebar,
                                       )
        self.btn_distance.pack(side="left", fill="both",
                               expand="yes", padx=10, pady=5)

        self.degree_bar = Scale(panel, from_=1, to=360, tickinterval=10, label='Degree')
        self.degree_bar.set(30)
        self.degree_bar.pack(side="right")

        self.btn_distance = tki.Button(panel, text="Reset Degree", relief="raised", command=self.updateDegreebar)
        self.btn_distance.pack(side="right", fill="both",
                               expand="yes", padx=10, pady=5)

    def openFlipWindow(self):
        """
        open the flip window and initial all the button and text
        """
        
        panel = Toplevel(self.root)
        panel.wm_title("Gesture Recognition")

        self.btn_flipl = tki.Button(
            panel, text="Flip Left", relief="raised", command=self.telloFlip_l)
        self.btn_flipl.pack(side="bottom", fill="both",
                            expand="yes", padx=10, pady=5)

        self.btn_flipr = tki.Button(
            panel, text="Flip Right", relief="raised", command=self.telloFlip_r)
        self.btn_flipr.pack(side="bottom", fill="both",
                            expand="yes", padx=10, pady=5)

        self.btn_flipf = tki.Button(
            panel, text="Flip Forward", relief="raised", command=self.telloFlip_f)
        self.btn_flipf.pack(side="bottom", fill="both",
                            expand="yes", padx=10, pady=5)

        self.btn_flipb = tki.Button(
            panel, text="Flip Backward", relief="raised", command=self.telloFlip_b)
        self.btn_flipb.pack(side="bottom", fill="both",
                            expand="yes", padx=10, pady=5)
       
    def takeSnapshot(self):
        """
        save the current frame of the video as a jpg file and put it into outputpath
        """

        # grab the current timestamp and use it to construct the filename
        ts = datetime.datetime.now()
        filename = "{}.jpg".format(ts.strftime("%Y-%m-%d_%H-%M-%S"))

        p = os.path.sep.join((self.outputPath, filename))

        # save the file
        cv2.imwrite(p, cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR))
        print(self.frame)
        print("[INFO] saved {}".format(filename))


    def pauseVideo(self):
        """
        Toggle the freeze/unfreze of video
        """
        if self.btn_pause.config('relief')[-1] == 'sunken':
            self.btn_pause.config(relief="raised")
            self.tello.video_freeze(False)
        else:
            self.btn_pause.config(relief="sunken")
            self.tello.video_freeze(True)

    def telloTakeOff(self):
        return self.tello.takeoff()                

    def telloLanding(self):
        return self.tello.land()

    def telloFlip_l(self):
        return self.tello.flip('l')

    def telloFlip_r(self):
        return self.tello.flip('r')

    def telloFlip_f(self):
        return self.tello.flip('f')

    def telloFlip_b(self):
        return self.tello.flip('b')

    def telloCW(self, degree):
        return self.tello.rotate_cw(degree)

    def telloCCW(self, degree):
        return self.tello.rotate_ccw(degree)

    def telloMoveForward(self, distance):
        return self.tello.move_forward(distance)

    def telloMoveBackward(self, distance):
        return self.tello.move_backward(distance)

    def telloMoveLeft(self, distance):
        return self.tello.move_left(distance)

    def telloMoveRight(self, distance):
        return self.tello.move_right(distance)

    def telloUp(self, dist):
        return self.tello.move_up(dist)

    def telloDown(self, dist):
        return self.tello.move_down(dist)

    def updateTrackBar(self):
        self.my_tello_hand.setThr(self.hand_thr_bar.get())

    def updateDistancebar(self):
        self.distance = self.distance_bar.get()
        print('reset distance to %.1f' % self.distance)

    def updateDegreebar(self):
        self.degree = self.degree_bar.get()
        print('reset distance to %d' % self.degree)

    def on_keypress_w(self, event):
        print("up %d m" % self.distance)
        self.telloUp(self.distance)

    def on_keypress_s(self, event):
        print("down %d m" % self.distance)
        self.telloDown(self.distance)

    def on_keypress_a(self, event):
        print("ccw %d degree" % self.degree)
        self.tello.rotate_ccw(self.degree)

    def on_keypress_d(self, event):
        print("cw %d m" % self.degree)
        self.tello.rotate_cw(self.degree)

    def on_keypress_up(self, event):
        print("forward %d m" % self.distance)
        self.telloMoveForward(self.distance)

    def on_keypress_down(self, event):
        print("backward %d m" % self.distance)
        self.telloMoveBackward(self.distance)

    def on_keypress_left(self, event):
        print("left %d m" % self.distance)
        self.telloMoveLeft(self.distance)

    def on_keypress_right(self, event):
        print("right %d m" % self.distance)
        self.telloMoveRight(self.distance)

    def on_keypress_enter(self, event):
        if self.frame is not None:
            self.registerFace()
        self.tmp_f.focus_set()

    def onClose(self):
        """
        set the stop event, cleanup the camera, and allow the rest of
        
        the quit process to continue
        """
        print("[INFO] closing...")
        self.stopEvent.set()
        del self.tello
        self.root.quit()
예제 #38
0
class FourBarGUI(object):
    """
    GUI to model a 4-bar mechanism.
    """
    def __init__(self, wdw, r, c):
        """
        Determines layout of the canvas,
        number of rows and colums is r and c.
        """
        wdw.title('a 4-bar mechanism')
        self.fbr = FourBar()
        self.rows = r
        self.cols = c
        self.ox = c/3
        self.oy = 3*r/4
        # print "A =" , (self.ox, self.oy)
        self.togo = False
        # the canvas and start, stop, and clear buttons
        self.c = Canvas(wdw, width=self.cols, height=self.rows, bg='green')
        self.c.grid(row=1, column=2, columnspan=2)
        self.startbut = Button(wdw, text='start', command = self.start)
        self.startbut.grid(row=3, column=2, sticky=W+E)
        self.stopbut = Button(wdw, text='stop', command = self.stop)
        self.stopbut.grid(row=3, column=3, sticky=W+E)
        self.clearbut = Button(wdw, text='clear', command = self.clear)
        self.clearbut.grid(row=3, column=4, columnspan=3, sticky=W+E)
        # the length of the crank
        self.crank_lbl = Label(wdw, text='crank', justify=LEFT)
        self.crank_lbl.grid(row=0, column=0)
        self.crank_bar = IntVar()
        self.L = Scale(wdw, orient='vertical', from_=0, to=self.rows/2, \
            tickinterval=20, resolution=1, length=self.rows, \
            variable=self.crank_bar, command=self.draw_mechanism)
        self.L.set(self.fbr.crank)
        self.L.grid(row=1, column=0)
        # the angle that drives the crank
        self.angle_lbl = Label(wdw, text='angle', justify=LEFT)
        self.angle_lbl.grid(row=0, column=1)
        self.angle = DoubleVar()
        self.t = Scale(wdw, orient='vertical', from_=0, to=6.30, \
            tickinterval=0.30, resolution=0.01, length=self.rows, \
            variable=self.angle, command=self.draw_mechanism)
        self.t.grid(row=1, column=1)
        self.angle.set(self.fbr.angle)
        # the bar at the right
        self.right_bar_lbl = Label(wdw, text='right bar', justify=LEFT)
        self.right_bar_lbl.grid(row=0, column=4)
        self.right_bar = IntVar()
        self.r = Scale(wdw, orient='vertical', from_=0, to=self.rows/2, \
            tickinterval=20, resolution=1, length=self.rows, \
            variable=self.right_bar, command=self.draw_mechanism)
        self.r.grid(row=1, column=4)
        self.right_bar.set(self.fbr.right)
        # the top bar attached to the crank
        self.top_bar_lbl = Label(wdw, text='top bar', justify=LEFT)
        self.top_bar_lbl.grid(row=0, column=5)
        self.r_top_bar = IntVar()
        self.R = Scale(wdw, orient='vertical', from_=0, to=self.rows/2, \
            tickinterval=20, resolution=1, length=self.rows, \
            variable=self.r_top_bar, command=self.draw_mechanism)
        self.R.grid(row=1, column=5)
        self.r_top_bar.set(self.fbr.top)
        # the scale for the coupler bar
        self.coupler_bar_lbl = Label(wdw, text='coupler', justify=LEFT)
        self.coupler_bar_lbl.grid(row=0, column=6)
        self.coupler_bar = IntVar()
        self.cpl = Scale(wdw, orient='vertical', from_=0, to=self.rows/2, \
            tickinterval=20, resolution=1, length=self.rows, \
            variable=self.coupler_bar, command=self.draw_mechanism)
        self.cpl.grid(row=1, column=6)
        self.coupler_bar.set(self.fbr.coupler)
        # the horizontal bottom bar
        self.flat_lbl = Label(wdw, text='right joint', justify=RIGHT)
        self.flat_lbl.grid(row=2, column=1)
        self.flat = IntVar()
        self.f = Scale(wdw, orient='horizontal', from_=0, to=self.rows/2, \
            tickinterval=50, resolution=1, length=self.cols, \
            variable=self.flat, command=self.draw_mechanism)
        self.f.grid(row=2, column=2, columnspan=2)
        self.flat.set(self.fbr.flat)
        # coordinates of the coupler point appear on top
        self.ex = Entry(wdw) # for x value
        self.ex.grid(row=0, column=2)
        self.ex.insert(INSERT, "x = ")
        self.ey = Entry(wdw) # for y value
        self.ey.grid(row=0, column=3)
        self.ey.insert(INSERT,"y = ")
        # check button for drawing of coupler curve
        self.curve = IntVar()
        self.cb = Checkbutton(wdw, text='coupler', \
            variable=self.curve, onvalue=1, offvalue=0)
        self.curve.set(1)
        self.cb.grid(row=3, column=0)
        # draw the mechanism on canvas
        self.draw_mechanism(0)

    def update_values(self):
        """
        Takes all values of the scales and updates
        the data attributes of self.fbr.
        """
        self.fbr.flat = self.flat.get()
        self.fbr.crank = self.crank_bar.get()
        self.fbr.top = self.r_top_bar.get()
        self.fbr.right = self.right_bar.get()
        self.fbr.coupler = self.coupler_bar.get()
        self.fbr.angle = self.angle.get()
        #self.fbr.print_joints()

    def draw_coupler_point(self, p):
        """
        Draws coupler point with coordinates in p
        if the curve checkbox is on.
        Note that the previous values for the coordinates
        of the coupler point are stored in the entry fields.
        """
        if self.curve.get() == 1:
            px = self.ox + p[0]
            py = self.oy - p[1]
            eqx = self.ex.get()
            Lx = eqx.split('=')
            if Lx[1] == ' ':
                qx = 0.0
            else:
                qx = float(Lx[1])
            eqy = self.ey.get()
            Ly = eqy.split('=')
            if Ly[1] == ' ':
                qy = 0.0
            else:
                qy = float(Ly[1])
            if (qx != 0.0) and (qy != 0.0):
                qx = self.ox + qx
                qy = self.oy - qy
                self.c.create_line(qx, qy, px, py, width=1)

    def fill_entries(self, p):
        """
        Fills the entry fields with the coordinates
        of the coupler point in p.
        """
        sx = 'x = %f' % p[0]
        sy = 'y = %f' % p[1]
        self.ex.delete(0, END)
        self.ex.insert(INSERT, sx)
        self.ey.delete(0, END)
        self.ey.insert(INSERT, sy)

    def draw_link(self, p, q, s):
        """
        Draws the link from point with coordinates in p
        to the point with coordinates in q, using s as tag.
        """
        self.c.delete(s)
        px = self.ox + p[0]
        py = self.oy - p[1]
        qx = self.ox + q[0]
        qy = self.oy - q[1]
        self.c.create_line(px, py, qx, qy, width=2, tags=s)

    def draw_mechanism(self, v):
        """
        Fills the canvas with the current model
        of the planar 4-bar mechanism.
        Because this command is called by the sliders,
        the argument v is needed but not used.
        """
        self.update_values()
        L = self.fbr.joints()
        for i in range(0, len(L)):
            p = L[i]
            px = self.ox + p[0]
            py = self.oy - p[1]
            sj = 'joint%d' % i
            self.c.delete(sj)
            self.c.create_oval(px-6, py-6, px+6, py+6, width=1, \
                outline='black', fill='red', tags=sj)
        self.draw_link(L[0], L[2], 'link0')
        self.draw_link(L[1], L[3], 'link1')
        self.draw_link(L[2], L[3], 'link2')
        self.draw_link(L[2], L[4], 'link3')
        self.draw_coupler_point(L[4])
        self.fill_entries(L[4])

    def start(self):
        """
        Starts the animation, adding 0.01 to angle.
        """
        self.togo = True
        while self.togo:
            theta = self.angle.get()
            theta = theta + 0.01
            if theta > 6.28:
                theta = 0
            self.angle.set(theta)
            self.draw_mechanism(0)
            self.c.update()

    def stop(self):
        """
        Stops the animation.
        """
        self.togo = False

    def clear(self):
        """
        Clears the canvas.
        """
        self.c.delete(ALL)
예제 #39
0
class EnviroDialog(Dialog):
    """
    Dialog for editing the simulation environment details
    """
    def __init__(self, parent, populator=None, manager=None):
        """
        Construct the dialog
        :param parent:          The tk element that is the parent of the dialog
        :return:                An instance of EnviroDialog
        """
        self._entries = {
            "floor_texture": None,
            "wall_height": None,
            "edge_width": None,
            "sky_texture": None,
            "start_node": None
        }
        Dialog.__init__(self, parent=parent, title="EnvironmentConfiguration", populator=populator, manager=manager)

    def body(self, parent):
        """
        Overridden method defining the body of the dialog
        :param parent:
        :return:
        """
        self._floorSel = ImagePicker(parent, "Floor Texture:",
                                     default=self._entries["floor_texture"], auto_move=True, move_fold="Data")
        self._floorSel.grid(row=0, columnspan=4)
        self._skySel = ImagePicker(parent, "Sky Texture:", default=self._entries["sky_texture"], auto_move=True, move_fold="Data")
        self._skySel.grid(row=1, columnspan=4)

        Label(parent, text="Wall Height:", width=10, anchor=W).grid(row=2, column=0, sticky=W)
        Label(parent, text="Edge Width:", width=10, anchor=W).grid(row=3, column=0, sticky=W)

        self._wallScale = Scale(parent, from_=10, to=1000, orient=HORIZONTAL)
        if self._entries["wall_height"] is not None:
            self._wallScale.set(self._entries["wall_height"])
        self._wallScale.grid(row=2, column=1, columnspan=2, sticky=W)

        self._edgeScale = Scale(parent, from_=10, to=1000, orient=HORIZONTAL)
        if self._entries["edge_width"] is not None:
            self._edgeScale.set(self._entries["edge_width"])
        self._edgeScale.grid(row=3, column=1, columnspan=2, sticky=W)

        Label(parent, text="Starting Node:", anchor=W).grid(row=4, column=0, sticky=W)
        self._start_node = Label(parent, text=self._entries["start_node"], anchor=W)
        self._start_node.grid(row=4, column=1, sticky=W)

    def populate(self, manager):

        self._entries["floor_texture"]  = manager.floor_texture
        self._entries["edge_width"]     = manager.edge_width
        self._entries["sky_texture"]    = manager.sky_texture
        self._entries["start_node"]     = manager.start_node
        self._entries["edge_width"]     = manager.edge_width
        self._entries["wall_height"]    = manager.wall_height

    def validate(self):
        (result, message) = DataValidator.validate(DataStore.EVENT.ENVIRONMENT_EDIT, {
            "floor_texture" : self._floorSel.get(),
            "sky_texture"   : self._skySel.get()
        })
        if result is not True:
            tkMessageBox.showerror("Input Error", message)
        return result

    def apply(self):
        self._entries["floor_texture"] = self._floorSel.get()
        self._entries["edge_width"] = self._edgeScale.get()
        self._entries["sky_texture"] = self._skySel.get()
        self._entries["wall_height"] = self._wallScale.get()
        self._manager.inform(DataStore.EVENT.ENVIRONMENT_EDIT, self._entries)

    def auto_populate(self):
        self._floorSel.set(Defaults.Environment.FLOOR_TEXTURE)
        self._skySel.set(Defaults.Environment.SKY_TEXTURE)
        self._wallScale.set(Defaults.Environment.WALL_HEIGHT)
        self._edgeScale.set(Defaults.Environment.EDGE_WIDTH)
        self._start_node.config(text=Defaults.Environment.START_NODE)
예제 #40
0
SPRING_CONSTANT = 0.01 # Contant for sprint force
COULOMB_CONSTANT = 0.01 # Constant for coulomb force
WALL_CONSTANT = 0.250 # Static constant used for a wall force to center the nodes
TIME_CONSTANT = 1.0 # Time constant for speed of forces
DECAY_CONSTANT = 1.0 # Speed of damping both overall force and velocity

#Initializes the Tkinter frame and sliders
root = Tk()
#Adds horizontal sliders at the bottom for FDL constants
timeInput = Scale(root, from_=1, to=500,orient=HORIZONTAL,label="Time",relief = FLAT)
springInput = Scale(root, from_=1, to=1000,orient=HORIZONTAL,label="Spring",relief = FLAT)
coulombInput = Scale(root, from_=1, to=1000,orient=HORIZONTAL,label="Coulomb",relief = FLAT)
decayInput = Scale(root, from_=0, to=100,orient=HORIZONTAL,label="Decay",relief = FLAT)

#Sets initial FDL constant values
timeInput.set(100)
springInput.set(250)
coulombInput.set(500)
decayInput.set(90)

#Initializes the canvas for animation 
canvas = Canvas(width=width, height=height, bg="#f0f0f0")
canvas.pack(fill = "both", expand = 1, padx=50)

#Adds teh sliders to the tkinter frame after the canvas for positioning
timeInput.pack(side=LEFT, padx=50, pady=10)
springInput.pack(side=LEFT, padx=50, pady=10)
coulombInput.pack(side=LEFT, padx=50, pady=10)
decayInput.pack(side=LEFT, padx=50, pady=10)

#Smallest node size in pixels
예제 #41
0
class Controls:
    def __init__(self, profile):
        self.profile = profile

        self.show_rgb_mask = False
        self.show_hsv_mask = False

    def start(self, master):

        self.master = master
        master.title("Controls")

        self.rgb_red_min = Scale(master, from_=0, to=255, background="red")
        self.rgb_red_max = Scale(master, from_=0, to=255, background="red")

        self.hue_label = Label(master, text="hue", background="white")
        self.sat_label = Label(master, text="sat", background="white")
        self.val_label = Label(master, text="val", background="white")

        self.rgb_green_min = Scale(master, from_=0, to=255, background="green")
        self.rgb_green_max = Scale(master, from_=0, to=255, background="green")

        self.rgb_blue_min = Scale(master, from_=0, to=255, background="blue")
        self.rgb_blue_max = Scale(master, from_=0, to=255, background="blue")

        self.hsv_hue_min = Scale(master, from_=0, to=255, background="white")
        self.hsv_hue_max = Scale(master, from_=0, to=255, background="white")

        self.hsv_sat_min = Scale(master, from_=0, to=255, background="white")
        self.hsv_sat_max = Scale(master, from_=0, to=255, background="white")

        self.hsv_val_min = Scale(master, from_=0, to=255, background="white")
        self.hsv_val_max = Scale(master, from_=0, to=255, background="white")

        # set default values
        self.rgb_red_min.set(self.profile.red[0])
        self.rgb_red_max.set(self.profile.red[1])

        self.rgb_green_min.set(self.profile.green[0])
        self.rgb_green_max.set(self.profile.green[1])

        self.rgb_blue_min.set(self.profile.blue[0])
        self.rgb_blue_max.set(self.profile.blue[1])

        self.hsv_hue_min.set(self.profile.hsv_hue[0])
        self.hsv_hue_max.set(self.profile.hsv_hue[1])

        self.hsv_sat_min.set(self.profile.hsv_sat[0])
        self.hsv_sat_max.set(self.profile.hsv_sat[1])

        self.hsv_val_min.set(self.profile.hsv_val[0])
        self.hsv_val_max.set(self.profile.hsv_val[1])

        self.show_rgb_mask_var = IntVar()
        self.show_rgb_mask_check = Checkbutton(master,
                                               text="RGB Mask",
                                               variable=self.show_rgb_mask_var)

        self.show_hsv_mask_var = IntVar()
        self.show_hsv_mask_check = Checkbutton(master,
                                               text="HSV Mask",
                                               variable=self.show_hsv_mask_var)

        # LAYOUT
        self.rgb_red_min.grid(row=0, column=0)
        self.rgb_red_max.grid(row=0, column=1)
        self.hue_label.grid(row=1, column=0, columnspan=2)
        self.sat_label.grid(row=1, column=2, columnspan=2)
        self.val_label.grid(row=1, column=4, columnspan=2)

        self.rgb_green_min.grid(row=0, column=2)
        self.rgb_green_max.grid(row=0, column=3)

        self.rgb_blue_min.grid(row=0, column=4)
        self.rgb_blue_max.grid(row=0, column=5)

        self.hsv_hue_min.grid(row=2, column=0)
        self.hsv_hue_max.grid(row=2, column=1)

        self.hsv_sat_min.grid(row=2, column=2)
        self.hsv_sat_max.grid(row=2, column=3)

        self.hsv_val_min.grid(row=2, column=4)
        self.hsv_val_max.grid(row=2, column=5)

        self.show_rgb_mask_check.grid(row=3, column=0)
        self.show_hsv_mask_check.grid(row=3, column=1)

    def update_profile(self):

        self.rgb_red_min.set(
            min(self.rgb_red_min.get(), self.rgb_red_max.get()))
        self.rgb_red_max.set(
            max(self.rgb_red_min.get(), self.rgb_red_max.get()))

        self.profile.red = [self.rgb_red_min.get(), self.rgb_red_max.get()]

        self.profile.green = [
            self.rgb_green_min.get(),
            self.rgb_green_max.get()
        ]

        self.profile.blue = [self.rgb_blue_min.get(), self.rgb_blue_max.get()]

        self.profile.hsv_hue = [self.hsv_hue_min.get(), self.hsv_hue_max.get()]

        self.profile.hsv_sat = [self.hsv_sat_min.get(), self.hsv_sat_max.get()]

        self.profile.hsv_val = [self.hsv_val_min.get(), self.hsv_val_max.get()]

        self.show_rgb_mask = self.show_rgb_mask_var.get() == 1
        self.show_hsv_mask = self.show_hsv_mask_var.get() == 1
예제 #42
0
파일: GUI.py 프로젝트: NissankaW/Mariokart3
class SteeringFrame(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)   
        self.parent = parent
        self.initialize()
        
    def initialize(self):
        self.grid()
        self.entryVariable = StringVar()
        self.entry = Entry(self, textvariable=self.entryVariable)
        self.entry.grid(column=0,row=0,sticky='EW')
        self.entry.bind("<Return>", self.OnPressEnter)

        button = Button(self,text="Set Steering", command=self.OnButtonClick)
        button.grid(column=1,row=0)

        self.labelVariable = StringVar()
        label = Label(self,textvariable=self.labelVariable,
                              anchor="w",fg="white",bg="green")
        label.grid(column=0,row=1,columnspan=1,sticky='EW')
        self.labelVariable.set("Start..")

        left = Button(self,text="Left", command=self.Left)
        left.grid(column=0,row=2)

        right = Button(self,text="Right", command=self.Right)
        right.grid(column=1,row=2)

        centre = Button(self,text="Centre", command=self.Centre)
        centre.grid(column=3,row=2)

        self.steerVariable = StringVar()
        steerState = Label(self,textvariable=self.steerVariable,
                           anchor="w",fg="white",bg="green")
        steerState.grid(column=0,row=3,columnspan=1,sticky='EW')
        self.steerVariable.set("Start..")
        
        self.turn_angle = steering.GetTurnAngle();
        
        self.slider = Scale(self, from_=-self.turn_angle, to=self.turn_angle, 
                            orient=HORIZONTAL, command=self.setSteerState)
        self.slider.grid(column=0, row=4, columnspan=3, sticky='EW')        

        self.grid_columnconfigure(0,weight=1)
        self.update()
        #self.geometry(self.geometry()) # caused busy wait?
        self.entry.focus_set()
        #self.entry.selection_range(0, Tkinter.END) # caused busy wait?

    def OnButtonClick(self):
        steerAngle = int(self.entryVariable.get())
        steering.SetAngle(steerAngle)
        self.slider.set(steerAngle)
        self.labelVariable.set("Steering set: " + str(steerAngle) )
        self.entry.focus_set()
        self.entry.selection_range(0, END)
        
    def OnPressEnter(self,event):
        steerAngle = int(self.entryVariable.get())
        steering.SetAngle(steerAngle)
        self.slider.set(steerAngle)
        self.labelVariable.set("Steering set: " + str(steerAngle) )
        self.entry.focus_set()
        self.entry.selection_range(0, END)


    def Left(self):
        self.steerVariable.set("LEFT")
        steering.TurnLeft()
        self.slider.set(-self.turn_angle)

    def Right(self):
        self.steerVariable.set("RIGHT")
        steering.TurnRight()
        self.slider.set(self.turn_angle)

    def Centre(self):
        self.steerVariable.set("CENTRE")
        steering.TurnStraight()
        self.slider.set(0)
        
    def setSteerState(self, val):
        val = self.slider.get()
        steering.SetAngle(val)
        steerAngle = val;
        self.steerVariable.set("Steering: " + str(val) )           
예제 #43
0
class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind((host, port))
        self.grid()
        self.columnconfigure(0, minsize=100)
        self.columnconfigure(1, minsize=200)
        self.columnconfigure(2, minsize=200)
        self.columnconfigure(3, minsize=150)
        self.columnconfigure(4, minsize=150)
        self.columnconfigure(5, minsize=150)
        self.columnconfigure(6, minsize=150)
        self.create_widgets()
        self.settables = self.assemble_settables()
        self.gui_logger = logging.getLogger('gui')
        self.request_update()

    def create_widgets(self):
        self.create_monitor()
        self.create_check_buttons()
        self.create_ranges()
        self.create_scales()
        self.create_radio_buttons()
        self.create_voices()
        self.quitButton = Button(self, text='Quit', command=self.quit)
        self.quitButton.grid(columnspan=7, sticky=E + W)

    def assemble_settables(self):
        settables = self.winfo_children()
        for w in settables:
            settables += w.winfo_children()
        return filter(lambda w: w.__class__.__name__ in ['Scale', 'Checkbutton'], settables)

    def create_radio_buttons(self):
        # Scale related
        entries = ['DIATONIC', 'HARMONIC', 'MELODIC', 'PENTATONIC', 'PENTA_MINOR']
        self.scale = StringVar()
        self.scale.set('DIATONIC')
        self.rb_frame = Frame(self)
        for e in entries:
            rb = Radiobutton(self.rb_frame, value=e, text=e, anchor=W,
                             command=self.send_scale, variable=self.scale)
            rb.grid(row=len(self.rb_frame.winfo_children()), sticky=W)
        self.rb_frame.grid(column=1, row=len(self.grid_slaves(column=1)), rowspan=3)

    def create_monitor(self):
        self.monitor_frame = LabelFrame(self, text="Monitor and Transport")
        this_cycle = Scale(self.monitor_frame, label='cycle_pos', orient=HORIZONTAL,
                         from_=1, to=16, resolution=1)
        this_cycle.disable, this_cycle.enable = (None, None)
        this_cycle.ref = 'cycle_pos'
        this_cycle.grid(column=0, row=0, sticky=E + W)
        self.updateButton = Button(self.monitor_frame,
                                   text='Reload all Settings',
                                   command=self.request_update)
        self.updateButton.grid(row=1, sticky=E + W)
        self.ForceCaesuraButton = Button(self.monitor_frame,
                                         text='Force Caesura',
                                         command=self.force_caesura)
        self.ForceCaesuraButton.grid(row=2, sticky=E + W)
        self.saveBehaviourButton = Button(self.monitor_frame,
                                        text='Save current behaviour',
                                        command=self.request_saving_behaviour)
        self.saveBehaviourButton.grid(row=3, sticky=E + W)
        self.saveBehaviourNameEntry = Entry(self.monitor_frame)
        self.saveBehaviourNameEntry.grid(row=4, sticky=E + W)
        self.saveBehaviourNameEntry.bind('<KeyRelease>', self.request_saving_behaviour)
        self.selected_behaviour = StringVar()
        self.selected_behaviour.trace('w', self.new_behaviour_chosen)
        self.savedBehavioursMenu = OptionMenu(self.monitor_frame,
                                            self.selected_behaviour, None,)
        self.savedBehavioursMenu.grid(row=5, sticky=E + W)
        self.monitor_frame.grid(column=0, row=10, sticky=E + W)

    def request_update(self):
        self.send({'sys': 'update'})

    def request_saving_behaviour(self, event=None):
        """callback for save behaviour button and textentry"""
        if event and event.widget == self.saveBehaviourNameEntry:
            if event.keysym == 'Return':
                name = self.saveBehaviourNameEntry.get()
                self.saveBehaviourNameEntry.delete(0, len(name))
            else:
                return
        else:  # button was pressed
            name = self.saveBehaviourNameEntry.get()
        if name:
            self.send({'sys': ['save_behaviour', name]})

    def force_caesura(self):
        self.send({'force_caesura': True})

    def create_voices(self):
        voice_ids = ['1', '2', '3', '4']
        SCALES = OrderedDict([
                  ('pan_pos', {'min': -1, 'max': 1, 'start': 0.5, 'res': 0.001}),
                  ('volume', {'min': 0, 'max': 1, 'start': 0.666, 'res': 0.001}),
                  ('slide_duration_msecs', {'min': 0, 'max': 2000, 'start': 60, 'res': 1}),
                  ('slide_duration_prop', {'min': 0, 'max': 2, 'start': 0.666, 'res': 0.001}),
                  ('binaural_diff', {'min': 0, 'max': 66, 'start': 0.2, 'res': 0.01})
                ])

        for vid in voice_ids:
            counter = 0
            for sca in SCALES:
                name = 'voice_' + vid + '_' + sca
                setattr(self, 'min_' + name, SCALES[sca]['min'])
                setattr(self, 'max_' + name, SCALES[sca]['max'])
                this_sca = Scale(self, label=sca, orient=HORIZONTAL,
                                from_=getattr(self, 'min_' + name),
                                to=getattr(self, 'max_' + name),
                                resolution=SCALES[sca]['res'])
                this_sca.enable = ('enable' in SCALES[sca].keys() and
                                   SCALES[sca]['enable'] or None)
                this_sca.disable = ('disable' in SCALES[sca].keys() and
                                    SCALES[sca]['disable'] or None)
                this_sca.grid(column=int(2 + int(vid)), row=counter, sticky=E + W)
                this_sca.bind("<ButtonRelease>", self.scale_handler)
                this_sca.ref = name
                counter += 1
        CHECK_BUTTONS = OrderedDict(
                 [('mute', False),
                  ('automate_binaural_diffs', True),
                  ('automate_note_duration_prop', True),
                  ('use_proportional_slide_duration', {'val': True, 'label': 'proportional slide'}),
                  ('automate_pan', True),
                  ('automate_wavetables', True)])
        for vid in voice_ids:
            counter = 0
            cb_frame = LabelFrame(self, text="Voice {0} - Automation".format(vid))
            setattr(self, 'voice_' + vid + '_cb_frame', cb_frame)
            for cb in CHECK_BUTTONS:
                options = CHECK_BUTTONS[cb]
                name = 'voice_' + vid + '_' + cb
                label = (options['label'] if isinstance(options, dict) and
                                             'label' in options.keys() else
                                              (cb[9:] if cb[:9] == 'automate_' else cb))
                setattr(self, name, IntVar(value=type(options) == dict and options['val'] or options))
                self.this_cb = Checkbutton(cb_frame, text=label, variable=getattr(self, name))
                self.this_cb.bind('<Button-1>', self.check_boxes_handler)
                self.this_cb.disable = None
                self.this_cb.grid(sticky=W, column=0, row=counter)
                self.this_cb.ref = name
                counter += 1
            # add trigger wavetable-button
            trigWavetableButton = Button(cb_frame, text='Next Wavetable')
            trigWavetableButton.bind('<Button-1>', self.trigger_waveform_handler)
            trigWavetableButton.ref = 'voice_' + vid + "_trigger_wavetable"
            trigWavetableButton.grid(row=counter)
            cb_frame.grid(column=int(vid) + 2, row=5, sticky=E + W + N, rowspan=8)
        for vid in voice_ids:
            generation_types = ["random", "random_harmonic", "harmonic"]
            partial_pools = ["even", "odd", "all"]
            prefix = 'voice_' + vid + '_'
            types_name = prefix + 'wavetable_generation_type'
            pools_name = prefix + 'partial_pool'
            setattr(self, types_name, StringVar())
            getattr(self, types_name).set("random")
            setattr(self, pools_name, StringVar())
            getattr(self, pools_name).set("all")
            target_frame = getattr(self, 'voice_' + vid + '_cb_frame')
            gen_typ_frame = LabelFrame(target_frame, text="type")
            gen_typ_frame.grid(row=len(target_frame.winfo_children()), sticky=W)
            for gen_t in generation_types:
                gen_t_entry = Radiobutton(gen_typ_frame, value=gen_t, text=gen_t, anchor=W,
                                          variable=getattr(self, types_name))
                gen_t_entry.bind('<ButtonRelease-1>', self.wt_handler)
                gen_t_entry.ref = types_name
                gen_t_entry.grid(row=len(gen_typ_frame.winfo_children()), sticky=W)
            pp_frame = LabelFrame(target_frame, text="harmonics")
            for pp in partial_pools:
                pp_entry = Radiobutton(pp_frame, value=pp, text=pp, anchor=W,
                                        variable=getattr(self, pools_name))
                pp_entry.bind('<ButtonRelease-1>', self.wt_handler)
                pp_entry.ref = pools_name
                pp_entry.grid(row=len(pp_frame.winfo_children()), sticky=E + W)
            this_num_partials = Scale(pp_frame, label='number of harmonics', orient=HORIZONTAL,
                             from_=1, to=24, resolution=1)
            this_num_partials.ref = prefix + 'num_partials'
            this_num_partials.grid(column=0, row=len(pp_frame.winfo_children()), sticky=E + W)
            this_num_partials.bind("<ButtonRelease>", self.scale_handler)
            pp_frame.grid(row=len(target_frame.winfo_children()), sticky=E + W)

    def wt_handler(self, event):
        print event.widget.tk
        ref = event.widget.ref
        self.send({ref: getattr(self, ref).get()})

    def create_check_buttons(self):
        self.cb_frame = LabelFrame(self, text="Global Settings")
        for cb in CHECK_BUTTONS:
            label = cb
            target_parent = self.cb_frame
            if isinstance(CHECK_BUTTONS[cb], dict) and  'sub_frame' in CHECK_BUTTONS[cb].keys():
                target_parent = getattr(self, CHECK_BUTTONS[cb]['sub_frame'])
            setattr(self, cb, IntVar(value=type(CHECK_BUTTONS[cb]) == dict and
                                           CHECK_BUTTONS[cb]['val'] or
                                           CHECK_BUTTONS[cb]))
            self.this_cb = Checkbutton(target_parent, text=label, variable=getattr(self, cb))
            self.this_cb.bind('<Button-1>', self.check_boxes_handler)
            self.this_cb.disable = (type(CHECK_BUTTONS[cb]) == dict and
                                   'disable' in CHECK_BUTTONS[cb].keys())
            self.this_cb.grid(sticky=W, column=0, row=len(target_parent.winfo_children()))
            self.this_cb.ref = cb
        for but in GLOBAL_BUTTONS:
            label = but
            ele = GLOBAL_BUTTONS[but]
            this_but = Button(self.cb_frame, text=but)
            this_but.bind('<ButtonRelease-1>', getattr(self, ele['handler']))
            this_but.ref = but
            this_but.grid(sticky=W, column=0, row=len(self.cb_frame.winfo_children()))
        self.cb_frame.grid(column=0, row=0, rowspan=10, sticky=N)

    def new_behaviour_chosen(self, a, b, c):
        self.send({'sys': ['change_behaviour', self.selected_behaviour.get()]})

    def set_value(self, name, val):
        '''sets a widget to the specified value

        various different widget types need custom setting functionality'''

        direct = ['scale', 'wavetable_generation_type', 'partial_pool']
        if filter(lambda x: match("(voice_\d_|)" + x, name), direct):
            self.gui_logger.info("setting: '{0}' to '{1}' in GUI".format(name, val))
            getattr(self, name).set(val)
            return
        if name == 'saved_behaviours' and len(val):
            self.savedBehavioursMenu.destroy()
            self.savedBehavioursMenu = OptionMenu(self.monitor_frame,
                                                  self.selected_behaviour, *sorted(val))
            self.savedBehavioursMenu.grid(row=5, sticky=E + W)
            return
        for w in self.settables:
            typ = w.__class__.__name__
            if w.ref == name:
                #print "setting '{0}' of type: '{1}' to: {2}".format(name, typ, val)
                if typ == 'Scale':
                    w.set(val)
                elif typ == "Checkbutton":
                    w.select() if val else w.deselect()

    def check_boxes_handler(self, event):
        '''handles checkbox events.

        shows and hides gui elements according to their enable/disable fields'''
        #print event.__dict__
        #print event.widget.__dict__
        ref = event.widget.ref
        val = not getattr(self, ref).get()  # because is read before the var is changed
        self.send({ref: val})
        #print ref, val
        # handle gui elements
        # enable/disable functionality temporarily(?) commented on:
        # Wed Aug 17 09:39:54 CEST 2011
#        if event.widget.disable:
#            for w in self.children.values():
#
#                # this try clause is for debugging, remove when stable
#                try:
#                    w.ref
#                    #print w.ref
#                except:
#                    pass
#                if (w.__class__.__name__ == 'Scale' and
#                    (w.disable or w.enable)):
#                    if w.disable == ref:
#                        if val:
#                            w.grid()
#                        else:
#                            w.grid_remove()
#                    elif w.enable == ref:
#                        if val:
#                            w.grid_remove()
#                        else:
#                            w.grid()
#                    #print w.disable, w.enable

    def create_scales(self):
        counter = 0
        for sca in SCALES:
            label = SCALES[sca]['label'] if 'label'  in SCALES[sca].keys() else sca
            setattr(self, 'min_' + sca, SCALES[sca]['min'])
            setattr(self, 'max_' + sca, SCALES[sca]['max'])
            self.this_scale = Scale(self, label=label, orient=HORIZONTAL,
                                    from_=getattr(self, 'min_' + sca),
                                    to=getattr(self, 'max_' + sca),
                                    resolution=SCALES[sca]['res'])
            self.this_scale.set(SCALES[sca]['start'])
            self.this_scale.enable = ('enable' in SCALES[sca].keys() and
                                      SCALES[sca]['enable'] or None)
            self.this_scale.disable = ('disable' in SCALES[sca].keys() and
                                      SCALES[sca]['disable'] or None)
            if 'pos' in SCALES[sca].keys():
                pos = SCALES[sca]['pos']
                col = pos['c']
                row = pos['r']
            else:
                row = counter
                col = 1
                counter += 1
            self.this_scale.grid(column=col, row=row, sticky=E + W)
            self.this_scale.ref = sca
            self.this_scale.bind("<ButtonRelease>", self.scale_handler)

    def scale_handler(self, event):
        self.send({event.widget.ref: event.widget.get()})
        self.gui_logger.info("handling scale: {0}, with new value: {1}".format(
                  event.widget.ref, event.widget.get()))

    def trigger_waveform_handler(self, event):
        self.send({event.widget.ref: True})
        #print event.widget.ref, "- triggering wavetable"

    def send_scale(self):
        do = {'scale': self.scale.get()}
        self.send(do)
        #print do

    def send(self, msg):
        self.gui_logger.info("sending: {0}".format(msg))
        self.send_sock.sendto(json.dumps(msg), (remote_host, send_port))

    def create_ranges(self):
        counter = 0
        for ran in RANGES:
            setattr(self, 'min_' + ran, RANGES[ran]['min'])
            setattr(self, 'max_' + ran, RANGES[ran]['max'])
            self.this_min_scale = Scale(self, label='min ' + ran, orient=HORIZONTAL,
                                        from_=getattr(self, 'min_' + ran),
                                        to=getattr(self, 'max_' + ran),
                                        resolution=RANGES[ran]['res'])
            self.this_max_scale = Scale(self, label='max ' + ran, orient=HORIZONTAL,
                                        from_=getattr(self, 'min_' + ran),
                                        to=getattr(self, 'max_' + ran),
                                        resolution=RANGES[ran]['res'])
            self.this_min_scale.set(RANGES[ran]['min_start'])
            self.this_max_scale.set(RANGES[ran]['max_start'])
            self.this_min_scale.enable = ('enable' in RANGES[ran].keys() and
                                           RANGES[ran]['enable'] or None)
            self.this_min_scale.disable = ('disable' in RANGES[ran].keys() and
                                            RANGES[ran]['disable'] or None)
            self.this_max_scale.enable = ('enable' in RANGES[ran].keys() and
                                          RANGES[ran]['enable'] or None)
            self.this_max_scale.disable = ('disable' in RANGES[ran].keys() and
                                          RANGES[ran]['disable'] or None)
            self.this_min_scale.grid(column=2, row=counter, sticky=E + W)
            self.this_max_scale.grid(column=2, row=counter + 1, sticky=E + W)
            self.this_min_scale.ref = 'min_' + ran
            self.this_max_scale.ref = 'max_' + ran
            self.this_min_scale.bind("<ButtonRelease>", self.scale_handler)
            self.this_max_scale.bind("<ButtonRelease>", self.scale_handler)
            counter += 2

    def socket_read_handler(self, file, mask):
        data_object = json.loads(file.recv(1024))
        do = data_object.items()[0]
        #print "do:", do
        self.set_value(do[0], do[1])
예제 #44
0
class Visualiser(object):
    '''
    Generic Offline Visualiser. Subclasses need to be used that specify
    how to handle a data source.
    '''
    
    ### Public functions ###

    def __init__(self,
                 title="Visualisation",
                 width=400,
                 height=400,
                 recording=False,
                 recordPattern=None,
                 paused=False,
                 source=None):
        '''
        Constructor.

        Params:
        title: string - Title of the visualisation window
        width: int - Width of the visualisation window
        height: int - Height of the visualisation window
        recording: boolean - Start with recording enabled?
        recordPattern: string - Pattern for recorded images,
          e.g., cylinders%05g.png
        paused: boolean - Start with playback paused?
        source:- The data source to read.
          What is required here varies by visualiser.
        '''

        # Visualisation options
        self.vis_features = []
        self.vis_frame = 0
        self.vis_frameStep = 1
        self.vis_jumping = False
        self.vis_recording = recording
        self.vis_recordPattern = recordPattern
        self.vis_paused = paused
        self.vis_source = source

        # VTK structures
        self.vtk_cells = vtkCellArray()
        self.vtk_renderer = vtkRenderer()

        # Tk structures
        self.tk_root = Tk()
        self.tk_root.title(title)
        self.tk_root.grid_rowconfigure(0, weight=1)
        self.tk_root.grid_columnconfigure(0, weight=3)
        self.tk_root.bind('<Destroy>', self.destroyed)
        if not self.vis_paused: self.tk_root.after(100, self.animate)            

        self.tk_renderWidget = vtkTkRenderWidget(self.tk_root,
                                                 width=width,
                                                 height=height)
        self.tk_renderWidget.grid(row=0, column=0, sticky=N+S+E+W)
        self.tk_renderWidget.GetRenderWindow().AddRenderer(self.vtk_renderer)

        self.tk_featureFrame = Frame(self.tk_root)
        self.tk_featureFrame.grid(row=0, column=1, rowspan=2)
        Label(self.tk_featureFrame, text='Features:').grid(row=0, column=0)

        self.tk_controlFrame = Frame(self.tk_root)
        self.tk_controlFrame.grid(row=1, column=0)

        self.tk_quit = Button(self.tk_controlFrame, text="Quit",
                              command=self.shutdown)
        self.tk_quit.grid(row=0, column=0, columnspan=2)

        def pause():
            if self.vis_paused:
                self.tk_pause.config(text='Pause')
                self.tk_root.after(100, self.animate)
            else:
                self.tk_pause.config(text='Resume')
            self.vis_paused ^= True
        self.tk_pause = Button(self.tk_controlFrame, text="Pause", command=pause)
        self.tk_pause.grid(row=0, column=2, columnspan=2)

        if self.vis_recordPattern is not None:
            def record():
                if self.vis_recording:
                    self.tk_record.config(text='Start Recording')
                else:
                    self.tk_record.config(text='Stop Recording')
                self.vis_recording ^= True
            self.tk_record = Button(self.tk_controlFrame, text="Start Recording", command=record)
            self.tk_record.grid(row=0, column=4, columnspan=2)
            if self.vis_recording:
                self.tk_record.config(text="Stop Recording")

        def make_seek_button(label, column, frame):
            def jump():
                self.jumpTo(frame)
            b = Button(self.tk_controlFrame,
                       text=label,
                       command=jump)
            b.grid(row=1, column=column, sticky=W+E)
            return b
        self.tk_seek_start = make_seek_button("|<", 0, 0)
        self.tk_seek_back10 = make_seek_button("<<", 1,
                                               lambda: self.vis_frame - 10)
        self.tk_seek_back1 = make_seek_button("<", 2,
                                              lambda: self.vis_frame - 1)
        self.tk_seek_forward1 = make_seek_button(">", 3,
                                                 lambda: self.vis_frame + 1)
        self.tk_seek_forward10 = make_seek_button(">>", 4,
                                                  lambda: self.vis_frame + 10)
        self.tk_seek_end = make_seek_button(">|", 5,
                                            self.getMaxFrameNumber)

        Label(self.tk_controlFrame, text='Frame').grid(row=2, column=0,
                                                       sticky=W+E)
        def changeFrame(frame):
            if not self.vis_jumping:
                self.vis_jumping = True
                self.jumpTo(self.tk_frame.get())
                self.vis_jumping = False
        self.tk_frame = Scale(self.tk_controlFrame, command=changeFrame,
                              from_=0, to=0, orient=HORIZONTAL)
        self.tk_frame.grid(row=2, column=1, columnspan=2, sticky=W+E)

        Label(self.tk_controlFrame, text='Step').grid(row=2, column=3,
                                                     sticky=W+E)
        def changeFrameStep(step):
            self.vis_frameStep = int(step)
        self.tk_frameStep = Scale(self.tk_controlFrame, command=changeFrameStep,
                                  from_=1, to=1, orient=HORIZONTAL)
        self.tk_frameStep.grid(row=2, column=4, columnspan=2, sticky=W+E)

        self.setupGrid()

    def add_feature(self, feature):
        '''Add a feature to this visualiser'''
        self.vis_features.append(feature)
        feature.button(self.tk_featureFrame).grid(row=len(self.vis_features),
                                                  column=0, sticky=W+E)
        feature.visualiser = self

    def run(self):
        '''Start the visualiser'''
        self.redraw()
        self.tk_root.mainloop()

    ### Private funcitions ###

    def resetSliders(self):
        '''
        Recalculate the upper bound on the frame and frameStep
        sliders.
        '''
        maxFrame = self.getMaxFrameNumber()
        self.tk_frame.config(to=maxFrame)
        self.tk_frameStep.config(to=maxFrame)

    def jumpTo(self, frame):
        '''
        Jump to a given frame. If frame is a function, jump to the
        return value of frame().
        '''
        oldFrame = self.vis_frame
        if hasattr(frame, '__call__'):
            self.vis_frame = frame()
        else:
            self.vis_frame = frame

        maxFrame = self.getMaxFrameNumber()

        if self.vis_frame < 0:
            self.vis_frame = 0
        elif self.vis_frame > maxFrame:
            self.vis_frame = maxFrame
            self.vis_paused = True
            self.tk_pause.config(text='Resume')

        self.tk_frame.set(self.vis_frame)
        self.redraw(oldFrame != self.vis_frame)

    def redraw(self, update=False):
        self.resetSliders()
        for feature in [ f for f in self.vis_features if not f.dynamic ]:
            feature.draw(self.vtk_renderer)
        if update:
            for feature in [ f for f in self.vis_features if f.dynamic]:
                f.redraw(self.vtk_renderer)
        self.tk_renderWidget.GetRenderWindow().Render()
        self.tk_root.update_idletasks()

    ### Gui events ###

    def destroyed(self, event):
        if event.widget == self.tk_root:
            self.shutdown()

    def shutdown(self):
        self.tk_root.withdraw()
        self.tk_root.destroy()

    def animate(self):
        if not self.vis_paused:
            self.jumpTo(self.vis_frame + self.vis_frameStep)
            if self.vis_recording and self.vis_recordPattern is not None:
                self.save_image()
            self.tk_root.after(100, self.animate)

    def save_image(self):
        extmap = {'.jpg' : vtkJPEGWriter,
                  '.jpeg' : vtkJPEGWriter,
                  '.png' : vtkPNGWriter,
                  '.pnm' : vtkPNMWriter}
        _, ext = splitext(self.vis_recordPattern)
        try: writer = extmap[ext.lower()]()
        except KeyError:
            print 'ERROR: Can\'t handle %s extension. Recording disabled.' % ext
            self.vis_recordPattern = None
            return

        win = self.vtk_renderer.GetRenderWindow()
        w2i = vtkWindowToImageFilter()
        w2i.SetInput(win)
        w2i.Update()
        writer.SetInput(w2i.GetOutput())
        writer.SetFileName(self.vis_recordPattern % self.vis_frame)
        win.Render()
        writer.Write()

    ### Things subclasses need to override ###

    def setupGrid(self):
        '''
        Populate the vtkCellArray instance at
        self.vtk_cells. Subclasses are required to override this
        function to read from their source as appropriate.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::setupGrid!')

    def getMaxFrameNumber(self):
        '''
        Return the maximum frame number. This will need to be defined
        by a subclass.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::getMaxFrameNumber!')

    def getQuantityPoints(self, quantityName, dynamic=True, frameNumber=0):
        '''
        Return the points of a quantity at a given frame as a list
        [float]. Subclasses need to override this.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::getQuantityPoints!')

    def getQuantityDict(self):
        '''
        Return the values of all quantities at a given time as a
        dictionary. Sublclasses need to override this.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::getQuantityDict!')
print "If Wekinator is not already listening for OSC, we will get an error."
print "*******"

send_address = '127.0.0.1', 6448

# OSC basic client
c = OSC.OSCClient()
c.connect(send_address)  # set the address for all following messages


def showValues():
    label1.config(text=str(w1.get()))
    label1.after(100, showValues)
    oscmsg = OSC.OSCMessage()
    oscmsg.setAddress("/wek/inputs")
    oscmsg.append(float(w1.get()))
    c.send(oscmsg)


master = Tk()
w1 = Scale(master, from_=100, to=0, length=400, tickinterval=10)
w1.set(0)
w1.pack()

label1 = Label(master, fg="green")
label1.pack()

showValues()

master.mainloop()
예제 #46
0
파일: dashboard.py 프로젝트: ilnurgi/robot
class Application(object):
    def __init__(self):
        self.logger = get_logger('dashboard')

        self.server = SocketServer.UDPServer(
            (settings.DASHBOARD_HOST, settings.DASHBOARD_PORT),
            self.handle_request)
        self.server.timeout = settings.DASHBOARD_REQUEST_TIMEOUT

        self.raw_telem_time = 0
        self.raw_telem_bat = 0
        self.raw_telem_temp = 0
        self.raw_telem_photo = 0

        self.__init_main()
        self.__init_motor()
        self.__init_light()
        self.__init_video()
        self.__init_telem()

    def __init_main(self):
        self.window = Tk()
        self.window.wm_minsize(400, 400)

    def __init_motor(self):
        self.w_lf_motor = LabelFrame(self.window, text=u'Моторы')
        self.w_scale_motor1 = Scale(self.w_lf_motor, from_=-255, to=255)
        self.w_scale_motor2 = Scale(self.w_lf_motor, from_=-255, to=255)

        self.w_lf_motor.place(relx=0, rely=0, relwidth=1, relheight=0.3)
        self.w_scale_motor1.place(relx=0, rely=0, relwidth=1, relheight=1)
        self.w_scale_motor2.place(relx=0.5, rely=0, relwidth=1, relheight=1)

    def __init_light(self):
        self.w_lf_light = LabelFrame(self.window, text=u'Свет')
        self.w_l_light = Label(self.w_lf_light,
                               text=u'Выключен',
                               fg='red',
                               font='Arial 20')

        self.w_lf_light.place(relx=0, rely=0.3, relwidth=1, relheight=0.15)
        self.w_l_light.place(relx=0, rely=0, relwidth=1, relheight=1)

    def __init_video(self):
        self.w_lf_video = LabelFrame(self.window, text=u'Видео')
        self.w_l_video = Label(self.w_lf_video,
                               text=u'Выключен',
                               fg='red',
                               font='Arial 20')
        self.w_b_show = Button(self.w_lf_video,
                               text=u'mplayer',
                               command=self.start_mplayer)

        self.w_lf_video.place(relx=0, rely=0.45, relwidth=1, relheight=0.15)
        self.w_l_video.place(relx=0, rely=0, relwidth=0.7, relheight=1)
        self.w_b_show.place(relx=0.7, rely=0, relwidth=0.3, relheight=1)

    def __init_telem(self):
        # телеметрия
        self.w_lf_telem = LabelFrame(self.window, text=u'Телеметрия')
        self.w_l_telem_time = Label(self.w_lf_telem,
                                    text=u'0',
                                    font='Arial 15')
        self.w_l_telem_bat = Label(self.w_lf_telem, text=u'0', font='Arial 15')
        self.w_l_telem_temp = Label(self.w_lf_telem,
                                    text=u'0',
                                    font='Arial 15')
        self.w_l_telem_photo = Label(self.w_lf_telem,
                                     text=u'0',
                                     font='Arial 15')

        self.w_lf_telem.place(relx=0, rely=0.6, relwidth=1, relheight=0.4)

        Label(self.w_lf_telem, text=u'Время:',
              font='Arial 15').place(relx=0,
                                     rely=0,
                                     relwidth=0.5,
                                     relheight=0.25)
        Label(self.w_lf_telem, text=u'Батарея:',
              font='Arial 15').place(relx=0,
                                     rely=0.25,
                                     relwidth=0.5,
                                     relheight=0.25)
        Label(self.w_lf_telem, text=u'Температура:',
              font='Arial 15').place(relx=0,
                                     rely=0.5,
                                     relwidth=0.5,
                                     relheight=0.25)
        Label(self.w_lf_telem, text=u'Освещенность:',
              font='Arial 15').place(relx=0,
                                     rely=0.75,
                                     relwidth=0.5,
                                     relheight=0.25)

        self.w_l_telem_time.place(relx=0.5,
                                  rely=0,
                                  relwidth=0.5,
                                  relheight=0.25)
        self.w_l_telem_bat.place(relx=0.5,
                                 rely=0.25,
                                 relwidth=0.5,
                                 relheight=0.25)
        self.w_l_telem_temp.place(relx=0.5,
                                  rely=0.5,
                                  relwidth=0.5,
                                  relheight=0.25)
        self.w_l_telem_photo.place(relx=0.5,
                                   rely=0.75,
                                   relwidth=0.5,
                                   relheight=0.25)

    def set_motor_value(self, left_value, right_value):
        if left_value > 255:
            left_value = 255
        elif left_value < -255:
            left_value = -255
        self.w_scale_motor1.set(left_value)

        if right_value > 255:
            right_value = 255
        elif right_value < -255:
            right_value = -255
        self.w_scale_motor2.set(right_value)

    def set_light(self, value):
        """
        устанавливает значение для фонарика
        :param value:
        """
        if value == 1:
            self.w_l_light['text'] = u'Включен'
            self.w_l_light['fg'] = 'green'
        else:
            self.w_l_light['text'] = u'Выключен'
            self.w_l_light['fg'] = 'red'

    def set_video(self, value):
        """
        устанавливает значение для фонарика
        :param value:
        """
        if value == 1:
            self.w_l_video['text'] = u'Включен'
            self.w_l_video['fg'] = 'green'
        else:
            self.w_l_video['text'] = u'Выключен'
            self.w_l_video['fg'] = 'red'

    def set_time(self, value):
        """
        устанавливает значение для даты
        :param value:
        """
        if self.raw_telem_time == value:
            return
        self.raw_telem_time = value

        try:
            value = datetime.fromtimestamp(value).strftime('%Y.%m.%d %H:%M:%S')
        except Exception as err:
            print(err)
            self.logger.debug(str(err))

        self.w_l_telem_time['text'] = value

    def set_bat(self, value):
        """
        устанавливает значение для батареи
        :param value:
        """
        if self.raw_telem_bat == value:
            return
        self.raw_telem_bat = value

        self.w_l_telem_bat['text'] = value

    def set_temp(self, value):
        """
        устанавливает значение для температуры
        :param value:
        """
        if self.raw_telem_temp == value:
            return
        self.raw_telem_temp = value

        self.w_l_telem_temp['text'] = '{0} ({1})'.format(
            round((value * 3.3 / 1024 - 0.5) / 0.01, 3), value)

    def set_photo(self, value):
        """
        устанавливает значение для температуры
        :param value:
        """
        if self.raw_telem_photo == value:
            return
        self.raw_telem_photo = value

        self.w_l_telem_photo['text'] = value

    def start_mplayer(self):
        """
        включает mplayer
        """
        process = subprocess.Popen(settings.VIDEO_SHOW_CMD, shell=True)

    def handle_request(self, request, client_address, server):
        """
        обработка входных данных
        :param request:
        :param client_address:
        :param server:
        :return:
        """
        _request, _socket = request

        if ',' not in _request:
            return

        values = [int(i) for i in _request.split(',')]

        self.set_motor_value(*values[:2])
        self.set_light(values[2])
        self.set_video(values[3])
        self.set_time(values[4])
        self.set_temp(values[5])
        self.set_bat(values[6])
        self.set_photo(values[7])

    def wait_request(self):
        """"""
        self.server.handle_request()
        self.register_mainloop()

    def register_mainloop(self):
        """
        регистриуем обработчик, который периодический будет обрабатывать события
        """
        self.window.after(after_timeout, self.wait_request)

    def run(self):
        """"""
        try:
            self.register_mainloop()
            self.window.mainloop()
        except KeyboardInterrupt:
            pass
        except Exception as err:
            self.logger.debug(err)
            import traceback
            self.logger.debug(traceback.format_exc())
            raise
예제 #47
0
파일: pycx_gui.py 프로젝트: daanjo3/ICS2017
class GUI:
    def __init__(self,
                 model,
                 title='PyCX Simulator',
                 interval=0,
                 stepSize=1,
                 param_gui_names=None):
        self.model = model
        self.titleText = title
        self.timeInterval = interval
        self.stepSize = stepSize
        self.param_gui_names = param_gui_names
        if param_gui_names is None:
            self.param_gui_names = {}
        self.param_entries = {}
        self.statusStr = ""
        self.running = False
        self.modelFigure = None
        self.currentStep = 0

        self.initGUI()

    def initGUI(self):
        #create root window
        self.rootWindow = Tk()
        self.statusText = StringVar(value=self.statusStr)
        self.setStatusStr("Simulation not yet started")

        self.rootWindow.wm_title(self.titleText)
        self.rootWindow.protocol('WM_DELETE_WINDOW', self.quitGUI)
        self.rootWindow.geometry('550x700')
        self.rootWindow.columnconfigure(0, weight=1)
        self.rootWindow.rowconfigure(0, weight=1)

        self.frameSim = Frame(self.rootWindow)

        self.frameSim.pack(expand=YES, fill=BOTH, padx=5, pady=5, side=TOP)
        self.status = Label(self.rootWindow,
                            width=40,
                            height=3,
                            relief=SUNKEN,
                            bd=1,
                            textvariable=self.statusText)
        self.status.pack(side=TOP, fill=X, padx=1, pady=1, expand=NO)

        self.runPauseString = StringVar()
        self.runPauseString.set("Run")
        self.buttonRun = Button(self.frameSim,
                                width=30,
                                height=2,
                                textvariable=self.runPauseString,
                                command=self.runEvent)
        self.buttonRun.pack(side=TOP, padx=5, pady=5)

        self.showHelp(
            self.buttonRun,
            "Runs the simulation (or pauses the running simulation)")
        self.buttonStep = Button(self.frameSim,
                                 width=30,
                                 height=2,
                                 text="Step Once",
                                 command=self.stepOnce)
        self.buttonStep.pack(side=TOP, padx=5, pady=5)
        self.showHelp(self.buttonStep, "Steps the simulation only once")
        self.buttonReset = Button(self.frameSim,
                                  width=30,
                                  height=2,
                                  text="Reset",
                                  command=self.resetModel)
        self.buttonReset.pack(side=TOP, padx=5, pady=5)
        self.showHelp(self.buttonReset, "Resets the simulation")

        for param in self.model.params:
            var_text = self.param_gui_names.get(param, param)
            can = Canvas(self.frameSim)
            lab = Label(can,
                        width=25,
                        height=1 + var_text.count('\n'),
                        text=var_text,
                        anchor=W,
                        takefocus=0)
            lab.pack(side='left')
            ent = Entry(can, width=11)
            val = getattr(self.model, param)
            if isinstance(val, bool):
                val = int(val)  # Show 0/1 which can convert back to bool
            ent.insert(0, str(val))
            ent.pack(side='left')
            can.pack(side='top')
            self.param_entries[param] = ent
        if self.param_entries:
            self.buttonSaveParameters = Button(
                self.frameSim,
                width=50,
                height=1,
                command=self.saveParametersCmd,
                text="Save parameters to the running model",
                state=DISABLED)
            self.showHelp(
                self.buttonSaveParameters, "Saves the parameter values.\n" +
                "Not all values may take effect on a running model\n" +
                "A model reset might be required.")
            self.buttonSaveParameters.pack(side='top', padx=5, pady=5)
            self.buttonSaveParametersAndReset = Button(
                self.frameSim,
                width=50,
                height=1,
                command=self.saveParametersAndResetCmd,
                text="Save parameters to the model and reset the model")
            self.showHelp(
                self.buttonSaveParametersAndReset,
                "Saves the given parameter values and resets the model")
            self.buttonSaveParametersAndReset.pack(side='top', padx=5, pady=5)

        can = Canvas(self.frameSim)
        lab = Label(can,
                    width=25,
                    height=1,
                    text="Step size ",
                    justify=LEFT,
                    anchor=W,
                    takefocus=0)
        lab.pack(side='left')
        self.stepScale = Scale(can,
                               from_=1,
                               to=500,
                               resolution=1,
                               command=self.changeStepSize,
                               orient=HORIZONTAL,
                               width=25,
                               length=150)
        self.stepScale.set(self.stepSize)
        self.showHelp(
            self.stepScale,
            "Skips model redraw during every [n] simulation steps\n" +
            "Results in a faster model run.")
        self.stepScale.pack(side='left')
        can.pack(side='top')

        can = Canvas(self.frameSim)
        lab = Label(can,
                    width=25,
                    height=1,
                    text="Step visualization delay in ms ",
                    justify=LEFT,
                    anchor=W,
                    takefocus=0)
        lab.pack(side='left')
        self.stepDelay = Scale(can,
                               from_=0,
                               to=max(2000, self.timeInterval),
                               resolution=10,
                               command=self.changeStepDelay,
                               orient=HORIZONTAL,
                               width=25,
                               length=150)
        self.stepDelay.set(self.timeInterval)
        self.showHelp(
            self.stepDelay, "The visualization of each step is " +
            "delays by the given number of " + "milliseconds.")
        self.stepDelay.pack(side='left')
        can.pack(side='top')

    def setStatusStr(self, newStatus):
        self.statusStr = newStatus
        self.statusText.set(self.statusStr)

    #model control functions
    def changeStepSize(self, val):
        self.stepSize = int(val)

    def changeStepDelay(self, val):
        self.timeInterval = int(val)

    def saveParametersCmd(self):
        for param, entry in self.param_entries.items():
            val = entry.get()
            if isinstance(getattr(self.model, param), bool):
                val = bool(int(val))
            setattr(self.model, param, val)
            # See if the model changed the value (e.g. clipping)
            new_val = getattr(self.model, param)
            if isinstance(new_val, bool):
                new_val = int(new_val)
            entry.delete(0, END)
            entry.insert(0, str(new_val))
        self.setStatusStr("New parameter values have been set")

    def saveParametersAndResetCmd(self):
        self.saveParametersCmd()
        self.resetModel()

    def runEvent(self):
        if not self.running:
            self.running = True
            self.rootWindow.after(self.timeInterval, self.stepModel)
            self.runPauseString.set("Pause")
            self.buttonStep.configure(state=DISABLED)
            if self.param_entries:
                self.buttonSaveParameters.configure(state=NORMAL)
                self.buttonSaveParametersAndReset.configure(state=DISABLED)
        else:
            self.stopRunning()

    def stopRunning(self):
        self.running = False
        self.runPauseString.set("Continue Run")
        self.buttonStep.configure(state=NORMAL)
        self.drawModel()
        if self.param_entries:
            self.buttonSaveParameters.configure(state=NORMAL)
            self.buttonSaveParametersAndReset.configure(state=NORMAL)

    def stepModel(self):
        if self.running:
            if self.model.step() is True:
                self.stopRunning()
            self.currentStep += 1
            self.setStatusStr("Step " + str(self.currentStep))
            self.status.configure(foreground='black')
            if (self.currentStep) % self.stepSize == 0:
                self.drawModel()
            self.rootWindow.after(int(self.timeInterval * 1.0 / self.stepSize),
                                  self.stepModel)

    def stepOnce(self):
        self.running = False
        self.runPauseString.set("Continue Run")
        self.model.step()
        self.currentStep += 1
        self.setStatusStr("Step " + str(self.currentStep))
        self.drawModel()
        if self.param_entries:
            self.buttonSaveParameters.configure(state=NORMAL)

    def resetModel(self):
        self.running = False
        self.runPauseString.set("Run")
        self.model.reset()
        self.currentStep = 0
        self.setStatusStr("Model has been reset")
        self.drawModel()

    def drawModel(self):
        if self.modelFigure is None:
            self.modelFigure = plt.figure()
            plt.ion()
            # plt.show() will cause the plot to be actually displayed
            plt.show()
        self.model.draw()

        # Tell matplotlib to redraw too. The darwin-version works with more
        # types of matplotlib backends, but seems to fail on some Linux
        # machines. Hence we use the TkAgg specific method when available.

        if sys.platform == 'darwin':
            self.modelFigure.canvas.manager.show()
        else:
            self.modelFigure.canvas.manager.window.update()

    def start(self):
        if self.model.step.__doc__:
            self.showHelp(self.buttonStep, self.model.step.__doc__.strip())

        self.model.reset()
        self.drawModel()
        self.rootWindow.mainloop()

    def quitGUI(self):
        plt.close('all')
        self.rootWindow.quit()
        self.rootWindow.destroy()

    def showHelp(self, widget, text):
        def setText(self):
            self.statusText.set(text)
            self.status.configure(foreground='blue')

        def showHelpLeave(self):
            self.statusText.set(self.statusStr)
            self.status.configure(foreground='black')

        widget.bind("<Enter>", lambda e: setText(self))
        widget.bind("<Leave>", lambda e: showHelpLeave(self))
def sunfounder_client(ip, key):
        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
        from Tkinter import Tk, Button, Label, Scale, HORIZONTAL

        print "Connecting to IP", ip

        ctrl_cmd = ['forward', 'backward', 'left', 'right', 'stop', 'read cpu_temp', 'home', 'distance', 'x+', 'x-', 'y+', 'y-', 'xy_home']

        top = Tk()   # Create a top window
        top.title('Sunfounder Raspberry Pi Smart Video Car')

        HOST = ip    # Server(Raspberry Pi) IP address
        PORT = 21567
        BUFSIZ = 1024             # buffer size
        ADDR = (HOST, PORT)

        tcpCliSock = socket(AF_INET, SOCK_STREAM)   # Create a socket
        tcpCliSock.connect(ADDR)                    # Connect with the server
        # =============================================================================
        # The function is to send the command forward to the server, so as to make the 
        # car move forward.
        # ============================================================================= 
        def forward_fun(event):
                print "\nUser command = forward"
                print "Encrypted command = ",crypto.AES_encrypt('forward',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('forward',key)))

        def backward_fun(event):
                print '\nUser command = backward'
                print "Encrypted command = ",crypto.AES_encrypt('backward',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('backward',key)))

        def left_fun(event):
                print '\nUser command = left'
                print "Encrypted command = ",crypto.AES_encrypt('left',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('left',key)))

        def right_fun(event):
                print '\nUser command = right'
                print "Encrypted command = ",crypto.AES_encrypt('right',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('right',key)))

        def stop_fun(event):
                print '\nUser command = stop'
                print "Encrypted command = ",crypto.AES_encrypt('stop',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('stop',key)))

        def home_fun(event):
                print '\nUser command = home'
                print "Encrypted command = ",crypto.AES_encrypt('home',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('home',key)))

        def x_increase(event):
                print '\nUser command = x+'
                print "Encrypted command = ",crypto.AES_encrypt('x+',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('x+',key)))

        def x_decrease(event):
                print '\nUser command = x-'
                print "Encrypted command = ",crypto.AES_encrypt('x-',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('x-',key)))

        def y_increase(event):
                print '\nUser command = y+'
                print "Encrypted command = ",crypto.AES_encrypt('y+',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('y+',key)))

        def y_decrease(event):
                print '\nUser command = y-'
                print "Encrypted command = ",crypto.AES_encrypt('y-',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('y-',key)))

        def xy_home(event):
                print '\nUser command = xy_home'
                print "Encrypted command = ",crypto.AES_encrypt('xy_home',key)[2]
                tcpCliSock.send(str(crypto.AES_encrypt('xy_home',key)))

        # =============================================================================
        # Exit the GUI program and close the network connection between the client 
        # and server.
        # =============================================================================
        def quit_fun(event):
                print "\nShutting down program..."
                top.quit()
                tcpCliSock.send(str(crypto.AES_encrypt('stop',key)))
                tcpCliSock.close()

        # =============================================================================
        # Create buttons
        # =============================================================================
        Btn0 = Button(top, width=5, text='Forward')
        Btn1 = Button(top, width=5, text='Backward')
        Btn2 = Button(top, width=5, text='Left')
        Btn3 = Button(top, width=5, text='Right')
        Btn4 = Button(top, width=5, text='Quit')
        Btn5 = Button(top, width=5, height=2, text='Home')

        # =============================================================================
        # Buttons layout
        # =============================================================================
        Btn0.grid(row=0,column=1)
        Btn1.grid(row=2,column=1)
        Btn2.grid(row=1,column=0)
        Btn3.grid(row=1,column=2)
        Btn4.grid(row=3,column=2)
        Btn5.grid(row=1,column=1)

        # =============================================================================
        # Bind the buttons with the corresponding callback function.
        # =============================================================================
        Btn0.bind('<ButtonPress-1>', forward_fun)  # When button0 is pressed down, call the function forward_fun().
        Btn1.bind('<ButtonPress-1>', backward_fun)
        Btn2.bind('<ButtonPress-1>', left_fun)
        Btn3.bind('<ButtonPress-1>', right_fun)
        Btn0.bind('<ButtonRelease-1>', stop_fun)   # When button0 is released, call the function stop_fun().
        Btn1.bind('<ButtonRelease-1>', stop_fun)
        Btn2.bind('<ButtonRelease-1>', stop_fun)
        Btn3.bind('<ButtonRelease-1>', stop_fun)
        Btn4.bind('<ButtonRelease-1>', quit_fun)
        Btn5.bind('<ButtonRelease-1>', home_fun)

        # =============================================================================
        # Create buttons
        # =============================================================================
        Btn07 = Button(top, width=5, text='X+', bg='red')
        Btn08 = Button(top, width=5, text='X-', bg='red')
        Btn09 = Button(top, width=5, text='Y-', bg='red')
        Btn10 = Button(top, width=5, text='Y+', bg='red')
        Btn11 = Button(top, width=5, height=2, text='HOME', bg='red')

        # =============================================================================
        # Buttons layout
        # =============================================================================
        Btn07.grid(row=1,column=5)
        Btn08.grid(row=1,column=3)
        Btn09.grid(row=2,column=4)
        Btn10.grid(row=0,column=4)
        Btn11.grid(row=1,column=4)

        # =============================================================================
        # Bind button events
        # =============================================================================
        Btn07.bind('<ButtonPress-1>', x_increase)
        Btn08.bind('<ButtonPress-1>', x_decrease)
        Btn09.bind('<ButtonPress-1>', y_decrease)
        Btn10.bind('<ButtonPress-1>', y_increase)
        Btn11.bind('<ButtonPress-1>', xy_home)
        #Btn07.bind('<ButtonRelease-1>', home_fun)
        #Btn08.bind('<ButtonRelease-1>', home_fun)
        #Btn09.bind('<ButtonRelease-1>', home_fun)
        #Btn10.bind('<ButtonRelease-1>', home_fun)
        #Btn11.bind('<ButtonRelease-1>', home_fun)

        # =============================================================================
        # Bind buttons on the keyboard with the corresponding callback function to 
        # control the car remotely with the keyboard.
        # =============================================================================
        top.bind('<KeyPress-a>', left_fun)   # Press down key 'A' on the keyboard and the car will turn left.
        top.bind('<KeyPress-d>', right_fun) 
        top.bind('<KeyPress-s>', backward_fun)
        top.bind('<KeyPress-w>', forward_fun)
        top.bind('<KeyPress-h>', home_fun)
        top.bind('<KeyRelease-a>', home_fun) # Release key 'A' and the car will turn back.
        top.bind('<KeyRelease-d>', home_fun)
        top.bind('<KeyRelease-s>', stop_fun)
        top.bind('<KeyRelease-w>', stop_fun)

        spd = 50

        def changeSpeed(ev=None):
                tmp = 'speed'
                global spd
                spd = speed.get()
                data = tmp + str(spd)  # Change the integers into strings and combine them with the string 'speed'.  
                #print 'sendData = %s' % data
                print '\nUser command = ', data
                print "Encrypted command = ",crypto.AES_encrypt(data,key)[2]

                tcpCliSock.send(str(crypto.AES_encrypt(data,key)))  # Send the speed data to the server(Raspberry Pi)

        label = Label(top, text='Speed:', fg='red')  # Create a label
        label.grid(row=6, column=0)                  # Label layout

        speed = Scale(top, from_=0, to=100, orient=HORIZONTAL, command=changeSpeed)  # Create a scale
        speed.set(50)
        speed.grid(row=6, column=1)

        def main():
                top.mainloop()

        if __name__ == '__main__':
                main()
예제 #49
0
파일: GUI 1.1.py 프로젝트: Retiwer/GUI
def tabla():
    global New_Ind_0, New_Ind_1, Amount_People, Index_Variables, Index_Gender
    global Tabla_Datos, Lista_Indice, New_Ind_2, State_2, Var_G2, Var_G3
    global Var_G6, Index_Var

    State_0 = map((lambda var: var.get()), Variable_CB_0)
    State_1 = Var_G2.get()
    State_2 = Var_G3.get()
    New_Ind_0 = []
    New_Ind_1 = []
    New_Ind_2 = []

    print "Variables"
    for i in range(len(State_0)):
        if State_0[i] == 1:
            print i, List_Variables[i]
            New_Ind_0.append(Index_Variables[i])
    print ''

    print "Genero"
    print State_1, List_Gender[State_1]
    New_Ind_1.append(Index_Gender[State_1])
    print ''

    print "Parametro"
    print State_2, List_Var[State_2]
    New_Ind_2.append(Index_Var[State_2])
    print ''

    Flag_0 = 0  #Bandera para discriminar celdas vacias
    Aux_0 = 0  #Auxiliar 0, valor de la celda de datos                                                            #Auxiliar 1, valor de la celda de la variable
    Lista_Indice = []  #Lista donde se almacena el indice de la tabla de datos
    Lista_Temp = []  #Vector auxiliar para armar la Matriz
    Tabla_Datos = numpy.zeros(
        (0, len(New_Ind_0)
         ))  #Matriz con los datos de dimensiones 0x(Numero de variables)

    for i in range(2, Amount_People,
                   1):  #Desde la primera Columna hasta la ultima
        Flag_0 = 0  #Bandera en 0
        for j in New_Ind_0:  #Desde la primera Fila hasta la ultima
            Aux_0 = Sheet.cell(
                row=i, column=j
            ).value  #Aux_0 toma el valor de datos de la celda leida                        #Aux_1 toma el valor de la variable en la misma fila
            if Aux_0 is None or Val_Check(
                    i
            ) == 1:  #Si ni la celda de la variable ni la del dato carecen de valor
                Flag_0 = 1  #Bandera en 1
            else:
                Aux_0 = Sheet.cell(
                    row=i, column=j
                ).value * 1.0  #Valor de la tabla pasa de int a float
                Lista_Temp.append(
                    Aux_0
                )  #Se crea una lista temporal con el valor de la celda de datos
        if Flag_0 == 0:  #Si la bandera no fue levantada
            Tabla_Datos = numpy.vstack(
                (Tabla_Datos, Lista_Temp)
            )  #Se agrega la lista de datos sobre la Tabla que se esta generando
            Lista_Indice.append(
                i)  #Srea una lista indice de la tabla original del Excel
        Lista_Temp = [
        ]  #Se reinicia la lista para la siguiente fila                                         #Devuelve la Tablaz y el Indice

    global vart
    vart = IntVar()
    scale = Scale(top,
                  label="    Number of Clusters",
                  orient=HORIZONTAL,
                  variable=vart,
                  from_=2,
                  to=10,
                  length=200,
                  width=28)
    scale.set(3)
    scale.place(x=130, y=32, width=150)

    Var_G6 = IntVar()
    my_objects_5 = []
    for i in range(3):
        my_objects_5.append(MyClass(i))
    k = 0
    d = 0
    for i in ["Kmeans", "MeanShift", "DBSCAN"]:
        my_objects_5[k] = Radiobutton(top, text=i, variable=Var_G6, value=k)
        my_objects_5[k].place(x=120, y=105 + d * 20)
        k = k + 1
        d = d + 1