예제 #1
0
class AnimationWidget(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        vbox = QtGui.QVBoxLayout()
        self.canvas = MyMplCanvas(self, width=5, height=4, dpi=100)
        vbox.addWidget(self.canvas)

        hbox = QtGui.QHBoxLayout()
        self.start_button = QtGui.QPushButton("start", self)
        self.stop_button = QtGui.QPushButton("stop", self)
        self.start_button.clicked.connect(self.on_start)
        self.stop_button.clicked.connect(self.on_stop)
        hbox.addWidget(self.start_button)
        hbox.addWidget(self.stop_button)
        vbox.addLayout(hbox)
        self.setLayout(vbox)

        self.x = np.linspace(0, 5*np.pi, 400)
        self.p = 0.0
        self.y = np.sin(self.x + self.p)
        self.line, = self.canvas.axes.plot(self.x, self.y, animated=True, lw=2)

    def update_line(self, i):
        self.p += 0.1
        y = np.sin(self.x + self.p)
        self.line.set_ydata(y)
        return [self.line]

    def on_start(self):
        self.ani = FuncAnimation(self.canvas.figure, self.update_line,
                                 blit=True, interval=25)

    def on_stop(self):
        self.ani._stop()
예제 #2
0
class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowTitle("application main window")
        self.main_widget = QtWidgets.QWidget(self)

        vbox = QtWidgets.QVBoxLayout(self.main_widget)

        self.canvas = MyMplCanvas(self.main_widget, width=5, height=4, dpi=100)  ###attention###
        vbox.addWidget(self.canvas)

        hbox = QtWidgets.QHBoxLayout(self.main_widget)
        self.start_button = QPushButton("start", self)
        self.stop_button = QPushButton("stop", self)
        self.exit_button = QPushButton("exit", self)

        self.start_button.clicked.connect(self.on_start)
        self.stop_button.clicked.connect(self.on_stop)
        self.exit_button.clicked.connect(self.on_exit)

        hbox.addWidget(self.start_button)
        hbox.addWidget(self.stop_button)
        hbox.addWidget(self.exit_button)

        vbox.addLayout(hbox)
        self.setLayout(vbox)

        self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)

        global n_drops
        global scat
        global rain_drops
        rain_drops = np.zeros(n_drops, dtype=[('position', float, 2)])
        self.scat = self.canvas.axes.scatter(rain_drops['position'][:, 0], rain_drops['position'][:, 1], s=10, lw=0.5)

    def update_line(self, i):
        global n_drops
        global scat
        global rain_drops
        rain_drops['position'] = np.random.uniform(0, 100, (n_drops, 2))

        self.scat.set_offsets(rain_drops['position'])

        return self.scat,

    def on_start(self):
        self.ani = FuncAnimation(self.canvas.figure, self.update_line,
                                 blit=True, interval=25)

    def on_stop(self):
        self.ani._stop()

    def on_exit(self):
        self.close()
예제 #3
0
class AnimationGui(HasTraits):

    figure = Instance(Figure, ())
    system = Instance(Catenary, ())

    view = View(Group(Group(
        Item("object.system.g"),
        Item("object.system.length"),
        Item("object.system.k"),
        Item("object.system.dump"),
    ),
                      Item("figure", editor=MPLFigureEditor(toolbar=True)),
                      show_labels=False,
                      orientation='horizontal'),
                width=800,
                height=600,
                resizable=True)

    def __init__(self, **kw):
        super(AnimationGui, self).__init__(**kw)
        self.axe = self.figure.add_subplot(111)

    def start_timer(self):
        self.system.ode_init()
        self.line, = self.axe.plot(self.system.x,
                                   -self.system.y,
                                   "-o",
                                   animated=True)
        self.axe.set_xlim(-0.1, 1.1)
        self.axe.set_ylim(-1, 0.1)
        self.ani = FuncAnimation(self.figure,
                                 self.update_figure,
                                 blit=True,
                                 interval=20)

    def stop_timer(self):
        self.ani._stop()

    def update_figure(self, frame):
        self.system.ode_step(0.2)
        self.line.set_data(self.system.x, -self.system.y)
        return self.line,
예제 #4
0
파일: catenary.py 프로젝트: Andor-Z/scpy2
class AnimationGui(HasTraits):
    
    figure = Instance(Figure, ())
    system = Instance(Catenary, ())

    view = View(
        Group(
            Group(
                Item("object.system.g"),
                Item("object.system.length"),
                Item("object.system.k"),
                Item("object.system.dump"),
            ),
            Item("figure", editor=MPLFigureEditor(toolbar=True)),
            show_labels = False,
            orientation = 'horizontal'
        ),
        width = 800,
        height = 600,
        resizable = True)
        
    def __init__(self, **kw):
        super(AnimationGui, self).__init__(**kw)
        self.axe = self.figure.add_subplot(111)
        
    def start_timer(self):
        self.system.ode_init()
        self.line, = self.axe.plot(self.system.x, -self.system.y, 
                                       "-o", animated=True)
        self.axe.set_xlim(-0.1, 1.1)
        self.axe.set_ylim(-1, 0.1)
        self.ani = FuncAnimation(self.figure, self.update_figure, 
                                 blit=True, interval=20)
                                 
    def stop_timer(self):
        self.ani._stop()
        
    def update_figure(self, frame):
        self.system.ode_step(0.2)
        self.line.set_data(self.system.x, -self.system.y)
        return self.line,
예제 #5
0
class AnimationWidget(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        vbox = QtGui.QVBoxLayout()
        self.canvas = MyMplCanvas(self, width=5, height=4, dpi=100)
        vbox.addWidget(self.canvas)

        hbox = QtGui.QHBoxLayout()
        self.start_button = QtGui.QPushButton("start", self)
        self.stop_button = QtGui.QPushButton("stop", self)
        self.start_button.clicked.connect(self.on_start)
        self.stop_button.clicked.connect(self.on_stop)
        hbox.addWidget(self.start_button)
        hbox.addWidget(self.stop_button)
        vbox.addLayout(hbox)
        self.setLayout(vbox)

        self.x = np.linspace(0, 5 * np.pi, 400)
        self.p = 0.0
        self.y = np.sin(self.x + self.p)
        self.line, = self.canvas.axes.plot(self.x, self.y, animated=True, lw=2)

    def update_line(self, i):
        self.p += 0.1
        y = np.sin(self.x + self.p)
        self.line.set_ydata(y)
        return [self.line]

    def on_start(self):
        self.ani = FuncAnimation(self.canvas.figure,
                                 self.update_line,
                                 blit=True,
                                 interval=25)

    def on_stop(self):
        self.ani._stop()
예제 #6
0
class AnimationWindow(wx.Frame):
    def __init__(self,
                 parent,
                 data_list,
                 config=None,
                 yvals=None,
                 mode="1D",
                 pks=None,
                 pksmode="mz",
                 *args,
                 **kwargs):
        """
        A simple window for animating mulitple 1D or 2D plots in a sequence.
        :param parent: Parent window. Passed to wx.Frame.
        :param data_list: List of data to be plotted
        :param config: UniDecConfig object
        :param yvals: Titles for the plots.
        :param mode: 1 = 1D plots, 2 = 2D plots
        :param args:
        :param kwargs: 
        :return: None
        """
        wx.Frame.__init__(self, parent, title="Plot Animations", size=(-1, -1))
        # Initialize parameters
        if mode == "2D":
            self.mode = 2
        else:
            self.mode = 1
        if config is None:
            self.config = unidecstructure.UniDecConfig()
            self.config.initialize()
        else:
            self.config = config

        self.datalist = data_list
        self.pks = pks
        self.pksmode = pksmode

        if self.pksmode == "mz":
            self.xlabel = "m/z (Th)"
            self.testkda = False
        elif self.pksmode == "CCS":
            self.xlabel = "CCS"
            self.testkda = False
        else:
            self.xlabel = "Mass (Da)"
            self.testkda = True

        self.yvals = yvals
        if self.yvals is None:
            self.yvals = list(range(0, len(data_list)))

        self.dim = 1
        self.pos = -1
        self.play = False

        self.animation = None

        # Create GUI

        # Make the menu
        filemenu = wx.Menu()
        menu_save_fig = filemenu.Append(wx.ID_ANY, "Save Figures",
                                        "Save all figures at selected path")
        self.Bind(wx.EVT_MENU, self.on_save_fig, menu_save_fig)

        menu_bar = wx.MenuBar()
        menu_bar.Append(filemenu, "&File")
        self.SetMenuBar(menu_bar)

        self.CreateStatusBar(2)
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)

        if self.mode == 1:
            self.plot = plot1d.Plot1d(panel)
        else:
            self.plot = plot2d.Plot2d(panel)
        sizer.Add(self.plot, 0, wx.EXPAND)

        controlsizer = wx.BoxSizer(wx.HORIZONTAL)

        sb = wx.StaticBox(panel, label='Frame Rate (ms/frame)')
        sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
        frmax = 2000

        frmin = 1
        self.frslider = wx.Slider(
            panel, wx.ID_ANY, 500, frmin, frmax, (30, 60), (250, -1),
            wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS)
        self.frslider.SetTickFreq(100)
        sbs.Add(self.frslider, 0, wx.EXPAND)
        self.Bind(wx.EVT_COMMAND_SCROLL_THUMBRELEASE, self.update_framerate,
                  self.frslider)
        controlsizer.Add(sbs, 0, wx.EXPAND)

        self.playbutton = wx.ToggleButton(panel, label="Play")
        self.nextbutton = wx.Button(panel, label="Next")
        self.backbutton = wx.Button(panel, label="Back")

        controlsizer.Add(self.backbutton, 0, wx.EXPAND)
        controlsizer.Add(self.playbutton, 0, wx.EXPAND)
        controlsizer.Add(self.nextbutton, 0, wx.EXPAND)

        self.Bind(wx.EVT_TOGGLEBUTTON, self.on_play, self.playbutton)
        self.Bind(wx.EVT_BUTTON, self.on_next, self.nextbutton)
        self.Bind(wx.EVT_BUTTON, self.on_back, self.backbutton)

        self.ctlautoscale = wx.CheckBox(panel, label="Autoscale")
        controlsizer.Add(self.ctlautoscale, 0, wx.EXPAND)
        if self.mode == 2:
            self.ctlautoscale.SetValue(True)

        sizer.Add(controlsizer, 0, wx.EXPAND)

        panel.SetSizer(sizer)
        sizer.Fit(self)

        self.Bind(wx.EVT_CLOSE, self.on_close, self)

        self.init()
        self.Centre()
        self.Show(True)

    def on_close(self, e):
        """
        Stop the animation and close the window.
        :param e: Unused event
        :return: None
        """
        print("Closing")
        try:
            self.animation._stop()
        except:
            pass
        self.Destroy()

    def update(self, frame_number):
        """
        Continues to increment the plot to the next value in the data_list. Will stop if self.play is False.
        :param frame_number: Required but unused. Filled by FuncAnimation.
        :return: 0
        """
        if self.play:
            self.pos += 1
            self.update_plot()
            return 0
        else:
            return 0

    def update_plot(self):
        """
        Increment to the next data set and update the plot with the new data.
        Tries to keep some of the old plotting parameters like the zoom the same.
        Stops the animation if an error occurs.
        :return: None
        """
        try:
            if self.pks is not None:
                self.refresh_plot()
                self.add_peaks()
                return
            self.pos %= len(self.datalist)
            newdata = self.datalist[self.pos]
            title = str(self.yvals[self.pos])

            if self.mode == 1:
                # 1D Plot
                line = self.plot.subplot1.lines[0]
                xlim = self.plot.subplot1.get_xlim()
                ylim = self.plot.subplot1.get_ylim()
                line.set_data(newdata[:, 0], newdata[:, 1])

                self.plot.subplot1.set_title(title)

                autoflag = self.ctlautoscale.GetValue()
                if autoflag:
                    self.plot.subplot1.set_autoscale_on(True)
                    self.plot.subplot1.relim()
                    self.plot.subplot1.autoscale_view(True, True, True)
                else:
                    self.plot.subplot1.set_xlim(xlim)
                    self.plot.subplot1.set_ylim(ylim)
                self.plot.repaint()

            else:
                # 2D plot
                xlim = self.plot.subplot1.get_xlim()
                ylim = self.plot.subplot1.get_ylim()
                self.plot.contourplot(newdata,
                                      self.config,
                                      xlab=self.xlabel,
                                      title=title,
                                      repaint=False)
                autoflag = self.ctlautoscale.GetValue()
                if not autoflag:
                    self.plot.subplot1.set_xlim(xlim)
                    self.plot.subplot1.set_ylim(ylim)
                self.plot.add_title(title)
                self.plot.repaint()
        except Exception as e:
            self.animation._stop()
            print(e)

    def init(self):
        """
        Create a fresh plot and start the animation.
        :return: None
        """
        self.pos = 0
        self.refresh_plot()
        self.animation = FuncAnimation(self.plot.figure,
                                       self.update,
                                       interval=500)
        self.animation._start()

    def on_play(self, e):
        """
        Toggles self.play on or off. Will break the while loop in self.update if self.play = False.
        :param e: Unused event
        :return: None
        """
        tog = self.playbutton.GetValue()
        if tog:
            self.play = True
        else:
            self.play = False
        pass

    def refresh_plot(self):
        """
        Create a fresh plot from the top.
        :return: None
        """
        self.pos %= len(self.datalist)
        newdata = self.datalist[self.pos]
        title = str(self.yvals[self.pos])

        if self.mode == 1:
            self.plot.plotrefreshtop(newdata[:, 0],
                                     newdata[:, 1],
                                     title,
                                     self.xlabel,
                                     "Intensity",
                                     "",
                                     self.config,
                                     test_kda=self.testkda)
            self.plot.add_title(title)
            if self.pks is not None:
                self.add_peaks()
        else:
            self.plot.contourplot(newdata,
                                  self.config,
                                  xlab=self.xlabel,
                                  title=title)
            self.plot.add_title(title)

    def on_next(self, e):
        """
        Plot the next data set in data_list.
        :param e: Unused event
        :return: None
        """
        self.pos += 1
        self.update_plot()
        pass

    def on_back(self, e):
        """
        Plot the previous data set in data_list.
        :param e: Unused event
        :return: None
        """
        self.pos -= 1
        self.update_plot()
        pass

    def update_framerate(self, e):
        """
        Change the frame rate. Restart the animation with fresh frame rate.
        :param e: Unused event
        :return: None
        """
        framerate = self.frslider.GetValue()
        # print "Updated framerate to:", framerate
        # self.animation._interval=framerate
        # self.animation.new_frame_seq()
        self.animation._stop()
        self.animation = FuncAnimation(self.plot.figure,
                                       self.update,
                                       interval=framerate)
        self.animation._start()

    def add_peaks(self, e=None):
        if self.pksmode == "mz":
            self.add_peaks_mz()
        else:
            self.add_peaks_mass()

    def add_peaks_mz(self, e=None):
        for p in self.pks.peaks:
            if p.ignore == 0:
                list1 = []
                list2 = []
                mztab = p.mztab[self.pos]
                mztab2 = p.mztab2[self.pos]
                if (not ud.isempty(mztab)) and (not ud.isempty(mztab2)):
                    mztab = np.array(mztab)
                    mztab2 = np.array(mztab2)
                    maxval = np.amax(p.mztab[:, :, 1])
                    for k in range(0, len(mztab)):
                        if mztab[k, 1] > self.config.peakplotthresh * maxval:
                            list1.append(mztab2[k, 0])
                            list2.append(mztab2[k, 1])
                            # print mztab[k]
                    self.plot.plotadddot(np.array(list1), np.array(list2),
                                         p.color, p.marker)
        self.plot.repaint()

    def add_peaks_mass(self, e=None):
        for p in self.pks.peaks:
            if p.ignore == 0:
                pos = ud.nearest(self.datalist[self.pos][:, 0], p.mass)
                data = self.datalist[self.pos][pos]
                if data[1] > self.config.peakplotthresh * np.amax(
                        self.datalist[self.pos][:, 1]):
                    self.plot.plotadddot(data[0], data[1], p.color, p.marker)
        self.plot.repaint()

    def on_save_fig(self, e=None):
        path = FileDialogs.save_file_dialog()
        base, ext = os.path.splitext(path)
        #self.init()
        #self.save_fig(base,ext)
        for i in range(0, len(self.datalist)):
            self.on_next(None)
            self.save_fig(base, ext)

    def save_fig(self, base, ext):
        path = base + str(self.pos) + ext
        print(self.pos, path)
        self.plot.save_figure(path)
예제 #7
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(980, 460)
        self.time = time.time()
        self.started = False
        self.x = [0]
        self.y = [1]

        # 布局
        self.canvas = MyCanvas(self, width=5, height=4, dpi=100)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        # 小部件布局
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(260, 20, 60, 20))
        self.label.setObjectName("label")
        self.QLineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.QLineEdit.setGeometry(QtCore.QRect(260, 50, 140, 18))
        self.QLineEdit.setObjectName("QLineEdit")
        self.QLineEdit.setReadOnly(True)
        self.label_1 = QtWidgets.QLabel(self.centralwidget)
        self.label_1.setGeometry(QtCore.QRect(260, 90, 60, 20))
        self.label_1.setObjectName("label_1")
        self.QLineEdit_1 = QtWidgets.QLineEdit(self.centralwidget)
        self.QLineEdit_1.setGeometry(QtCore.QRect(260, 120, 140, 18))
        self.QLineEdit_1.setObjectName("QLineEdit_1")
        self.QLineEdit_1.setReadOnly(True)
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(260, 165, 60, 20))
        self.label_2.setObjectName("label_2")
        self.QLineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
        self.QLineEdit_2.setGeometry(QtCore.QRect(260, 195, 140, 18))
        self.QLineEdit_2.setObjectName("QLineEdit_2")
        self.QLineEdit_2.setReadOnly(True)

        # 大部件布局
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect(10, 20, 220, 192))
        self.listWidget.setObjectName("listWidget")
        self.listWidget.addItem("%2s%13s%15s"%('编号','进入时间','服务时间'))
        self.textList = QtWidgets.QTextEdit(self.centralwidget)
        self.textList.setGeometry(QtCore.QRect(10, 230, 400, 200))
        self.textList.setObjectName("textList")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(420, 20, 550, 420))
        self.groupBox.setObjectName("groupBox")
        # self.textList.setStyleSheet("background-color:black")
        # self.textList.setTextColor(QtGui.QColor(255, 255, 255))
        self.textList.setReadOnly(True)
        self.gridlayout = QtWidgets.QGridLayout(self.groupBox)  # 继承容器groupBox
        self.gridlayout.addWidget(self.canvas)

        # 多余布局
        # self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        # self.pushButton.setGeometry(QtCore.QRect(330, 370, 75, 23))
        # self.pushButton.setObjectName("pushButton")
        # self.pushButton0 = QtWidgets.QPushButton(self.centralwidget)
        # self.pushButton0.setGeometry(QtCore.QRect(420, 370, 75, 23))
        # self.pushButton0.setObjectName("pushButton0")
        # self.pushButton.setVisible(False)
        # self.pushButton0.setVisible(False)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 660, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        # 事件
        self.listWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) #参数QtCore.Qt.CustomContextMenu
        self.contextMenu = QtWidgets.QMenu()
        self.outContextMenu = QtWidgets.QMenu()
        self.actionIns = self.outContextMenu.addAction(QtGui.QIcon("./resource/+.png"), u'|  添加')
        self.listWidget.customContextMenuRequested[QtCore.QPoint].connect(self.showMenu)
        self.actionIns.triggered.connect(self.insertItem)

        self.line, = self.canvas.axes.plot(self.x, self.y, animated=True, lw=2)
        # self.canvas.axes.set_xlim([0, 100])
        # self.canvas.axes.set_ylim([0, 10])
        self.canvas.axes.set_xbound(0,100)
        self.canvas.axes.set_ybound(0,10)
        # self.canvas.axes.set_xlabel(u'时间')
        # self.canvas.axes.set_ylabel(u'线程id')
        # self.pushButton.clicked.connect(self.on_start)
        # self.pushButton0.clicked.connect(self.on_stop)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "多级轮转抢占式"))
        # self.pushButton.setText(_translate("MainWindow", "开始"))
        # self.pushButton0.setText(_translate("MainWindow", "暂停"))
        self.label.setText(_translate("MainWindow", "队列一:"))
        self.label_1.setText(_translate("MainWindow", "队列二:"))
        self.label_2.setText(_translate("MainWindow", "队列三:"))

    # 添加方法
    def insertItem(self):
        self.getText()
        global NUM
        NUM += 1

    # 输入对话框
    def getText(self):
        server, okPressed = QtWidgets.QInputDialog.getText(self.centralwidget, "服务时间", "请输入该线程的服务时间:", QtWidgets.QLineEdit.Normal, "")
        if okPressed and server.isdigit():
            if self.listWidget.count() == 1:
                # self.pushButton.setVisible(True)
                # self.pushButton0.setVisible(True)
                global startTime
                startTime = time.time()
                first = NUM
                second = int(time.time() - startTime)
                thrid = int(server)
                Process = process.process(NUM, second, int(server))
                # 线程处理数据
                self.apply = multiply.applyRound(True, 0,self)
                self.apply.dictP[NUM] = Process
                self.apply.start()
                # 启动画图
                self.on_start()
            else:
                first = NUM
                second = self.apply.allTime
                thrid = int(server)
                print('新的线程加入队列...')
                Process = process.process(NUM, second, int(server))
                self.apply.hasSomeProcessCome = True
                self.apply.dictP[NUM] = Process
            s = (f'  {str(first)}\t{str(second)}\t {str(thrid)}')
            self.listWidget.addItem(s)

    # 显示列表菜单
    def showMenu(self,point):
        item = self.listWidget.itemAt(point)
        if item:
            pass
        else:
            self.outContextMenu.show()
            self.outContextMenu.exec_(QtGui.QCursor.pos())

    # 暂停
    def stopThread(self):
        pass

    # 开始
    def awaitThread(self):
        pass

    # 以下均为画图
    # 更新
    def update_line(self, i):
        # i = time.time() - self.time
        # self.canvas.axes.cla()
        # self.x.append(i)
        # self.y.append(i * random.randint(0, 2))
        # print(self.x)
        # print(self.y)

        # 更新方法一
        # self.canvas.axes.set_xlim([0, max(self.x) + 1])
        # self.canvas.axes.set_ylim([0, max(self.y) + 1])
        # self.canvas.axes.update_datalim([[0, max(self.x) + 1],[0, max(self.y) + 1]])

        # 更新方法二
        # self.canvas.axes.cla()
        # self.canvas.axes.set_xbound(0, max(self.x) + 1)
        # self.canvas.axes.set_ybound(0, max(self.y) + 1)

        # 更新方法三
        # self.canvas.axes.set_xticks([0, max(self.x) + 1])
        # self.canvas.axes.set_yticks([0, max(self.y) + 1])
        # self.canvas.axes.set_axis_on()

        # 以上方法都没有什么用

        self.line.set_xdata(self.x)
        self.line.set_ydata(self.y)
        return [self.line]

    # 开始暂停(开始)
    def on_start(self):
        if self.started:
            pass
        else:
            self.ani = FuncAnimation(self.canvas.figure, self.update_line,
                                 blit=True, interval=1050)
            self.started = True

    # 开始暂停(暂停)
    def on_stop(self):
        if self.started:
            self.ani._stop()
            self.started = False
        else:
            self.ani._stop()
class ConcreteSimulation(AbstractSimulation, ObserverClient):
    def __init__(self):
        super().__init__()
        plt.ioff()
        self.DPI = MainConfiguration().DPI
        self.ani = None
        self.fig = plt.figure(figsize=(self.width / self.DPI,
                                       self.height / self.DPI),
                              dpi=self.DPI)
        self.fig.subplots_adjust(left=0,
                                 bottom=0.05,
                                 right=0.95,
                                 top=1,
                                 wspace=0,
                                 hspace=0)
        self.fig.patch.set_facecolor(Theme().default_bg)
        self.ax = self.fig.add_subplot()
        for spine in self.ax.spines.values():
            spine.set_visible(False)
        self.days = 0
        self.ax.set_facecolor(Theme().plot_bg)
        self.fig.set_edgecolor(Theme().plot_bg)
        self.ax.set_xticks([])
        self.ax.set_yticks([])
        self.last_core_radius = MainConfiguration().SUBJECT_SIZE * 2
        self.last_infection_radius = (
            MainConfiguration().SUBJECT_INFECTION_RADIUS +
            MainConfiguration().SUBJECT_SIZE) * 2
        self.ax.plot()
        self.draw_standby_pattern()

    def get_init_func(self):
        self.days = 0

        if MainConfiguration().QUARANTINE_MODE.get():
            ConcreteSimulation.draw_quarantine_boundaries(self.ax)

        if MainConfiguration().COMMUNITY_MODE.get():
            ConcreteSimulation.draw_community_boundaries_on_ax(self.ax)
        else:
            ConcreteSimulation.draw_main_simulation_canvas_movement_bounds(
                self.ax)

        self.ax.set_xticks([])
        self.ax.set_yticks([])
        self.ax.set_xlim(0, self.width)
        self.ax.set_ylim(0, self.height)
        #self.ax.axis('off')

        self._box_of_particles.count_them()

        self.previous_infected = len(
            self._box_of_particles.counts["INFECTED"]) + len(
                self._box_of_particles.counts["ASYMPTOMATIC"])
        self.previous_r = 1

        self.notify(self._box_of_particles.counts)
        self.notify({
            "DAY": 0,
            "R_RATE": "{:.2f}".format(self.previous_r),
            "R_GROWTH": "0.0%"
        })

        self.ax.plot([],
                     marker=".",
                     fillstyle="full",
                     linestyle="",
                     color=Theme().immune,
                     markersize=self.last_core_radius)

        self.ax.plot([],
                     marker=".",
                     fillstyle="none",
                     linestyle="",
                     color=Theme().immune,
                     markersize=self.last_infection_radius)

        # susceptible
        self.ax.plot([],
                     marker=".",
                     fillstyle="full",
                     linestyle="",
                     color=Theme().susceptible,
                     markersize=self.last_core_radius)

        self.ax.plot([],
                     marker=".",
                     fillstyle="none",
                     color=Theme().susceptible,
                     linestyle="",
                     markersize=self.last_infection_radius)

        # asymptomatic
        self.ax.plot([],
                     marker=".",
                     fillstyle="full",
                     linestyle="",
                     color=Theme().asymptomatic,
                     markersize=self.last_core_radius)

        self.ax.plot([],
                     marker=".",
                     fillstyle="none",
                     color=Theme().asymptomatic,
                     linestyle="",
                     markersize=self.last_infection_radius)
        # infected

        self.ax.plot([],
                     marker=".",
                     fillstyle="full",
                     linestyle="",
                     color=Theme().infected,
                     markersize=self.last_core_radius)

        self.ax.plot([],
                     marker=".",
                     fillstyle="none",
                     color=Theme().infected,
                     linestyle="",
                     markersize=self.last_infection_radius)

        def func():
            return self.ax.lines

        return func

    def get_animation_function(self):
        def func(i):
            frames_per_day = MainConfiguration().get_frames_per_day()

            self.move_guys(i)
            if i % frames_per_day == 0 and i != 0:
                self.days += 1

                r_rate = self._box_of_particles.r_rate
                try:
                    r_growth = (r_rate - self.previous_r) / self.previous_r
                except ZeroDivisionError:
                    r_growth = 0
                self.previous_r = r_rate
                r_rate = "{0:.2f}".format(r_rate)
                r_growth = "{0:.2f}%".format(r_growth * 100)
                self.notify({
                    "DAY": int(self.days),
                    "R_RATE": r_rate,
                    "R_GROWTH": r_growth
                })
            self.notify(self._box_of_particles.counts)

            infected_coords = self.get_current_coordinates_by_key("INFECTED")
            immune_coords = self.get_current_coordinates_by_key("IMMUNE")
            susceptible_coords = self.get_current_coordinates_by_key(
                "SUSCEPTIBLE")
            asymptomatic_coords = self.get_current_coordinates_by_key(
                "ASYMPTOMATIC")

            self.ax.lines[0].set_data(*immune_coords)
            self.ax.lines[1].set_data(*immune_coords)

            self.ax.lines[2].set_data(*susceptible_coords)
            self.ax.lines[3].set_data(*susceptible_coords)

            self.ax.lines[4].set_data(*asymptomatic_coords)
            self.ax.lines[5].set_data(*asymptomatic_coords)

            self.ax.lines[6].set_data(*infected_coords)
            self.ax.lines[7].set_data(*infected_coords)
            core_radius = MainConfiguration().SUBJECT_SIZE * 2
            infection_radius = (MainConfiguration().SUBJECT_INFECTION_RADIUS +
                                MainConfiguration().SUBJECT_SIZE) * 2

            if core_radius != self.last_core_radius or infection_radius != self.last_infection_radius:
                self.last_core_radius = core_radius
                self.last_infection_radius = infection_radius
                self.ax.lines[0].set_markersize(core_radius)
                self.ax.lines[1].set_markersize(infection_radius)

                self.ax.lines[0].set_markersize(core_radius)
                self.ax.lines[1].set_markersize(infection_radius)

                self.ax.lines[2].set_markersize(core_radius)
                self.ax.lines[3].set_markersize(infection_radius)

                self.ax.lines[4].set_markersize(core_radius)
                self.ax.lines[5].set_markersize(infection_radius)
                self.ax.lines[6].set_markersize(core_radius)
                self.ax.lines[7].set_markersize(infection_radius)
            # self._box_of_particles    .print_counts()"""
            return self.ax.lines

        return func

    def start(self):
        for x in self.fig.axes:
            x.clear()
        init_func = self.get_init_func()
        animation_function = self.get_animation_function()
        self.ani = FuncAnimation(self.fig,
                                 animation_function,
                                 init_func=init_func,
                                 interval=1000 /
                                 MainConfiguration().FRAMES_PER_SECOND,
                                 blit=True)
        return self.ani

    def reset(self):
        self._marker_radius = MainConfiguration().SUBJECT_SIZE
        self._infection_zone_radius = MainConfiguration(
        ).SUBJECT_INFECTION_RADIUS + MainConfiguration().SUBJECT_SIZE
        self.pause()
        if self.ani is not None:
            self.ani._stop()
            self.ani = None
        del self._box_of_particles
        #self.ani = None
        self._box_of_particles = DefaultContainer() if MainConfiguration().COMMUNITY_MODE.get() is not True\
            else CommunitiesContainer()
        for x in self.fig.axes:
            x.clear()
        self.ax.set_xticks([])
        self.ax.set_yticks([])
        #self.start()
        self.notify(None)
        self.draw_standby_pattern()
        self.ax.plot()
        self.fig.canvas.draw()

    def resume(self):
        if self.ani is not None:
            self.ani.event_source.start()

    def pause(self):
        if self.ani is not None:
            self.ani.event_source.stop()

    @staticmethod
    def draw_community_boundaries_on_ax(ax):
        cells = MainConfiguration().get_community_cells_border_bounds()
        for cell in cells:
            x = cell[0][0]
            y = cell[1][0]
            width = cell[0][1] - x
            height = cell[1][1] - y
            ax.add_patch(
                patches.Rectangle((x, y),
                                  width,
                                  height,
                                  facecolor="none",
                                  linewidth=1,
                                  edgecolor=Theme().infected,
                                  linestyle="--"))

    @staticmethod
    def draw_quarantine_boundaries(ax):
        if MainConfiguration().QUARANTINE_MODE.get():
            q_dims = MainConfiguration().get_quarantine_dimensions()
            inner_padding = MainConfiguration().INNER_PADDING
            ax.text(q_dims["x"] + inner_padding,
                    q_dims["y"] + inner_padding,
                    "QUARANTINE",
                    color=Theme().infected,
                    fontsize="large",
                    rotation=90)
            ax.add_patch(
                patches.Rectangle((q_dims["x"], q_dims["y"]),
                                  q_dims["width"],
                                  q_dims["height"],
                                  facecolor="none",
                                  linewidth=1,
                                  edgecolor=Theme().infected,
                                  linestyle="--"))

    @staticmethod
    def draw_main_simulation_canvas_movement_bounds(ax):
        q_dims = MainConfiguration().get_particle_movement_border_bounds()
        ax.add_patch(
            patches.Rectangle((q_dims[0, 0], q_dims[1, 0]),
                              q_dims[0, 1] - q_dims[0, 0],
                              q_dims[1, 1] - q_dims[1, 0],
                              facecolor="none",
                              linewidth=1,
                              edgecolor=Theme().infected,
                              linestyle="--"))

    def draw_standby_pattern(self):
        self.ax.set_xticks([])
        self.ax.set_yticks([])
        self.ax.set_xlim(0, self.width)
        self.ax.set_ylim(0, self.height)
        q_dims = MainConfiguration().get_simulation_canvas_total_bounds()
        self.ax.add_patch(
            patches.Rectangle(
                (q_dims[0, 0] + MainConfiguration().INNER_PADDING,
                 q_dims[1, 0] + MainConfiguration().INNER_PADDING),
                q_dims[0, 1] - q_dims[0, 0] -
                2 * MainConfiguration().INNER_PADDING,
                q_dims[1, 1] - q_dims[1, 0] -
                2 * MainConfiguration().INNER_PADDING,
                facecolor="none",
                linewidth=1,
                edgecolor=Theme().infected,
                linestyle="--"))
        width = MainConfiguration().get_simulation_canvas_total_bounds()[0][1]
        self.ax.text(width - 330,
                     2 * MainConfiguration().INNER_PADDING,
                     "Simulation area - standby".upper(),
                     color=Theme().infected,
                     fontsize="x-large",
                     rotation=0)
예제 #9
0
class RunAnalysisInput(QDialog):
    def __init__(self, project, analysis_ID, analysis_type_label, *args, **kwargs):
        super().__init__(*args, **kwargs)
        uic.loadUi('data/user_input/ui/Analysis/runAnalysisInput.ui', self)

        icons_path = 'data\\icons\\'
        self.icon = QIcon(icons_path + 'pulse.png')
        self.setWindowIcon(self.icon)

        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        # self.setWindowModality(Qt.WindowModal)

        self.label_title = self.findChild(QLabel, 'label_title')
        self.label_message = self.findChild(QLabel, 'label_message')
        self.label_message.setWordWrap(True)
        self.config_title_font()
        self.config_message_font()

        self.project = project
        self.solve = None
        self.analysis_ID = analysis_ID
        self.analysis_type_label = analysis_type_label
        self.frequencies = self.project.frequencies
        self.damping = self.project.global_damping
        self.modes = self.project.modes
        self.solution_acoustic = None
        self.solution_structural = None
        self.convergence_dataLog = None
        self.natural_frequencies_acoustic = []
        self.natural_frequencies_structural = []
        self.complete = False

        LoadingScreen('SOLUTION IN PROGRESS', 'Processing the cross-sections',  target=self.process_cross_sections, project=project)
        if self.project.preprocessor.stop_processing:
            self.project.preprocessor.stop_processing = False
            return

        LoadingScreen('SOLUTION IN PROGRESS', 'Preparing the model to solve', target=self.preparing_mathematical_model_to_solve)  
        self.pre_non_linear_convergence_plot()

        LoadingScreen('SOLUTION IN PROGRESS', 'Solving the analysis',  target=self.process_analysis, project=project)
        self.post_non_linear_convergence_plot()  

        if self.project.preprocessor.stop_processing:
            self.reset_all_results()
            self.project.preprocessor.stop_processing = False
        else:
            LoadingScreen('SOLUTION IN PROGRESS', 'Post-processing the obtained results', target=self.post_process_results)
            self.exec()
            self.check_warnings()

    def pre_non_linear_convergence_plot(self):
        if isinstance(self.solve, SolutionAcoustic):
            if self.analysis_ID in [3,5,6]:
                if self.solve.non_linear:
                    fig = plt.figure(figsize=[8,6])
                    ax  = fig.add_subplot(1,1,1)
                    self.anime = FuncAnimation(fig, self.solve.graph_callback, fargs=(fig,ax), interval=2000)
                    self.anime._start()
                    plt.ion()
                    plt.show()

    def post_non_linear_convergence_plot(self):
        if isinstance(self.solve, SolutionAcoustic):
            if self.analysis_ID in [3,5,6]:
                if self.solve.non_linear:
                    self.anime._stop()

    def process_cross_sections(self):

        t0i = time()
        self.complete = False
        self.project.process_cross_sections_mapping()
        self.project.time_to_process_cross_sections = time() - t0i

    def preparing_mathematical_model_to_solve(self):

        t0 = time()
        if self.analysis_ID in [0,1,3,5,6]:
            if self.frequencies is None:
                return
            if len(self.frequencies) == 0:
                return

        if self.project.preprocessor._process_beam_nodes_and_indexes():
            if self.analysis_ID not in [0,1,2]:
                title = "INCORRECT ANALYSIS TYPE"
                message = "There are only BEAM_1 elements in the model, therefore, \nonly structural analysis are allowable."
                info_text = [title, message, window_title_2]
                PrintMessageInput(info_text)
                return

        if self.analysis_ID == 2:
            self.project.preprocessor.enable_fluid_mass_adding_effect(reset=True)
            self.solve = self.project.get_structural_solve()

        elif self.analysis_ID == 4:
            self.solve = self.project.get_acoustic_solve()

        elif self.analysis_ID == 3:
            self.solve = self.project.get_acoustic_solve()

        elif self.analysis_ID in [5,6]:
            self.project.preprocessor.enable_fluid_mass_adding_effect()
            self.solve = self.project.get_acoustic_solve()
            
        else:
            self.project.preprocessor.enable_fluid_mass_adding_effect(reset=True)
            self.solve = self.project.get_structural_solve()

        self.project.time_to_preprocess_model = time() - t0
       
    def process_analysis(self):
        
        t0 = time()

        if self.analysis_ID == 0:
            self.solution_structural = self.solve.direct_method(self.damping) # Structural Harmonic Analysis - Direct Method

        elif self.analysis_ID == 1: # Structural Harmonic Analysis - Mode Superposition Method
            self.solution_structural = self.solve.mode_superposition(self.modes, self.damping)

        elif self.analysis_ID == 3: # Acoustic Harmonic Analysis - Direct Method
            self.solution_acoustic, self.convergence_dataLog = self.solve.direct_method()

        elif self.analysis_ID == 5: # Coupled Harmonic Analysis - Direct Method
            
            t0_acoustic = time()
            self.solution_acoustic, self.convergence_dataLog = self.solve.direct_method() #Acoustic Harmonic Analysis - Direct Method
            self.project.time_to_solve_acoustic_model = time() - t0_acoustic
            
            self.project.set_acoustic_solution(self.solution_acoustic)
            self.solve = self.project.get_structural_solve()
            
            t0_structural = time()
            self.solution_structural = self.solve.direct_method(self.damping) #Coupled Harmonic Analysis - Direct Method
            self.project.time_to_solve_structural_model = time() - t0_structural
            
        elif self.analysis_ID == 6: # Coupled Harmonic Analysis - Mode Superposition Method
            
            t0_acoustic = time()
            self.solution_acoustic, self.convergence_dataLog = self.solve.direct_method() #Acoustic Harmonic Analysis - Direct Method
            self.project.time_to_solve_acoustic_model = time() - t0_acoustic
            
            self.project.set_acoustic_solution(self.solution_acoustic)
            self.solve = self.project.get_structural_solve()
            
            t0_structural = time()
            self.solution_structural = self.solve.mode_superposition(self.modes, self.damping)
            self.project.time_to_solve_structural_model = time() - t0_structural
            
        elif self.analysis_ID == 2: # Structural Modal Analysis
            self.natural_frequencies_structural, self.solution_structural = self.solve.modal_analysis(modes = self.modes, sigma=self.project.sigma)

        elif self.analysis_ID == 4: # Acoustic Modal Analysis
            self.natural_frequencies_acoustic, self.solution_acoustic = self.solve.modal_analysis(modes = self.modes, sigma=self.project.sigma)
        
        self.project.time_to_solve_model = time() - t0

        if isinstance(self.solve, SolutionAcoustic):
            if self.analysis_ID in [3,5,6]:
                if self.solve.non_linear:
                    sleep(2)

    def post_process_results(self): 

        t0 = time()
        self.project.set_perforated_plate_convergence_dataLog(self.convergence_dataLog)
        if self.analysis_ID == 2:
            
            if self.solution_structural is None:
                return

            self.project.set_structural_solution(self.solution_structural)
            self.project.set_structural_natural_frequencies(self.natural_frequencies_structural.tolist())

        elif self.analysis_ID == 4:
                    
            if self.solution_acoustic is None:
                return

            self.project.set_acoustic_solution(self.solution_acoustic)
            self.project.set_acoustic_natural_frequencies(self.natural_frequencies_acoustic.tolist())
        
        elif self.analysis_ID == 3:

            if self.solution_acoustic is None:
                return

            self.project.set_acoustic_solution(self.solution_acoustic)
        
        elif self.analysis_ID in [0,1,5,6]:
            
            if self.solution_structural is None:
                return

            self.project.set_structural_solve(self.solve)
            self.project.set_structural_solution(self.solution_structural)
            self.dict_reactions_at_constrained_dofs = self.solve.get_reactions_at_fixed_nodes(self.damping)
            self.dict_reactions_at_springs, self.dict_reactions_at_dampers = self.solve.get_reactions_at_springs_and_dampers()
            self.project.set_structural_reactions([ self.dict_reactions_at_constrained_dofs,
                                                    self.dict_reactions_at_springs,
                                                    self.dict_reactions_at_dampers  ])

        self.project.time_to_postprocess = time() - t0
        _times =  [self.project.time_to_process_cross_sections, self.project.time_to_preprocess_model, self.project.time_to_solve_model, self.project.time_to_postprocess]
        self.project.total_time = sum(_times)
        self.print_final_log()
        self.complete = True

    def check_warnings(self):
        # WARNINGS REACHED DURING SOLUTION
        title = self.analysis_type_label
        message = ""
        if self.analysis_type_label == "Harmonic Analysis - Structural":
            if self.solve.flag_ModeSup_prescribed_NonNull_DOFs:
                message = self.solve.warning_ModeSup_prescribedDOFs
            if self.solve.flag_Clump and self.analysis_ID==1:
                message = self.solve.warning_Clump[0]
        if self.analysis_type_label == "Modal Analysis - Structural":
            if self.solve.flag_Modal_prescribed_NonNull_DOFs:
                message = self.solve.warning_Modal_prescribedDOFs[0] 
        if message != "":
            PrintMessageInput([title, message, window_title_2])

    def reset_all_results(self):

        self.solution_structural = None
        self.solution_acoustic = None

        if self.analysis_ID == 2:
            self.project.set_structural_solution(None)
            self.project.set_structural_natural_frequencies(None)
        elif self.analysis_ID == 4: 
            self.project.set_acoustic_solution(None)
            self.project.set_acoustic_natural_frequencies(None)
        elif self.analysis_ID == 3:
            self.project.set_acoustic_solution(None)
        elif self.analysis_ID in [0,1,5,6]:
            self.project.set_acoustic_solution(None)
            self.project.set_structural_solution(None)
            self.project.set_structural_reactions([ {}, {}, {} ])

    def config_title_font(self):
        font = QFont()
        font.setPointSize(19)
        font.setBold(True)
        font.setItalic(True)
        font.setFamily("Arial")
        # font.setWeight(60)
        self.label_title.setFont(font)
        self.label_title.setStyleSheet("color:black")

    def config_message_font(self):
        font = QFont()
        font.setPointSize(17)
        font.setBold(True)
        # font.setItalic(True)
        font.setFamily("Arial")
        # font.setWeight(60)
        self.label_message.setFont(font)
        self.label_message.setStyleSheet("color:blue")

    def print_final_log(self):

        text = "Solution finished!\n\n"
        # text += "Time to check all entries: {} [s]\n".format(round(self.project.time_to_checking_entries, 6))
        text += "Time to load/create the project: {} [s]\n".format(round(self.project.time_to_load_or_create_project, 4))
        text += "Time to process cross-sections: {} [s]\n".format(round(self.project.time_to_process_cross_sections, 4))
        text += "Time elapsed in pre-processing: {} [s]\n".format(round(self.project.time_to_preprocess_model, 4))
        if self.analysis_ID in [5,6]:
            text += "Time to solve the acoustic model: {} [s]\n".format(round(self.project.time_to_solve_acoustic_model, 4))
            text += "Time to solve the structural model: {} [s]\n".format(round(self.project.time_to_solve_structural_model, 4))
        else:
            text += "Time to solve the model: {} [s]\n".format(round(self.project.time_to_solve_model, 4))
        text += "Time elapsed in post-processing: {} [s]\n\n".format(round(self.project.time_to_postprocess, 4))
        text += "Total time elapsed: {} [s]\n\n\n".format(round(self.project.total_time, 4))

        text += "Press ESC to continue..."
        self.label_message.setText(text)
예제 #10
0
class CalibrationUI():
    def __init__(self, SharedVariables_class, calculator_class):
        self.SV = SharedVariables_class
        self.CALCULATOR = calculator_class

        self.calibration_MainWindow = QtWidgets.QMainWindow()
        self.calibration_gui = C_GUI.Ui_MainWindow()
        self.calibration_gui.setupUi(self.calibration_MainWindow)

        self.temp_calibrate_x = self.SV.calibrate_x
        self.temp_calibrate_y = self.SV.calibrate_y
        self.temp_calibrate_angle = self.SV.calibrate_angle
        self.temp_calibrate_x_multi = self.SV.calibrate_x_multi
        self.temp_calibrate_y_multi = self.SV.calibrate_y_multi
        self.temp_calibrate_angle_multi = self.SV.calibrate_angle_multi

        self.calibration_gui.XCalibration_constant_spinBox.valueChanged.connect(
            self.x_spin)
        self.calibration_gui.YCalibration_constant_spinBox.valueChanged.connect(
            self.y_spin)
        self.calibration_gui.AngleCalibration_constant_spinBox.valueChanged.connect(
            self.angle_spin)
        self.calibration_gui.XCalibration_spinBox.valueChanged.connect(
            self.x_spin_multi)
        self.calibration_gui.YCalibration_spinBox.valueChanged.connect(
            self.y_spin_multi)
        self.calibration_gui.AngleCalibration_spinBox.valueChanged.connect(
            self.angle_spin_multi)
        self.calibration_gui.XCalibration_constant_slider.valueChanged.connect(
            self.x_slider)
        self.calibration_gui.YCalibration_constant_slider.valueChanged.connect(
            self.y_slider)
        self.calibration_gui.AngleCalibration_constant_slider.valueChanged.connect(
            self.angle_slider)
        self.calibration_gui.XCalibration_slider.valueChanged.connect(
            self.x_slider_multi)
        self.calibration_gui.YCalibration_slider.valueChanged.connect(
            self.y_slider_multi)
        self.calibration_gui.AngleCalibration_slider.valueChanged.connect(
            self.angle_slider_multi)
        self.calibration_MainWindow.closeEvent = self.closeEvent
        self.calibration_gui.ExitBtn.clicked.connect(
            self.calibration_MainWindow.close)
        self.calibration_gui.ConfirmBtn.clicked.connect(self.ConfirmBtn_click)
        self.calibration_gui.ResetBtn.clicked.connect(self.ResetBtn_click)
        self.calibration_gui.ExportBtn.clicked.connect(self.ExportBtn_click)
        self.calibration_gui.ImportBtn.clicked.connect(self.ImportBtn_click)

        self.initial_line, = self.calibration_gui.Calibration.calibration_map_axes.plot(
            self.SV.local_obstacle_x, self.SV.local_obstacle_y, 'g.')
        self.current_line, = self.calibration_gui.Calibration.calibration_map_axes.plot(
            self.SV.local_obstacle_x, self.SV.local_obstacle_y, 'b.')
        self.calibrate_line, = self.calibration_gui.Calibration.calibration_map_axes.plot(
            self.SV.local_obstacle_x, self.SV.local_obstacle_y, 'r.')
        self.position_line, = self.calibration_gui.Calibration.calibration_map_axes.plot(
            self.SV.vision_data[0], self.SV.vision_data[1], 'bo')
        self.calibrate_position_line, = self.calibration_gui.Calibration.calibration_map_axes.plot(
            self.SV.vision_data[0], self.SV.vision_data[1], 'ro')

    def show_window(self):
        self.calibration_MainWindow.show()
        self.calibration_animation = FuncAnimation(
            self.calibration_gui.Calibration.figure,
            self.animation,
            blit=True,
            interval=50)

    def close_window(self):
        self.calibration_MainWindow.close()

    def x_spin(self):
        self.temp_calibrate_x = self.calibration_gui.XCalibration_constant_spinBox.value(
        )
        self.calibration_gui.XCalibration_constant_label.setText(
            "X Calibration : {}".format(self.temp_calibrate_x))
        self.calibration_gui.XCalibration_constant_slider.setValue(
            self.temp_calibrate_x)

    def x_spin_multi(self):
        self.temp_calibrate_x_multi = self.calibration_gui.XCalibration_spinBox.value(
        ) / 100
        self.calibration_gui.XCalibration_label.setText(
            "X Calibration multiply: {} %".format(
                self.calibration_gui.XCalibration_spinBox.value()))
        self.calibration_gui.XCalibration_slider.setValue(
            self.calibration_gui.XCalibration_spinBox.value())

    def x_slider(self):
        self.temp_calibrate_x = self.calibration_gui.XCalibration_constant_slider.value(
        )
        self.calibration_gui.XCalibration_constant_label.setText(
            "X Calibration : {}".format(self.temp_calibrate_x))
        self.calibration_gui.XCalibration_constant_spinBox.setValue(
            self.temp_calibrate_x)

    def x_slider_multi(self):
        self.temp_calibrate_x_multi = self.calibration_gui.XCalibration_slider.value(
        ) / 100
        self.calibration_gui.XCalibration_label.setText(
            "X Calibration multiply: {} %".format(
                self.calibration_gui.XCalibration_slider.value()))
        self.calibration_gui.XCalibration_spinBox.setValue(
            self.calibration_gui.XCalibration_slider.value())

    def y_spin(self):
        self.temp_calibrate_y = self.calibration_gui.YCalibration_constant_spinBox.value(
        )
        self.calibration_gui.YCalibration_constant_label.setText(
            "Y Calibration : {}".format(self.temp_calibrate_y))
        self.calibration_gui.YCalibration_constant_slider.setValue(
            self.temp_calibrate_y)

    def y_spin_multi(self):
        self.temp_calibrate_y_multi = self.calibration_gui.YCalibration_spinBox.value(
        ) / 100
        self.calibration_gui.YCalibration_label.setText(
            "Y Calibration multiply : {} %".format(
                self.calibration_gui.YCalibration_spinBox.value()))
        self.calibration_gui.YCalibration_slider.setValue(
            self.calibration_gui.YCalibration_spinBox.value())

    def y_slider(self):
        self.temp_calibrate_y = self.calibration_gui.YCalibration_constant_slider.value(
        )
        self.calibration_gui.YCalibration_constant_label.setText(
            "Y Calibration : {}".format(self.temp_calibrate_y))
        self.calibration_gui.YCalibration_constant_spinBox.setValue(
            self.temp_calibrate_y)

    def y_slider_multi(self):
        self.temp_calibrate_y_multi = self.calibration_gui.YCalibration_slider.value(
        ) / 100
        self.calibration_gui.YCalibration_label.setText(
            "Y Calibration multiply: {} %".format(
                self.calibration_gui.YCalibration_slider.value()))
        self.calibration_gui.YCalibration_spinBox.setValue(
            self.calibration_gui.YCalibration_slider.value())

    def angle_spin(self):
        self.temp_calibrate_angle = self.calibration_gui.AngleCalibration_constant_spinBox.value(
        )
        self.calibration_gui.AngleCalibration_constant_label.setText(
            "Angle Calibration : {}".format(self.temp_calibrate_angle))
        self.calibration_gui.AngleCalibration_constant_slider.setValue(
            self.temp_calibrate_angle)

    def angle_spin_multi(self):
        self.temp_calibrate_angle_multi = self.calibration_gui.AngleCalibration_spinBox.value(
        ) / 100
        self.calibration_gui.AngleCalibration_label.setText(
            "Angle Calibration multiply : {} %".format(
                self.calibration_gui.AngleCalibration_spinBox.value()))
        self.calibration_gui.AngleCalibration_slider.setValue(
            self.calibration_gui.AngleCalibration_spinBox.value())

    def angle_slider(self):
        self.temp_calibrate_angle = self.calibration_gui.AngleCalibration_constant_slider.value(
        )
        self.calibration_gui.AngleCalibration_constant_label.setText(
            "Angle Calibration : {}".format(self.temp_calibrate_angle))
        self.calibration_gui.AngleCalibration_constant_spinBox.setValue(
            self.temp_calibrate_angle)

    def angle_slider_multi(self):
        self.temp_calibrate_angle_multi = self.calibration_gui.AngleCalibration_slider.value(
        ) / 100
        self.calibration_gui.AngleCalibration_label.setText(
            "Angle Calibration multiply: {} %".format(
                self.calibration_gui.AngleCalibration_slider.value()))
        self.calibration_gui.AngleCalibration_spinBox.setValue(
            self.calibration_gui.AngleCalibration_slider.value())

    def ConfirmBtn_click(self):
        self.SV.calibrate_x = self.temp_calibrate_x
        self.SV.calibrate_y = self.temp_calibrate_y
        self.SV.calibrate_angle = self.temp_calibrate_angle
        self.SV.calibrate_x_multi = self.temp_calibrate_x_multi
        self.SV.calibrate_y_multi = self.temp_calibrate_y_multi
        self.SV.calibrate_angle_multi = self.temp_calibrate_angle_multi
        self.CALCULATOR.show_message("Confirm calibration : x : {} , y : {} , angle : {}  \
            x multi : {} , y multi : {} , angle multi : {}" \
            .format(self.SV.calibrate_x, self.SV.calibrate_y, self.SV.calibrate_angle, \
                self.SV.calibrate_x_multi, self.SV.calibrate_y_multi, self.SV.calibrate_angle_multi))

    def ResetBtn_click(self):
        self.initial_line.set_data(self.SV.local_obstacle_x,
                                   self.SV.local_obstacle_y)

    def closeEvent(self, event):
        self.CALCULATOR.show_message("Calibration stop")
        self.calibration_animation._stop()
        self.SV.calibration_run = False
        event.accept()

    def animation(self, i):
        self.calibration_gui.VisionData_label.setText(str(self.SV.vision_data))

        temp_vision_x, temp_vision_y, temp_vision_angle_radian = self.CALCULATOR.get_calibrate_temp_vision_xy_angle(
            self.temp_calibrate_x, self.temp_calibrate_y,
            self.temp_calibrate_x_multi, self.temp_calibrate_y_multi,
            self.temp_calibrate_angle, self.temp_calibrate_angle_multi)
        temp_local_obstacle_x, temp_local_obstacle_y = self.CALCULATOR.get_calibrate_temp_local_obstacle(
            temp_vision_x, temp_vision_y, temp_vision_angle_radian,
            self.SV.lidar_radius, self.SV.lidar_angle)

        self.current_line.set_data(self.SV.local_obstacle_x,
                                   self.SV.local_obstacle_y)
        self.calibrate_line.set_data(temp_local_obstacle_x,
                                     temp_local_obstacle_y)
        self.position_line.set_data(self.SV.vision_data[0],
                                    self.SV.vision_data[1])
        self.calibrate_position_line.set_data(temp_vision_x, temp_vision_y)
        self.calibration_gui.Calibration.calibration_map_axes.autoscale(True)

        return self.current_line, self.calibrate_line, self.position_line, self.calibrate_position_line, self.initial_line,

    def ExportBtn_click(self):
        try:
            name = QtWidgets.QFileDialog.getSaveFileName(self.calibration_MainWindow, \
                'Save File', "", "Rover Calibration Files (*.calibration);;Text Files (*.txt);;All Files (*)")
            if name != ("", ""):
                file = open(name[0], 'w')
                text = "x{}xm{}y{}ym{}a{}am{}".format(self.SV.calibrate_x, self.SV.calibrate_x_multi, \
                    self.SV.calibrate_y, self.SV.calibrate_y_multi, self.SV.calibrate_angle, self.SV.calibrate_angle_multi)
                file.write(text)
                file.close()
        except TypeError:
            traceback.print_exc()

    def ImportBtn_click(self):
        name = QtWidgets.QFileDialog.getOpenFileName(self.calibration_MainWindow, \
            'Open File', "", "Rover Calibration Files (*.calibration);;Text Files (*.txt);;All Files (*)")
        if name != ("", ""):
            file = open(name[0], 'r')
            text = file.read()
            self.temp_calibrate_x = int(text[text.index("x") +
                                             1:text.index("xm")])
            self.temp_calibrate_x_multi = float(text[text.index("xm") +
                                                     2:text.index("y")])
            self.temp_calibrate_y = int(text[text.index("y") +
                                             1:text.index("ym")])
            self.temp_calibrate_y_multi = float(text[text.index("ym") +
                                                     2:text.index("a")])
            self.temp_calibrate_angle = int(text[text.index("a") +
                                                 1:text.index("am")])
            self.temp_calibrate_angle_multi = float(text[text.index("am") +
                                                         2:len(text)])
            self.calibration_gui.XCalibration_constant_slider.setValue(
                self.temp_calibrate_x)
            self.calibration_gui.YCalibration_constant_slider.setValue(
                self.temp_calibrate_y)
            self.calibration_gui.AngleCalibration_constant_slider.setValue(
                self.temp_calibrate_angle)
            self.calibration_gui.XCalibration_slider.setValue(
                self.temp_calibrate_x_multi * 100)
            self.calibration_gui.YCalibration_slider.setValue(
                self.temp_calibrate_y_multi * 100)
            self.calibration_gui.AngleCalibration_slider.setValue(
                self.temp_calibrate_angle_multi * 100)
            # print(
            #     self.temp_calibrate_x, self.temp_calibrate_x_multi,
            #     self.temp_calibrate_y, self.temp_calibrate_y_multi,
            #     self.temp_calibrate_angle, self.temp_calibrate_angle_multi
            #     )

            file.close()
예제 #11
0
class ROVER_gui():
    def __init__(self):
        os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
        app = QtWidgets.QApplication(sys.argv)
        app.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
        MainWindow = QtWidgets.QMainWindow()

        self.gui = GUI.Ui_MainWindow()
        self.gui.setupUi(MainWindow)

        self.SV = SharedVariables()
        self.SV.gui = self.gui
        self.CALCULATOR = Calculator(self.SV)

        self.current_speed = 0
        self.show_vision_status_dict = {
            0: "Booting",
            1: "Waiting for command",
            2: "Loading data",
            3: ":Locating, please move around",
            4: ":Working normally",
            5: ":Lost current position"
        }

        self.rover_run, self.lidar_server_run, self.vision_server_run, \
        self.animation_run, self.vision_build_map_mode, self.vision_use_map_mode, \
        self.SV.calibration_run, self.keyboard_control_run, self.vision_idle \
            = False, False, False, False, False, False, False, False, False

        self.check_status_rover_run_list = [
            self.rover_run, self.vision_server_run, self.lidar_server_run
        ]

        self.check_status_rover_Btn_list = [
            self.gui.RoverMainOnOffBtn, self.gui.VisionOnOffBtn,
            self.gui.LidarOnOffBtn
        ]

        self.check_status_func_run_list = [
            self.animation_run, self.vision_build_map_mode,
            self.vision_use_map_mode, self.SV.calibration_run,
            self.keyboard_control_run
        ]

        self.check_status_func_Btn_list = [
            self.gui.ShowMapBtn, self.gui.VisionBuildMapBtn,
            self.gui.VisionUseMapBtn, self.gui.CalibrationBtn,
            self.gui.KeyboardControlBtn
        ]

        self.gui.StopAllBtn.clicked.connect(self.StopAllBtn_click)
        self.gui.KeyboardControlBtn.clicked.connect(
            self.KeyboardControlBtn_click)
        self.gui.VisionBuildMapBtn.clicked.connect(
            self.VisionBuildMapBtn_click)
        self.gui.VisionBuildMapStopBtn.clicked.connect(
            self.VisionBuildMapStopBtn_click)
        self.gui.VisionUseMapBtn.clicked.connect(self.VisionUseMapBtn_click)
        self.gui.VisionUseMapStopBtn.clicked.connect(
            self.VisionUseMapStopBtn_click)
        self.gui.ShowMapBtn.clicked.connect(self.show_map)
        self.gui.ShowMap_AddBtn.clicked.connect(self.ShowMap_AddBtn_click)
        self.gui.KeyboardControl_SetSpeedBtn.clicked.connect(
            self.KeyboardControl_SetSpeedBtn_click)
        self.gui.KeyBoardControl_speed.valueChanged.connect(
            self.KeyBoardControl_speed_value_change)
        self.gui.CalibrationBtn.clicked.connect(self.calibration)

        self.gui_get_lidar_vision_client = rover_socket.UDP_client(
            50010, 0, '192.168.5.2')
        self.gui_get_rover_status_client = rover_socket.UDP_client(
            50012, 0, '192.168.5.2')
        self.gui_rover_command_client = rover_socket.UDP_client(
            50013, 0, '192.168.5.2')

        self.get_data_retry = 0
        self.get_data_timer = QtCore.QTimer()
        self.get_data_timer.timeout.connect(self.get_data_from_rover)
        self.get_data_timer.start(40)
        self.get_rover_status_retry = 0
        self.get_rover_status_timer = QtCore.QTimer()
        self.get_rover_status_timer.timeout.connect(self.get_rover_status)
        self.get_rover_status_timer.start(40)
        self.check_status_timer = QtCore.QTimer()
        self.check_status_timer.timeout.connect(self.check_status)
        self.check_status_timer.start(100)

        self.show_map()

        self.gui.tabWidget.setCurrentIndex(0)
        # self.gui.tabWidget.currentChanged.connect(self.show_map)

        MainWindow.show()
        sys.exit(app.exec_())

    def check_status(self):
        for i, j in zip(
            [self.rover_run, self.vision_server_run, self.lidar_server_run],
                range(len(self.check_status_rover_run_list))):
            if i:
                self.check_status_rover_Btn_list[j].setStyleSheet(
                    "background-color: rgb(0, 255, 0);")
            else:
                self.check_status_rover_Btn_list[j].setStyleSheet(
                    "background-color: rgb(255, 0, 0);")

        for i, j in zip([
                self.animation_run, self.vision_build_map_mode,
                self.vision_use_map_mode, self.SV.calibration_run,
                self.keyboard_control_run
        ], range(len(self.check_status_func_run_list))):
            if i:
                self.check_status_func_Btn_list[j].setStyleSheet(
                    "background-color: rgb(0, 255, 93);")
            else:
                self.check_status_func_Btn_list[j].setStyleSheet(
                    "background-color: rgb(112, 155, 255);")

    def get_rover_status(self):
        '''Specialize for getting rover status'''
        def show_vision_status():
            '''Explain vision status meanning'''
            if self.SV.vision_status in self.show_vision_status_dict:
                self.gui.VisionStatus_text.setText("{} : {}".format(
                    self.SV.vision_status,
                    self.show_vision_status_dict[self.SV.vision_status]))
            else:
                self.gui.VisionStatus_text.setText("{} : unknown".format(
                    self.SV.vision_status))

        self.gui_get_rover_status_client.send_list([1])
        temp_rover_status_receive = self.gui_get_rover_status_client.recv_list(
        )
        if temp_rover_status_receive is not None:
            self.gui.LidarUSB_text.setText("USB Port: " + str(temp_rover_status_receive[0]) \
                + "\n Status: " + str(temp_rover_status_receive[1]))

            self.lidar_server_run, self.SV.vision_status, self.vision_server_run, \
            self.vision_idle, self.rover_run, self.current_speed, \
            self.vision_build_map_mode, self.vision_use_map_mode = \
                temp_rover_status_receive[2:10]

            self.get_rover_status_retry = 0
            show_vision_status()
            self.gui.CurrentSpeed_text.setText(str(self.current_speed))
        else:
            self.get_rover_status_retry += 1
            if self.get_rover_status_retry > 50:
                self.lidar_server_run, self.rover_run, self.vision_server_run = \
                    False, False, False
                self.gui.CurrentSpeed_text.setText("No connection")
                self.gui.LidarUSB_text.setText("No connection")
                self.gui.VisionStatus_text.setText("No connection")

    def get_data_from_rover(self):
        '''Get data from rover and turn into map'''
        self.gui_get_lidar_vision_client.send_list(
            [1])  # Send anything to make sure connection always open
        temp_lidar_vision_receive = self.gui_get_lidar_vision_client.recv_list(
            32768)
        if temp_lidar_vision_receive is not None:
            self.SV.lidar_data = numpy.asarray(temp_lidar_vision_receive[0])
            self.SV.lidar_angle = self.SV.lidar_data[:,
                                                     1] * (-1) + 0.0 * math.pi
            self.SV.lidar_radius = self.SV.lidar_data[:, 2]
            self.SV.vision_data = temp_lidar_vision_receive[1]

            if self.SV.vision_data[3] == 4:
                self.CALCULATOR.calculate_vision_xy_angle()
                self.CALCULATOR.calculate_local_obstacle()
                self.CALCULATOR.calculate_arrow()

    def calibration(self):
        if not hasattr(self, "CAL_GUI"):
            self.CAL_GUI = CalibrationUI(self.SV, self.CALCULATOR)

        if not self.vision_idle and self.vision_server_run and self.lidar_server_run:
            if not self.SV.calibration_run and not self.CAL_GUI.calibration_MainWindow.isVisible(
            ):
                self.CAL_GUI.show_window()
                self.SV.calibration_run = True
            else:
                self.CAL_GUI.close_window()
                self.SV.calibration_run = False
        else:
            self.CALCULATOR.show_message(
                "For calibration, lidar, vision should be 'On' and \
                vision should be either build map mode or use map mode")

    def show_map(self):
        def plot_lidar_map(i):
            self.lidar_plot.set_xdata(self.SV.lidar_angle)
            self.lidar_plot.set_ydata(self.SV.lidar_radius)
            return self.lidar_plot,

        def plot_global_map(i):
            self.gui.GlobalMap.global_map_axes.set_xlim(
                self.CALCULATOR.get_x_axis_limit())
            self.gui.GlobalMap.global_map_axes.set_ylim(
                self.CALCULATOR.get_y_axis_limit())
            self.global_map_plot_vision.set_data(self.SV.vision_x,
                                                 self.SV.vision_y)
            self.global_map_plot_local_obstacle.set_data(
                self.SV.local_obstacle_x, self.SV.local_obstacle_y)
            self.global_map_plot_arrow.set_data(self.SV.arrow_x,
                                                self.SV.arrow_y)
            self.global_map_plot_global_obstacle.set_data(
                self.SV.global_obstacle_x, self.SV.global_obstacle_y)

            return self.global_map_plot_local_obstacle, self.global_map_plot_vision, self.global_map_plot_arrow, self.global_map_plot_global_obstacle,

        # print("show map")
        if not self.animation_run:
            self.lidar_plot, = self.gui.LidarMap.lidar_axes.plot(0, 0, 'b.')

            self.global_map_plot_arrow, = self.gui.GlobalMap.global_map_axes.plot(
                [], [], 'g', linewidth=3)
            self.global_map_plot_vision, = self.gui.GlobalMap.global_map_axes.plot(
                [], [], 'ro', linewidth=200)
            self.global_map_plot_local_obstacle, = self.gui.GlobalMap.global_map_axes.plot(
                [], [], 'b.')
            self.global_map_plot_global_obstacle, = self.gui.GlobalMap.global_map_axes.plot(
                [], [], 'k.')

            self.lidar_animation = FuncAnimation(self.gui.LidarMap.figure,
                                                 plot_lidar_map,
                                                 blit=True,
                                                 interval=50)
            self.global_animation = FuncAnimation(self.gui.GlobalMap.fig,
                                                  plot_global_map,
                                                  blit=True,
                                                  interval=50)
            self.CALCULATOR.show_message("Show Map Start")
            self.animation_run = True
        else:
            self.lidar_animation._stop()
            self.global_animation._stop()
            self.CALCULATOR.show_message("Show Map Stop")
            self.animation_run = False

    def ShowMap_AddBtn_click(self):
        self.CALCULATOR.get_global_obstacle()

    def StopAllBtn_click(self):
        self.CALCULATOR.show_message("Stop ALL")

        if self.animation_run:
            self.lidar_animation._stop()
            self.global_animation._stop()
            self.gui.GlobalMap.global_map_axes.clear()
            self.animation_run = False

        if self.keyboard_control_run:
            self.KeyboardControlTimer.stop()
            self.gui_keyboard_control_client.close()

    def KeyboardControlBtn_click(self):
        def controller():
            if keyboard.is_pressed('w') and not keyboard.is_pressed(
                    'a') and not keyboard.is_pressed('d'):
                self.gui_keyboard_control_client.send_list(['w'])
            elif keyboard.is_pressed('w') and keyboard.is_pressed(
                    'a') and not keyboard.is_pressed('d'):
                self.gui_keyboard_control_client.send_list(['wa'])
            elif keyboard.is_pressed('w') and not keyboard.is_pressed(
                    'a') and keyboard.is_pressed('d'):
                self.gui_keyboard_control_client.send_list(['wd'])
            elif keyboard.is_pressed('s') and not keyboard.is_pressed(
                    'a') and not keyboard.is_pressed('d'):
                self.gui_keyboard_control_client.send_list(['s'])
            elif keyboard.is_pressed('s') and keyboard.is_pressed(
                    'a') and not keyboard.is_pressed('d'):
                self.gui_keyboard_control_client.send_list(['sa'])
            elif keyboard.is_pressed('s') and not keyboard.is_pressed(
                    'a') and keyboard.is_pressed('d'):
                self.gui_keyboard_control_client.send_list(['sd'])
            elif keyboard.is_pressed('d') and not keyboard.is_pressed(
                    'w') and not keyboard.is_pressed('s'):
                self.gui_keyboard_control_client.send_list(['d'])
            elif keyboard.is_pressed('a') and not keyboard.is_pressed(
                    'w') and not keyboard.is_pressed('s'):
                self.gui_keyboard_control_client.send_list(['a'])


            self.gui.KeyUp.setStyleSheet("background-color: rgb(0, 255, 0);") \
                if keyboard.is_pressed('w') else \
                    self.gui.KeyUp.setStyleSheet("background-color: rgb(255, 255, 255);")

            self.gui.KeyDown.setStyleSheet("background-color: rgb(0, 255, 0);") \
                if keyboard.is_pressed('s') else \
                self.gui.KeyDown.setStyleSheet("background-color: rgb(255, 255, 255);")

            self.gui.KeyRight.setStyleSheet("background-color: rgb(0, 255, 0);") \
                if keyboard.is_pressed('d') else \
                self.gui.KeyRight.setStyleSheet("background-color: rgb(255, 255, 255);")

            self.gui.KeyLeft.setStyleSheet("background-color: rgb(0 255, 0);") \
                if keyboard.is_pressed('a') else \
                    self.gui.KeyLeft.setStyleSheet("background-color: rgb(255, 255, 255);")

        self.gui_keyboard_control_client = rover_socket.UDP_client(
            50011, 0, '192.168.5.2')
        self.KeyboardControlTimer = QtCore.QTimer()
        self.KeyboardControlTimer.timeout.connect(controller)

        if not self.keyboard_control_run:
            self.CALCULATOR.show_message('Keyboard Control Start')
            self.KeyboardControlTimer.start(50)
            self.keyboard_control_run = True
        else:
            self.KeyboardControlTimer.stop()
            self.gui_keyboard_control_client.close()
            self.CALCULATOR.show_message('Keyboard Control Stop')
            self.keyboard_control_run = False

    def KeyboardControl_SetSpeedBtn_click(self):
        if self.rover_run:
            self.gui_rover_command_client.send_list(
                ["gss", self.gui.KeyBoardControl_speed.value()])
            self.CALCULATOR.show_message(
                "Set Car Speed " + str(self.gui.KeyBoardControl_speed.value()))
        else:
            self.CALCULATOR.show_message("Warring : ROVER is not running")

    def KeyBoardControl_speed_value_change(self):
        self.gui.SetSpeed_label.setText(
            str(self.gui.KeyBoardControl_speed.value()))

    def WayPointBtn_click(self):
        self.CALCULATOR.show_message("Way Point mode start !")

    def VisionUseMapBtn_click(self):
        if self.vision_idle:
            self.gui_rover_command_client.send_list(
                ['gum', self.gui.UseMapID.value()])
            self.CALCULATOR.show_message('Vision start use map')
        else:
            if self.vision_server_run:
                self.CALCULATOR.show_message('Vision module is busy')
            else:
                self.CALCULATOR.show_message('Vision is not working')

    def VisionBuildMapBtn_click(self):
        if self.vision_idle:
            self.gui_rover_command_client.send_list(
                ['gbm', self.gui.BuildMapID.value()])
            self.CALCULATOR.show_message("Vision start building map")
        else:
            if self.vision_server_run:
                self.CALCULATOR.show_message('Vision module is busy')
            else:
                self.CALCULATOR.show_message('Vision is not working')

    def VisionBuildMapStopBtn_click(self):
        if not self.vision_idle and self.vision_build_map_mode:
            self.gui_rover_command_client.send_list(['gbms'])
            self.CALCULATOR.show_message(
                "Vision module is reseting please wait until ROVER reseting")
        else:
            self.CALCULATOR.show_message(
                "Vision is either idling or in use map mode")

    def VisionUseMapStopBtn_click(self):
        if not self.vision_idle and self.vision_use_map_mode:
            self.gui_rover_command_client.send_list(['gums'])
            self.CALCULATOR.show_message(
                "Vision module is reseting please wait until ROVER reseting")
        else:
            self.CALCULATOR.show_message(
                "Vision is either idling or in build map mode")
class Simulation(object):
	def __init__(self, fig=None, figsize=(6,6), period=10, xlim=(-2, 2), ylim=(-2, 2)):
		'''
		Constructor for the base model. 
		Must be called explicitly from the constructor of the derived class
		
		Arguments:
			figsize [inches]: Sets the size of the window containing the simulation.
			period_ms [ms]:      Sets the time between each update of the simulation.
			xlim [m]:         Sets the size of the x-axis in simulation distance units, typically meters
			ylim [m]:         Sets the size of the y-axis in simulation distance units, typically meters
		'''


		self.period_ms = period
		self.period_s = self.period_ms/1000.0
		self.state = []
		self.input = []
		self.time = 0.0
		self.iteration = 0
		self.state_posterior = []
		 
		if fig :
			self.figure = figure
		else:
			self.figure = figure(num=None, figsize=figsize, dpi=80, facecolor='w', edgecolor='k')
			
		self.axes = self.figure.add_subplot(111, autoscale_on=False, xlim=xlim, ylim=ylim)
		self.event_source = self.figure.canvas.new_timer()
		self.event_source.interval = self.period_ms

		self.controller = None
		self.controllers_arr = [None]*3
		
	def startAnimation(self, iterations=0):
		'''
		This method must be called to begin the simulation and will block until the simulation is finished.
		
		Arguments:
			iterations []: Number of times the update method will be called.
		'''
		if iterations == 0 :
			frames=None
		else :
			frames=range(iterations)
		
		self.reset(self.controller.reset_ar())
		self.ani = FuncAnimation(self.figure, self.update, frames=frames, interval=self.period_ms, repeat=False, event_source=self.event_source)
		self.figure.show()
		
		return self.state_posterior
			
		
	def reset(self, reset_arr):
		'''
		This methods sets the initial condition of state and time and is called prior to each simulation.
		
		Example:
			self.time = 0.0
			self.state = [0.0 , 0.0]
		'''
		raise NotImplementedError("This method is just an interface. Implement in inheriting class")
	
	def update(self, iteration_number):
		'''
		This method runs the simulation steps by calling:
			- The control method to generate control input
			- The model method for updating the state
			- The draw method to update the figure
			- The upkeep method to record data and control the simulation
			
		Arguments:
			iteration_number [] : The iteration number.
		'''
		self.iteration = iteration_number
		self.time = self.time + self.period_s
		self.control()
		self.model()
		self.draw()
		self.upkeep()

	def control(self):
		'''
		This method handles the control algorithm. Must return input vector for model
		'''
		pass
	   
	def model(self):
		'''
		This method calculates the new state of the system. Must return new state.
		'''
		raise NotImplementedError("This method is just an interface. Implement in inheriting class")

	def draw(self):
		'''
		This method handles updating or redrawing the figure
		'''
		raise NotImplementedError("This method is just an interface. Implement in inheriting class")    

	def upkeep(self):
		'''
		This method handles saving data for later plotting or analysis
		'''
		pass
	
	def stop(self):
		'''
		This method stops the animation 
		'''
		self.ani._stop()