Пример #1
1
    def initUI(self):
        self.parent.title("Buttons")
        self.style = Style()
        self.style.theme_use("default")

        frame = Frame(self, relief=GROOVE, borderwidth=5)
        frame.pack(fill=BOTH, expand=1)
        self.pack(fill = BOTH, expand = 1)

        self.imageLabel = Label(frame, image = "")
        self.imageLabel.pack(fill=BOTH, expand=1)

        closeButton = Button(self, text="Close")
        closeButton.pack(side=RIGHT)
        okButton = Button(self, text="OK")
        okButton.pack(side=RIGHT)

        options = [item for item in dir(cv2.cv) if item.startswith("CV_CAP_PROP")]
        option = OptionMenu(self, self.key, *options)
        self.key.set(options[0])
        option.pack(side="left")

        spin = Spinbox(self, from_=0, to=1, increment=0.05)
        self.val = spin.get()
        spin.pack(side="left")
Пример #2
0
class StarterWindow(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.wm_title("FRCA QBase Reader - Start Menu")
        self.exambtn = Button(self, text="start an exam", command=self.startExam)
        self.exambtn.pack()
        self.maxquestvar = IntVar()
        self.maxquest = Spinbox(self, from_=1, to=1667, width=4, textvariable=self.maxquestvar)
        self.maxquest.pack()
        self.questbtn = Button(self, text="start single questions", command=self.startQuestions)
        self.questbtn.pack()
        self.um = """User manual:\n
		Start either an exam or single questions\n
		Go to next question either with mouse or the <right arrow>\n
		Toggle checkboxes either with mouse or <keyboard buttons 1-5>\n
		In single question mode, show answer either with mouse or <return>\n
		In exam mode, results will display after the set question number\n
		Text can be made bigger/smaller with <Up> or <Down> keyboard arrows"""
        self.usermanual = Label(self, text=self.um, justify=LEFT)
        self.usermanual.pack()

    def startExam(self):
        call(["python", "exam.py", str(self.maxquestvar.get())])

    def startQuestions(self):
        call(["python", "quest_by_quest.py"])
Пример #3
0
    def ventanaImprimir(self):
        t = Toplevel(self)
        t.wm_title("Imprimir")

        Label(t, text="Numero de Copias por etiqueta").pack()
        w = Spinbox(t, from_=1, to=10)
        w.pack()

        buttonImprimir = Button(t, text="Imprimir",  command=lambda:self.imprimir(int(w.get()),t))
        buttonImprimir.pack()
Пример #4
0
def buscar():
    root = Tkinter.Toplevel()

    jorn = Spinbox(root, from_=0, to=50)

    def boton():
        listar(jorn.get())

    but = Tkinter.Button(root, text="Buscar", command=boton)

    jorn.pack(side=LEFT)
    but.pack(side=RIGHT)
    root.mainloop()
Пример #5
0
def init_slow_time(root):
    slow_time_frame = Frame(root)
    slow_time_frame.pack(fill=X)

    slow_time_label = Label(slow_time_frame, text='Slowing time [0; 10] sec:')
    slow_time_label.pack(side='left')

    slow_time = Spinbox(slow_time_frame, from_=0, to=10, width=4)
    slow_time.delete(0, 1)
    slow_time.insert(0, 5)
    slow_time.pack(side='right')

    return slow_time_frame, slow_time_label, slow_time
Пример #6
0
def init_speed_sup(root):
    speed_sup_frame = Frame(root)
    speed_sup_frame.pack(fill=X)

    speed_sup_label = Label(speed_sup_frame,
                            text='Max initial speed [0; 200]:')
    speed_sup_label.pack(side='left')

    speed_sup = Spinbox(speed_sup_frame, from_=0, to=200, width=4)
    speed_sup.delete(0, 1)
    speed_sup.insert(0, 60)
    speed_sup.pack(side='right')

    return speed_sup_frame, speed_sup_label, speed_sup
Пример #7
0
def init_speed_inf(root):
    speed_inf_frame = Frame(root)
    speed_inf_frame.pack(fill=X)

    speed_inf_label = Label(speed_inf_frame,
                            text='Min initial speed [0; 200]:')
    speed_inf_label.pack(side='left')

    speed_inf = Spinbox(speed_inf_frame, from_=0, to=200, width=4)
    speed_inf.delete(0, 1)
    speed_inf.insert(0, 30)
    speed_inf.pack(side='right')

    return speed_inf_frame, speed_inf_label, speed_inf
Пример #8
0
def init_range_of_vision(root):
    range_of_vision_frame = Frame(root)
    range_of_vision_frame.pack(fill=X)

    range_of_vision_label = Label(range_of_vision_frame,
                                  text='Range of vision [1; 10] (in cars):')
    range_of_vision_label.pack(side='left')

    range_of_vision = Spinbox(range_of_vision_frame, from_=1, to=10, width=4)
    range_of_vision.delete(0, 1)
    range_of_vision.insert(0, 3)
    range_of_vision.pack(side='right')

    return range_of_vision_frame, range_of_vision_label, range_of_vision
Пример #9
0
def init_spawn_sup(root):
    spawn_sup_frame = Frame(root)
    spawn_sup_frame.pack(fill=X)

    spawn_sup_label = Label(spawn_sup_frame,
                            text='Max spawn interval [0; 10] sec:')
    spawn_sup_label.pack(side='left')

    spawn_sup = Spinbox(spawn_sup_frame, from_=0, to=10, width=4)
    spawn_sup.delete(0, 1)
    spawn_sup.insert(0, 5)
    spawn_sup.pack(side='right')

    return spawn_sup_frame, spawn_sup_label, spawn_sup
Пример #10
0
def init_slow_factor(root):
    slow_factor_frame = Frame(root)
    slow_factor_frame.pack(fill=X)

    slow_factor_label = Label(slow_factor_frame, text='Slowing factor [0; 1]:')
    slow_factor_label.pack(side='left')

    slow_factor = Spinbox(slow_factor_frame,
                          from_=0,
                          to=1,
                          width=4,
                          increment=0.1)
    slow_factor.delete(0, 3)
    slow_factor.insert(0, 0.5)
    slow_factor.pack(side='right')

    return slow_factor_frame, slow_factor_label, slow_factor
Пример #11
0
def listar(n):
    conn = sqlite3.connect('marca.db')
    root = Tkinter.Toplevel()
    frame = Frame(root)
    frame2 = Frame(root)

    cursor = conn.execute("SELECT PARTIDO from CRONICAS WHERE JORNADA LIKE '" +
                          n + "'")

    partidos = []
    for c in cursor:
        partidos.append(c[0])

    def cambio():
        cursor = conn.execute(
            "SELECT CRONICA FROM CRONICAS WHERE PARTIDO LIKE '" +
            partido.get() + "'")
        for row in cursor:
            sql = "SELECT * FROM GOLES WHERE CRONICA LIKE '%" + row[0] + "%'"

        cursor = conn.execute(sql)
        lista.delete(0, END)
        i = 0
        for row in cursor:
            i += 1
            lista.insert(
                i, "EQUIPO: " + row[0] + "        JUGADOR: " + row[1] +
                "       MINUTO: " + row[2])

    partido = Spinbox(frame, values=partidos, command=cambio)
    etiq = Label(frame, text="Elija Partido:")
    barra = Scrollbar(frame2)
    lista = Listbox(frame2, width=80, height=8)

    frame.pack(side=LEFT)
    frame2.pack(side=LEFT)
    lista.pack(side=LEFT, fill=BOTH)
    barra.pack(side=RIGHT, fill=Y)
    barra.config(command=lista.yview)

    etiq.pack(side=TOP)
    partido.pack(side=RIGHT)

    root.mainloop()
    conn.close()
Пример #12
0
def choose_cutoff(data, time):
    import matplotlib.pyplot as plt
    import numpy as np
    # import Tkinter as tk
    import sys
    from Tkinter import Spinbox, Tk, Button, LEFT  # , mainloop
    # from Tkinter import *

    global choose
    choose = True
    # i = 0
    global cut
    cut = 100

    # global l_line
    # l_line = plt.axvline(cut)

    def combine_funcs(*funcs):
        def combined_func(*args, **kwargs):
            for f in funcs:
                f(*args, **kwargs)

        return combined_func

    def destroywindows(**kwargs):
        for m in kwargs:
            m.destroy()
        for f in kwargs:
            f.close()
        # master.destroy()

    def setvalues(var, value):
        var = value
        return var

    def choosefalse():
        global choose
        choose = False
        # print(choose)

    def spintocut():
        global cut
        cut = int(cutspin.get())
        # print(cut)

    # def callback():
    # print("something")
    # global l_line
    # l_line(cut)
    # l_line = plt.axvline(cut)
    # plt.draw()
    # plt.ion()
    # plt.pause(0.05)

    # plt.figure('data')
    # plt.plot(data)
    # plt.show(block=False)
    # # plt.draw()

    while choose is True:
        plt.figure('data')
        plt.plot(data)
        # l_line = plt.axvline(cut)
        plt.axvline(np.shape(data)[0] - cut)
        # plt.draw()
        plt.show(block=False)
        # plt.ion()
        # plt.pause(0.05)

        # print(choose)
        # print(cut)

        master = Tk()

        # print(type(data[0]))

        cutspin = Spinbox(master,
                          from_=0,
                          to=np.shape(data)[0],
                          textvariable=cut)  # , command=callback)
        cutspin.delete(0)
        cutspin.insert(0, cut)

        cutspin.pack()
        # print(type(cutspin))
        # print(cutspin.get())
        applyButton = Button(master,
                             text='apply',
                             command=combine_funcs(spintocut, plt.close,
                                                   master.destroy))
        applyButton.pack(side=LEFT)
        goonButton = Button(master,
                            text='go on',
                            command=combine_funcs(master.destroy, plt.close,
                                                  choosefalse))
        goonButton.pack(side=LEFT)
        quitButton = Button(master, text='quit', command=sys.exit)
        quitButton.pack(side=LEFT)

        master.mainloop()
        # Tk.update()
        # plt.update()
        # plt.show(block=False)

        # l_left.remove()
        # l_right.remove()
        # plt.draw()

    cutoff = cut

    return cutoff
Пример #13
0
    def refreshWidget(self):
        #print "refresh"
        self.card_win.pack_forget()

        #Card window
        self.card_win = PanedWindow(self.card_win.master, orient=VERTICAL)
        self.card_win.pack(side=TOP, expand=True, fill=BOTH, pady=2, padx=2)

        #Create the name zone
        name_zone = PanedWindow(self.card_win, orient=HORIZONTAL)
        name = StringVar()
        name.set(self.name)
        from deck_creation import blocked_creature

        def modifName(*args):
            old = self.name in blocked_creature
            self.name = name.get()
            if old or self.name in blocked_creature:
                self.refreshWidget()

        name.trace("w", modifName)
        name_wid = Entry(name_zone, width=30, textvariable=name)
        name_wid.pack()
        name_zone.add(name_wid)
        #Create the cost ad star stringvar
        #print int(floor(self.getCost()))
        self.cost = StringVar()
        self.stars = StringVar()
        cost_wid = Label(None,
                         textvariable=self.cost,
                         background='red',
                         width=5,
                         anchor=W)
        star_wid = Label(None,
                         textvariable=self.stars,
                         background='blue',
                         anchor=E)
        self.cost.set(str(int(floor(self.getCost()))))
        self.stars.set("*" * self.getStars())
        #Add them in name zone
        name_zone.add(cost_wid)
        name_zone.add(star_wid)

        #Create an Image Zone
        image_zone = Button(self.card_win, command=self.choosePhoto)
        if hasattr(self, "photofile") and self.photofile:
            print "Image: ", self.photofile
            try:
                img = Image.open(self.photofile)
            except:
                decomp = self.photofile.split('/')
                for i in range(1, 6):
                    try:
                        fname = "/".join(decomp[-i:])
                        print "try to open", fname
                        img = Image.open(fname)
                        self.photofile = fname
                        break
                    except:
                        self.photofile = None
        if self.photofile:
            w, h = img.size
            if w > 300 or h > 200:
                img = img.resize((w / 2, h / 2), Image.LINEAR)
            image_zone.image = ImageTk.PhotoImage(img)
            image_zone.config(image=image_zone.image)
            #print "IMAGE CHANGED"
        else:
            from os import path
            fname = self.name.replace(" ", "_")
            if path.isfile("Cards/" + fname + ".png"):
                image_zone.config(text='image can be taken from\n' + "Cards/" +
                                  fname + ".png",
                                  background='white',
                                  anchor=CENTER)
            else:
                image_zone.config(text='clic to choose image',
                                  background='white',
                                  anchor=CENTER)

        image_zone.pack

        # POWER ZONE
        power_zone = PanedWindow(self.card_win, orient=VERTICAL)

        #fenetre=self.card_win.master
        def removePowerCreator(px):
            def removePower(*args):
                #print 'avant',list_pow
                self.bonus.remove(px)
                #print 'apres',list_pow
                #self.card_win.pack_forget()
                self.refreshWidget()

            return removePower

        for p in self.bonus:
            powline = PanedWindow(self.card_win, orient=HORIZONTAL)
            pow_wid = p.initWidget(powline)
            powline.add(pow_wid)
            removepow = Button(powline,
                               text="X",
                               command=removePowerCreator(p),
                               anchor=E)
            removepow.pack()
            powline.add(removepow)
            power_zone.add(powline)

        def addPower(*args):
            name = addBonus.get()
            print "added :", name
            import cardPowers
            self.bonus += [eval('cardPowers.' + name + '()')]
            self.bonus[-1].parent = self.bonus
            self.bonus[-1].card = self
            #self.card_win.pack_forget()
            self.refreshWidget()

        #Add bonus Option menu
        addBonus = StringVar(power_zone)
        addBonus.set("add bonus")  # default value
        if not self.pv: addBonus_wid = getSpellMenu(power_zone, addBonus)
        else: addBonus_wid = getBonusMenu(power_zone, addBonus)
        addBonus.trace('w', addPower)
        if self.pv > 0 or len(self.bonus) == 0:
            addBonus_wid.pack()
            #Add this to power zone
            power_zone.add(addBonus_wid)

        #Create save zone
        save_zone = PanedWindow(self.card_win, orient=HORIZONTAL)
        lv = int(localopen("progression", "r").read())
        if self.monster_type != "all" and not (lv < 8 and self.name
                                               in blocked_creature):
            save_wid = Button(save_zone, text="Save", command=self.postAndSave)
        elif self.monster_type != "all":
            save_wid = Button(save_zone,
                              text="creature in campaign",
                              command=None)
        else:
            save_wid = Button(save_zone, text="nead type", command=None)
        save_wid.pack()
        #Create the open button
        save_zone.pack()
        if Card.monster_list.keys():
            self.opening = StringVar(save_zone)
            self.opening.set("Open")
            choice = Card.monster_list.keys()
            choice.sort()
            #print all_monsters.keys()
            open_wid = OptionMenu(save_zone, self.opening, *choice)
            self.opening.trace('w', self.Open)
            open_wid.pack()
            save_zone.add(open_wid)

        if Card.monster_list.keys():
            self.delete = StringVar(save_zone)
            self.delete.set("Delete")
            choice = Card.monster_list.keys()
            choice.sort()
            delete_wid = OptionMenu(save_zone, self.delete, *choice)
            self.delete.trace('w', self.clicDelete)
            delete_wid.pack()
            save_zone.add(delete_wid)

        #Create the type button
        self.category = StringVar(save_zone)
        self.category.set(self.monster_type)
        choice = [
            file2name(t, "_monsters.sav")
            for t in glob.glob("CardFiles/*_monsters.sav")
        ]
        if "recup" in choice:
            choice.remove("recup")
        #print all_monsters.keys()
        category_wid = OptionMenu(save_zone, self.category, *choice)
        self.category.trace('w', self.setFile)

        category_wid.pack()

        #Add it to save zone
        save_zone.add(save_wid)
        save_zone.add(category_wid)

        #Create a new Strength zone for att and pv
        strength_zone = PanedWindow(self.card_win, orient=HORIZONTAL)
        att = StringVar()
        att.set(str(self.att))
        pv = StringVar()
        pv.set(str(self.pv))

        def modifiedAttPv(*args):
            print "modifiedAttPv"
            self.pv = int(pv.get())
            if self.pv < 1 and self.is_spell == False:
                if len(self.bonus) == 0:
                    self.is_spell = True
                    self.refreshWidget()
                else:
                    self.pv = 1
                    self.refreshWidget()
            if self.pv > 0 and self.is_spell == True:
                if len(self.bonus) == 0:
                    self.is_spell = False
                    self.refreshWidget()
                else:
                    self.pv = 0
                    self.refreshWidget()
            self.att = int(att.get())
            self.getCost()

        att_wid = Spinbox(strength_zone,
                          from_=0,
                          to=1000,
                          textvariable=att,
                          command=modifiedAttPv)
        att_wid.pack()
        strength_zone.add(att_wid)
        strength_zone.add(
            Label(strength_zone,
                  text='       ',
                  background='white',
                  anchor=CENTER))
        pv_wid = Spinbox(strength_zone,
                         from_=0,
                         to=1000,
                         textvariable=pv,
                         command=modifiedAttPv)
        pv_wid.pack()
        strength_zone.add(pv_wid)

        #Put it all in window
        self.card_win.add(name_zone)
        self.card_win.add(image_zone)
        self.card_win.add(power_zone)
        self.card_win.add(strength_zone)
        self.card_win.add(save_zone)

        self.card_win.pack()
class AntroidGUI(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.protocol("WM_DELETE_WINDOW", self.myquit)
        self.etat = True
        self.readstate = True
        self.title("Antroid Map")
        self.turns = {}
        self.selectTurn = -1
        self.caselength = 10
        self.CaseMarge = 20
        self.var = StringVar()
        self.initGUI()

    def initGUI(self):
        frame = Frame(self, width=630, height=500)
        self.panel = PanedWindow(frame, orient=HORIZONTAL)

        self.LeftFrame(self.panel)
        self.RightFrame(self.panel)
        self.panel.add(self.LFrame)
        self.panel.add(self.RFrame)
        self.panel.pack()
        frame.pack()

    def LeftFrame(self, parent):
        self.LFrame = Frame(parent, width=500, height=500)
        self.maptroid = Canvas(self.LFrame, bg='black', width=500, height=500)
        if self.selectTurn >= 0:
            self.printMap()

        self.maptroid.pack()
        self.LFrame.pack()

    def RightFrame(self, parent):
        self.RFrame = Frame(parent, width=130, height=500)
        if self.selectTurn >= 0:
            self.printInfo()
        self.FrameInfo = None
        self.updateT = True
        self.RFrame.pack()

    def setreadstate(self, readstate):
        self.readstate = readstate

    def addTurn(self, turnnumber, turnvalue):
        self.turns[turnnumber] = turnvalue
        self.updateGui(turnnumber)
        return self.etat

    def updateGui(self, turn):
        self.selectTurn = turn
        self.updateMap()
        self.updateInfo()

    def updateMap(self):
        self.maptroid.delete(ALL)
        self.printMap()

    def updateInfo(self):
        if self.FrameInfo:
            if self.updateT:
                self.frameT.destroy()
                self.printTurn()
            self.frameAnts.destroy()
            self.frameAnt.destroy()
            self.printAnts()
            self.updateT = True
        else:
            self.printInfo()

    def updateSpin_turn(self):
        turn = int(self.Spin_T.get())
        self.updateT = False
        self.updateGui(turn)

    def validateTurn(self, event):
        try:
            turn = int(self.Spin_T.get())
        except ValueError:
            turn = self.selectTurn
        if turn in self.turns.keys():
            if turn != self.selectTurn:
                self.updateT = False
                self.updateGui(turn)
        else:
            turn = self.selectTurn

    def choiceAnt(self, event):
        i = self.listbox.curselection()
        id_a = self.listbox.get(i)
        self.frameAnt.destroy()
        self.printInfoAnt(int(id_a))

    def printInfo(self):
        self.FrameInfo = Frame(self.RFrame)
        self.printTurn()
        self.printAnts()
        self.FrameInfo.pack()

    def printTurn(self):
        frameS = PanedWindow(self.FrameInfo, orient=HORIZONTAL)
        turns = Label(frameS, text="Tour :")
        self.var.set(str(self.selectTurn))
        self.Spin_T = Spinbox(frameS,
                              values=self.turns.keys(),
                              command=self.updateSpin_turn,
                              textvariable=self.var)
        self.Spin_T.bind('<Return>', self.validateTurn)
        turns.pack()
        self.Spin_T.pack()
        frameS.add(turns)
        frameS.add(self.Spin_T)
        frameS.pack()
        self.frameT = frameS

    def printAnts(self):
        frameAnts = Frame(self.FrameInfo)
        Text_A = Label(frameAnts, text="Fourmie :")
        s1 = Scrollbar(frameAnts)
        l1 = Listbox(frameAnts)
        id_ants = self.checkAnts()
        for i in id_ants:
            l1.insert(i, str(i))
        s1.config(command=l1.yview)
        l1.config(yscrollcommand=s1.set)
        l1.bind('<ButtonRelease-1>', self.choiceAnt)
        self.listbox = l1
        Text_A.pack(side=TOP)
        l1.pack(side=LEFT)
        s1.pack(side=RIGHT)
        frameAnts.pack()

        self.printInfoAnt(id_ants[0])
        self.frameAnts = frameAnts

    def printInfoAnt(self, i):
        self.frameAnt = PanedWindow(self.FrameInfo, orient=VERTICAL)
        t_Ant = Label(self.frameAnt, text="Information Ant : %d" % (i))
        (t_brain, t_energie, t_acide) = self.getInfoAnt(i)
        a_b = Label(self.frameAnt, text=t_brain)
        a_e = Label(self.frameAnt, text=t_energie)
        a_a = Label(self.frameAnt, text=t_acide)
        t_Ant.pack(side=TOP)
        self.frameAnt.add(t_Ant)
        self.frameAnt.add(a_b)
        self.frameAnt.add(a_e)
        self.frameAnt.add(a_a)
        self.frameAnt.pack()

    def printMap(self):
        turn = self.turns[self.selectTurn]
        # Information on this turn
        config = turn[0]
        Yants = turn[1]
        EAnts = turn[2]
        InitMap = turn[3]
        Cases = turn[4]

        (MaxX, MaxY, N) = InitMap
        self.MinX = 0
        self.MinY = 0
        MaxX_map = MaxX * self.caselength + (self.CaseMarge * 2)
        MaxY_map = MaxY * self.caselength + (self.CaseMarge * 2)
        #configure canvas
        self.maptroid.config(scrollregion=(0, 0, MaxX_map, MaxY_map))
        x1 = self.CaseMarge
        y1 = self.CaseMarge
        x2 = MaxX * self.caselength + self.CaseMarge
        y2 = MaxY * self.caselength + self.CaseMarge
        self.maptroid.create_rectangle(x1, y1, x2, y2, fill="white")

        # affiche case
        for case in Cases:
            self.printCase(case)
        # affiche your ants
        for ant in Yants:
            # nb A : Your Ant 'ID X Y DX DY E A B'
            (id_a, x, y, dx, dy, e, a, b) = ant
            self.printAnt((x, y, dx, dy, b))
        # affiche enemy ants
        for ant in EAnts:
            self.printAnt(ant)

        #to move map
        self.maptroid.bind('<ButtonPress-1>', self.grab)
        self.maptroid.bind('<B1-Motion>', self.drag)
        self.maptroid.bind('<MouseWheel>', self.mapZoom)
        self.maptroid.bind("<Button-4>", self.mapZoom)
        self.maptroid.bind("<Button-5>", self.mapZoom)

    def printCase(self, case):
        (x, y, c, s) = case
        (x1, y1, x2, y2) = self.getPoint(x, y)
        color = COLOR[c][s]
        if c % 2 == 0:
            self.maptroid.create_rectangle(x1, y1, x2, y2, fill=color)
        else:
            self.maptroid.create_rectangle(x1,
                                           y1,
                                           x2,
                                           y2,
                                           fill=COLOR[GRASS][s])
            self.maptroid.create_oval(x1, y1, x2, y2, fill=color)

    def printAnt(self, ant):
        (x, y, dx, dy, brain) = ant
        (x1, y1, x2, y2) = self.getPoint(x, y)
        self.maptroid.create_oval(x1, y1, x2, y2, fill="red4")

    def getPoint(self, x, y):
        x1 = (x - self.MinX) * self.caselength + self.CaseMarge
        y1 = (y - self.MinY) * self.caselength + self.CaseMarge
        x2 = x1 + self.caselength
        y2 = y1 + self.caselength
        return (x1, y1, x2, y2)

    def grab(self, event):
        self._y = event.y
        self._x = event.x

    def drag(self, event):
        self.maptroid.yview('scroll', self._y - event.y, 'units')
        self.maptroid.xview('scroll', self._x - event.x, 'units')
        self._y = event.y
        self._x = event.x

    def mapZoom(self, event):
        # respond to Linux or Windows wheel event
        if event.num == 5 or event.delta == -120:
            self.caselength -= 5
            self.caselength = max(self.caselength, 10)
        if event.num == 4 or event.delta == 120:
            self.caselength += 5
            self.caselength = min(self.caselength, 40)
        self.CaseMarge = self.caselength
        self.updateMap()

    def getInfoAnt(self, id_ant):
        turn = self.turns[self.selectTurn]
        YAnt = turn[1]
        B_Text = "Brain :"
        E_Text = "Energie :"
        A_Text = "Acide :"
        for ant in YAnt:
            (id_a, x, y, dx, dy, e, a, b) = ant
            if b != 1:
                b = 0
            if (id_ant == id_a):
                B_Text = "Brain : " + BRAIN[b]
                E_Text = "Energie : %d" % (e)
                A_Text = "Acide : %d" % (a)

        return (B_Text, E_Text, A_Text)

    def checkAnts(self):
        turn = self.turns[self.selectTurn]
        YAnt = turn[1]
        ants_id = []
        for ant in YAnt:
            (id_a, x, y, dx, dy, e, a, b) = ant
            ants_id.append(id_a)
        return ants_id

    def myquit(self):
        self.etat = False
        if not self.readstate:
            self.quit()
def create_entry(_main_row_, _desc_txt, _def_txt_, t_len, ckbc=None, fn=None):
    ''' creates a tkinter entry '''
    _row_ = Frame(_main_row_)

    if ckbc <> None and fn <> None:
        label0 = Label(_row_, width=3, text="  ", anchor='w')
        cvar = IntVar()
        label1 = Checkbutton(_row_,
                             width=0,
                             variable=cvar,
                             command=fn,
                             anchor='w')
        label2 = Label(_row_, width=t_len, text=_desc_txt + "  ", anchor='w')

        ckbc.append([cvar, label1])

    else:
        label0 = Label(_row_, width=3, text=" >", anchor='w')
        label1 = Label(_row_, width=t_len, text=_desc_txt, anchor='w')
        label2 = Label(_row_, width=2, text=" :", anchor='w')

    if type(_def_txt_) == str:
        Ent_It = Entry(_row_)  #, width=13)
        Ent_It.insert('end', _def_txt_)

    elif type(_def_txt_) in [list, tuple]:

        if type(_def_txt_[1]) in [set]:

            _nums_ = [str(x) for x in sorted(list(_def_txt_[1]))]
            Ent_It = StringVar()
            aux_spin = Spinbox(_row_,
                               textvariable=Ent_It,
                               values=tuple(_nums_))

            Ent_It.set(_def_txt_[0])
        else:
            Ent_It = StringVar()
            aux_ddl = Drop_Down_List(
                _row_,
                textvariable=Ent_It,
                values=tuple(_def_txt_[1]),
                #state = "readonly"
            )
            aux_ddl.bind("<Key>", lambda e: "break")  # Magic
            Ent_It.set(_def_txt_[0])

    finalspace = Label(_row_, width=5, text=" ", anchor='w')

    # Just packing
    label0.pack(side='left', padx=1)
    label1.pack(side='left', padx=6)
    label2.pack(side='left', padx=0)

    if type(_def_txt_) == str:
        Ent_It.pack(side='left', expand=True, fill=X)
    elif type(_def_txt_) in [list, tuple] and type(_def_txt_[1]) == set:
        aux_spin.pack(side='left', expand=True, fill=X)
    else:
        aux_ddl.pack(side='left', expand=True, fill=X)

    finalspace.pack(side='right', padx=0)
    _row_.pack(side='top', fill=X, pady=3)

    # For tracing purposes list appending
    return Ent_It
Пример #16
0
class Outlier4dfp(Frame):
    def __init__(self,
                 parent,
                 filename=None,
                 filename_roi=None,
                 filename_csv=None,
                 dirname=None,
                 obj_return_value=None):
        Frame.__init__(self, parent)
        self.parent = parent
        self.obj_return_value = obj_return_value

        # check filenames
        if filename is None or not os.path.isfile(filename):
            if dirname is not None:
                filename = tkFileDialog.askopenfilename(initialdir=dirname)
            else:
                filename = tkFileDialog.askopenfilename()

        if not os.path.isfile(filename):
            parent.destroy()
            return

        if filename_roi is None or not os.path.isfile(filename_roi):
            if dirname is not None:
                filename_roi = tkFileDialog.askopenfilename(initialdir=dirname)
            else:
                filename_roi = tkFileDialog.askopenfilename()

        if not os.path.isfile(filename_roi):
            parent.destroy()
            return

        if dirname is None:
            self.dirname = os.path.dirname(filename)
        else:
            self.dirname = dirname

        if filename_csv is None:
            filename_csv = os.path.join(
                self.dirname,
                filename_wo_ext(os.path.basename(filename)) + '.csv')

        self.filename = filename
        self.filename_roi = filename_roi
        self.filename_csv = filename_csv

        self.dat = nib.load(filename).get_data()
        self.shape = self.dat.shape
        print self.shape
        dz = self.shape[2]
        df = self.shape[-1]

        self.badenc = np.zeros((dz, df), dtype=np.int16)
        self.prev = np.zeros((dz, df), dtype=np.int16)
        self.z = 0

        self.initUI()
        self.run()

        #if filename_csv is not None and os.path.isfile(filename_csv):
        #    self.run_read()

    def reset(self):
        dz = self.shape[2]
        df = self.shape[-1]
        self.badenc[:, :] = np.zeros((dz, df), dtype=np.int16)
        self.prev[:, :] = np.zeros((dz, df), dtype=np.int16)

    def make_checkbox_all(self, frame, width=4, ncol=20):
        self.lst_checkbox_slices_values = []
        self.lst_checkbox_slices = []
        ii = 0

        for z in range(self.shape[2]):
            self.lst_checkbox_slices_values.append(
                [BooleanVar() for f in range(self.shape[3])])
            boxes = [
                Checkbutton(frame,
                            text=str('%s' % f),
                            variable=self.lst_checkbox_slices_values[z][f],
                            width=width) for f in range(self.shape[3])
            ]
            jj = 0
            for f in range(self.shape[3]):
                btn = boxes[f]
                btn.grid(row=z, column=f)
                jj += 1
                if ncol is not None and ncol <= jj:
                    ii += 1
                    jj = 0

            self.lst_checkbox_slices.append(boxes)
            if jj > 0:
                ii += 1

    def make_checkbox(self, frame, width=4, ncol=20):
        #self.lst_checkbox_slices_values = [BooleanVar() for f in range(self.shape[3])]
        self.lst_checkbox_slices_values = [
            IntVar() for f in range(self.shape[3])
        ]
        self.lst_checkbox_slices = [
            Checkbutton(frame,
                        text=str('%s' % f),
                        variable=self.lst_checkbox_slices_values[f],
                        width=width,
                        command=functools.partial(self.click_check, f))
            for f in range(self.shape[3])
        ]

        ii = 0
        jj = 0
        for f in range(self.shape[3]):
            btn = self.lst_checkbox_slices[f]
            btn.grid(row=ii, column=jj)
            jj += 1
            if ncol is not None and ncol <= jj:
                jj = 0
                ii += 1

        if jj > 0:
            ii += 1

    def click_check(self, f):
        value = self.lst_checkbox_slices_values[f].get()
        if value == 1:
            value = 0
        else:
            value = 1
        self.lst_checkbox_slices_values[f].set(value)
        self.badenc[self.z, f] = value
        print self.z, f, self.badenc[self.z, f]

    def set_z(self, z=None):
        if z is None:
            z = self.z
        else:
            self.z = z

        for i in range(len(self.lst_checkbox_slices_values)):
            chkbox = self.lst_checkbox_slices_values[i]
            # FIXME
            # avail chkbox
            if self.prev[z, i] > 0 or self.badenc[z, i] > 0:
                to_check = True
                to_check = 1
                self.lst_checkbox_slices[i].select()
            else:
                to_check = False
                to_check = 0
                self.lst_checkbox_slices[i].deselect()

            chkbox.set(to_check)
            # avail

    def run(self):
        dat = self.dat
        roi = nib.load(self.filename_roi).get_data().astype(bool)

        print dat.shape
        print roi.shape

        dz = self.shape[2]
        df = self.shape[3]

        self.values = np.zeros((dz, df), dtype=dat.dtype)
        for z in range(dz):
            for f in range(df):
                self.values[z, f] = dat[:, :, z, f][roi[:, :, z]].mean()

        self.draw_slice()

    def draw_slice(self):
        z = self.z
        df = self.shape[3]

        print z
        #r = self.frame_graph.axes.boxplot(self.values.T)

        sorted_values = np.sort(self.values[z, :])
        q1 = sorted_values[df / 4]
        q2 = sorted_values[df / 2]
        q3 = sorted_values[df - df / 4]
        iqr = q3 - q1
        #if1 = q1 - 1.5*iqr
        #if2 = q3 + 1.5*iqr
        of1 = q1 - 3 * iqr
        of2 = q3 + 3 * iqr

        xx = np.arange(df)
        z_mean = self.values[z, :].mean()
        z_std = self.values[z, :].std()
        #z_min  = self.values[z,:].min()
        #z_max  = self.values[z,:].max()

        #self.frame_graph.axes.hold(False)
        self.frame_graph.axes.clear()
        self.frame_graph.axes.plot([0, df], [z_mean, z_mean], 'k-')
        #self.frame_graph.axes.hold(True)
        self.frame_graph.axes.plot([0, df],
                                   [z_mean + 1 * z_std, z_mean + 1 * z_std],
                                   'y--')
        self.frame_graph.axes.plot([0, df],
                                   [z_mean + 2 * z_std, z_mean + 2 * z_std],
                                   'g--')
        self.frame_graph.axes.plot([0, df],
                                   [z_mean + 3 * z_std, z_mean + 3 * z_std],
                                   'b--')
        self.frame_graph.axes.plot([0, df], [of2, of2], 'r-')

        for f in range(df):
            if self.prev[z, f] > 0:
                self.frame_graph.axes.plot(f, self.values[z, f], 'ko')
                self.frame_graph.axes.text(f + 0.2, self.values[z, f], str(f))
            elif of1 < self.values[z, f] < of2:
                #if self.values[z,f] < z_mean + 3*z_std:
                self.frame_graph.axes.plot(f, self.values[z, f], 'bo')
                if self.values[z, f] > z_mean + 3 * z_std:
                    self.frame_graph.axes.text(f + 0.2, self.values[z, f],
                                               str(f))
            else:
                self.frame_graph.axes.plot(f, self.values[z, f], 'ro')
                self.frame_graph.axes.text(f + 0.2, self.values[z, f], str(f))

        self.frame_graph.draw()
        self.set_z(z)

    def run_read(self):
        filename = tkFileDialog.askopenfilename(initialdir=self.dirname)
        if filename == '':
            return

        with open(filename) as f:
            values = [[int(tmp) for tmp in line.strip().split(',')]
                      for line in f.readlines()]

        self.prev[:, :] = values

    def run_save(self):
        filename = tkFileDialog.asksaveasfilename(
            initialdir=os.path.dirname(self.filename_csv),
            initialfile=os.path.basename(self.filename_csv))
        if filename == '':
            return

        dz = self.shape[2]
        df = self.shape[-1]

        badenc = self.badenc.copy()
        badenc[self.prev > 0] = 1

        with open(filename, 'w') as f:
            for z in range(dz):
                f.write('%s\n' % (','.join([str(tmp)
                                            for tmp in badenc[z, :]])))

        with open(os.path.join(self.dirname, 'badenc.dat'), 'wb') as fout:
            if False:
                for z in range(dz):
                    row = struct.pack('i' * df, *badenc[z, :])
                    fout.write(row)

            fout.write('%s %s\n' % (dz, df))
            for z in range(dz):
                row = ' '.join(str(tmp) for tmp in badenc[z, :])
                fout.write('%s\n' % row)

        if self.obj_return_value is not None:
            self.obj_return_value.delete(0, len(self.obj_return_value.get()))
            self.obj_return_value.insert(0, filename)

    def initUI(self):
        self.frame_top = Frame(self)
        self.frame_graph = MplCanvas(self)
        self.frame_bottom = Frame(self)

        Label(self.frame_top, text='Z = ').pack(side=LEFT)
        self.spin_z = Spinbox(self.frame_top,
                              from_=0,
                              to=self.shape[2] - 1,
                              increment=1,
                              command=self.change_z)
        self.spin_z.pack(side=LEFT)
        self.make_checkbox(self.frame_bottom, width=4)

        Label(self.frame_top, text='   CSV').pack(side=LEFT)
        self.txt_filename_csv = Entry(self.frame_top)
        self.txt_filename_csv.pack(side=LEFT)
        self.button_read = Button(self.frame_top,
                                  text='Read',
                                  command=self.run_read)
        self.button_read.pack(side=LEFT)
        self.button_save = Button(self.frame_top,
                                  text='Save',
                                  command=self.run_save)
        self.button_save.pack(side=LEFT)

        Label(self.frame_top, text='   ').pack(side=LEFT)
        button_reset = Button(self.frame_top, text='Reset',
                              command=self.reset).pack(side=LEFT)

        self.frame_top.pack(side=TOP)
        self.frame_graph.get_tk_widget().pack(fill=BOTH, expand=TRUE)
        self.frame_bottom.pack(fill=BOTH, expand=TRUE)
        self.pack(fill=BOTH, expand=True)

    def change_z(self):
        self.z = int(self.spin_z.get())
        self.draw_slice()

    def reset_box(self, box, text):
        box.delete(0, len(box.get()))
        box.insert(0, text)
Пример #17
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()
Пример #18
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()
Пример #19
0
class TTTUI(object):

    default_ply = 6
    neither_color = '#%02x%02x%02x' % (255, 255, 255)  # white
    player_color = '#%02x%02x%02x' % (62, 188, 0)  # green
    computer_color = '#%02x%02x%02x' % (192, 35, 3)  # red
    win_color = '#%02x%02x%02x' % (25, 111, 254)  # blue

    def __init__(self):
        # TTT related
        self.ttt = Board(ply=9)
        self.human_first = True

        # UI related
        self.root = Tk()
        self.root.resizable(0, 0)
        self.root.title("3D TTT")

        # TTT frames
        self.ttt_frames = [Frame(self.root) for x in range(3)]
        for i in range(3):
            self.ttt_frames[i].grid(row=0, column=i)
        self.button_pos = dict()
        self._init_board()

        # control frame
        self.control_frame = Frame(self.root, padx=5, pady=5)
        self.control_frame.grid(row=1, column=1)
        self.new_game_btn = Button(self.control_frame, text='New Game', \
                command=lambda: self.reset())
        self.new_game_btn.pack(side=LEFT, fill=BOTH, expand=True)
        self.toggle_human_first_btn = Button(self.control_frame, \
                text='Human First', command=lambda: self.toggle_human_first())
        self.toggle_human_first_btn.pack(side=RIGHT, fill=BOTH, expand=True)
        self.ply_box = Spinbox(self.control_frame, from_=1, to=20, \
                textvariable=self.ttt.difficulty, command=lambda: self.reset())
        self.ply_box.pack(side=RIGHT, fill=BOTH, expand=True)

        # start UI
        self.update_pieces()
        self.start()
        self.root.mainloop()

    def toggle_human_first(self):
        self.human_first = not self.human_first
        self.toggle_human_first_btn.config(text='Human First' if \
                self.human_first else 'Computer First')
        self.reset()

    def _find_button(self, frame, r, c):
        for child in frame.children.values():
            info = child.grid_info()
            if info['row'] == r and info['column'] == c:
                return child
        return None

    def update_pieces(self):
        player_pieces = self.ttt.get_moves(self.ttt.human)
        computer_pieces = self.ttt.get_moves(self.ttt.ai)

        cnt = 0
        for b, board in enumerate(self.ttt.board):
            for r, row in enumerate(board):
                for c, col in enumerate(row):
                    color = self.neither_color
                    text = '-'
                    occupied = False
                    if cnt in player_pieces:
                        color = self.player_color
                        text = self.ttt.human
                    if cnt in computer_pieces:
                        color = self.computer_color
                        text = self.ttt.ai
                    if self.ttt.complete and cnt in self.ttt.winning_combo:
                        color = self.win_color
                    btn = self.button_pos[cnt]
                    btn.config(text=text, bg=color, state=DISABLED if \
                            occupied else NORMAL)
                    cnt += 1

    def place_human(self, position):
        if position in self.ttt.allowed_moves and not self.ttt.complete:
            self.ttt.move(position, self.ttt.human)
            self.ttt.human_turn = False
            self.update_pieces()
            self.place_computer()

    def place_computer(self):
        if not self.ttt.complete:
            self.ttt.computers_move()
            self.update_pieces()

    def reset(self):
        self.ttt.reset()
        self.ttt.difficulty = self.default_ply if not \
                self.ply_box.get().isdigit() else int(self.ply_box.get())
        self.ttt.human_turn = self.human_first
        self.update_pieces()
        self.start()

    def _init_board(self):
        cnt = 0
        for b, board in enumerate(self.ttt.board):
            for x, row in enumerate(board):
                for y, cell in enumerate(row):
                    padding = (0, 0)
                    if y == 2 and b != 2:
                        padding = (0, 12)
                    btn = Button(self.ttt_frames[b], width=8, height=4, \
                            command=lambda x=cell: self.place_human(x))
                    btn.grid(row=x, column=y, padx=padding)
                    self.button_pos[cnt] = btn
                    cnt += 1

    def start(self):
        if not self.ttt.human_turn:
            self.place_computer()
Пример #20
0
class ToolBar(Frame):
	def __init__(self, root, printer, settings, logger, *arg):
		self.app = root
		self.printer = printer
		self.settings = settings
		self.logger = logger
		
		self.app.printing = False
		self.app.connected = False
		self.app.paused = False
		
		Frame.__init__(self, root, *arg)
		topBar = Frame(self)
		topBar.grid(row=1, column=1, columnspan=3, sticky=W)
		speedBar = Frame(self)
		speedBar.grid(row=1, column=5, sticky=E)
		bottomBar = Frame(self)
		bottomBar.grid(row=2, column=1, columnspan=6, sticky=W+E)
		
		self.bPort = Button(topBar, text="Port", width=BWIDTH, command=self.doPort)
		self.bPort.pack(side=LEFT, padx=2, pady=2)
		ports = self.scanSerial()
		self.spPort = Spinbox(topBar, values=ports, state="readonly")
		self.spPort.pack(side=LEFT, padx=2, pady=2)
		l = Label(topBar, text=" @ ")
		l.pack(side=LEFT, padx=2, pady=2)
		self.spBaud = Spinbox(topBar, values=baudChoices)
		self.spBaud.pack(side=LEFT, padx=2, pady=2)
		self.spBaud.delete(0, END)
		self.spBaud.insert(0, 115200)
		self.spBaud.config(state="readonly")

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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


			if self.app.sduploading:
				self.bPrint.config(text=printText[PR_PRINT], state=DISABLED)
				self.bPrintMode = PR_PRINT
			else:
				self.bPrint.config(text=printText[PR_RESTART], state=NORMAL)
				self.bPrintMode = PR_RESTART
		else:
			# we still are waiting for the report, but reset everything if the printer is still moving
			if self.waitPos != self.printer.queueindex:
				self.waitPos = self.printer.queueindex
				self.maxWait114 = MAXWAIT114
				
			self.app.master.after(500, self.check114Response)
	
	def doPort(self):
		l = self.scanSerial()
		self.spPort.config(values=l)
		if len(l) == 0:
			self.bConnect.config(state=DISABLED)
		else:
			self.bConnect.config(state=NORMAL)
	
	def scanSerial(self):
		"""scan for available ports. return a list of device names."""
		baselist=[]
		if os.name=="nt":
			try:
				key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
				i=0
				while(1):
					baselist+=[_winreg.EnumValue(key,i)[1]]
					i+=1
			except:
				pass
		return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') +glob.glob("/dev/tty.*")+glob.glob("/dev/cu.*")+glob.glob("/dev/rfcomm*")
	
	def doSD(self):
		self.app.doSD()
Пример #21
0
    def run(self):  # run the whole app
        self.root = tk.Tk()
        self.root2 = tk.Tk()
        self.root3 = tk.Tk()
        self.root.title('Keyboard Simulation')

        # keyboard setup
        self.canvas = tk.Canvas(self.root,
                                width=self.winWidth,
                                height=self.winHeight)
        self.canvas.pack(side=LEFT)

        #
        self.S = Scrollbar(self.root2)
        self.T = Text(self.root2, height=4, width=50)

        self.S.pack(side=RIGHT, fill=Y, expand=True)
        self.T.pack(side=LEFT, fill=Y, expand=True)
        #self.S.pack()
        #self.T.pack()

        self.S.config(command=self.T.yview)
        self.T.config(yscrollcommand=self.S.set)
        self.T.delete(1.0, END)
        self.T.insert(END, self.inputText)
        self.T.see(END)

        l = Label(self.root3, text="Hover time Limit:", state='disabled')
        l.pack()

        w = Spinbox(self.root3, from_=0, to=10)
        w.pack()
        w.delete(0, "end")
        w.insert(0, 4)

        l2 = Label(self.root3, text="Hover select progress:")
        l2.pack()

        self.progress = ttk.Progressbar(self.root3,
                                        orient="horizontal",
                                        length=200,
                                        mode="determinate")
        self.progress["value"] = 0
        self.progress["maximum"] = 10

        self.progress.pack()

        def hv_toggle():
            if self.hv_btn.config('text')[-1] == "Hover Select: On":
                self.hv_btn.config(text="Hover Select: off")
                self.hoverOn = not self.hoverOn
            else:
                self.hv_btn.config(text="Hover Select: On")
                self.hoverOn = not self.hoverOn

        self.hv_btn = tk.Button(self.root3,
                                text="Hover Select: On",
                                command=hv_toggle)
        self.hv_btn.pack()

        def ck_toggle():
            if self.ck_btn.config('text')[-1] == "Click Select: On":
                self.ck_btn.config(text="Click Select: off")
                self.clickOn = not self.clickOn
            else:
                self.ck_btn.config(text="Click Select: On")
                self.clickOn = not self.clickOn

        self.ck_btn = tk.Button(self.root3,
                                text="Click Select: On",
                                command=ck_toggle)
        self.ck_btn.pack()

        #self.hoverlimit = int(w.get())
        if self.clickOn:
            self.root.bind('<Button-1>', self.clickEvent)

        def timerFired():
            try:
                self.hoverlimit = int(w.get())
            except:
                pass

            self.progress["value"] = self.progress[
                "maximum"] * self.hoverDt / self.hoverlimit

            self.lightUpHovering()
            self.movementLogging()
            if self.hoverOn:
                self.hoverSelect()
            self.redrawAll()
            self.canvas.after(self.dt, timerFired)

        self.appStartTime = time.time()
        timerFired()
        self.root.protocol("WM_DELETE_WINDOW", self.exitEvent)
        self.root2.protocol("WM_DELETE_WINDOW", self.exitEvent)
        self.root3.protocol("WM_DELETE_WINDOW", self.exitEvent)
        self.root.mainloop()  # This call BLOCKS
        self.root2.mainloop()
        self.root3.mainloop()
Пример #22
0
class TTTUI(object):

    default_ply = 6
    neither_color = '#%02x%02x%02x' % (255, 255, 255)  # white
    player_color = '#%02x%02x%02x' % (62, 188, 0)  # green
    computer_color = '#%02x%02x%02x' % (192, 35, 3)  # red
    win_color = '#%02x%02x%02x' % (25, 111, 254)  # blue

    def __init__(self):
        # TTT related
        self.ttt = Board(ply=9)
        self.human_first = True

        # UI related
        self.root = Tk()
        self.root.resizable(0, 0)
        self.root.title("3D TTT")

        # TTT frames
        self.ttt_frames = [Frame(self.root) for x in range(3)]
        for i in range(3):
            self.ttt_frames[i].grid(row=0, column=i)
        self.button_pos = dict()
        self._init_board()

        # control frame
        self.control_frame = Frame(self.root, padx=5, pady=5)
        self.control_frame.grid(row=1, column=1)
        self.new_game_btn = Button(self.control_frame, text='New Game', \
                command=lambda: self.reset())
        self.new_game_btn.pack(side=LEFT, fill=BOTH, expand=True)
        self.toggle_human_first_btn = Button(self.control_frame, \
                text='Human First', command=lambda: self.toggle_human_first())
        self.toggle_human_first_btn.pack(side=RIGHT, fill=BOTH, expand=True)
        self.ply_box = Spinbox(self.control_frame, from_=1, to=20, \
                textvariable=self.ttt.difficulty, command=lambda: self.reset())
        self.ply_box.pack(side=RIGHT, fill=BOTH, expand=True)

        # start UI
        self.update_pieces()
        self.start()
        self.root.mainloop()

    def toggle_human_first(self):
        self.human_first = not self.human_first
        self.toggle_human_first_btn.config(text='Human First' if \
                self.human_first else 'Computer First')
        self.reset()

    def _find_button(self, frame, r, c):
        for child in frame.children.values():
            info = child.grid_info()
            if info['row'] == r and info['column'] == c:
                return child
        return None

    def update_pieces(self):
        player_pieces = self.ttt.get_moves(self.ttt.human)
        computer_pieces = self.ttt.get_moves(self.ttt.ai)

        cnt = 0
        for b, board in enumerate(self.ttt.board):
            for r, row in enumerate(board):
                for c, col in enumerate(row):
                    color = self.neither_color
                    text = '-'
                    occupied = False
                    if cnt in player_pieces:
                        color = self.player_color
                        text = self.ttt.human
                    if cnt in computer_pieces:
                        color = self.computer_color
                        text = self.ttt.ai
                    if self.ttt.complete and cnt in self.ttt.winning_combo:
                        color = self.win_color
                    btn = self.button_pos[cnt]
                    btn.config(text=text, bg=color, state=DISABLED if \
                            occupied else NORMAL)
                    cnt += 1

    def place_human(self, position):
        if position in self.ttt.allowed_moves and not self.ttt.complete:
            self.ttt.move(position, self.ttt.human)
            self.ttt.human_turn = False
            self.update_pieces()
            self.place_computer()

    def place_computer(self):
        if not self.ttt.complete:
            self.ttt.computers_move()
            self.update_pieces()

    def reset(self):
        self.ttt.reset()
        self.ttt.difficulty = self.default_ply if not \
                self.ply_box.get().isdigit() else int(self.ply_box.get())
        self.ttt.human_turn = self.human_first
        self.update_pieces()
        self.start()

    def _init_board(self):
        cnt = 0
        for b, board in enumerate(self.ttt.board):
            for x, row in enumerate(board):
                for y, cell in enumerate(row):
                    padding = (0, 0)
                    if y == 2 and b != 2:
                        padding = (0, 12)
                    btn = Button(self.ttt_frames[b], width=8, height=4, \
                            command=lambda x=cell: self.place_human(x))
                    btn.grid(row=x, column=y, padx=padding)
                    self.button_pos[cnt] = btn
                    cnt += 1

    def start(self):
        if not self.ttt.human_turn:
            self.place_computer()
Пример #23
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()
Пример #24
0
    def refreshWidget(self) :
        #print "refresh"
        self.card_win.pack_forget()
        
        #Card window      
        self.card_win = PanedWindow(self.card_win.master, orient=VERTICAL)
        self.card_win.pack(side=TOP, expand=True, fill=BOTH, pady=2, padx=2)
        
        
        #Create the name zone
        name_zone=PanedWindow(self.card_win, orient=HORIZONTAL)
        name = StringVar() 
        name.set(self.name)
        def modifName(*args) :
            self.name=name.get()
        name.trace("w", modifName)
        name_wid=Entry(name_zone, width=30,textvariable=name)
        name_wid.pack()
        name_zone.add(name_wid)
        #Create the cost ad star stringvar
        #print int(floor(self.getCost()))
        self.cost=StringVar()
        self.stars=StringVar()
        cost_wid=Label(None, textvariable=self.cost, background='red',width=5, anchor=W)
        star_wid=Label(None, textvariable=self.stars, background='blue', anchor=E)
        self.cost.set(str(int(floor(self.getCost()))))
        self.stars.set("*"*self.getStars())
        #Add them in name zone
        name_zone.add(cost_wid)
        name_zone.add(star_wid)
        
        
        #Create an Image Zone
        image_zone=Button(self.card_win,  command=self.choosePhoto)
        if hasattr(self,"photofile") and self.photofile :            
            print "Image: ",self.photofile
            try :
               img=Image.open(self.photofile)
            except :
               decomp=self.photofile.split('/')
               for i in range(1,6) :
                   try :
                       fname="/".join(decomp[-i:])
                       print "try to open",fname
                       img=Image.open(fname)
                       self.photofile=fname
                       break
                   except :
                       self.photofile=None
        if self.photofile :
            w, h = img.size
            if w>300 or h>200 :
               img=img.resize((w/2,h/2),Image.LINEAR)
            image_zone.image=ImageTk.PhotoImage(img)
            image_zone.config(image=image_zone.image)
            #print "IMAGE CHANGED"
        else :
            from os import path
            name=self.name.replace(" ","_")
            if path.isfile("Cards/"+name+".png") :
                image_zone.config(text='image can be taken from\n'+"Cards/"+name+".png",background='white',anchor=CENTER)
            else :
                image_zone.config(text='clic to choose image',background='white',anchor=CENTER)

        image_zone.pack
        
        
        # POWER ZONE
        power_zone=PanedWindow(self.card_win, orient=VERTICAL)
        #fenetre=self.card_win.master
        def removePowerCreator(px) :
            def removePower(*args) :
                #print 'avant',list_pow
                self.bonus.remove(px)
                #print 'apres',list_pow
                #self.card_win.pack_forget()
                self.refreshWidget()
            return removePower
        for p in self.bonus :
            powline =  PanedWindow(self.card_win, orient=HORIZONTAL)
            pow_wid=p.initWidget(powline)
            powline.add(pow_wid)
            removepow=Button(powline, text="X", command=removePowerCreator(p), anchor=E)
            removepow.pack()
            powline.add(removepow)
            power_zone.add(powline) 
        def addPower(*args) :
            name=addBonus.get()
            print "added :",name
            import cardPowers
            self.bonus+=[eval('cardPowers.'+name+'()')]
            self.bonus[-1].parent=self.bonus
            self.bonus[-1].card=self
            #self.card_win.pack_forget()
            self.refreshWidget()
        #Add bonus Option menu
        addBonus = StringVar(power_zone)
        addBonus.set("add bonus") # default value
        if not self.pv:  addBonus_wid = getSpellMenu(power_zone, addBonus)
        else: addBonus_wid = getBonusMenu(power_zone, addBonus) 
        addBonus.trace('w', addPower)
        if self.pv>0 or len(self.bonus)==0 :
            addBonus_wid.pack()
            #Add this to power zone
            power_zone.add(addBonus_wid)
        
        #Create save zone
        save_zone = PanedWindow(self.card_win, orient=HORIZONTAL)
        if self.monster_type != "all":
            save_wid = Button(save_zone, text="Save", command=self.postAndSave)
        else:
            save_wid = Button(save_zone, text="---", command=None)
        save_wid.pack()
        #Create the open button
        save_zone.pack()        
        if Card.monster_list.keys():
            self.opening = StringVar(save_zone)
            self.opening.set("Open")
            choice = Card.monster_list.keys()
            choice.sort()
            #print all_monsters.keys()
            open_wid = OptionMenu(save_zone, self.opening,*choice)
            self.opening.trace('w', self.Open)
            open_wid.pack()
            save_zone.add(open_wid)
        
        if Card.monster_list.keys():
            self.delete = StringVar(save_zone)
            self.delete.set("Delete")
            choice = Card.monster_list.keys()
            choice.sort()
            delete_wid = OptionMenu(save_zone, self.delete,*choice)
            self.delete.trace('w', self.clicDelete)
            delete_wid.pack()
            save_zone.add(delete_wid)
        
        #Create the type button
        self.category = StringVar(save_zone)
        self.category.set(self.monster_type)
        choice = [t[t.index("\\")+1:t.index("_monsters.sav")] for t in glob.glob("CardFiles/*_monsters.sav")]
        if "recup" in choice:
            choice.remove("recup")
        #print all_monsters.keys()
        category_wid = OptionMenu(save_zone, self.category,*choice)
        self.category.trace('w', self.setFile)
        
        
        
        category_wid.pack()
        
        #Add it to save zone
        save_zone.add(save_wid)
        save_zone.add(category_wid)
        
        #Create a new Strength zone for att and pv
        strength_zone=PanedWindow(self.card_win, orient=HORIZONTAL)
        att=StringVar()
        att.set(str(self.att))
        pv=StringVar() ; pv.set(str(self.pv))
        def modifiedAttPv(*args) :
            self.pv=int(pv.get())
            if self.pv<1 and self.is_spell==False :
                if len(self.bonus)==0 :
                    self.is_spell=True
                    self.refreshWidget()
                else :
                    self.pv=1
                    self.refreshWidget()
            if self.pv>0 and self.is_spell==True :
                if len(self.bonus)==0 :
                    self.is_spell=False
                    self.refreshWidget()
                else :
                    self.pv=0
                    self.refreshWidget()            
            self.att=int(att.get())
            self.getCost()
        att_wid = Spinbox(strength_zone, from_=0, to=1000,textvariable=att,command=modifiedAttPv)
        att_wid.pack()
        strength_zone.add(att_wid)
        strength_zone.add(Label(strength_zone, text='       ', background='white', 
             anchor=CENTER))
        pv_wid = Spinbox(strength_zone, from_=0, to=1000,textvariable=pv,command=modifiedAttPv)
        pv_wid.pack()
        strength_zone.add(pv_wid)
        
        #Put it all in window
        self.card_win.add(name_zone)
        self.card_win.add(image_zone)
        self.card_win.add(power_zone)  
        self.card_win.add(strength_zone)
        self.card_win.add(save_zone)
        
        
        self.card_win.pack()                      
Пример #25
0
class ChargenColor:
    def __init__(self, parent):
        self.colorNegative = []
        self.colorNeutral = []
        self.colorPositive = []

        self.scaleNegative = 0.0
        self.scalePositive = 0.0

        self.cNegative = '#ff0000'
        self.cNeutral = '#000000'
        self.cPositive = '#0000ff'

        self.minNegativeLbl = Label(rootC, text='Min Found: -')
        self.maxPositiveLbl = Label(rootC, text='Max Found: -')

        self.scaleLbl = Label(rootC, text='Scale: - to -')

        self.sclSelectPositive = Spinbox(rootC)
        self.sclSelectPositive.insert(0, 0.0)
        self.sclSelectNegative = Spinbox(rootC)
        self.sclSelectNegative.insert(0, 0.0)

        self.buttonNegativeCharge = Button(
            rootC, text='Negative Charge Color', command=self.chooseNegativeCharge)
        self.buttonNeutralCharge = Button(
            rootC, text='Neutral Charge Color', command=self.chooseNeutralCharge)
        self.buttonPositiveCharge = Button(
            rootC, text='Positive Charge Color', command=self.choosePositiveCharge)
        self.buttonBG = Button(
            rootC, text='Background Color', command=self.chooseBackground)

        self.buttonUpdateColor = Button(
            rootC, text='Update', command=self.updateColor)

        self.title = Label(rootC, text="Select your colors")
        self.buttonClose = Button(rootC, text="Close", command=rootC.destroy)

        self.buttonBG.pack()
        self.title.pack()
        self.buttonNegativeCharge.pack()
        self.buttonNeutralCharge.pack()
        self.buttonPositiveCharge.pack()
        self.minNegativeLbl.pack()
        self.maxPositiveLbl.pack()
        self.scaleLbl.pack()
        self.sclSelectNegative.pack()
        self.sclSelectPositive.pack()
        self.buttonUpdateColor.pack()
        self.buttonClose.pack()

    def chooseNegativeCharge(self):
        self.colorNegative = askcolor(
            color=self.cNegative, title="Negative Charge Color")
        self.buttonNegativeCharge.config(fg=self.colorNegative[1])
        self.cNegative = self.colorNegative[1]

    def chooseNeutralCharge(self):
        self.colorNeutral = askcolor(
            color=self.cNeutral, title="Neutral Charge Color")
        self.buttonNeutralCharge.config(fg=self.colorNeutral[1])
        self.cNeutral = self.colorNeutral[1]

    def choosePositiveCharge(self):
        self.colorPositive = askcolor(
            color=self.cPositive, title="Positive Charge Color")
        self.buttonPositiveCharge.config(fg=self.colorPositive[1])
        self.cPositive = self.colorPositive[1]

    def chooseBackground(self):
        bgcolor = askcolor(
            color=self.cPositive, title="Positive Charge Color")
        cmd.set_color("bg_chargy_color", bgcolor[0])
        cmd.bg_color("bg_chargy_color")

    def updateColor(self):
        selection = 'all'
        stored.atoms_charge = []
        stored.atoms_colors = []
        cmd.map_new('chargyc_map', selection="(all)")

        if not self.colorNeutral:
            tkMessageBox.showerror("Error", "Set Neutral Color, Please")
            return
        if not self.colorNegative:
            tkMessageBox.showerror("Error", "Set Negative Color, Please")
            return
        if not self.colorPositive:
            tkMessageBox.showerror("Error", "Set Positive Color, Please")
            return

        cmd.iterate_state(1, '(' + selection + ')',
                          'stored.atoms_charge.append(partial_charge)')

        _i = 0
        minValue = None
        maxValue = None
        while _i < len(stored.atoms_charge):
            color = []
            if _i == 0:
                maxValue = stored.atoms_charge[_i]
                minValue = stored.atoms_charge[_i]

            if(stored.atoms_charge[_i] > maxValue):
                maxValue = stored.atoms_charge[_i]
            if stored.atoms_charge[_i] < minValue:
                minValue = stored.atoms_charge[_i]
            _i += 1

        self.minNegativeLbl["text"] = 'Min Found: ' + str(round(minValue, 3))
        self.maxPositiveLbl["text"] = 'Max Found: ' + str(round(maxValue, 3))

        if(self.scaleNegative == 0.0 and self.scalePositive == 0.0):
            self.scaleNegative = round(minValue, 3)
            self.scalePositive = round(maxValue, 3)
            self.sclSelectNegative.delete(0, "end")
            self.sclSelectPositive.delete(0, "end")
            self.sclSelectNegative.insert(0, round(minValue, 3))
            self.sclSelectPositive.insert(0, round(maxValue, 3))
        else:
            self.scaleNegative = float(self.sclSelectNegative.get())
            self.scalePositive = float(self.sclSelectPositive.get())
            minValue = float(self.sclSelectNegative.get())
            maxValue = float(self.sclSelectPositive.get())

        self.scaleLbl["text"] = 'Scale: ' + str(
            self.scaleNegative) + ' to ' + str(self.scalePositive)

        middleValue = 0
        if(maxValue < 0):
            maxValue = 0
        if(minValue > 0):
            minValue = 0

        _i = 0
        while _i < len(stored.atoms_charge):
            color = []
            cmd.set_color("neutral_color", self.colorNeutral[0])
            cmd.set_color("positive_color", self.colorPositive[0])
            cmd.set_color("negative_color", self.colorNegative[0])
            if(stored.atoms_charge[_i] >= middleValue):
                if(stored.atoms_charge[_i] == middleValue):
                    cmd.set_color(str(_i) + "_color", self.colorNeutral[0])
                else:
                    cmd.set_color(str(_i) + "_color", self.getColor(
                        self.colorNeutral[0], self.colorPositive[0], maxValue, stored.atoms_charge[_i] if stored.atoms_charge[_i] < maxValue else maxValue))
            else:
                cmd.set_color(str(_i) + "_color", self.getColor(
                    self.colorNeutral[0], self.colorNegative[0], abs(minValue), abs(stored.atoms_charge[_i]) if abs(stored.atoms_charge[_i]) < abs(minValue) else abs(minValue)))

            index = cmd.get_color_index(str(_i) + "_color")
            stored.atoms_colors.append(index)
            _i += 1

        cmd.alter_state(1, '(' + selection + ')',
                        "color=stored.atoms_colors.pop(0)")
        cmd.ramp_new('chargy_ramp', 'chargyc_map', range=[self.scaleNegative, ((self.scaleNegative+self.scalePositive)/2.0), self.scalePositive],
                     color=['negative_color', 'neutral_color', 'positive_color'])

    def getColor(self, color, colorMax, step, index):
        colorStep = [0, 0, 0]

        colorStep[0] = ((colorMax[0]-color[0])/step)
        colorStep[1] = ((colorMax[1]-color[1])/step)
        colorStep[2] = ((colorMax[2]-color[2])/step)

        return [
            1.0 if (color[0] + (colorStep[0]*index)) /
            255.0 >= 1 else (color[0] + (colorStep[0]*index))/255.0,
            1.0 if (color[1] + (colorStep[1]*index)) /
            255.0 >= 1 else (color[1] + (colorStep[1]*index))/255.0,
            1.0 if (color[2] + (colorStep[2]*index)) /
            255.0 >= 1 else (color[2] + (colorStep[2]*index))/255.0
        ]
class AntroidGUI(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.protocol("WM_DELETE_WINDOW", self.myquit)
        self.etat = True
        self.readstate = True
        self.title("Antroid Map")
        self.turns = {}
        self.selectTurn = -1
        self.caselength = 10
        self.CaseMarge = 20
        self.var = StringVar()
        self.initGUI()

    def initGUI(self):
        frame = Frame(self, width =630, height = 500)
        self.panel = PanedWindow(frame, orient=HORIZONTAL)

        self.LeftFrame(self.panel)
        self.RightFrame(self.panel)
        self.panel.add(self.LFrame)
        self.panel.add(self.RFrame)
        self.panel.pack()
        frame.pack()

    def LeftFrame(self, parent):
        self.LFrame=Frame(parent, width = 500, height = 500)
        self.maptroid = Canvas(self.LFrame,bg='black',width=500,height=500)
        if self.selectTurn >= 0:
            self.printMap()

        self.maptroid.pack()
        self.LFrame.pack()

    def RightFrame(self, parent):
        self.RFrame = Frame(parent, width = 130, height = 500)
        if self.selectTurn >= 0:
            self.printInfo()
        self.FrameInfo = None
        self.updateT = True
        self.RFrame.pack()

    def setreadstate(self, readstate):
        self.readstate = readstate

    def addTurn(self, turnnumber, turnvalue):
        self.turns[turnnumber] = turnvalue
        self.updateGui(turnnumber)
        return self.etat

    def updateGui(self, turn):
        self.selectTurn = turn
        self.updateMap()
        self.updateInfo()

    def updateMap(self):
        self.maptroid.delete(ALL)
        self.printMap()

    def updateInfo(self):
        if self.FrameInfo:
            if self.updateT:
                self.frameT.destroy()
                self.printTurn()
            self.frameAnts.destroy()
            self.frameAnt.destroy()
            self.printAnts()
            self.updateT = True
        else:
            self.printInfo()

    def updateSpin_turn(self):
        turn = int(self.Spin_T.get())
        self.updateT = False
        self.updateGui(turn)

    def validateTurn(self, event):
        try:
            turn = int(self.Spin_T.get())
        except ValueError:
            turn = self.selectTurn
        if turn in self.turns.keys():
            if turn != self.selectTurn:
                self.updateT = False
                self.updateGui(turn)
        else:
            turn = self.selectTurn


    def choiceAnt(self,event):
        i = self.listbox.curselection()
        id_a = self.listbox.get(i)
        self.frameAnt.destroy()
        self.printInfoAnt(int(id_a))

    def printInfo(self):
        self.FrameInfo=Frame(self.RFrame)
        self.printTurn()
        self.printAnts()
        self.FrameInfo.pack()

    def printTurn(self):
        frameS = PanedWindow(self.FrameInfo, orient=HORIZONTAL)
        turns = Label(frameS, text="Tour :")
        self.var.set(str(self.selectTurn))
        self.Spin_T = Spinbox(frameS, values=self.turns.keys(), command =
                self.updateSpin_turn ,textvariable=self.var)
        self.Spin_T.bind('<Return>', self.validateTurn)
        turns.pack()
        self.Spin_T.pack()
        frameS.add(turns)
        frameS.add(self.Spin_T)
        frameS.pack()
        self.frameT = frameS

    def printAnts(self):
        frameAnts = Frame(self.FrameInfo)
        Text_A = Label(frameAnts, text="Fourmie :")
        s1 = Scrollbar(frameAnts)
        l1 = Listbox(frameAnts)
        id_ants = self.checkAnts()
        for i in id_ants: l1.insert(i, str(i))
        s1.config(command = l1.yview)
        l1.config(yscrollcommand = s1.set)
        l1.bind('<ButtonRelease-1>',self.choiceAnt)
        self.listbox = l1
        Text_A.pack(side = TOP)
        l1.pack(side = LEFT)
        s1.pack(side = RIGHT)
        frameAnts.pack()

        self.printInfoAnt(id_ants[0])
        self.frameAnts = frameAnts


    def printInfoAnt(self, i):
        self.frameAnt = PanedWindow(self.FrameInfo, orient=VERTICAL)
        t_Ant = Label(self.frameAnt, text="Information Ant : %d" %(i))
        (t_brain,t_energie,t_acide) = self.getInfoAnt(i)
        a_b = Label(self.frameAnt, text=t_brain)
        a_e = Label(self.frameAnt, text=t_energie)
        a_a = Label(self.frameAnt, text=t_acide)
        t_Ant.pack(side = TOP)
        self.frameAnt.add(t_Ant)
        self.frameAnt.add(a_b)
        self.frameAnt.add(a_e)
        self.frameAnt.add(a_a)
        self.frameAnt.pack()

    def printMap(self):
        turn = self.turns[self.selectTurn]
        # Information on this turn
        config = turn[0]
        Yants = turn[1]
        EAnts = turn[2]
        InitMap = turn[3]
        Cases = turn[4]

        (MaxX,MaxY,N) = InitMap
        self.MinX = 0
        self.MinY = 0
        MaxX_map = MaxX * self.caselength + (self.CaseMarge *2)
        MaxY_map = MaxY * self.caselength + (self.CaseMarge *2)
        #configure canvas
        self.maptroid.config(scrollregion=(0,0,MaxX_map,MaxY_map))
        x1 = self.CaseMarge
        y1 = self.CaseMarge
        x2 = MaxX * self.caselength + self.CaseMarge
        y2 = MaxY * self.caselength +self.CaseMarge
        self.maptroid.create_rectangle(x1, y1, x2, y2, fill="white")

        # affiche case
        for case in Cases:
            self.printCase(case)
        # affiche your ants
        for ant in Yants:
        # nb A : Your Ant 'ID X Y DX DY E A B'
            (id_a,x,y,dx,dy,e,a,b) = ant
            self.printAnt((x,y,dx,dy,b))
        # affiche enemy ants 
        for ant in EAnts:
            self.printAnt(ant)

        #to move map
        self.maptroid.bind('<ButtonPress-1>',self.grab)
        self.maptroid.bind('<B1-Motion>',self.drag)
        self.maptroid.bind('<MouseWheel>',self.mapZoom)
        self.maptroid.bind("<Button-4>", self.mapZoom)
        self.maptroid.bind("<Button-5>", self.mapZoom)

    def printCase(self, case):
        (x,y,c,s) = case
        (x1, y1, x2, y2) = self.getPoint(x, y)
        color = COLOR[c][s]
        if c%2 == 0:
            self.maptroid.create_rectangle(x1, y1, x2, y2, fill=color)
        else:
            self.maptroid.create_rectangle(x1, y1, x2, y2, fill=COLOR[GRASS][s])
            self.maptroid.create_oval(x1, y1, x2, y2, fill=color)

    def printAnt(self, ant):
        (x,y,dx,dy,brain) = ant
        (x1, y1, x2, y2) = self.getPoint(x, y)
        self.maptroid.create_oval(x1, y1, x2, y2, fill="red4")

    def getPoint(self, x, y):
        x1 = (x - self.MinX) * self.caselength + self.CaseMarge
        y1 = (y - self.MinY) * self.caselength + self.CaseMarge
        x2 = x1 + self.caselength
        y2 = y1 + self.caselength
        return (x1, y1, x2, y2)

    def grab(self,event):
        self._y = event.y
        self._x = event.x

    def drag(self, event):
        self.maptroid.yview('scroll',self._y-event.y,'units')
        self.maptroid.xview('scroll',self._x-event.x,'units')
        self._y = event.y
        self._x = event.x

    def mapZoom(self, event):
        # respond to Linux or Windows wheel event
        if event.num == 5 or event.delta == -120:
            self.caselength -= 5
            self.caselength = max(self.caselength, 10)
        if event.num == 4 or event.delta == 120:
            self.caselength += 5
            self.caselength = min(self.caselength, 40)
        self.CaseMarge = self.caselength
        self.updateMap()

    def getInfoAnt(self,id_ant):
        turn = self.turns[self.selectTurn]
        YAnt = turn[1]
        B_Text = "Brain :"
        E_Text = "Energie :"
        A_Text = "Acide :"
        for ant in YAnt:
            (id_a,x,y,dx,dy,e,a,b) = ant
            if b != 1 :
                b = 0
            if(id_ant == id_a):
                B_Text = "Brain : " + BRAIN[b]
                E_Text = "Energie : %d" % (e)
                A_Text = "Acide : %d" % (a)

        return (B_Text,E_Text,A_Text)

    def checkAnts(self):
        turn = self.turns[self.selectTurn]
        YAnt = turn[1]
        ants_id = []
        for ant in YAnt:
            (id_a,x,y,dx,dy,e,a,b) = ant
            ants_id.append(id_a)
        return ants_id

    def myquit(self):
        self.etat = False
        if not self.readstate:
            self.quit()