Пример #1
0
class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        layout = QVBoxLayout()

        upper_windows = QHBoxLayout()
        lower_windows = QHBoxLayout()

        map_window = RoomView()
        scanner = ScannerView()
        discovered_map = DiscoveredMapView()
        upper_windows.addWidget(map_window)
        upper_windows.addWidget(scanner)
        upper_windows.addWidget(discovered_map)

        buttons = QHBoxLayout()

        self.start_button = QPushButton("Start")
        buttons.addWidget(self.start_button)

        self.config_button = QPushButton("Setup")
        buttons.addWidget(self.config_button)

        self.load_scenario_button = QPushButton("Load Scenario")
        buttons.addWidget(self.load_scenario_button)

        self.save_button = QPushButton("Save Scenario")
        buttons.addWidget(self.save_button)

        export_button = QPushButton("Export Map")
        buttons.addWidget(export_button)

        self.forward_button = QPushButton("Forward")
        buttons.addWidget(self.forward_button)

        self.anticlockwise_button = QPushButton("Turn Anti-Clockwise")
        buttons.addWidget(self.anticlockwise_button)

        self.clockwise_button = QPushButton("Turn Clockwise")
        buttons.addWidget(self.clockwise_button)

        lower_windows.addLayout(buttons)
        layout.addLayout(upper_windows)
        layout.addLayout(lower_windows)
        self.setLayout(layout)

        self.setWindowTitle("Room Scanner")

        self.forward_button.setDisabled(True)
        self.anticlockwise_button.setDisabled(True)
        self.clockwise_button.setDisabled(True)

        self.controller = GUIController(map_window, scanner, discovered_map)
        self.start_button.clicked.connect(self.start_GUI_controller)
        self.forward_button.clicked.connect(
            self.controller.send_command_forward)
        self.clockwise_button.clicked.connect(
            self.controller.send_command_rotate_clockwise)
        self.anticlockwise_button.clicked.connect(
            self.controller.send_command_rotate_anticlockwise)
        self.save_button.clicked.connect(self.save_scenario)
        export_button.clicked.connect(self.export_map)
        self.config_button.clicked.connect(self.open_config_window)
        self.load_scenario_button.clicked.connect(self.open_load_window)

        self.database = DatabaseManager()

        self.start_pos = None
        self.previous_start_pos = None
        self.square_size = None
        self.open_config_window(
            close_immediately=True
        )  # So that the default settings are retrieved and stored

    def open_config_window(self, close_immediately=False):
        self.dialog = ConfigDialog(self.previous_start_pos, self.square_size)
        self.dialog.setModal(True)
        self.dialog.finished.connect(self.get_config_window_info)
        if close_immediately:
            self.dialog.close()
        else:
            self.dialog.open()

    def get_config_window_info(self, finish_code):
        if finish_code == 1:
            # Get the data back from the window
            # If it doesn't exist, disable the start button
            self.robot_name = self.dialog.robot_layout.robot_select_dropdown.currentText(
            )
            self.room_name = self.dialog.room_layout.room_select_dropdown.currentText(
            )
            start_pos_x = self.dialog.room_layout.start_pos_x.text()
            start_pos_y = self.dialog.room_layout.start_pos_y.text()
            square_size = self.dialog.square_size_text_edit.text()

            if self.room_name is None or self.room_name is None or square_size == "" or start_pos_x == "" or start_pos_y == "":
                self.start_button.setDisabled(True)
            else:
                self.start_button.setDisabled(False)
                self.start_pos = int(start_pos_x), int(start_pos_y)
                self.previous_start_pos = int(start_pos_x), int(start_pos_y)
                self.start_angle = 90
                self.square_size = int(square_size)
                self.cartographer_grid = None
        else:
            self.start_button.setDisabled(True)

    def open_load_window(self):
        dialog = ScenarioLoader()
        dialog.exec_()

        scenario_name = dialog.scenario_select.currentText()
        if scenario_name == "":
            return

        scenario_data = self.database.get_scenario_by_name(scenario_name)
        self.robot_name, self.room_name, self.square_size, self.cartographer_grid, robot_x, robot_y, self.start_angle = scenario_data
        self.cartographer_grid = json.loads(self.cartographer_grid)
        self.start_pos = robot_x, robot_y
        self.previous_start_pos = None
        self.start_GUI_controller()

    def start_GUI_controller(self):
        if self.start_button.text() == "Start":
            # Change it to a stop button
            self.start_button.setText("Stop")

            # Disable/enable buttons
            self.forward_button.setDisabled(False)
            self.anticlockwise_button.setDisabled(False)
            self.clockwise_button.setDisabled(False)
            self.config_button.setDisabled(True)
            self.load_scenario_button.setDisabled(True)
            self.forward_button.repaint()
            self.anticlockwise_button.repaint()
            self.clockwise_button.repaint()
            self.config_button.repaint()
            self.load_scenario_button.repaint()

            # Load all data from the database
            robot_data = self.database.get_robot_by_name(self.robot_name)
            rects = self.database.get_rects_by_room_name(self.room_name)
            room_size = self.database.get_room_width_height_by_room_name(
                self.room_name)
            self.controller.run(robot_data, room_size, rects, self.start_pos,
                                self.start_angle, self.square_size,
                                self.cartographer_grid)

        elif self.start_button.text() == "Stop":
            self.start_button.setText("Start")

            # Disable/enable buttons
            self.forward_button.setDisabled(True)
            self.anticlockwise_button.setDisabled(True)
            self.clockwise_button.setDisabled(True)
            self.config_button.setDisabled(False)
            self.load_scenario_button.setDisabled(False)
            self.forward_button.repaint()
            self.anticlockwise_button.repaint()
            self.clockwise_button.repaint()
            self.config_button.repaint()
            self.load_scenario_button.repaint()

    def save_scenario(self):
        name_getter = QDialog()
        question = QLabel("Input Name:")
        line_edit = QLineEdit()
        submit = QPushButton("Confirm")
        submit.setDefault(True)
        submit.clicked.connect(name_getter.close)

        layout = QHBoxLayout()
        layout.addWidget(question)
        layout.addWidget(line_edit)
        layout.addWidget(submit)
        name_getter.setLayout(layout)
        name_getter.exec_()

        name = line_edit.text()
        if name == "":
            return

        cartographer_grid = self.controller.controller.cartographer.grid
        robot_x, robot_y = self.controller.controller.hardware.pos
        robot_angle = self.controller.controller.hardware.rotation

        self.database.add_scenario(name, self.room_name, self.robot_name,
                                   self.square_size, cartographer_grid,
                                   robot_x, robot_y, robot_angle)

    def export_map(self):
        filename = QFileDialog.getSaveFileName(filter="Images (*.png)")[0]
        if filename == "":
            return
        self.controller.discovered_map_scene.save_image(filename)

    def close(self):
        self.database.connection.close()
        super(MainWindow, self).close()
Пример #2
0
class ConfigDialog(QDialog):
    def __init__(self, previous_start_pos, previous_square_size):
        super(ConfigDialog, self).__init__()
        self.setWindowTitle("Configure Settings")

        self.database = DatabaseManager()
        self.main_layout = QVBoxLayout()

        # Robot select
        self.robot_layout = RobotSelect(self.database)
        self.main_layout.addLayout(self.robot_layout)

        # Room select
        self.room_layout = RoomSelect(self.database, previous_start_pos,
                                      self.validate_input)
        self.main_layout.addLayout(self.room_layout)

        # Square size
        self.square_size_layout = QHBoxLayout()
        self.square_size_label = QLabel("Square Size: ")
        self.square_size_text_edit = QLineEdit()
        if previous_square_size is None:
            previous_square_size = DEFAULT_SQUARE_SIZE
        self.square_size_text_edit.setText(str(previous_square_size))

        self.square_size_layout.addWidget(self.square_size_label)
        self.square_size_layout.addWidget(self.square_size_text_edit)
        self.main_layout.addLayout(self.square_size_layout)

        # Done button
        self.done_button = QPushButton("Done")
        self.main_layout.addWidget(self.done_button)
        self.done_button.clicked.connect(self.close)
        self.done_button.setDefault(True)
        self.robot_layout.set_main_button_default.connect(
            self.done_button.setDefault)
        self.robot_layout.set_main_button_default.connect(
            self.done_button.repaint)

        # Get all info together for input validation
        self.start_pos_line_edits = self.room_layout.get_start_pos_line_edits()
        self.room_select_dropdown = self.room_layout.room_select_dropdown
        self.robot_select_dropdown = self.robot_layout.robot_select_dropdown

        self.start_pos_line_edits[0].textChanged.connect(self.validate_input)
        self.start_pos_line_edits[1].textChanged.connect(self.validate_input)
        self.room_select_dropdown.currentIndexChanged.connect(
            self.validate_input)
        self.robot_select_dropdown.currentIndexChanged.connect(
            self.validate_input)
        self.square_size_text_edit.textChanged.connect(self.validate_input)
        self.validate_input()

        self.setLayout(self.main_layout)

    def validate_input(self):
        start_x = self.start_pos_line_edits[0].text()
        start_y = self.start_pos_line_edits[1].text()
        robot_dropdown_text = self.robot_select_dropdown.currentText()
        room_dropdown_text = self.room_select_dropdown.currentText()
        square_size = self.square_size_text_edit.text()

        valid = self.validate_values(start_x, start_y, robot_dropdown_text,
                                     room_dropdown_text, square_size)

        if valid:
            self.done_button.setDisabled(False)
            self.done_button.repaint()
        else:
            self.done_button.setDisabled(True)
            self.done_button.repaint()

    def validate_values(self, x, y, robot_dropdown_text, room_dropdown_text,
                        square_size):
        # room_dropdown_text must not be empty
        if room_dropdown_text == "":
            return False

        # robot_dropdown_text must not be empty
        if robot_dropdown_text == "":
            return False

        width, height = self.database.get_room_width_height_by_room_name(
            room_dropdown_text)

        # x must be a positive integer between 0 and <width>
        try:
            x = int(x)
        except ValueError:
            return False
        if x <= 0 or x >= width:
            return False

        # y must be a positive integer between 0 and <width>
        try:
            y = int(y)
        except ValueError:
            return False
        if y <= 0 or y >= height:
            return False

        # square_size must be an integer that is a factor of both width and height and < 0
        try:
            square_size = int(square_size)
        except ValueError:
            return False

        if square_size <= 0:
            return False

        if width % square_size != 0:
            return False
        if height % square_size != 0:
            return False

        return True

    def close(self):
        robot_name = self.robot_layout.robot_select_dropdown.currentText()
        room_name = self.room_layout.room_select_dropdown.currentText()

        self.database.update_date_used(("Robot", "Room"),
                                       (robot_name, room_name))
        self.database.connection.close()
        self.done(1)