Example #1
0
 def showLoading(self):
     self.attemptedMarkov = True
     popup = Toplevel()
     text = Message(popup, text="The Markov Generator is still loading!\n\nText will show up when loaded!")
     text.pack()
     closePop = Button(popup, text="Okay!", command=popup.destroy)
     closePop.pack()  
Example #2
0
    def concolefooter(self):
        footerframe = Frame(self.master)
        footerframe.config(padx=5, pady=5, bg=Styles.colours["darkGrey"])
        title = Message(footerframe, text="Console:",
                        justify=CENTER, bg=Styles.colours["darkGrey"],
                        foreground=Styles.colours["yellow"],
                        width=100, font=Styles.fonts["entry"])

        consoletext = Text(footerframe, height=5, width=80, bg=Styles.colours["darkGrey"],
                           foreground=Styles.colours["grey"], state=NORMAL, relief=FLAT, font=Styles.fonts["console"])
        consoletext.insert(END, "Welcome to Project Bi")
        consoletext.config(state=DISABLED)
        self.console.setconsolefield(consoletext)
        scroll = Scrollbar(footerframe, command=consoletext.yview, relief=FLAT)
        consoletext.configure(yscrollcommand=scroll.set)

        self.boptimize = yellowbutton(footerframe, "Optimize", 20, lambda e: self.observerstage())
        deactivatebutton(self.boptimize)
        self.boptimize.pack(side=RIGHT, fill=BOTH, padx=5, pady=5)
        self.boptimize.configure(font=Styles.fonts["h1Button"])

        title.pack(side=LEFT, fill=BOTH)
        scroll.pack(side=LEFT, fill=BOTH)
        consoletext.pack(side=LEFT, fill=BOTH)
        footerframe.grid(row=2, column=0, sticky=W + E + N + S, columnspan=2)

        return footerframe
def OnButtonClick():
    

    e2.focus_set()
    e2.selection_range(0, END)

    e3.focus_set()
    e3.selection_range(0, END)

    e4.focus_set()
    e4.selection_range(0, END)
    
    win = Toplevel()
    win.title("Program Answer")
    if len(oracle_old_connection(e2.get(), e3.get())) > 0:
        cur = oracle_connection()
        alter_string = 'alter user %s identified by %s' % (e2.get(), e4.get())
        cur.execute(alter_string)
        message = "Password Successfully Updated"
        
        msg = Message(win, text=message)
        msg.pack()
        button = Button(win, text='OK', command=win.destroy)
        button.pack()
    else:
        message = "Error!!!!"
        
        msg = Message(win, text=message)
        msg.pack()
        button = Button(win, text='OK', command=win.destroy)
        button.pack()
def about():
    help_window = tk.Toplevel(master) 
    help_window.geometry("1000x1000")
    help_window.title("About the Bunimovich Stadia Evolution Viewer")
          
    text = Message(help_window, text = TEXT, padx = 100)
    text.pack()
Example #5
0
class Data_Cell(Cell):
    def __init__(self,
                 master,
                 variable,
                 anchor=W,
                 bordercolor=None,
                 borderwidth=1,
                 padx=0,
                 pady=0,
                 background=None,
                 foreground=None,
                 font=None):
        Cell.__init__(self,
                      master,
                      background=background,
                      highlightbackground=bordercolor,
                      highlightcolor=bordercolor,
                      highlightthickness=borderwidth,
                      bd=0)

        self._message_widget = Message(self,
                                       textvariable=variable,
                                       font=font,
                                       background=background,
                                       foreground=foreground)
        self._message_widget.pack(expand=True,
                                  padx=padx,
                                  pady=pady,
                                  anchor=anchor)
Example #6
0
 def Msg(name):
     master = tk()
     master.title('Error message')
     msg = Message(master, text='unable to load ' + name + ' from file')
     # msg.config()
     msg.pack()
     # close_button = Button(master, text='OK', command=master.destroy)
     mainloop()
Example #7
0
def About():
    top = Toplevel()
    top.title("About this application...")
    msg = Message(top,
                  text="Turing Machine simulator\nWritten on python 2.7 \
                              using Tkinter\n2016 Kyiv, IASA\nby Illya Barziy")
    msg.pack()
    button = Button(top, text="OK", command=top.destroy)
    button.pack()
 def message_box_notification(self, txt):
     #crate the top level for message box
     mess_box = Toplevel()
     mess_box.title("Message")
     #create the message text
     msg = Message(mess_box, text = txt)
     msg.pack()
     #create top level close button
     mess_box_close = Button(mess_box, text = "OK", command = mess_box.destroy)
     mess_box_close.pack()
Example #9
0
 def info(self):
     #Infoseite zeigen
     top = Toplevel()
     top.title(u"Über dieses Programm...")
     
     msg = Message(top, text=u'Dieses Programm dient zur Auswertung von Messungen für die Bestimmung des Weiterreißwiderstands nach DIN ISO 6133:2004-05\n\nZur Detektion der Maxima dient ein Algorithmus aus MATLAB (http://billauer.co.il/peakdet.html) verwendet, welcher nach Python übersetzt wurden.\n\nDas Programm entscheidet je nach Anzahl der Maxima selbst, welche Vorgabe für die Auswertung zu verwenden ist.\n\n\n\nErstellt von Lukas Scheffler')
     msg.pack()
     
     button = Button(top, text="Verbergen", command=top.destroy)
     button.pack()
Example #10
0
	def onSetParams(self):
		top = Toplevel(self.parent)
		top.title("Model Setup")
		msg = Message(top, text="")
		msg.pack()
		
		applyb = Button(top, text="Apply", command=top.destroy)
		closeb = Button(top, text="Close", command=top.destroy)
		applyb.pack()
		closeb.pack()
Example #11
0
class Data_Cell(Cell):
    def __init__(self, master, variable, anchor=W, bordercolor=None, borderwidth=1, padx=0, pady=0, background=None, foreground=None, font=None):
        Cell.__init__(self, master, background=background, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=borderwidth, bd= 0)

        self._message_widget = Message(self, textvariable=variable, font=font, background=background, foreground=foreground)
        self._message_widget.pack(expand=True, padx=padx, pady=pady, anchor=anchor)

        self.bind("<Configure>", self._on_configure)

    def _on_configure(self, event):
        self._message_widget.configure(width=event.width)
Example #12
0
def make_error_dialog(player_dlg):
    error_dlg = Toplevel(master=player_dlg);
    error_dlg.title( "Error" );
    error_dlg.grab_set();
    error_msg = Message(error_dlg, aspect=300, text="Player count must be between %d and %d" % (MIN_PLAYER_COUNT, MAX_PLAYER_COUNT) )
    error_msg.pack();
    error_button = Button(error_dlg, text="OK", \
                            command=error_dlg.destroy);
    error_button.pack();
    error_dlg.update();
    return
class Data_Cell(Cell):
    """
     A Class used as a data cell for a table widget

    Methods
    -------
    _on_configure()
            Description | Message widget configuration

    """
    def __init__(self,
                 master,
                 variable,
                 anchor=CENTER,
                 bordercolor=None,
                 borderwidth=1,
                 padx=0,
                 pady=0,
                 background=None,
                 foreground=None,
                 font=None):
        """
        Parameters
        ----------

        :param master: the master of the data cell
        :param variable: data variable
        :param anchor: anchor
        :param bordercolor: the color of the border
        :param borderwidth: the width of the data cell border
        :param padx: x coordinate padding
        :param pady: y coordinate padding
        :param background: background color
        :param foreground: foreground color
        :param font: text font
        """
        Cell.__init__(self,
                      master,
                      background=background,
                      highlightbackground=bordercolor,
                      highlightcolor=bordercolor,
                      highlightthickness=borderwidth,
                      bd=0)

        self._message_widget = Message(self,
                                       textvariable=variable,
                                       font=font,
                                       background=background,
                                       foreground=foreground)

        self._message_widget.pack(padx=padx, pady=pady, anchor=anchor)

        self._message_widget.configure(width=110, pady=1.2)
Example #14
0
	def help_f(self):
		top = Toplevel()
		top.title("HELP")
		msg = Message(top, width= 500,
                 text="Noise Threshold (NT) - Noise Based Main Threshold \
(Sigmas)\n Threshold 1 - Main Threshold (LSBs) \n Threshold 2 - End of Pulse Error \n \
Threshold 3 - End of Tail Error \n When Thr1 = Thr3 = 0 their values are defined as: \n \
(THR1 = NT (LSBs) / THR3 = NT*NOISE_ADC / 5)")
		msg.pack()

		button = Button(top, text="Close", command=top.destroy)
		button.pack()
Example #15
0
    def help_f(self):
        top = Toplevel()
        top.title("HELP")
        msg = Message(top,
                      width=500,
                      text="Noise Threshold (NT) - Noise Based Main Threshold \
(Sigmas)\n Threshold 1 - Main Threshold (LSBs) \n Threshold 2 - End of Pulse Error \n \
Threshold 3 - End of Tail Error \n When Thr1 = Thr3 = 0 their values are defined as: \n \
(THR1 = NT (LSBs) / THR3 = NT*NOISE_ADC / 5)")
        msg.pack()

        button = Button(top, text="Close", command=top.destroy)
        button.pack()
Example #16
0
    def create_path(self):
        width_msg = 100
        width_path = 400

        path_frame = Frame(self.root)
        path_frame.pack(fill=X)
        # read
        read_frame = Frame(path_frame)
        read_frame.pack(fill=X)
        read_msg = Message(read_frame, width=width_msg, text='Video path:')
        read_msg.pack(side=LEFT)
        read_path = Message(read_frame, width=width_path, text='file1')
        read_path.pack(side=LEFT)
        read_btn = Button(read_frame, text="Choose file", command=self.click_read)
        read_btn.pack(side=RIGHT)
        # save
        save_frame = Frame(path_frame)
        save_frame.pack(fill=X)
        save_msg = Message(save_frame, width=width_msg, text='Save to:')
        save_msg.pack(side=LEFT)
        save_path = Message(save_frame, width=width_path, text='file2')
        save_path.pack(side=LEFT)
        save_btn = Button(save_frame, text="Choose file", command=self.click_save)
        save_btn.pack(side=RIGHT)

        self.read_path = read_path
        self.save_path = save_path
Example #17
0
class Panle:
    def __init__(self, master):
        
        self.frame = Frame(master)
        self.frame.pack(side=TOP)
        self.label = Tkinter.Label(self.frame, text='wordEcho')
        self.label.pack()
        self.input = Entry(self.frame, width=45)
        self.input.pack(side=LEFT)
        self.button = Button(self.frame, text='翻译')
        self.button.pack(side=RIGHT)
        self.frame2 = Scrollbar(master)
        self.frame2.pack(side=TOP)
        self.ms = Message(self.frame2,  anchor='w', width=150)
        self.ms.pack()
Example #18
0
class AlreadyExistsDialog(Dialog):
    def __init__(self, master_frame, new, old, variable, class_=None, relx=0.5, rely=0.3):
        Dialog.__init__(self, master_frame, 'Warning!',
                        class_, relx, rely)
        self.new = new
        self.old = old
        self.variable = variable
        
        self.text = "Warning: Customer Found with the same name.\n" + \
        "\nNew record: " + new[1] + " " + new[2] + " " + new[0] + \
        " (" + new[3] + ") - " + new[4].strftime("%m/%d/%Y") + \
        "\nOld record: " + old[1] + " " + old[2] + " " + old[0] + \
        " (" + old[3] + ") - " + old[4].strftime("%m/%d/%Y") + \
        "\n\n Cancel to edit entry, Override to replace old entry."
        

    def show(self):
        self.setup()

        self.msg = Message(self.root, text=self.text, aspect=400)
        self.msg.pack(expand=True, fill=BOTH)

        self.frame = Frame(self.root)
        
        b1 = Button(self.frame, text="Cancel", command=self.cancel)
        b1.pack(side=LEFT, fill=BOTH, expand=True, padx=10)
        b2 = Button(self.frame, text="Override", command=self.replace)
        b2.pack(side=LEFT, fill=BOTH, expand=True, padx=10)
        #b3 = Button(self.frame, text="Add Duplicate", command=self.add_duplicate)
        #b3.pack(side=LEFT, fill=BOTH, expand=True)
        
        self.frame.pack(padx=10, pady=10)

        self.root.bind('<Return>', self.cancel)
        
        self.enable()

    def cancel(self, event=None):
        self.variable.set(0)
        self.root.quit()

    def replace(self):
        self.variable.set(1)
        self.root.quit()

    def add_duplicate(self):
        self.variable.set(2)
        self.wm_delete_window()
Example #19
0
    def help_f(self):
		top = Toplevel()
		top.title("HELP")
		msg = Message(top, width= 500,
             text="COEFF Calibration Procedure: \n \
             Input Start Point and Length of the pulse \n \
             Input an initial guess of the pulse amplitude \n \
             Use a ROI with at least 1000 samples of baseline \n \
             and 1000 samples after pulse end \n \
             Adjust loop range and step until a graph error \n \
             with a minimum is observed \n \
             Refine the search to increase precision")
		msg.pack()

		button = Button(top, text="Close", command=top.destroy)
		button.pack()
Example #20
0
    def help_f(self):
        top = Toplevel()
        top.title("HELP")
        msg = Message(top,
                      width=500,
                      text="COEFF Calibration Procedure: \n \
             Input Start Point and Length of the pulse \n \
             Input an initial guess of the pulse amplitude \n \
             Use a ROI with at least 1000 samples of baseline \n \
             and 1000 samples after pulse end \n \
             Adjust loop range and step until a graph error \n \
             with a minimum is observed \n \
             Refine the search to increase precision")
        msg.pack()

        button = Button(top, text="Close", command=top.destroy)
        button.pack()
Example #21
0
class mainheader():
    def __init__(self, master, console,params,maingui):
        self.frame = Frame(master)
        self.frame.config(padx=5, pady=5, bg=Styles.colours["darkGrey"])
        self.frame.grid(row=0, column=0, sticky=W + E + N + S,columnspan=2)
        self.title = Message(self.frame, text="ProjectB: Selection",
                        justify=CENTER, bg=Styles.colours["darkGrey"],
                        foreground=Styles.colours["yellow"],
                        width=300, font=Styles.fonts["h1"])

        def importsettings(event):
            f = tkFileDialog.askopenfilename(parent=master, title='Choose a file')
            parsemodifycustomvar(params,parsein(f,parseintosimple(params),console))
            maingui.ready("model")
            maingui.ready("bayes")

        def exportfile(event):
            f = tkFileDialog.asksaveasfilename(parent=master, title='Choose a file')
            parseout(f,parseintosimple(params),console)

        self.bimport = camobutton(self.frame, "Import Settings", 15,importsettings)
        self.bexport = camobutton(self.frame, "Export Settings", 15,exportfile)
        self.badvset = yellowbutton(self.frame, "Advanced Settings", 20)

        self.badvset.bind("<Button-1>", lambda a: AdvancedSettings(console,params))
        self.qb = qbutton(self.frame)

        self.title.pack(side=LEFT, fill=BOTH, padx=5, pady=5)
        self.qb.pack(side=RIGHT, fill=BOTH, padx=5, pady=5)
        self.badvset.pack(side=RIGHT, fill=BOTH, padx=5, pady=5)
        self.bexport.pack(side=RIGHT, fill=BOTH, padx=5, pady=5)
        self.bimport.pack(side=RIGHT, fill=BOTH, padx=5, pady=5)

    def destroy(self):
        self.frame.destroy()

    def observationstage(self):
        self.bimport.destroy()
        self.bexport.destroy()
        self.badvset.destroy()
        self.title.config(text="ProjectB: Observation")

    def evaluationstage(self):
        self.title.config(text="ProjectB: Evaluation")
Example #22
0
 def help(self):
     #Hilfeseite zeigen
     top = Toplevel()
     top.title("Hilfe")
     
     label1 = ttk.Label(top, text = u"Projekt öffnen/erstellen", font=self.normal_font)
     label1.pack()
     
     msg1 = Message(top, text=u'Über Datei -> Neu muss zu Beginn eine .txt-Datei erstellt werden. In dieser werden die Ergebnisse der Auswertung gespeichert.\n\nAlternativ kann über Datei -> Öffnen... ein bereits existierendes Projekt mit den neuen Ergebnissen erweitert werden. \n\n')
     msg1.pack()
     
     label2 = ttk.Label(top, text = u"Messung importieren und auswerten", font=self.normal_font)
     label2.pack()
     
     msg2 = Message(top, text=u'Zunächst muss über Datei -> Messung importieren die gewünschte Messung importiert werden.\n\nAnschließend werden Delta X und Delta Y so eingestellt, dass nur die gewünschten Maxima (rote Punkte im Graphen) vom Algorithmus erkannt werden.\n\nZur Berechnung des Weiterreißwiderstandes wird die Probendicke benötigt. Diese muss im entsprechenden Fenster eingetragen werden (Trennung durch . nicht durch ,  Bsp: 1.75).\n\nÜber die Schaltfläche Berechnen werden die gewünschten Werte berechnet.\n\nNachdem der Probenname und optional ein Kommentar zur Messung in die entsprechenden Fenster eingetragen wurden, lässt sich die Auswertung im zuvor gewählten Projekt abspeichern.')
     msg2.pack()
     
     button = Button(top, text="Verbergen", command=top.destroy)
     button.pack()
Example #23
0
	def drawWindow(self):
		#cache the images to display
		self.redditraw = Image.open("reddit.png").resize((40,40), Image.ANTIALIAS)
		self.redditimg = ImageTk.PhotoImage(self.redditraw)
		
		self.twitterraw = Image.open("twitter.png").resize((40,40), Image.ANTIALIAS)
		self.twitterimg = ImageTk.PhotoImage(self.twitterraw)
		
		for post in self.posts:
			frame = Frame(self)
			frame.pack(side=TOP, fill=X)
			
			#this was for using web images
			#file = cStringIO.StringIO(urllib.urlopen("location").read())
			
			#draw 
			if post.type == "RedditPost":
				reddit = Label(frame, image=self.redditimg)
				reddit.image = self.redditimg
				#reddit.bind("<1>", lambda event, url=post[1]: web.open_new(url))
				reddit.pack(side=LEFT)
			else:
				twitter = Label(frame, image=self.twitterimg)
				twitter.image = self.twitterimg
				#twitter.bind("<1>", lambda event, url=post[1]: web.open_new(url))
				twitter.pack(side=LEFT)
			
			body = Frame(frame)
			body.pack(fill=BOTH)
			
			#the actual post body
			title = Message(body, text=post.title, foreground="#0000dd", justify=LEFT, width=550)
			#title.bind("<1>", lambda event, url=post[4]: web.open_new(url))
			title.pack(anchor=W)
			
			#date and author
			details = Label(body, text=post.date+" by "+post.user)
			details.pack(anchor=W)
def vis_thread():
    global txt, color, txt2, color2

    def update():
        global txt, color, txt2, color2
        msg.config(text=txt, background=color)
        msg2.config(text=txt2, background=color2)
        root.after(250, update)

    root = Tk()
    root.geometry("900x600")

    msg = Message(root, text=txt, background=color)
    msg.config(font=('times', 200, 'italic bold'))
    msg.pack()

    msg2 = Message(root, text=txt2, background=color2)
    msg2.config(font=('times', 70, 'italic bold'))
    msg2.pack()

    root.after(250, update)

    root.mainloop()
Example #25
0
class PVapplicaton(Frame):
    """
    classdocs
    """
    def __init__(self, master=None):
        """
        Constructor
        """
        Frame.__init__(self,
                       master,
                       name='pvApplication',
                       bg='black',
                       padx=5,
                       pady=5)
        # set black background, pad sides with 15 points, top/bottom 5 points
        # fill=BOTH fills in padding with background color
        # w/o fill=BOTH padding is default color
        # side=TOP is the default
        self.pack(fill=BOTH)
        master.resizable(False, False)  # not resizable in x or y
        master.title(PVAPP_TXT)  # set title bar of master (a.k.a. root)
        master.protocol("WM_DELETE_WINDOW", self._quit)  # close window to quit

        self.validationConstants = self.readJSON('validationConstants')
        self.messagetext = self.readJSON('messagetext' + '.' + LANGUAGE)
        MAX_STRINGS = self.validationConstants["pvapplication"]["numStrs"]
        MAX_MODULES = self.validationConstants["pvapplication"]["numMods"]
        MAX_SUNS = self.validationConstants["pvapplication"]["sysEe"]
        CAPTION_FONT = nametofont('TkCaptionFont')  # font for titles

        # PVsystem
        pvSys = self.pvSys = PVsystem()

        # variables
        numStrs = self.numStrs = IntVar(self, NUMBERSTRS, 'numStrs')
        numMods = self.numMods = IntVar(self, NUMBERMODS, 'numMods')
        numCells = self.numCells = IntVar(self, NUMBERCELLS, 'numCells')
        txtIsys = self.txtIsys = DoubleVar(self, name='txtIsys')
        txtVsys = self.txtVsys = DoubleVar(self, name='txtVsys')
        txtPsys = self.txtPsys = DoubleVar(self, name='txtPsys')
        txtImp = self.txtImp = StringVar(self, name='txtImp')
        txtVmp = self.txtVmp = StringVar(self, name='txtVmp')
        txtPmp = self.txtPmp = StringVar(self, name='txtPmp')
        txtIsc = self.txtIsc = StringVar(self, name='txtIsc')
        txtVoc = self.txtVoc = StringVar(self, name='txtVoc')
        txtFF = self.txtFF = StringVar(self, name='txtFF')
        txtEff = self.txtEff = StringVar(self, name='txtEff')
        sysEe = self.sysEe = DoubleVar(self, 1, name='sysEe')
        txtImp.set("{:7.3f}".format(self.pvSys.Imp))  # [A]
        txtVmp.set("{:7.3f}".format(self.pvSys.Vmp))  # [V]
        txtPmp.set("{:7.3f}".format(self.pvSys.Pmp / 1000))  # [kW]
        txtIsc.set("{:7.3f}".format(self.pvSys.Isc))  # [A]
        txtVoc.set("{:7.3f}".format(self.pvSys.Voc))  # [V]
        txtFF.set("{:7.3f}".format(self.pvSys.FF * 100))  # [%]
        txtEff.set("{:7.3f}".format(self.pvSys.eff * 100))  # [%]
        self.msgtext = StringVar(self, READY_MSG, 'msgtext')

        # must register vcmd and invcmd as Tcl functions
        vcmd = (self.register(self.validateWidget), '%d', '%i', '%P', '%s',
                '%S', '%v', '%V', '%W')
        invcmd = (self.register(self.invalidWidget), '%d', '%i', '%P', '%s',
                  '%S', '%v', '%V', '%W')

        # SP logo
        # convert image to tk-compatible format (.gif, .pgm, or .ppm)
        self.SPlogo = ImageTk.PhotoImage(Image.open(SPLOGO))
        # bg='black' fills extra space with black
        # anchor=W aligns photoimage on left side, NW is no different
        # padding is ignored by images, use borderwidth
        Label(self, image=self.SPlogo, borderwidth=5, bg='black',
              anchor=W).pack(fill=BOTH)
        # fill=BOTH expands the photoimage to fill parent frame
        # w/o fill=BOTH photoimage is centered in frame even with anchor=W
        # Intro text
        introText = 'PVmismatch calculates I-V and P-V curves as well as the'
        introText += ' max power point (MPP) for any sized system.\nSet the'
        introText += ' number of strings in the system, the number of modules'
        introText += ' per string and the number cells per module.'
        # anchor=W aligns message on left side, NW is no different
        # fg='white' sets text color to white, default is black, so it doesn't
        #   show on black background
        # default aspect is 150%, about as wide as high, or set width>0
        Message(self,
                text=introText,
                width=750,
                bg='black',
                fg='white',
                anchor=W).pack(fill=BOTH)
        # fill=BOTH expands the message to fill parent frame
        # w/o fill=BOTH message is centered in frame even with anchor=W

        # PVsystem frame
        pvSysFrame = self.pvSysFrame = Frame(master, name='pvSysFrame')
        # fill=BOTH keeps widgets in frame on left when window is resized
        pvSysFrame.pack(fill=BOTH)

        # PVsystem matplotlib figure canvas
        self.pvSysPlotFrame = Frame(pvSysFrame, name='pvSysPlotFrame')
        pvSysPlotFrame = self.pvSysPlotFrame
        pvSysPlotFrame.pack(side=RIGHT)
        pvSysPlot = self.pvSysPlot = pvSys.plotSys()
        self.pvSysFigCanvas = FigureCanvasTkAgg(pvSysPlot,
                                                master=pvSysPlotFrame,
                                                resize_callback=None)
        pvSysFigCanvas = self.pvSysFigCanvas
        pvSysFigCanvas.get_tk_widget()._name = 'pvSysFigCanvas'  # IGNORE:W0212
        pvSysFigCanvas.show()
        # NB: FigureCanvasTkAgg._tkcanvas is FigureCanvasTkAgg.get_tk_widget()
        pvSysFigCanvas.get_tk_widget().pack(fill=BOTH)
        pvSysToolbar = NavigationToolbar2TkAgg(pvSysFigCanvas, pvSysPlotFrame)
        pvSysToolbar.update()
        pvSysToolbar.pack(fill=BOTH)

        # PVsystem data frame
        pvSysDataFrame = self.pvSysDataFrame = Frame(pvSysFrame,
                                                     name='pvSysDataFrame')
        pvSysDataFrame.pack(side=LEFT)
        _row = 0
        Label(pvSysDataFrame, text='PVsystem',
              font=CAPTION_FONT).grid(row=_row, columnspan=3, sticky=W)

        # number of strings
        _row += 1  # row 1
        Label(pvSysDataFrame, text='Number of Strings').grid(row=_row,
                                                             columnspan=2,
                                                             sticky=W)
        # use textVar to set number of strings from LOAD, RESET or default
        spinboxCnf = {
            'name': 'numStrSpinbox',
            'from_': 1,
            'to': MAX_STRINGS,
            'textvariable': numStrs,
            'width': 5,
            'validate': 'all',
            'validatecommand': vcmd,
            'invalidcommand': invcmd,
            'command': self.updatePVsys
        }
        self.numStrSpinbox = Spinbox(pvSysDataFrame, cnf=spinboxCnf)
        self.numStrSpinbox.bind("<Return>", self.keyBinding)
        self.numStrSpinbox.grid(row=_row, column=2)

        # number of modules
        _row += 1  # row 2
        Label(pvSysDataFrame, text='Number of Modules').grid(row=_row,
                                                             columnspan=2,
                                                             sticky=W)
        # number of modules spinbox
        spinboxCnf = {
            'name': 'numModSpinbox',
            'from_': 1,
            'to': MAX_MODULES,
            'textvariable': numMods,
            'width': 5,
            'validate': 'all',
            'validatecommand': vcmd,
            'invalidcommand': invcmd,
            'command': self.updatePVsys
        }
        self.numModSpinbox = Spinbox(pvSysDataFrame, cnf=spinboxCnf)
        self.numModSpinbox.bind("<Return>", self.keyBinding)
        self.numModSpinbox.grid(row=_row, column=2)

        # number of cells
        _row += 1  # row 3
        Label(pvSysDataFrame, text='Number of Cells').grid(row=_row,
                                                           columnspan=2,
                                                           sticky=W)
        # http://www.logilab.org/card/pylintfeatures#basic-checker
        # pylint: disable = W0142
        self.numCellOption = OptionMenu(pvSysDataFrame,
                                        numCells,
                                        *MODSIZES,
                                        command=self.updatePVsys)
        # pylint: enable = W0142
        self.numCellOption._name = 'numCellOption'  # IGNORE:W0212
        self.numCellOption.grid(row=_row, column=2)

        # Advanced Configuration button
        _row += 1  # row 14
        buttonCnf = {
            'name': 'advCnfButton',
            'text': 'Advanced Configuration',
            'command': self.startAdvCnf_tk
        }
        pvStrButton = self.pvStrButton = Button(pvSysDataFrame, buttonCnf)
        pvStrButton.grid(row=_row, columnspan=3, sticky=(E + W))

        # slider to explore IV curves
        _row += 1  # row 4, 5 & 6
        self.pvSysScale = Scale(pvSysDataFrame,
                                orient=HORIZONTAL,
                                label='I-V Curve',
                                font=CAPTION_FONT,
                                command=self.getIV,
                                showvalue=False,
                                from_=0,
                                to=(pvSys.pvconst.npts - 1))
        self.pvSysScale.grid(row=_row, columnspan=3, sticky=(E + W))
        # Isys
        Label(pvSysDataFrame, text='Isys [A]').grid(row=(_row + 1))
        self.pvIsys = Entry(pvSysDataFrame, textvariable=txtIsys, width=7)
        self.pvIsys.grid(row=(_row + 2))
        # Vsys
        Label(pvSysDataFrame, text='Vsys [V]').grid(row=(_row + 1), column=1)
        self.pvVsys = Entry(pvSysDataFrame, textvariable=txtVsys, width=7)
        self.pvVsys.grid(row=(_row + 2), column=1)
        # Psys
        Label(pvSysDataFrame, text='Psys [kW]').grid(row=(_row + 1), column=2)
        self.pvPsys = Entry(pvSysDataFrame, textvariable=txtPsys, width=7)
        self.pvPsys.grid(row=(_row + 2), column=2)

        # Imp, Vmp & Pmp
        _row += 3  # row 7, 8, 9, 10, 11 & 12
        Label(pvSysDataFrame, text='I-V Characteristics',
              font=CAPTION_FONT).grid(row=_row, columnspan=3, sticky=W)
        Label(pvSysDataFrame, text='Imp [A]').grid(row=(_row + 1))
        Label(pvSysDataFrame, text='Vmp [V]').grid(row=(_row + 1), column=1)
        Label(pvSysDataFrame, text='Pmp [kW]').grid(row=(_row + 1), column=2)
        self.pvImp = Entry(pvSysDataFrame,
                           textvariable=txtImp,
                           width=7,
                           state='readonly')
        self.pvImp.grid(row=(_row + 2))
        self.pvVmp = Entry(pvSysDataFrame,
                           textvariable=txtVmp,
                           width=7,
                           state='readonly')
        self.pvVmp.grid(row=(_row + 2), column=1)
        self.pvPmp = Entry(pvSysDataFrame,
                           textvariable=txtPmp,
                           width=7,
                           state='readonly')
        self.pvPmp.grid(row=(_row + 2), column=2)
        # Isc, Voc & FF
        Label(pvSysDataFrame, text='Isc [A]').grid(row=(_row + 3))
        Label(pvSysDataFrame, text='Voc [V]').grid(row=(_row + 3), column=1)
        Label(pvSysDataFrame, text='FF [%]').grid(row=(_row + 3), column=2)
        self.pvIsc = Entry(pvSysDataFrame,
                           textvariable=txtIsc,
                           width=7,
                           state='readonly')
        self.pvIsc.grid(row=(_row + 4))
        self.pvVoc = Entry(pvSysDataFrame,
                           textvariable=txtVoc,
                           width=7,
                           state='readonly')
        self.pvVoc.grid(row=(_row + 4), column=1)
        self.pvFF = Entry(pvSysDataFrame,
                          textvariable=txtFF,
                          width=7,
                          state='readonly')
        self.pvFF.grid(row=(_row + 4), column=2)
        Label(pvSysDataFrame, text='Efficiency [%]').grid(row=(_row + 5),
                                                          columnspan=2)
        self.pvEff = Entry(pvSysDataFrame,
                           textvariable=txtEff,
                           width=7,
                           state='readonly')
        self.pvEff.grid(row=(_row + 5), column=2)

        # set suns
        _row += 6  # row 13
        Label(pvSysDataFrame, text='Irradiance [suns]',
              font=CAPTION_FONT).grid(row=_row, columnspan=2, sticky=W)
        # number of modules spinbox
        spinboxCnf = {
            'name': 'sunSpinbox',
            'from_': 0.2,
            'to': MAX_SUNS,
            'increment': 0.1,
            'textvariable': sysEe,
            'width': 5,
            'validate': 'all',
            'validatecommand': vcmd,
            'invalidcommand': invcmd,
            'command': self.updatePVsys
        }
        self.sunSpinbox = Spinbox(pvSysDataFrame, cnf=spinboxCnf)
        self.sunSpinbox.bind("<Return>", self.keyBinding)
        self.sunSpinbox.grid(row=_row, column=2)

        # PVstring button
        _row += 1  # row 14
        buttonCnf = {
            'name': 'pvStrButton',
            'text': 'PVstring',
            'command': self.startPVstring_tk
        }
        pvStrButton = self.pvStrButton = Button(pvSysDataFrame, buttonCnf)
        pvStrButton.grid(row=_row, columnspan=3, sticky=(E + W))

        # toolbar
        toolbar = self.toolbarframe = Frame(master, name='toolbar')
        toolbar.pack(fill=BOTH)
        self.QUIT = Button(toolbar, text='Quit', command=self._quit)
        self.QUIT.pack(side=RIGHT)
        self.SAVE = Button(toolbar, text='Save', command=self._save)
        self.SAVE.pack(side=RIGHT)
        self.LOAD = Button(toolbar, text='Load', command=self._load)
        self.LOAD.pack(side=RIGHT)
        self.RESET = Button(toolbar, text='Reset', command=self._reset)
        self.RESET.pack(side=RIGHT)
        self.UPDATE = Button(toolbar, text='Update', command=self._update)
        self.UPDATE.pack(side=RIGHT)
        self.HELP = Button(toolbar, text='Help', command=self._help)
        self.HELP.pack(side=RIGHT)
        self.MESSAGE = Message(toolbar,
                               textvariable=self.msgtext,
                               width=500,
                               fg='red')
        self.MESSAGE.pack(side=LEFT)

#    Validation substitutions
#    %d  Type of action: 1 for insert, 0 for delete, or -1 for focus, forced or
#        textvariable validation.
#    %i  Index of char string to be inserted/deleted, if any, otherwise -1.
#    %P  The value of the spinbox should edition occur. If you are configuring
#        the spinbox widget to have a new textvariable, this will be the value
#        of that textvariable.
#    %s  The current value of spinbox before edition.
#    %S  The text string being inserted/deleted, if any. Otherwise it is an
#        empty string.
#    %v  The type of validation currently set.
#    %V  The type of validation that triggered the callback (key, focusin,
#        focusout, forced).
#    %W  The name of the spinbox widget.

# TODO: Fix these functions so that delete and overwrite work

    def validateWidget(self, *args):
        # W = Tkinter.W = 'w' is already used, so use W_ instead
        (d, i, P, s, S, v, V, W_) = args  # @UnusedVariable # IGNORE:W0612
        logging.debug(
            "OnValidate: d={}, i={}, P={}, s={}, S={}, v={}, V={}, W={}".
            format(*args))
        if W_ == ".pvSysFrame.pvSysDataFrame.numStrSpinbox":
            valType = INTEGERS
            valTest = lambda val: int(val)  # IGNORE:W0108
        elif W_ == ".pvSysFrame.pvSysDataFrame.numModSpinbox":
            valType = INTEGERS
            valTest = lambda val: int(val)  # IGNORE:W0108
        elif W_ == ".pvSysFrame.pvSysDataFrame.sunSpinbox":
            valType = FLOATS
            valTest = lambda val: float(val)  # IGNORE:W0108
        else:
            return False
        w = self.nametowidget(W_)
        w.config(validate=v)
        if S in valType:
            try:
                valTest(P)
            except ValueError:
                return False
            return True
        else:
            return False

    def invalidWidget(self, *args):
        (d, i, P, s, S, v, V, W_) = args  # @UnusedVariable # IGNORE:W0612
        logging.debug(
            "OnInvalid: d={}, i={}, P={}, s={}, S={}, v={}, V={}, W={}".format(
                *args))
        if W_ == ".pvSysFrame.pvSysDataFrame.numStrSpinbox":
            errText = 'Invalid number of strings!'
        elif W_ == ".pvSysFrame.pvSysDataFrame.numModSpinbox":
            errText = 'Invalid number of modules!'
        elif W_ == ".pvSysFrame.pvSysDataFrame.sunSpinbox":
            errText = 'Invalid irradiance!'
        else:
            errText = 'Unknown widget!'
        w = self.nametowidget(W_)
        w.config(validate=v)
        self.msgtext.set(errText)
        self.bell()

    def getIV(self, *args):
        logging.debug('args:\n\t%r', args)
        x = np.float64(float(args[0]) / self.pvSys.pvconst.npts / 2.)
        xp = np.concatenate(
            (self.pvSys.pvconst.negpts, self.pvSys.pvconst.pts),
            axis=0).flatten()
        Vsys = np.interp(x, xp, self.pvSys.Vsys)
        Isys = np.interp(x, xp, self.pvSys.Isys)
        Psys = Vsys * Isys / 1000
        self.txtVsys.set("{:7.3f}".format(Vsys))
        self.txtIsys.set("{:7.3f}".format(Isys))
        self.txtPsys.set("{:7.3f}".format(Psys))

    def startPVstring_tk(self):
        top = Toplevel()
        app = PVstring_tk(self, top)
        app.mainloop()
        # please destroy me or I'll continue to run in background
        top.destroy()

    def startAdvCnf_tk(self):
        """
        open advnaced config window
        """
        top = Toplevel(name='advCnfTop')
        app = AdvCnf_tk(self, top)
        app.mainloop()
        # please destroy me or I'll continue to run in background
        top.destroy()

    def keyBinding(self, event):
        logging.debug('event widget:\n\t%r', event.widget)
        logging.debug('event widget get:\n\t%r', event.widget.get())
        self.updatePVsys()

    def updatePVsys(self, *args, **kwargs):
        logging.debug('args:\n\t%r', args)
        logging.debug('kwargs:\n\t%r', kwargs)
        if args and isinstance(args[0], PVsystem_cls):
            pvsys = args[0]
            for n, pvstr in enumerate(pvsys.pvstrs):
                for pvmod in pvstr.pvmods:
                    pvmod.calcMod()
                pvstr.calcString()
                logging.debug('updating pvstring #%d: Pmp = %g[W]', n,
                              pvstr.Pstring.max())
            return
        PVAPP = "pvapplication"
        try:
            numStrs = self.numStrs.get()
            if not (0 < numStrs <= self.validationConstants[PVAPP]["numStrs"]):
                raise PVValidationError('numStrs', numStrs)
            numMods = self.numMods.get()
            if not (0 < numMods <= self.validationConstants[PVAPP]["numMods"]):
                raise PVValidationError('numMods', numMods)
            sysEe = self.sysEe.get()
            if not (0 < sysEe <= self.validationConstants[PVAPP]["sysEe"]):
                raise PVValidationError('sysEe', sysEe)
        except PVValidationError as err:
            logging.debug('err:\n\t%r', err)
            errtext = self.messagetext[PVAPP][err.argname]
            self.msgtext.set(errtext)
            self.bell()
            return
        numCells = self.numCells.get()
        self.msgtext.set(self.messagetext[PVAPP]["Ready"])
        pvconst = self.pvSys.pvconst
        pvcell = PVcell(Ee=sysEe)
        if numCells == 24:
            numCells = STD24
        elif numCells == 72:
            numCells = STD72
        elif numCells == 96:
            numCells = STD96
        elif numCells == 128:
            numCells = STD128
        pvmods = PVmodule(cell_pos=numCells, pvcells=pvcell)
        self.pvSys = PVsystem(pvconst,
                              numStrs,
                              numberMods=numMods,
                              pvmods=pvmods)
        self.updateIVstats()

    def updateIVstats(self):
        # reuse sysPlot figure and update pvSysFigCanvas
        self.pvSysPlot = self.pvSys.plotSys(self.pvSysPlot)
        self.pvSysFigCanvas.show()
        self.txtImp.set("{:7.3f}".format(self.pvSys.Imp))  # [A]
        self.txtVmp.set("{:7.3f}".format(self.pvSys.Vmp))  # [V]
        self.txtPmp.set("{:7.3f}".format(self.pvSys.Pmp / 1000))  # [kW]
        self.txtIsc.set("{:7.3f}".format(self.pvSys.Isc))  # [A]
        self.txtVoc.set("{:7.3f}".format(self.pvSys.Voc))  # [V]
        self.txtFF.set("{:7.3f}".format(self.pvSys.FF * 100))  # [%]
        self.txtEff.set("{:7.3f}".format(self.pvSys.eff * 100))  # [%]

    def _help(self):
        logging.debug('show docs in browser')
        webbrowser.open(DOCS)

    def _update(self):
        self.msgtext.set(READY_MSG)
        self.updatePVsys()

    def _reset(self):
        # number of strings integer variable
        self.numStrs.set(NUMBERSTRS)  # default
        # number of modules integer variable
        self.numMods.set(NUMBERMODS)  # default
        # number of cells integer variable
        self.numCells.set(NUMBERCELLS)  # default value is 96
        self.msgtext.set(READY_MSG)
        # TODO: need to reset advCnf too
        logging.debug('reset')

    def _load(self):
        logging.debug('load *.pv file')

    def _save(self):
        logging.debug('save *.pv file')

    def _quit(self):
        # this is necessary on Windows to prevent
        # Fatal Python Error: PyEval_RestoreThread: NULL tstate
        self.master.quit()  # stops mainloop
        self.master.destroy()

    def readJSON(self, JSONfilename):
        if not JSONfilename.endswith('json'):
            JSONfilename += '.json'
        JSONfullpath = os.path.join(JSONDIR, JSONfilename)
        with open(JSONfullpath, 'r') as JSONfile:
            JSONObjects = json.load(JSONfile)
            logging.debug('JSON objects loaded from %s.', JSONfullpath)
        return JSONObjects
Example #26
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()
class GetCfgSectionNameDialog(Toplevel):
    def __init__(self, parent, title, message, used_names, _htest=False):
        """
        message - string, informational message to display
        used_names - string collection, names already in use for validity check
        _htest - bool, change box location when running htest
        """
        Toplevel.__init__(self, parent)
        self.configure(borderwidth=5)
        self.resizable(height=FALSE, width=FALSE)
        self.title(title)
        self.transient(parent)
        self.grab_set()
        self.protocol("WM_DELETE_WINDOW", self.Cancel)
        self.parent = parent
        self.message = message
        self.used_names = used_names
        self.create_widgets()
        self.withdraw()  #hide while setting geometry
        self.update_idletasks()
        #needs to be done here so that the winfo_reqwidth is valid
        self.messageInfo.config(width=self.frameMain.winfo_reqwidth())
        self.geometry("+%d+%d" %
                      (parent.winfo_rootx() +
                       (parent.winfo_width() / 2 - self.winfo_reqwidth() / 2),
                       parent.winfo_rooty() +
                       ((parent.winfo_height() / 2 -
                         self.winfo_reqheight() / 2) if not _htest else 100))
                      )  #centre dialog over parent (or below htest box)
        self.deiconify()  #geometry set, unhide
        self.wait_window()

    def create_widgets(self):
        self.name = StringVar(self.parent)
        self.fontSize = StringVar(self.parent)
        self.frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
        self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
        self.messageInfo = Message(self.frameMain,
                                   anchor=W,
                                   justify=LEFT,
                                   padx=5,
                                   pady=5,
                                   text=self.message)  #,aspect=200)
        entryName = Entry(self.frameMain, textvariable=self.name, width=30)
        entryName.focus_set()
        self.messageInfo.pack(padx=5, pady=5)  #, expand=TRUE, fill=BOTH)
        entryName.pack(padx=5, pady=5)
        frameButtons = Frame(self, pady=2)
        frameButtons.pack(side=BOTTOM)
        self.buttonOk = Button(frameButtons,
                               text='Ok',
                               width=8,
                               command=self.Ok)
        self.buttonOk.pack(side=LEFT, padx=5)
        self.buttonCancel = Button(frameButtons,
                                   text='Cancel',
                                   width=8,
                                   command=self.Cancel)
        self.buttonCancel.pack(side=RIGHT, padx=5)

    def name_ok(self):
        ''' After stripping entered name, check that it is a  sensible
        ConfigParser file section name. Return it if it is, '' if not.
        '''
        name = self.name.get().strip()
        if not name:  #no name specified
            tkMessageBox.showerror(title='Name Error',
                                   message='No name specified.',
                                   parent=self)
        elif len(name) > 30:  #name too long
            tkMessageBox.showerror(
                title='Name Error',
                message='Name too long. It should be no more than ' +
                '30 characters.',
                parent=self)
            name = ''
        elif name in self.used_names:
            tkMessageBox.showerror(title='Name Error',
                                   message='This name is already in use.',
                                   parent=self)
            name = ''
        return name

    def Ok(self, event=None):
        name = self.name_ok()
        if name:
            self.result = name
            self.destroy()

    def Cancel(self, event=None):
        self.result = ''
        self.destroy()
class GetCfgSectionNameDialog(Toplevel):
    def __init__(self, parent, title, message, used_names, _htest=False):
        """
        message - string, informational message to display
        used_names - string collection, names already in use for validity check
        _htest - bool, change box location when running htest
        """
        Toplevel.__init__(self, parent)
        self.configure(borderwidth=5)
        self.resizable(height=FALSE, width=FALSE)
        self.title(title)
        self.transient(parent)
        self.grab_set()
        self.protocol("WM_DELETE_WINDOW", self.Cancel)
        self.parent = parent
        self.message = message
        self.used_names = used_names
        self.create_widgets()
        self.withdraw()  #hide while setting geometry
        self.update_idletasks()
        #needs to be done here so that the winfo_reqwidth is valid
        self.messageInfo.config(width=self.frameMain.winfo_reqwidth())
        self.geometry(
                "+%d+%d" % (
                    parent.winfo_rootx() +
                    (parent.winfo_width()/2 - self.winfo_reqwidth()/2),
                    parent.winfo_rooty() +
                    ((parent.winfo_height()/2 - self.winfo_reqheight()/2)
                    if not _htest else 100)
                ) )  #centre dialog over parent (or below htest box)
        self.deiconify()  #geometry set, unhide
        self.wait_window()
    def create_widgets(self):
        self.name = StringVar(self.parent)
        self.fontSize = StringVar(self.parent)
        self.frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
        self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
        self.messageInfo = Message(self.frameMain, anchor=W, justify=LEFT,
                    padx=5, pady=5, text=self.message) #,aspect=200)
        entryName = Entry(self.frameMain, textvariable=self.name, width=30)
        entryName.focus_set()
        self.messageInfo.pack(padx=5, pady=5) #, expand=TRUE, fill=BOTH)
        entryName.pack(padx=5, pady=5)
        frameButtons = Frame(self, pady=2)
        frameButtons.pack(side=BOTTOM)
        self.buttonOk = Button(frameButtons, text='Ok',
                width=8, command=self.Ok)
        self.buttonOk.pack(side=LEFT, padx=5)
        self.buttonCancel = Button(frameButtons, text='Cancel',
                width=8, command=self.Cancel)
        self.buttonCancel.pack(side=RIGHT, padx=5)

    def name_ok(self):
        ''' After stripping entered name, check that it is a  sensible
        ConfigParser file section name. Return it if it is, '' if not.
        '''
        name = self.name.get().strip()
        if not name: #no name specified
            tkMessageBox.showerror(title='Name Error',
                    message='No name specified.', parent=self)
        elif len(name)>30: #name too long
            tkMessageBox.showerror(title='Name Error',
                    message='Name too long. It should be no more than '+
                    '30 characters.', parent=self)
            name = ''
        elif name in self.used_names:
            tkMessageBox.showerror(title='Name Error',
                    message='This name is already in use.', parent=self)
            name = ''
        return name
    def Ok(self, event=None):
        name = self.name_ok()
        if name:
            self.result = name
            self.destroy()
    def Cancel(self, event=None):
        self.result = ''
        self.destroy()
Example #29
0
        init_main_window(root, ethan_eyes);
        app = Ethan(root, player_num, ethan_eyes);
        root.mainloop();
    return
    
#start program with dialog box, which will lead to either just terminating
#or making a game box
if __name__ == "__main__":
    player_dlg = Tk();
    player_dlg.geometry("%dx%d+%d+%d" % 
        (INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT, X_POS, Y_POS))
    # TODO: make dialog box show up in the middle of the screen based on
    # screen resolution
    player_dlg.title("How many players?")
    msg = Message(player_dlg, text="How many players will be playing this time?");
    msg.pack()
    player_count = Entry(player_dlg)
    player_count.pack()
    ethan_eyes_var = IntVar()
    ethan_eyes_check = Checkbutton(player_dlg, \
                                   text="enable Ethan Eyes", \
                                   var=ethan_eyes_var)
    ethan_eyes_check.pack()
    confirm_button = Button(player_dlg, text="OK", \
                            command=lambda: generate_main(player_dlg, \
                                                          player_count, \
                                                          ethan_eyes_var) );
    confirm_button.pack();
    cancle_button = Button(player_dlg, text="Cancel", \
                            command=lambda: player_dlg.quit() );
    cancle_button.pack();
def generate():
    ## Get the values of all variables ##
    cvar = constvar.get()        # Which variable is the constant one?
    sams = int(samples.get())    # Number of samples
    avg  = float(var.get())      # Average value of sampled variable
    eps  = eRange.get()          # Range of sampled variable
    para = float(const.get())    # Value of constant variable
    its  = int(iterations.get()) # Number of iterations
    star = int(start.get())      # First iteration to display to user
    styp = sampleType.get()      # Type of sampling method
    
    ## Set the view variables according to the check boxes make their default
    ## values an empty string.
    c,s,b = "","",""
    if c_check.get() == '1':
        c = "c"         # Indicates if cylinder view is checked.
    if s_check.get() == '1':
        s = "s"         # Indicates if spherical view is checked.
    if b_check.get() == '1':
        b = "b"         # Indicates if stadia view is checked.
    
    # get the eps value ready to pass to the plotter
    if eps == "pi/4":
        epsi = pi/4
    elif eps == "pi/16":
        epsi = pi/16
    elif eps == "pi/64":
        epsi = pi/64
    elif eps == "pi/256":
        epsi = pi/256
    elif eps == "pi/1024":
        epsi = pi/1024
    else:
        print "Invalid input from drop down menu"
    
    ## Make sure that the number of iterations and the first iteration to ##
    ## display are consistent ------------------------------------------- ##
    if its <= star:
        iteration_error_window = tk.Toplevel(master)
        iteration_error_window.geometry("300x150")
        iteration_error_window.title("ILLEGAL INPUT DETECTED")
          
        text = Message(iteration_error_window, text = ITERMESSAGE)
        text.pack()
        return False
    
    ## Make sure that theta is in the proper range ##    
    if cvar == "theta" and (para < 0 or para >= 2*pi):
        # para is a theta value and its outside of the [0,2pi) range.
        # Mod it into the [0,2pi) range.
        para = mod2pi(para)

    
    ## Make sure that phi is in the proper range ##
    if cvar == "phi" and (para <= -pi/2 or para >= pi/2):
        phi_error_window = tk.Toplevel(master)
        phi_error_window.geometry("400x300")
        phi_error_window.title("ILLEGAL INPUT DETECTED")
        
        text = Message(phi_error_window, text = PHIMESSAGE1)
        text.pack()
        return False
    ## Make sure that phi is in the proper range ##
    if cvar == "theta" and (avg - epsi <= -pi/2 or avg + epsi >= pi/2):
        phi_error_window = tk.Toplevel(master)
        phi_error_window.geometry("400x200")
        phi_error_window.title("ILLEGAL INPUT DETECTED")
        
        text = Message(phi_error_window, text = PHIMESSAGE2)
        text.pack()
        return False
    
    if plotter(cvar, sams, avg - epsi, avg + epsi, para, its+1, star, 2, \
                    styp, c + s + b):
        confirm_window = tk.Toplevel(master) 
        confirm_window.geometry("200x100")
        confirm_window.title("Success!")
        
        msg  = """
        Pdf(s) of the desired images were created 
        in the folder containing this application.
        """
        text = Message(confirm_window, text = msg, padx = 10)
        text.pack()

"------------------------------------- Label Update Method ------------------------------------**"


def update_the_label(newText):
    sleep(1)
    packable_update.configure(text=newText)
    root1.update_idletasks()


"------------------------------------- UI Packing/Execution ------------------------------------**"

#Setup Button to Trigger Main Method when Pressed
goButton = tk.Button(root1,
                     text="Start",
                     width=25,
                     command=mainMethod,
                     relief=tk.RAISED)

#Pack Elements into Root Window
panel.pack(side=tk.TOP, fill="both", expand="yes")
welcome1.pack()
welcome2.pack()
label.pack()
entry.pack()
goButton.pack(padx=5, pady=5)
packable_update.pack()

#Run the Code with UI
root1.mainloop()
Example #32
0
 def do_a_turn(self):
     # roll die
     die1_val = random.randint(1,6)
     die2_val = random.randint(1,6)
     # TODO: potentially simulate die motion like in matlab version
     # change die values on screen
     self.dice1_strvar.set(str(die1_val))
     self.dice2_strvar.set(str(die2_val))
     
     # check dice conditions
     ethan_val = int(self.ethan_strvar.get())
     player_val = int(self.player_strvars[self.player_turn].get())
     if (die1_val+die2_val == 4):
         # player gets ethan's stuff
         player_val = player_val + ethan_val
         ethan_val = 0
     elif (die1_val+die2_val == 2) and self.ethan_eyes:
         # player loses it all to ethan
         ethan_val = player_val + ethan_val
         player_val = 0
     else:
         # player loses one chip to ethan
         ethan_val = ethan_val + 1
         player_val = player_val - 1
     self.ethan_strvar.set(str(ethan_val))
     self.player_strvars[self.player_turn].set(str(player_val))
     # check for the lose condition
     total_chips = 0
     num_players_positive = 0
     for x in self.player_strvars:
         if int(x.get()) > 0:
             num_players_positive = num_players_positive + 1
         total_chips = total_chips + int(x.get())
     if total_chips == 0:
         # everybody loses
         error_dlg = Toplevel(master=self.main_window)
         error_dlg.geometry("%dx%d+%d+%d" % 
             (INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT, X_POS, Y_POS))
         error_dlg.title( "LOSERS" );
         error_dlg.grab_set();
         error_msg = Message(error_dlg, aspect=300, text="EVERYBODY LOSES, AE2015")
         error_msg.pack();
         error_button = Button(error_dlg, text="OK", \
                             command=lambda: self.destroy_all(error_dlg));
         error_button.pack();
         error_dlg.update();
     elif (num_players_positive == 1) and (player_val > ethan_val):
         #win condition, only for player who just moved
         player_name = self.player_name_list[self.player_turn].get();
         error_dlg = Toplevel(master=self.main_window)
         error_dlg.geometry("%dx%d+%d+%d" % 
             (INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT, X_POS, Y_POS))
         error_dlg.title( "WINNER" );
         error_dlg.grab_set();
         error_msg = Message(error_dlg, aspect=300, text="GOOD JOB %s, YOU BEAT ETHAN" % (player_name) )
         error_msg.pack();
         error_button = Button(error_dlg, text="OK", \
                                 command=error_dlg.destroy);
         error_button.pack();
         error_dlg.update();
     else:
         # game isn't over, increment turn to next positive player
         self.player_frame_list[self.player_turn].config(relief='flat', \
             borderwidth=0)
         num_players = len(self.player_strvars)
         found_next = 0
         self.current_turn = self.current_turn + 1
         while (found_next == 0):
             self.player_turn = (self.player_turn + 1) % num_players
             if int(self.player_strvars[self.player_turn].get()) > 0:
                 found_next = 1
         self.player_frame_list[self.player_turn].config(relief='raised', \
             borderwidth=2)    
     return
Example #33
0
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()
    if tkMessageBox.askyesno('Steam Library Exporter v0.9', 'Thanks for using Steam Library Exporter! \nWant to run it again?'):
        print "Running again!"
        entry.delete(0,tk.END)
        update_the_label("Ready (again)!")
    else:
        root1.destroy()

"------------------------------------- Label Update Method ------------------------------------**"

def update_the_label(newText):
    sleep(1)
    packable_update.configure(text = newText)
    root1.update_idletasks()

"------------------------------------- UI Packing/Execution ------------------------------------**"

#Setup Button to Trigger Main Method when Pressed
goButton = tk.Button(root1, text="Start", width=25, command=mainMethod, relief=tk.RAISED)

#Pack Elements into Root Window
panel.pack(side=tk.TOP, fill = "both", expand = "yes")
welcome1.pack()
welcome2.pack()
label.pack()
entry.pack()
goButton.pack(padx=5,pady=5)
packable_update.pack()

#Run the Code with UI
root1.mainloop()
Example #35
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()
Example #36
0
class Application(Frame):
    """Main application class"""
    json_file_name = "functions.json" # should be none after tests
    json_data = None
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.create_widgets()
        master.title("Regula falsi")
        master.minsize(width=100, height=100)
        master.config(menu=self.menubar)

    def calculate(self):
        """Does all the work"""
        item_number = self.fields.curselection()
        polynomial = self.json_data["functions"][int(item_number[0])]
        result_floating = None
        result_interval = None
        if self.json_data["method"] == "regula_falsi":
            try:
                result_floating = regula_falsi(polynomial["a"],
                                               polynomial["b"],
                                               function_from_list,
                                               polynomial["coeff"]
                                              )
            except MyError as error:
                result_floating = error.value
            except ZeroDivisionError:
                result_floating = "Unfortunately, division by 0 happened"
            try:
                result_interval = regula_falsi_interval(polynomial["a"],
                                                        polynomial["b"],
                                                        function_from_list,
                                                        polynomial["coeff"]
                                                       )
                result_interval = result_interval.format('%.20E')[9:]
                result_interval = result_interval[:-1]
            except MyError as error:
                result_interval = error.value
        elif self.json_data["method"] == "newton":
            try:
                result_floating = newton(polynomial["x"],
                                         polynomial["epsilon"],
                                         polynomial["max_iterations"],
                                         function_from_list,
                                         polynomial["coeff"],
                                         polynomial["derivative_coeff"]
                                        )
            except ZeroDivisionError:
                result_floating = "Unfortunately, division by zero happened"
            except MyError as error:
                result_floating = error.value
            try:
                result_interval = newton_interval(polynomial["x"],
                                                  polynomial["epsilon"],
                                                  polynomial["max_iterations"],
                                                  function_from_list,
                                                  polynomial["coeff"],
                                                  polynomial["derivative_coeff"]
                                                 )
                result_interval = result_interval.format('%.20E')[9:]
                result_interval = result_interval[:-1]
            except MyError as error:
                result_interval = error.value
        else:
            result_interval = "You propably"
            result_floating = "gave me wrong JSON"
        self.show_result_floating.config(text=result_interval)
        self.show_result_interval.config(text=result_floating)

    def read_json_file(self):
        """Reads function coefficients from json files"""
        self.fields.delete(0, END)
        self.json_file_name = load_file()
        with open(self.json_file_name) as json_file:
            self.json_data = json.load(json_file)
        for item in self.json_data["functions"]:
            self.fields.insert(END, item["coeff"])

    def create_widgets(self):
        """Creates buttons on the window and binds actions to them"""
        #listbox for the equations
        self.fields = Listbox(self, selectmode=SINGLE)
        self.fields.config(width=100)
        self.fields.pack()
        #button for calculating
        self.calculate_button = Button(self)
        self.calculate_button["text"] = "Calculate"
        self.calculate_button["command"] = self.calculate
        self.calculate_button.pack({"side": "left"})
        #to the end
        self.show_result_floating = Message(self, width=250)
        self.show_result_floating.pack()
        #second Message
        self.show_result_interval = Message(self, width=250)
        self.show_result_interval.pack()
        #adding menu buttons to the window
        self.menubar = Menu(self)
        self.menubar.add_command(label="Load file", command=self.read_json_file)
        self.menubar.add_command(label="Quit", command=self.quit)
Example #37
0
class Data_Cell(Cell):
    def __init__(self,
                 master,
                 variable,
                 anchor=W,
                 bordercolor=None,
                 borderwidth=1,
                 padx=0,
                 pady=0,
                 background=None,
                 foreground=None,
                 font=None,
                 row_num=0,
                 col_num=0,
                 table=None,
                 width=100,
                 text_to_img=None):
        Cell.__init__(self,
                      master,
                      background=background,
                      highlightbackground=bordercolor,
                      highlightcolor=bordercolor,
                      highlightthickness=borderwidth,
                      bd=0)
        self.background = background
        self.text_to_img = text_to_img
        self.variable = variable
        self.row_num = row_num
        self.table = table

        def change_var(*args):
            try:
                if self.text_to_img[self.variable.get()]:
                    #print(self.variable.get())
                    bg = background
                    fg = foreground
                    if self._message_widget:
                        bg = self._message_widget.cget('background')
                        fg = self._message_widget.cget('foreground')
                    self._message_widget.pack_forget()
                    self._message_widget = Label(
                        self,
                        width=width,
                        background=bg,
                        foreground=fg,
                        image=self.text_to_img[self.variable.get()])
                    self._message_widget.pack(expand=True,
                                              padx=padx,
                                              pady=pady,
                                              anchor=anchor)
                    self._message_widget.bind(
                        '<Button-1>',
                        lambda event, row=self.row_num, table=self.table:
                        cell_selected(event, table, row))
            except KeyError as e:
                pass
            return

        if text_to_img:
            variable.trace('w', change_var)

        self._message_widget = Message(self,
                                       width=width,
                                       textvariable=variable,
                                       font=font,
                                       background=background,
                                       foreground=foreground)
        self._message_widget.pack(expand=True,
                                  padx=padx,
                                  pady=pady,
                                  anchor=anchor)

        self.bind('<Button-1>',
                  lambda event, row=row_num, table=table: cell_selected(
                      event, table, row))
        self._message_widget.bind('<Button-1>',
                                  lambda event, row=row_num, table=table:
                                  cell_selected(event, table, row))
Example #38
0
# De message widget is hetzelfde als het Label maar biedt meer flexibiliteit voor text

from Tkinter import Tk, Message

master = Tk()
whatever_you_do = "Whatever you do will be insignificant, but it is very important that you do it.\n(Mahatma Gandhi)"
msg = Message(master, text=whatever_you_do)
msg.config(bg='lightgreen', font=('times', 24, 'italic'))
msg.pack()

master.mainloop()

# Alle magelijke opties voor de config van een message widget, kunnen hier teruggevonden worden:
# https://www.python-course.eu/tkinter_message_widget.php