def __init__(self,parent=None): QtGui.QMainWindow.__init__(self,parent) self.setWindowTitle("QtSimiam") self.resize(700,700) self.__create_toolbars() self.__create_menu() self.__create_statusbar() # Set intro message self.status_label.setText("Welcome to QtSimiam") # create XML file dialog self._world_dialog = QtGui.QFileDialog(self, "Select World File", "worlds", "WorldFile (*.xml)") self._world_dialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen) self._world_dialog.setFileMode(QtGui.QFileDialog.ExistingFile) # create supervisor file dialog self._supervisor_dialog = QtGui.QFileDialog(self, "Select Supervisor File", "supervisors", "Supervisor (*.py)") self._supervisor_dialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen) self._supervisor_dialog.setFileMode(QtGui.QFileDialog.ExistingFile) scrollArea = QtGui.QScrollArea(self) self.setCentralWidget(scrollArea) self.__viewer = SimulatorViewer() scrollArea.setWidget(self.__viewer) scrollArea.setWidgetResizable(True) #self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks) self.setDockOptions(QtGui.QMainWindow.DockOptions()) self.__sim_timer = QtCore.QTimer(self) self.__sim_timer.setInterval(10) self.__sim_timer.timeout.connect(self.__update_time) self.__sim_queue = queue.Queue() # create the simulator thread self._simulator_thread = sim.Simulator(self.__viewer.renderer, self.__sim_queue) self.__in_queue = self._simulator_thread._out_queue self.__dockmanager = DockManager(self) self.__dockmanager.apply_request.connect(self.apply_parameters) self._simulator_thread.start() self.__sim_timer.start()
class SimulationWidget(QtGui.QMainWindow): def __init__(self,parent=None): QtGui.QMainWindow.__init__(self,parent) self.setWindowTitle("QtSimiam") self.resize(700,700) self.__create_toolbars() self.__create_menu() self.__create_statusbar() # Set intro message self.status_label.setText("Welcome to QtSimiam") # create XML file dialog self._world_dialog = QtGui.QFileDialog(self, "Select World File", "worlds", "WorldFile (*.xml)") self._world_dialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen) self._world_dialog.setFileMode(QtGui.QFileDialog.ExistingFile) # create supervisor file dialog self._supervisor_dialog = QtGui.QFileDialog(self, "Select Supervisor File", "supervisors", "Supervisor (*.py)") self._supervisor_dialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen) self._supervisor_dialog.setFileMode(QtGui.QFileDialog.ExistingFile) scrollArea = QtGui.QScrollArea(self) self.setCentralWidget(scrollArea) self.__viewer = SimulatorViewer() scrollArea.setWidget(self.__viewer) scrollArea.setWidgetResizable(True) #self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks) self.setDockOptions(QtGui.QMainWindow.DockOptions()) self.__sim_timer = QtCore.QTimer(self) self.__sim_timer.setInterval(10) self.__sim_timer.timeout.connect(self.__update_time) self.__sim_queue = queue.Queue() # create the simulator thread self._simulator_thread = sim.Simulator(self.__viewer.renderer, self.__sim_queue) self.__in_queue = self._simulator_thread._out_queue self.__dockmanager = DockManager(self) self.__dockmanager.apply_request.connect(self.apply_parameters) self._simulator_thread.start() self.__sim_timer.start() def __create_toolbars(self): tbar = QtGui.QToolBar("Control",self) tbar.setAllowedAreas(QtCore.Qt.TopToolBarArea | QtCore.Qt.BottomToolBarArea) #self.__time_label = QtGui.QLabel("00:00.0",self) #self.__time_label.setToolTip("Elapsed time") #tbar.addWidget(self.__time_label) self.revaction = \ tbar.addAction(QtGui.QIcon("./res/image/arrow-left-double.png"), "Rewind", self._on_rewind) self.revaction.setStatusTip("Reset simulation") self.runaction = \ tbar.addAction(QtGui.QIcon("./res/image/arrow-right.png"), "Run", self._on_run) self.runaction.setStatusTip("Run simulation") self.pauseaction = \ tbar.addAction(QtGui.QIcon("./res/image/media-playback-pause-7.png"), "Pause", self._on_pause) self.pauseaction.setStatusTip("Pause simulation") self.revaction.setEnabled(False) self.runaction.setEnabled(False) self.pauseaction.setVisible(False) self.__speed_slider = QtGui.QSlider(QtCore.Qt.Horizontal,self) self.__speed_slider.setToolTip("Adjust speed") self.__speed_slider.setStatusTip("Adjust simulation speed") self.__speed_slider.setTickPosition(QtGui.QSlider.NoTicks) self.__speed_slider.setMaximumWidth(300) self.__speed_slider.setRange(-100,0) self.__speed_slider.setValue(0) self.__speed_slider.setEnabled(False) self.__speed_slider.valueChanged[int].connect(self._scale_time) tbar.addWidget(self.__speed_slider) self.__speed_label = QtGui.QLabel(" Speed: 1.0x",self) self.__speed_label.setToolTip("Current speed multiplier") tbar.addWidget(self.__speed_label) self.addToolBar(tbar) tbar = QtGui.QToolBar("View",self) tbar.setAllowedAreas(QtCore.Qt.TopToolBarArea | QtCore.Qt.BottomToolBarArea) a = tbar.addAction(QtGui.QIcon("./res/image/grid.png"), "Show/Hide grid") a.setStatusTip("Show/hide grid") a.triggered[bool].connect(self._show_grid) a.setCheckable(True) a.setChecked(False) a = tbar.addAction(QtGui.QIcon("./res/image/robot-sensors.png"), "Show/Hide sensors") a.setStatusTip("Show/hide robot sensors") a.triggered[bool].connect(self._show_sensors) a.setCheckable(True) a.setChecked(True) a = tbar.addAction(QtGui.QIcon("./res/image/robot-tracks.png"), "Show/Hide robot trajectores") a.setStatusTip("Show/hide robot trajectores") a.triggered[bool].connect(self._show_tracks) a.setCheckable(True) a.setChecked(True) zoom_group = QtGui.QActionGroup(tbar) a = tbar.addAction(QtGui.QIcon("./res/image/zoom-scene.png"), "Show all", self._zoom_scene) a.setStatusTip("Show the whole world in view") a.setCheckable(True) a.setChecked(True) zoom_group.addAction(a) a = tbar.addAction(QtGui.QIcon("./res/image/zoom-robot.png"), "Follow robot", self._zoom_robot) a.setStatusTip("Center the view on robot") a.setCheckable(True) a.setChecked(False) zoom_group.addAction(a) self.act_rot_robot = \ tbar.addAction(QtGui.QIcon("./res/image/zoom-robot-rot.png"), "Follow robot orientation", self._rot_robot) self.act_rot_robot.setStatusTip("Rotate the view with the robot") self.act_rot_robot.setCheckable(True) self.act_rot_robot.setChecked(False) self.act_rot_robot.setEnabled(False) self.__zoom_slider = QtGui.QSlider(QtCore.Qt.Horizontal,self) self.__zoom_slider.setTickPosition(QtGui.QSlider.NoTicks) self.__zoom_slider.setToolTip("Adjust zoom") self.__zoom_slider.setStatusTip("Zoom in/out on robot") self.__zoom_slider.setMaximumWidth(300) self.__zoom_slider.setRange(-100,100) self.__zoom_slider.setValue(0) self.__zoom_slider.setEnabled(False) self.__zoom_slider.valueChanged[int].connect(self._scale_zoom) tbar.addWidget(self.__zoom_slider) self.__zoom_label = QtGui.QLabel(" Zoom: 1.0x",self) self.__zoom_label.setToolTip("Current zoom factor") tbar.addWidget(self.__zoom_label) self.__zoom_factor = 0 self.addToolBar(tbar) def __create_menu(self): menu = QtGui.QMenuBar(self) self.setMenuBar(menu) file_menu = menu.addMenu("&File") a = file_menu.addAction(QtGui.QIcon.fromTheme("document-open"), "Open XML &World", self._on_open_world, QtGui.QKeySequence(QtGui.QKeySequence.Open)) a.setStatusTip("Open a new simulation") file_menu.addSeparator() a = file_menu.addAction(QtGui.QIcon.fromTheme("application-exit"), "E&xit", self.close, QtGui.QKeySequence(QtGui.QKeySequence.Quit) ) a.setToolTip("Quit the Program") a.setStatusTip("Exit QtSimiam") def __create_statusbar(self): self.setStatusBar(QtGui.QStatusBar()) self.status_label = QtGui.QLabel("",self.statusBar()) self.statusBar().addWidget(self.status_label) def closeEvent(self,event): self.__sim_timer.stop() self.__sim_queue.put(('stop',())) while self._simulator_thread.isAlive(): self.process_events(True) self._simulator_thread.join(0.1) super(SimulationWidget,self).closeEvent(event) def make_param_window(self,robot_id,name,parameters): # FIXME adding to the right for no reason self.__dockmanager.add_dock_right(robot_id, name, parameters) def load_world(self,filename): if not os.path.exists(filename): filename = os.path.join('worlds',filename) if not os.path.exists(filename): print "Cannot open file {}".format(filename) return self.__dockmanager.clear() #self.revaction.setEnabled(False) #self.runaction.setEnabled(True) self.__sim_queue.put(('read_config',(filename,))) # Slots @QtCore.pyqtSlot() def _on_rewind(self): # Start from the beginning self.pauseaction.setVisible(False) self.runaction.setVisible(True) self.pauseaction.setEnabled(False) self.revaction.setEnabled(False) self.__speed_slider.setEnabled(False) #self.__time_label.setText("00:00.0") self.__sim_queue.put(('reset_simulation',())) @QtCore.pyqtSlot() def _on_run(self): # Run/unpause self.pauseaction.setVisible(True) self.runaction.setVisible(False) self.runaction.setEnabled(False) self.__sim_queue.put(('start_simulation',())) @QtCore.pyqtSlot() def _on_pause(self): # Pause self.pauseaction.setVisible(False) self.runaction.setVisible(True) self.pauseaction.setEnabled(False) self.__speed_slider.setEnabled(False) self.__sim_queue.put(('pause_simulation',())) @QtCore.pyqtSlot() def _on_open_world(self): self._on_pause() if self._world_dialog.exec_(): self.load_world(self._world_dialog.selectedFiles()[0]) @QtCore.pyqtSlot(bool) def _show_grid(self,show): self.__sim_queue.put(('show_grid',(show,))) @QtCore.pyqtSlot(bool) def _show_sensors(self,show): self.__sim_queue.put(('show_sensors',(show,))) @QtCore.pyqtSlot(bool) def _show_tracks(self,show): self.__sim_queue.put(('show_tracks',(show,))) @QtCore.pyqtSlot() def _zoom_scene(self): self.__zoom_slider.setEnabled(False) self.act_rot_robot.setEnabled(False) self.__sim_queue.put(('focus_on_world',())) @QtCore.pyqtSlot() def _zoom_robot(self): self.__zoom_slider.setEnabled(True) self.act_rot_robot.setEnabled(True) self.__sim_queue.put(('focus_on_robot',(self.act_rot_robot.isChecked(),))) self.__sim_queue.put(('adjust_zoom',(5.0**(self.__zoom_slider.value()/100.0),))) @QtCore.pyqtSlot() def _rot_robot(self): self.__sim_queue.put(('focus_on_robot',(self.act_rot_robot.isChecked(),))) @QtCore.pyqtSlot(int) def _scale_zoom(self,value): zoom = 5.0**(value/100.0) self.__sim_queue.put(('adjust_zoom',(zoom,))) self.__zoom_label.setText(" Zoom: %.1fx"%(zoom)) @QtCore.pyqtSlot(int) def _scale_time(self,value): m = 10.0**((value-self.__zoom_factor)/100.0) self.__sim_queue.put(('set_time_multiplier',(m,))) self.__speed_label.setText(" Speed: %.1fx"%m) @QtCore.pyqtSlot() def __update_time(self): if self._simulator_thread.is_running(): t = self._simulator_thread.get_time() minutes = int(t//60) #self.__time_label.setText("%02d:%04.1f"%(minutes,t - minutes*60)) self.status_label.setText( "Simulation running... {:02d}:{:04.1f}".format(minutes,t - minutes*60)) self.process_events(True) def process_events(self, process_all = False): while not self.__in_queue.empty(): tpl = self.__in_queue.get() if isinstance(tpl,tuple) and len(tpl) == 2: name, args = tpl if name in self.__class__.__dict__: try: self.__class__.__dict__[name](self,*args) except TypeError: print "Wrong UI event parameters {}{}".format(name,args) raise else: print "Unknown UI event '{}'".format(name) else: print "Wrong UI event format '{}'".format(tpl) self.__in_queue.task_done() if not process_all: return def apply_parameters(self, robot_id, params): self.__sim_queue.put(('apply_parameters', (robot_id, params))) ### Queue processing def simulator_running(self): self.revaction.setEnabled(True) self.pauseaction.setEnabled(True) self.__speed_slider.setEnabled(True) def simulator_paused(self): self.runaction.setEnabled(True) #self.revaction.setEnabled(True) t = self._simulator_thread.get_time() minutes = int(t//60) #self.__time_label.setText("%02d:%04.1f"%(minutes,t - minutes*60)) self.status_label.setText( "Simulation paused... {:02d}:{:04.1f}".format(minutes,t - minutes*60)) self.__speed_slider.setEnabled(False) def simulator_reset(self): self.runaction.setEnabled(True) self.status_label.setText("Simulation ready") def simulator_stopped(self): # FIXME this function isn't necessary #self.__sim_timer.stop() self.runaction.setEnabled(False) self.pauseaction.setEnabled(False) self.revaction.setEnabled(False) self.__speed_slider.setEnabled(False) def update_view(self): self.__viewer.update_bitmap()