Exemplo n.º 1
0
    def __init__(self, parent, top):
        super(QWidget, self).__init__(parent)
        self.top = top
        hlayout = QHBoxLayout()
        self.layout = QGridLayout()
        hlayout.addLayout(self.layout)
        hlayout.setAlignment(hlayout, Qt.Alignment.AlignTop)
        self.setLayout(hlayout)
        self.row = 0

        self.__addLabel__("Gateway Services")
        self.__addLabel__("Gateway Host Name/IP Address")
        self.gatewayHostName = QLineEdit(self)
        self.__addInput__(self.gatewayHostName)

        self.__addLabel__("Exercise Data Server Host Name/IP Address")
        self.productionEDS = QLineEdit(self)
        self.prodEnable = QRadioButton("Production")
        self.prodEnable.setChecked(True)
        self.prodEnable.toggled.connect(self.radioProdClicked)
        self.prodEnable.setStyleSheet("QRadioButton{ width: 100; }")
        self.__addInputAndRadio__(self.productionEDS, self.prodEnable)
        self.testEDS = QLineEdit(self)
        self.testEnable = QRadioButton("Test")
        self.testEnable.toggled.connect(self.radioTestClicked)
        self.testEnable.setStyleSheet("QRadioButton{ width: 100; }")
        self.__addInputAndRadio__(self.testEDS, self.testEnable)

        self.__addLabel__("Messaging Port")
        self.messagePort = QLineEdit("61616")
        self.__addInput__(self.messagePort)
    def __init__(self):
        super(MainWidget, self).__init__()
        self.resize(500, 600)
        self.setWindowTitle("喜马拉雅下载 by[Zero] " + __VERSION__)
        self.mainlayout = QVBoxLayout()
        self.setLayout(self.mainlayout)
        self.groupbox = QGroupBox("选择类型")
        self.groupbox.setFixedHeight(50)
        hlayout = QHBoxLayout(self.groupbox)
        self.signal_m4a = QRadioButton("单个下载")
        self.mut_m4a = QRadioButton("专辑下载")
        self.vip_signal_m4a = QRadioButton("VIP单个下载")
        self.vip_m4a = QRadioButton("VIP专辑下载")

        hlayout.addWidget(self.signal_m4a)
        hlayout.addWidget(self.mut_m4a)
        hlayout.addWidget(self.vip_signal_m4a)
        hlayout.addWidget(self.vip_m4a)
        self.mainlayout.addWidget(self.groupbox)

        frame01 = QFrame(self)
        child_layout = QVBoxLayout()
        print(self.width())
        label01 = QLabel("链   接", self)
        label02 = QLabel("下载目录", self)
        self.url_lineedit = QLineEdit(self)
        self.dir_lineedit = QLineEdit(self)
        hlayout01 = QHBoxLayout()
        hlayout01.addWidget(label01, 1)
        hlayout01.addWidget(self.url_lineedit, 9)
        hlayout02 = QHBoxLayout()
        hlayout02.addWidget(label02, 1)
        hlayout02.addWidget(self.dir_lineedit, 9)
        child_layout.addLayout(hlayout01)
        child_layout.addLayout(hlayout02)
        child_layout.setContentsMargins(
            5, 0, 5, 0)  #(int left, int top, int right, int bottom)
        frame01.setLayout(child_layout)
        self.download_progressbar = QProgressBar()
        self.download_progressbar.setAlignment(
            QtCore.Qt.Alignment.AlignCenter)  #文字居中
        self.download_progressbar.setValue(88)
        self.download_btn = QPushButton("开始下载")
        self.show_plaintextedit = QPlainTextEdit()
        self.show_plaintextedit.setMinimumHeight(400)
        self.mainlayout.addWidget(frame01)
        self.mainlayout.addWidget(self.download_progressbar)
        self.mainlayout.addWidget(self.download_btn)
        self.mainlayout.addWidget(self.show_plaintextedit)
        self.mainlayout.addStretch()
        ### 设置stylesheet
        self.download_btn.setStyleSheet(
            'QPushButton:pressed{ text-align: center;background-color:red;}')
class SettingsDialog(QDialog):
    def __init__(self):
        """ Dialog to manage the settings of the application """
        super().__init__()
        self.setWindowTitle("Settings")
        self.setFixedSize(310, 250)

        # Create the general settings widgets for managing the text color,
        # text alignment, and author of the app's content
        # NOTE: Altering the default CSS attributes, such as the color, of a
        # widget can change its appearance. Hence, the button may appear
        # rectangular depending upon your platform
        self.text_color_button = QPushButton()
        self.text_color_button.setStyleSheet(
            "background-color: #000000")  # Black
        self.text_color_button.clicked.connect(self.selectTextColor)

        self.align_left = QRadioButton(text="Left")  # Default
        self.align_left.setChecked(True)
        self.align_center = QRadioButton(text="Center")
        self.align_center.setChecked(False)
        self.align_right = QRadioButton(text="Right")
        self.align_right.setChecked(False)

        # Layout and container for alignment radio buttons
        align_v_box = QVBoxLayout()
        align_v_box.setContentsMargins(0, 5, 0, 0)
        align_v_box.addWidget(self.align_left)
        align_v_box.addWidget(self.align_center)
        align_v_box.addWidget(self.align_right)

        align_frame = QFrame()
        align_frame.setFrameShape(QFrame.Shape.NoFrame)
        align_frame.setLayout(align_v_box)

        self.author_name = QLineEdit()
        self.author_name.setMinimumWidth(160)

        self.button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButtons.Ok
            | QDialogButtonBox.StandardButtons.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        dialog_layout = QFormLayout()
        dialog_layout.addRow("<b>Text Color:</b>", self.text_color_button)
        dialog_layout.addRow(HorizontalSeparator())
        dialog_layout.addRow("<b>Text Alignment:</b>", align_frame)
        dialog_layout.addRow(HorizontalSeparator())
        dialog_layout.addRow("<b>Author:</b>", self.author_name)
        dialog_layout.addWidget(self.button_box)
        self.setLayout(dialog_layout)

    def selectTextColor(self):
        """Change the background color of the QPushButton to reflect the
        selected color. This is used to set the text color of the main window's QLineEdit."""
        color = QColorDialog.getColor()  # Returns QColor object
        # Use color.name() to get the color in the format "#RRGGBB"
        self.text_color_button.setStyleSheet(
            f"background-color: {color.name()}")
Exemplo n.º 4
0
    def initGui(self):
        self.setWindowTitle('Selección de vuelo.')
        self.setFixedSize(500, 400)

        self.lbl_seleccion_vuelo = QLabel('Seleccione la clase de su vuelo:',
                                          self)
        self.lbl_seleccion_vuelo.move(50, 70)
        self.lbl_seleccion_vuelo.setFixedWidth(200)

        self.rbtn_1_clase = QRadioButton('Primera Clase.', self)
        self.rbtn_1_clase.move(50, 130)
        self.rbtn_1_clase.setFixedWidth(250)
        self.rbtn_1_clase.toggled.connect(self.seleccionar_clase)

        self.rbtn_2_clase = QRadioButton('Clase Negocios. ', self)
        self.rbtn_2_clase.move(50, 160)
        self.rbtn_2_clase.setFixedWidth(250)
        self.rbtn_2_clase.toggled.connect(self.seleccionar_clase)

        self.rbtn_3_clase = QRadioButton('Clase Económica.', self)
        self.rbtn_3_clase.move(50, 190)
        self.rbtn_3_clase.setFixedWidth(250)
        self.rbtn_3_clase.toggled.connect(self.seleccionar_clase)

        self.lbl_resultado_titulo = QLabel('Resultado:', self)
        self.lbl_resultado_titulo.move(50, 250)

        self.lbl_resultado = QLabel(self)
        self.lbl_resultado.move(50, 280)
        self.lbl_resultado.setFixedWidth(400)
Exemplo n.º 5
0
    def enterQuestionCodePageUI(self):
        layout = QFormLayout()

        self.enterQuestionCodePage.currPlayerTurnDisplay = QLabel()
        layout.addRow(self.enterQuestionCodePage.currPlayerTurnDisplay)

        enterColorLayout = QFormLayout()
        enterColorButtonGroup = QButtonGroup(self.enterQuestionCodePage)
        self.enterQuestionCodePage.yellowRadio = QRadioButton()
        self.enterQuestionCodePage.blueRadio = QRadioButton()
        self.enterQuestionCodePage.redRadio = QRadioButton()
        self.enterQuestionCodePage.yellowRadio.toggled.connect(
            self.enterColorRadioToggle)
        self.enterQuestionCodePage.blueRadio.toggled.connect(
            self.enterColorRadioToggle)
        self.enterQuestionCodePage.redRadio.toggled.connect(
            self.enterColorRadioToggle)
        enterColorButtonGroup.addButton(self.enterQuestionCodePage.yellowRadio)
        enterColorButtonGroup.addButton(self.enterQuestionCodePage.blueRadio)
        enterColorButtonGroup.addButton(self.enterQuestionCodePage.redRadio)
        enterColorLayout.addRow("Yellow",
                                self.enterQuestionCodePage.yellowRadio)
        enterColorLayout.addRow("Blue", self.enterQuestionCodePage.blueRadio)
        enterColorLayout.addRow("Red", self.enterQuestionCodePage.redRadio)

        combLayout = QHBoxLayout()
        combLayout.addLayout(enterColorLayout)
        layout.addRow(combLayout)

        self.enterQuestionCodePage.submitQuestionCodeButton = QPushButton(
            "&Submit Code!")
        self.enterQuestionCodePage.submitQuestionCodeButton.clicked.connect(
            self.submitQuestionCode)
        layout.addRow(self.enterQuestionCodePage.submitQuestionCodeButton)

        self.enterQuestionCodePage.setLayout(layout)
Exemplo n.º 6
0
    def __init__(self):
        super(Window, self).__init__()

        self.groupBox = QGroupBox("What is your favorite sport ?")
        self.radiobtn3 = QRadioButton("BasketBall")
        self.radiobtn3.setIcon(QIcon(""))
        self.radiobtn2 = QRadioButton("Swimming")
        self.radiobtn2.setIcon(QIcon(""))
        self.radiobtn1 = QRadioButton("FootBall")
        self.radiobtn1.setIcon(QIcon(""))

        self.label = QLabel("You Have Selected FootBall")
        self.title = " "
        self.left = 100
        self.top = 200
        self.width = 400
        self.height = 300

        self.InitWindow()
Exemplo n.º 7
0
class Services(QWidget):
    def __init__(self, parent, top):
        super(QWidget, self).__init__(parent)
        self.top = top
        hlayout = QHBoxLayout()
        self.layout = QGridLayout()
        hlayout.addLayout(self.layout)
        hlayout.setAlignment(hlayout, Qt.Alignment.AlignTop)
        self.setLayout(hlayout)
        self.row = 0

        self.__addLabel__("Gateway Services")
        self.__addLabel__("Gateway Host Name/IP Address")
        self.gatewayHostName = QLineEdit(self)
        self.__addInput__(self.gatewayHostName)

        self.__addLabel__("Exercise Data Server Host Name/IP Address")
        self.productionEDS = QLineEdit(self)
        self.prodEnable = QRadioButton("Production")
        self.prodEnable.setChecked(True)
        self.prodEnable.toggled.connect(self.radioProdClicked)
        self.prodEnable.setStyleSheet("QRadioButton{ width: 100; }")
        self.__addInputAndRadio__(self.productionEDS, self.prodEnable)
        self.testEDS = QLineEdit(self)
        self.testEnable = QRadioButton("Test")
        self.testEnable.toggled.connect(self.radioTestClicked)
        self.testEnable.setStyleSheet("QRadioButton{ width: 100; }")
        self.__addInputAndRadio__(self.testEDS, self.testEnable)

        self.__addLabel__("Messaging Port")
        self.messagePort = QLineEdit("61616")
        self.__addInput__(self.messagePort)

    def radioProdClicked(self):
        if self.sender().isChecked():
            self.testEnable.setChecked(False)

    def radioTestClicked(self):
        if self.sender().isChecked():
            self.prodEnable.setChecked(False)

    def __addLabel__(self, label):
        lbl = QLabel(label)
        self.layout.addWidget(lbl, self.row, 0, 1, -1)
        self.row += 1

    def __addInput__(self, input):
        self.layout.addWidget(input, self.row, 0, 1, 4)
        self.row += 1

    def __addInputAndRadio__(self, input, radio):
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 0)
        hbox.addWidget(input)
        hbox.addWidget(radio)
        widget = QWidget(self)
        widget.setLayout(hbox)
        self.layout.addWidget(widget, self.row, 0, 1, -1)
        self.row += 1

    def tabName(self):
        return 'Services'
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        # region Create CartPole instance and load initial settings

        # Create CartPole instance
        self.initial_state = create_cartpole_state()
        self.CartPoleInstance = CartPole(initial_state=self.initial_state)

        # Set timescales
        self.CartPoleInstance.dt_simulation = dt_simulation
        self.CartPoleInstance.dt_controller = controller_update_interval
        self.CartPoleInstance.dt_save = save_interval

        # set other settings
        self.CartPoleInstance.set_controller(controller_init)
        self.CartPoleInstance.stop_at_90 = stop_at_90_init
        self.set_random_experiment_generator_init_params()

        # endregion

        # region Decide whether to save the data in "CartPole memory" or not
        self.save_history = save_history_init
        self.show_experiment_summary = show_experiment_summary_init
        if self.save_history or self.show_experiment_summary:
            self.CartPoleInstance.save_data_in_cart = True
        else:
            self.CartPoleInstance.save_data_in_cart = False

        # endregion

        # region Other variables initial values as provided in gui_default_parameters.py

        # Start user controlled experiment/ start random experiment/ load and replay - on start button
        self.simulator_mode = simulator_mode_init
        self.slider_on_click = slider_on_click_init  # Update slider on click/update slider while hoovering over it
        self.speedup = speedup_init  # Default simulation speed-up

        # endregion

        # region Initialize loop-timer
        # This timer allows to relate the simulation time to user time
        # And (if your computer is fast enough) run simulation
        # slower or faster than real-time by predefined factor (speedup)
        self.looper = loop_timer(
            dt_target=(self.CartPoleInstance.dt_simulation / self.speedup))
        # endregion

        # region Variables controlling the state of various processes (DO NOT MODIFY)

        self.terminate_experiment_or_replay_thread = False  # True: gives signal causing thread to terminate
        self.pause_experiment_or_replay_thread = False  # True: gives signal causing the thread to pause

        self.run_set_labels_thread = True  # True if gauges (labels) keep being repeatedly updated
        # Stop threads by setting False

        # Flag indicating if the "START! / STOP!" button should act as start or as stop when pressed.
        # Can take values "START!" or "STOP!"
        self.start_or_stop_action = "START!"
        # Flag indicating whether the pause button should pause or unpause.
        self.pause_or_unpause_action = "PAUSE"

        # Flag indicating that saving of experiment recording to csv file has finished
        self.experiment_or_replay_thread_terminated = False

        self.user_time_counter = 0  # Measures the user time

        # Slider instant value (which is draw in GUI) differs from value saved in CartPole instance
        # if the option updating slider "on-click" is enabled.
        self.slider_instant_value = self.CartPoleInstance.slider_value

        self.noise = 'OFF'
        self.CartPoleInstance.NoiseAdderInstance.noise_mode = self.noise

        # endregion

        # region Create GUI Layout

        # region - Create container for top level layout
        layout = QVBoxLayout()
        # endregion

        # region - Change geometry of the main window
        self.setGeometry(300, 300, 2500, 1000)
        # endregion

        # region - Matplotlib figures (CartPole drawing and Slider)
        # Draw Figure
        self.fig = Figure(
            figsize=(25, 10)
        )  # Regulates the size of Figure in inches, before scaling to window size.
        self.canvas = FigureCanvas(self.fig)
        self.fig.AxCart = self.canvas.figure.add_subplot(211)
        self.fig.AxSlider = self.canvas.figure.add_subplot(212)
        self.fig.AxSlider.set_ylim(0, 1)

        self.CartPoleInstance.draw_constant_elements(self.fig, self.fig.AxCart,
                                                     self.fig.AxSlider)

        # Attach figure to the layout
        lf = QVBoxLayout()
        lf.addWidget(self.canvas)

        # endregion

        # region - Radio buttons selecting current controller
        self.rbs_controllers = []
        for controller_name in self.CartPoleInstance.controller_names:
            self.rbs_controllers.append(QRadioButton(controller_name))

        # Ensures that radio buttons are exclusive
        self.controllers_buttons_group = QButtonGroup()
        for button in self.rbs_controllers:
            self.controllers_buttons_group.addButton(button)

        lr_c = QVBoxLayout()
        lr_c.addStretch(1)
        for rb in self.rbs_controllers:
            rb.clicked.connect(self.RadioButtons_controller_selection)
            lr_c.addWidget(rb)
        lr_c.addStretch(1)

        self.rbs_controllers[self.CartPoleInstance.controller_idx].setChecked(
            True)

        # endregion

        # region - Create central part of the layout for figures and radio buttons and add it to the whole layout
        lc = QHBoxLayout()
        lc.addLayout(lf)
        lc.addLayout(lr_c)
        layout.addLayout(lc)

        # endregion

        # region - Gauges displaying current values of various states and parameters (time, velocity, angle,...)

        # First row
        ld = QHBoxLayout()
        # User time
        self.labTime = QLabel("User's time (s): ")
        self.timer = QTimer()
        self.timer.setInterval(100)  # Tick every 1/10 of the second
        self.timer.timeout.connect(self.set_user_time_label)
        self.timer.start()
        ld.addWidget(self.labTime)
        # Speed, angle, motor power (Q)
        self.labSpeed = QLabel('Speed (m/s):')
        self.labAngle = QLabel('Angle (deg):')
        self.labMotor = QLabel('')
        self.labTargetPosition = QLabel('')
        ld.addWidget(self.labSpeed)
        ld.addWidget(self.labAngle)
        ld.addWidget(self.labMotor)
        ld.addWidget(self.labTargetPosition)
        layout.addLayout(ld)

        # Second row of labels
        # Simulation time, Measured (real) speed-up, slider-value
        ld2 = QHBoxLayout()
        self.labTimeSim = QLabel('Simulation Time (s):')
        ld2.addWidget(self.labTimeSim)
        self.labSpeedUp = QLabel('Speed-up (measured):')
        ld2.addWidget(self.labSpeedUp)
        self.labSliderInstant = QLabel('')
        ld2.addWidget(self.labSliderInstant)
        layout.addLayout(ld2)

        # endregion

        # region - Buttons "START!" / "STOP!", "PAUSE", "QUIT"
        self.bss = QPushButton("START!")
        self.bss.pressed.connect(self.start_stop_button)
        self.bp = QPushButton("PAUSE")
        self.bp.pressed.connect(self.pause_unpause_button)
        bq = QPushButton("QUIT")
        bq.pressed.connect(self.quit_application)
        lspb = QHBoxLayout()  # Sub-Layout for Start/Stop and Pause Buttons
        lspb.addWidget(self.bss)
        lspb.addWidget(self.bp)

        # endregion

        # region - Sliders setting initial state and buttons for kicking the pole

        # Sliders setting initial position and angle
        lb = QVBoxLayout()  # Layout for buttons
        lb.addLayout(lspb)
        lb.addWidget(bq)
        ip = QHBoxLayout()  # Layout for initial position sliders
        self.initial_position_slider = QSlider(
            orientation=Qt.Orientation.Horizontal)
        self.initial_position_slider.setRange(
            -int(float(1000 * TrackHalfLength)),
            int(float(1000 * TrackHalfLength)))
        self.initial_position_slider.setValue(0)
        self.initial_position_slider.setSingleStep(1)
        self.initial_position_slider.valueChanged.connect(
            self.update_initial_position)
        self.initial_angle_slider = QSlider(
            orientation=Qt.Orientation.Horizontal)
        self.initial_angle_slider.setRange(-int(float(100 * np.pi)),
                                           int(float(100 * np.pi)))
        self.initial_angle_slider.setValue(0)
        self.initial_angle_slider.setSingleStep(1)
        self.initial_angle_slider.valueChanged.connect(
            self.update_initial_angle)
        ip.addWidget(QLabel("Initial position:"))
        ip.addWidget(self.initial_position_slider)
        ip.addWidget(QLabel("Initial angle:"))
        ip.addWidget(self.initial_angle_slider)
        ip.addStretch(0.01)

        # Slider setting latency
        self.LATENCY_SLIDER_RANGE_INT = 1000
        self.latency_slider = QSlider(orientation=Qt.Orientation.Horizontal)
        self.latency_slider.setRange(0, self.LATENCY_SLIDER_RANGE_INT)
        self.latency_slider.setValue(
            int(self.CartPoleInstance.LatencyAdderInstance.latency *
                self.LATENCY_SLIDER_RANGE_INT /
                self.CartPoleInstance.LatencyAdderInstance.max_latency))
        self.latency_slider.setSingleStep(1)
        self.latency_slider.valueChanged.connect(self.update_latency)
        ip.addWidget(QLabel("Latency:"))
        ip.addWidget(self.latency_slider)
        self.labLatency = QLabel('Latency (ms): {:.1f}'.format(
            self.CartPoleInstance.LatencyAdderInstance.latency * 1000))
        ip.addWidget(self.labLatency)

        # Buttons activating noise
        self.rbs_noise = []
        for mode_name in ['ON', 'OFF']:
            self.rbs_noise.append(QRadioButton(mode_name))

        # Ensures that radio buttons are exclusive
        self.noise_buttons_group = QButtonGroup()
        for button in self.rbs_noise:
            self.noise_buttons_group.addButton(button)

        lr_n = QHBoxLayout()
        lr_n.addWidget(QLabel('Noise:'))
        for rb in self.rbs_noise:
            rb.clicked.connect(self.RadioButtons_noise_on_off)
            lr_n.addWidget(rb)

        self.rbs_noise[1].setChecked(True)

        ip.addStretch(0.01)
        ip.addLayout(lr_n)
        ip.addStretch(0.01)

        # Buttons giving kick to the pole
        kick_label = QLabel("Kick pole:")
        kick_left_button = QPushButton()
        kick_left_button.setText("Left")
        kick_left_button.adjustSize()
        kick_left_button.clicked.connect(self.kick_pole)
        kick_right_button = QPushButton()
        kick_right_button.setText("Right")
        kick_right_button.adjustSize()
        kick_right_button.clicked.connect(self.kick_pole)
        ip.addWidget(kick_label)
        ip.addWidget(kick_left_button)
        ip.addWidget(kick_right_button)

        lb.addLayout(ip)
        layout.addLayout(lb)

        # endregion

        # region - Text boxes and Combobox to provide settings concerning generation of random experiment
        l_generate_trace = QHBoxLayout()
        l_generate_trace.addWidget(QLabel('Random experiment settings:'))
        l_generate_trace.addWidget(QLabel('Length (s):'))
        self.textbox_length = QLineEdit()
        l_generate_trace.addWidget(self.textbox_length)
        l_generate_trace.addWidget(QLabel('Turning Points (m):'))
        self.textbox_turning_points = QLineEdit()
        l_generate_trace.addWidget(self.textbox_turning_points)
        l_generate_trace.addWidget(QLabel('Interpolation:'))
        self.cb_interpolation = QComboBox()
        self.cb_interpolation.addItems(
            ['0-derivative-smooth', 'linear', 'previous'])
        self.cb_interpolation.currentIndexChanged.connect(
            self.cb_interpolation_selectionchange)
        self.cb_interpolation.setCurrentText(
            self.CartPoleInstance.interpolation_type)
        l_generate_trace.addWidget(self.cb_interpolation)

        layout.addLayout(l_generate_trace)

        # endregion

        # region - Textbox to provide csv file name for saving or loading data
        l_text = QHBoxLayout()
        textbox_title = QLabel('CSV file name:')
        self.textbox = QLineEdit()
        l_text.addWidget(textbox_title)
        l_text.addWidget(self.textbox)
        layout.addLayout(l_text)

        # endregion

        # region - Make strip of layout for checkboxes
        l_cb = QHBoxLayout()
        # endregion

        # region - Textbox to provide the target speed-up value
        l_text_speedup = QHBoxLayout()
        tx_speedup_title = QLabel('Speed-up (target):')
        self.tx_speedup = QLineEdit()
        l_text_speedup.addWidget(tx_speedup_title)
        l_text_speedup.addWidget(self.tx_speedup)
        self.tx_speedup.setText(str(self.speedup))
        l_cb.addLayout(l_text_speedup)

        self.wrong_speedup_msg = QMessageBox()
        self.wrong_speedup_msg.setWindowTitle("Speed-up value problem")
        self.wrong_speedup_msg.setIcon(QMessageBox.Icon.Critical)
        # endregion

        # region - Checkboxes

        # region -- Checkbox: Save/don't save experiment recording
        self.cb_save_history = QCheckBox('Save results', self)
        if self.save_history:
            self.cb_save_history.toggle()
        self.cb_save_history.toggled.connect(self.cb_save_history_f)
        l_cb.addWidget(self.cb_save_history)
        # endregion

        # region -- Checkbox: Display plots showing dynamic evolution of the system as soon as experiment terminates
        self.cb_show_experiment_summary = QCheckBox('Show experiment summary',
                                                    self)
        if self.show_experiment_summary:
            self.cb_show_experiment_summary.toggle()
        self.cb_show_experiment_summary.toggled.connect(
            self.cb_show_experiment_summary_f)
        l_cb.addWidget(self.cb_show_experiment_summary)
        # endregion

        # region -- Checkbox: Block pole if it reaches +/-90 deg
        self.cb_stop_at_90_deg = QCheckBox('Stop-at-90-deg', self)
        if self.CartPoleInstance.stop_at_90:
            self.cb_stop_at_90_deg.toggle()
        self.cb_stop_at_90_deg.toggled.connect(self.cb_stop_at_90_deg_f)
        l_cb.addWidget(self.cb_stop_at_90_deg)
        # endregion

        # region -- Checkbox: Update slider on click/update slider while hoovering over it
        self.cb_slider_on_click = QCheckBox('Update slider on click', self)
        if self.slider_on_click:
            self.cb_slider_on_click.toggle()
        self.cb_slider_on_click.toggled.connect(self.cb_slider_on_click_f)
        l_cb.addWidget(self.cb_slider_on_click)

        # endregion

        # endregion

        # region - Radio buttons selecting simulator mode: user defined experiment, random experiment, replay

        # List available simulator modes - constant
        self.available_simulator_modes = [
            'Slider-Controlled Experiment', 'Random Experiment', 'Replay'
        ]
        self.rbs_simulator_mode = []
        for mode_name in self.available_simulator_modes:
            self.rbs_simulator_mode.append(QRadioButton(mode_name))

        # Ensures that radio buttons are exclusive
        self.simulator_mode_buttons_group = QButtonGroup()
        for button in self.rbs_simulator_mode:
            self.simulator_mode_buttons_group.addButton(button)

        lr_sm = QHBoxLayout()
        lr_sm.addStretch(1)
        lr_sm.addWidget(QLabel('Simulator mode:'))
        for rb in self.rbs_simulator_mode:
            rb.clicked.connect(self.RadioButtons_simulator_mode)
            lr_sm.addWidget(rb)
        lr_sm.addStretch(1)

        self.rbs_simulator_mode[self.available_simulator_modes.index(
            self.simulator_mode)].setChecked(True)

        l_cb.addStretch(1)
        l_cb.addLayout(lr_sm)
        l_cb.addStretch(1)

        # endregion

        # region - Add checkboxes to layout
        layout.addLayout(l_cb)
        # endregion

        # region - Create an instance of a GUI window
        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)
        self.show()
        self.setWindowTitle('CartPole Simulator')

        # endregion

        # endregion

        # region Open controller-specific popup windows
        self.open_additional_controller_widget()
        # endregion

        # region Activate functions capturing mouse movements and clicks over the slider

        # This line links function capturing the mouse position on the canvas of the Figure
        self.canvas.mpl_connect("motion_notify_event", self.on_mouse_movement)
        # This line links function capturing the mouse position on the canvas of the Figure click
        self.canvas.mpl_connect("button_press_event", self.on_mouse_click)

        # endregion

        # region Introducing multithreading
        # To ensure smooth functioning of the app,
        # the calculations and redrawing of the figures have to be done in a different thread
        # than the one capturing the mouse position and running the animation
        self.threadpool = QThreadPool()
        # endregion

        # region Starts a thread repeatedly redrawing gauges (labels) of the GUI
        # It runs till the QUIT button is pressed
        worker_labels = Worker(self.set_labels_thread)
        self.threadpool.start(worker_labels)
        # endregion

        # region Start animation repeatedly redrawing changing elements of matplotlib figures (CartPole drawing and slider)
        # This animation runs ALWAYS when the GUI is open
        # The buttons of GUI only decide if new parameters are calculated or not
        self.anim = self.CartPoleInstance.run_animation(self.fig)
Exemplo n.º 9
0
class Window(QDialog):
    def __init__(self):
        super(Window, self).__init__()

        self.groupBox = QGroupBox("What is your favorite sport ?")
        self.radiobtn3 = QRadioButton("BasketBall")
        self.radiobtn3.setIcon(QIcon(""))
        self.radiobtn2 = QRadioButton("Swimming")
        self.radiobtn2.setIcon(QIcon(""))
        self.radiobtn1 = QRadioButton("FootBall")
        self.radiobtn1.setIcon(QIcon(""))

        self.label = QLabel("You Have Selected FootBall")
        self.title = " "
        self.left = 100
        self.top = 200
        self.width = 400
        self.height = 300

        self.InitWindow()

    def InitWindow(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.radioButton()

        vbox = QVBoxLayout()
        vbox.addWidget(self.groupBox)
        vbox.addWidget(self.label)
        self.setLayout(vbox)

        self.show()

    def radioButton(self):
        hbox = QHBoxLayout()

        self.radiobtn1.setChecked(True)
        self.radiobtn1.toggled.connect(self.OnRadioButton)
        hbox.addWidget(self.radiobtn1)

        self.radiobtn2.setChecked(False)
        self.radiobtn2.toggled.connect(self.OnRadioButton)
        hbox.addWidget(self.radiobtn2)

        self.radiobtn3.setChecked(False)
        self.radiobtn2.toggled.connect(self.OnRadioButton)
        hbox.addWidget(self.radiobtn3)

        self.groupBox.setLayout(hbox)

    def OnRadioButton(self):
        # Which radioBtn send message
        radioBtn = self.sender()

        if radioBtn.isChecked():
            self.label.setText("You Have Selected " + radioBtn.text())
Exemplo n.º 10
0
class ventanaPrincipal(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.initGui()

    def initGui(self):
        self.setWindowTitle('Selección de vuelo.')
        self.setFixedSize(500, 400)

        self.lbl_seleccion_vuelo = QLabel('Seleccione la clase de su vuelo:',
                                          self)
        self.lbl_seleccion_vuelo.move(50, 70)
        self.lbl_seleccion_vuelo.setFixedWidth(200)

        self.rbtn_1_clase = QRadioButton('Primera Clase.', self)
        self.rbtn_1_clase.move(50, 130)
        self.rbtn_1_clase.setFixedWidth(250)
        self.rbtn_1_clase.toggled.connect(self.seleccionar_clase)

        self.rbtn_2_clase = QRadioButton('Clase Negocios. ', self)
        self.rbtn_2_clase.move(50, 160)
        self.rbtn_2_clase.setFixedWidth(250)
        self.rbtn_2_clase.toggled.connect(self.seleccionar_clase)

        self.rbtn_3_clase = QRadioButton('Clase Económica.', self)
        self.rbtn_3_clase.move(50, 190)
        self.rbtn_3_clase.setFixedWidth(250)
        self.rbtn_3_clase.toggled.connect(self.seleccionar_clase)

        self.lbl_resultado_titulo = QLabel('Resultado:', self)
        self.lbl_resultado_titulo.move(50, 250)

        self.lbl_resultado = QLabel(self)
        self.lbl_resultado.move(50, 280)
        self.lbl_resultado.setFixedWidth(400)

    def seleccionar_clase(self):
        costo_vuelo = 0
        clase = ''

        if self.rbtn_1_clase.isChecked():
            costo_vuelo = '2.000.0'
            clase = 'Primera Clase'
        elif self.rbtn_2_clase.isChecked():
            costo_vuelo = '1.500.0'
            clase = 'Clase de Negocios'
        elif self.rbtn_3_clase.isChecked():
            costo_vuelo = '1.000.0'
            clase = 'Clase Económica'

        self.lbl_resultado.setText(
            f'El costo de su tiquete de {clase}, es de USD ${costo_vuelo}')
    def __init__(self):
        super(MPPIOptionsWindow, self).__init__()

        self.horizon_steps = controller_mppi.mpc_samples
        self.num_rollouts = controller_mppi.num_rollouts
        self.dd_weight = controller_mppi.dd_weight
        self.ep_weight = controller_mppi.ep_weight
        self.ekp_weight = controller_mppi.ekp_weight * 1.0e1
        self.ekc_weight = controller_mppi.ekc_weight * 1.0e-1
        self.cc_weight = controller_mppi.cc_weight * 1.0e-2
        self.ccrc_weight = controller_mppi.ccrc_weight * 1.0e-2
        self.R = controller_mppi.R  # How much to punish Q
        self.LBD = controller_mppi.LBD  # Cost parameter lambda
        self.NU = controller_mppi.NU  # Exploration variance

        layout = QVBoxLayout()

        ### Set Horizon Length
        horizon_options_layout = QVBoxLayout()

        self.horizon_label = QLabel("")
        self.horizon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        horizon_options_layout.addWidget(self.horizon_label)

        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(10, 300)
        slider.setValue(self.horizon_steps)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(10)
        slider.setSingleStep(10)
        horizon_options_layout.addWidget(slider)

        slider.valueChanged.connect(self.horizon_length_changed)

        ### Set Number of Rollouts
        rollouts_options_layout = QVBoxLayout()

        self.rollouts_label = QLabel("")
        self.rollouts_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        rollouts_options_layout.addWidget(self.rollouts_label)

        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(10, 3000)
        slider.setValue(self.num_rollouts)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(10)
        slider.setSingleStep(10)
        rollouts_options_layout.addWidget(slider)

        slider.valueChanged.connect(self.num_rollouts_changed)

        ### Set Cost Weights
        cost_weight_layout = QVBoxLayout()

        # Distance difference cost
        self.dd_weight_label = QLabel("")
        self.dd_weight_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.dd_weight_label)
        self.dd_label = QLabel("")
        self.dd_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.dd_label)
        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(0, 990)
        slider.setValue(self.dd_weight)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(10)
        slider.setSingleStep(10)
        cost_weight_layout.addWidget(slider)
        slider.valueChanged.connect(self.dd_weight_changed)

        # Potential energy cost
        self.ep_weight_label = QLabel("")
        self.ep_weight_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ep_weight_label)
        self.ep_label = QLabel("")
        self.ep_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ep_label)
        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(0, 1e5 - 1e3)
        slider.setValue(self.ep_weight)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(1e3)
        slider.setSingleStep(1e3)
        cost_weight_layout.addWidget(slider)
        slider.valueChanged.connect(self.ep_weight_changed)

        # Pole kinetic energy cost
        self.ekp_weight_label = QLabel("")
        self.ekp_weight_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ekp_weight_label)
        self.ekp_label = QLabel("")
        self.ekp_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ekp_label)
        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(0, 99)
        slider.setValue(self.ekp_weight)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(1)
        slider.setSingleStep(1)
        cost_weight_layout.addWidget(slider)
        slider.valueChanged.connect(self.ekp_weight_changed)

        # Cart kinetic energy cost
        self.ekc_weight_label = QLabel("")
        self.ekc_weight_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ekc_weight_label)
        self.ekc_label = QLabel("")
        self.ekc_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ekc_label)
        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(0, 99)
        slider.setValue(self.ekc_weight)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(1)
        slider.setSingleStep(1)
        cost_weight_layout.addWidget(slider)
        slider.valueChanged.connect(self.ekc_weight_changed)

        # Control cost
        self.cc_weight_label = QLabel("")
        self.cc_weight_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.cc_weight_label)
        self.cc_label = QLabel("")
        self.cc_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.cc_label)
        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(0, 99)
        slider.setValue(self.cc_weight)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(1)
        slider.setSingleStep(1)
        cost_weight_layout.addWidget(slider)
        slider.valueChanged.connect(self.cc_weight_changed)

        # Control change rate cost
        self.ccrc_weight_label = QLabel("")
        self.ccrc_weight_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ccrc_weight_label)
        self.ccrc_label = QLabel("")
        self.ccrc_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        cost_weight_layout.addWidget(self.ccrc_label)
        slider = QSlider(orientation=Qt.Orientation.Horizontal)
        slider.setRange(0, 99)
        slider.setValue(self.ccrc_weight)
        slider.setTickPosition(QSlider.TickPosition.TicksBelow)
        slider.setTickInterval(1)
        slider.setSingleStep(1)
        cost_weight_layout.addWidget(slider)
        slider.valueChanged.connect(self.ccrc_weight_changed)

        ### Set some more MPPI constants
        mppi_constants_layout = QVBoxLayout()

        # Quadratic cost penalty R
        textbox = QLineEdit()
        textbox.setText(str(self.R))
        textbox.textChanged.connect(self.R_changed)
        h_layout = QHBoxLayout()
        h_layout.addWidget(QLabel("Quadratic input cost penalty R ="))
        h_layout.addWidget(textbox)
        mppi_constants_layout.addLayout(h_layout)

        # Quadratic cost penalty LBD
        textbox = QLineEdit()
        textbox.setText(str(self.LBD))
        textbox.textChanged.connect(self.LBD_changed)
        h_layout = QHBoxLayout()
        h_layout.addWidget(QLabel("Importance of higher-cost rollouts LBD ="))
        h_layout.addWidget(textbox)
        mppi_constants_layout.addLayout(h_layout)

        # Quadratic cost penalty NU
        textbox = QLineEdit()
        textbox.setText(str(self.NU))
        textbox.textChanged.connect(self.NU_changed)
        h_layout = QHBoxLayout()
        h_layout.addWidget(QLabel("Exploration variance NU ="))
        h_layout.addWidget(textbox)
        mppi_constants_layout.addLayout(h_layout)

        # Sampling type
        h_layout = QHBoxLayout()
        btn1 = QRadioButton("iid")
        if btn1.text() == controller_mppi.SAMPLING_TYPE: btn1.setChecked(True)
        btn1.toggled.connect(lambda: self.toggle_button(btn1))
        h_layout.addWidget(btn1)
        btn2 = QRadioButton("random_walk")
        if btn2.text() == controller_mppi.SAMPLING_TYPE: btn2.setChecked(True)
        btn2.toggled.connect(lambda: self.toggle_button(btn2))
        h_layout.addWidget(btn2)
        btn3 = QRadioButton("uniform")
        if btn3.text() == controller_mppi.SAMPLING_TYPE: btn3.setChecked(True)
        btn3.toggled.connect(lambda: self.toggle_button(btn3))
        h_layout.addWidget(btn3)
        btn4 = QRadioButton("repeated")
        if btn4.text() == controller_mppi.SAMPLING_TYPE: btn4.setChecked(True)
        btn4.toggled.connect(lambda: self.toggle_button(btn4))
        h_layout.addWidget(btn4)
        btn5 = QRadioButton("interpolated")
        if btn5.text() == controller_mppi.SAMPLING_TYPE: btn5.setChecked(True)
        btn5.toggled.connect(lambda: self.toggle_button(btn5))
        h_layout.addWidget(btn5)
        mppi_constants_layout.addWidget(QLabel("Sampling type:"))
        mppi_constants_layout.addLayout(h_layout)

        ### Put together layout
        self.update_labels()
        self.update_slider_labels()
        layout.addLayout(horizon_options_layout)
        layout.addLayout(rollouts_options_layout)
        layout.addLayout(cost_weight_layout)
        layout.addLayout(mppi_constants_layout)

        self.setLayout(layout)
        self.setWindowFlags(self.windowFlags()
                            | Qt.WindowType.WindowStaysOnTopHint)
        self.setGeometry(0, 0, 400, 50)

        self.show()
        self.setWindowTitle("MPPI Options")

        self.timer = QTimer()
        self.timer.timeout.connect(self.update_labels)
        self.timer.start(100)
Exemplo n.º 12
0
    def __init__(self):
        super().__init__()
        self.setFixedSize(800, 410)
        self.setWindowTitle("PyLX16A Servo Testing Software")

        self.port_selection_box = QComboBox(self)
        self.port_selection_box.setFixedSize(200, 27)
        self.port_selection_box.move(30, 65)
        port_selection_box_label = QLabel("Select Port:", self)
        port_selection_box_label.move(30, 35)

        self.port_selection_box_refresh_button = QPushButton("Refresh", self)
        self.port_selection_box_refresh_button.setFixedSize(60, 23)
        self.port_selection_box_refresh_button.move(170, 38)

        self.id_selection_box = QListWidget(self)
        self.id_selection_box.setFixedSize(200, 200)
        self.id_selection_box.move(30, 135)
        id_selection_box_label = QLabel("Connected Servos:", self)
        id_selection_box_label.setFixedWidth(200)
        id_selection_box_label.move(30, 105)

        self.id_selection_box_refresh_button = QPushButton("Refresh", self)
        self.id_selection_box_refresh_button.setFixedSize(60, 23)
        self.id_selection_box_refresh_button.move(170, 108)

        self.set_id_line_edit = QLineEdit(self)
        self.set_id_line_edit.setFixedSize(50, 27)
        self.set_id_line_edit.move(80, 355)
        set_id_line_edit_label = QLabel("Set ID:", self)
        set_id_line_edit_label.move(30, 355)
        set_id_line_edit_label.setFixedSize(50, 27)

        self.set_id_button = QPushButton("Change ID!", self)
        self.set_id_button.setFixedSize(85, 27)
        self.set_id_button.move(145, 355)

        self.position_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.position_slider.setMinimum(0)
        self.position_slider.setMaximum(240)
        self.position_slider.setFixedWidth(200)
        self.position_slider.move(300, 55)
        self.position_slider_readout = QLabel("0.00°", self)
        self.position_slider_readout.setFixedWidth(50)
        self.position_slider_readout.move(450, 30)
        self.position_slider_readout.setAlignment(
            Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        position_slider_label = QLabel("Angle (degrees):", self)
        position_slider_label.move(300, 30)

        self.position_offset_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.position_offset_slider.setMinimum(-30)
        self.position_offset_slider.setMaximum(30)
        self.position_offset_slider.setFixedWidth(200)
        self.position_offset_slider.move(300, 125)
        self.position_offset_slider_readout = QLabel("0.00°", self)
        self.position_offset_slider_readout.setFixedWidth(50)
        self.position_offset_slider_readout.move(450, 100)
        self.position_offset_slider_readout.setAlignment(
            Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        position_offset_slider_label = QLabel("Angle offset (degrees):", self)
        position_offset_slider_label.setFixedWidth(200)
        position_offset_slider_label.move(300, 100)

        self.angle_lower_limit_textentry = QLineEdit(self)
        self.angle_lower_limit_textentry.setFixedWidth(50)
        self.angle_lower_limit_textentry.move(450, 175)
        self.angle_lower_limit_textentry.setValidator(
            QIntValidator(0, 240, self))
        self.angle_upper_limit_textentry = QLineEdit(self)
        self.angle_upper_limit_textentry.setFixedWidth(50)
        self.angle_upper_limit_textentry.move(450, 210)
        self.angle_upper_limit_textentry.setValidator(
            QIntValidator(0, 240, self))
        self.angle_lower_limit_textentry_label = QLabel(
            "Lower Limit (degrees):", self)
        self.angle_lower_limit_textentry_label.move(300, 175)
        self.angle_lower_limit_textentry_label.setFixedWidth(150)
        self.angle_upper_limit_textentry_label = QLabel(
            "Upper Limit (degrees):", self)
        self.angle_upper_limit_textentry_label.move(300, 210)
        self.angle_upper_limit_textentry_label.setFixedWidth(150)

        self.vin_lower_limit_textentry = QLineEdit(self)
        self.vin_lower_limit_textentry.setFixedWidth(50)
        self.vin_lower_limit_textentry.move(450, 265)
        self.vin_lower_limit_textentry.setValidator(
            QIntValidator(4500, 12000, self))
        self.vin_upper_limit_textentry = QLineEdit(self)
        self.vin_upper_limit_textentry.setFixedWidth(50)
        self.vin_upper_limit_textentry.move(450, 300)
        self.vin_upper_limit_textentry.setValidator(
            QIntValidator(4500, 12000, self))
        self.vin_lower_limit_textentry_label = QLabel(
            "Voltage Lower Limit (mV):", self)
        self.vin_lower_limit_textentry_label.move(300, 265)
        self.vin_lower_limit_textentry_label.setFixedWidth(150)
        self.vin_upper_limit_textentry_label = QLabel(
            "Voltage Upper Limit (mV):", self)
        self.vin_upper_limit_textentry_label.move(300, 300)
        self.vin_upper_limit_textentry_label.setFixedWidth(150)

        self.temp_limit_textentry = QLineEdit(self)
        self.temp_limit_textentry.setFixedWidth(50)
        self.temp_limit_textentry.move(450, 355)
        self.temp_limit_textentry.setValidator(QIntValidator(50, 100, self))
        self.temp_limit_textentry_label = QLabel("Temp Limit (°C):", self)
        self.temp_limit_textentry_label.move(300, 355)
        self.temp_limit_textentry_label.setFixedWidth(150)

        self.servo_mode_radio_button = QRadioButton("Servo Mode", self)
        self.servo_mode_radio_button.move(565, 50)
        self.motor_mode_radio_button = QRadioButton("Motor Mode", self)
        self.motor_mode_radio_button.move(565, 75)

        self.motor_speed_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.motor_speed_slider.setMinimum(-1000)
        self.motor_speed_slider.setMaximum(1000)
        self.motor_speed_slider.setFixedWidth(200)
        self.motor_speed_slider.move(565, 125)
        motor_speed_slider_label = QLabel("Motor Speed:", self)
        motor_speed_slider_label.move(565, 100)

        self.torque_enabled_checkbox = QCheckBox("Torque Enabled", self)
        self.torque_enabled_checkbox.move(565, 175)
        self.torque_enabled_checkbox.setFixedWidth(200)

        self.led_enabled_checkbox = QCheckBox("LED Enabled", self)
        self.led_enabled_checkbox.move(565, 210)
        self.led_enabled_checkbox.setFixedWidth(200)

        self.led_over_temp_checkbox = QCheckBox("LED Over Temperature", self)
        self.led_over_temp_checkbox.move(565, 258)
        self.led_over_temp_checkbox.setFixedWidth(200)
        self.led_over_voltage_checkbox = QCheckBox("LED Over Voltage", self)
        self.led_over_voltage_checkbox.move(565, 283)
        self.led_over_voltage_checkbox.setFixedWidth(200)
        self.led_rotor_locked_checkbox = QCheckBox("LED Rotor Locked", self)
        self.led_rotor_locked_checkbox.move(565, 308)
        self.led_rotor_locked_checkbox.setFixedWidth(200)

        self.physical_position_readout = QLabel("--°", self)
        self.physical_position_readout.move(565, 367)
        self.physical_position_readout.setFixedWidth(200)
        self.physical_position_readout_label = QLabel("Position", self)
        self.physical_position_readout_label.move(565, 347)

        self.temperature_readout = QLabel("-- °C", self)
        self.temperature_readout.move(635, 367)
        self.temperature_readout.setFixedWidth(200)
        self.temperature_readout_label = QLabel("Temperature", self)
        self.temperature_readout_label.move(635, 347)

        self.voltage_readout = QLabel("-- V", self)
        self.voltage_readout.move(730, 367)
        self.voltage_readout.setFixedWidth(200)
        self.voltage_readout_label = QLabel("Voltage", self)
        self.voltage_readout_label.move(730, 347)

        self.readout_update_timer = QTimer(self)
        self.readout_update_timer.timeout.connect(self.update_readouts)
        self.readout_update_timer.start(250)

        self.active_servo: LX16A = None

        self.position_slider.setValue(0)
        self.position_offset_slider.setValue(0)
        self.motor_speed_slider.setValue(0)
        self.id_selection_box_refresh_button.setEnabled(False)
        self.disable_widgets()

        self.port_selection_box.currentTextChanged.connect(
            self.port_selection_box_changed)
        self.port_selection_box_refresh_button.clicked.connect(
            self.port_refresh_button_clicked)
        self.id_selection_box.currentTextChanged.connect(
            self.id_selection_box_changed)
        self.id_selection_box_refresh_button.clicked.connect(
            self.id_refresh_button_clicked)
        self.set_id_button.pressed.connect(self.id_updated)
        self.position_slider.sliderMoved.connect(self.position_slider_updated)
        self.position_offset_slider.sliderMoved.connect(
            self.position_offset_slider_updated)
        self.angle_lower_limit_textentry.textChanged.connect(
            self.angle_lower_limit_updated)
        self.angle_upper_limit_textentry.textChanged.connect(
            self.angle_upper_limit_updated)
        self.vin_lower_limit_textentry.textChanged.connect(
            self.vin_lower_limit_updated)
        self.vin_upper_limit_textentry.textChanged.connect(
            self.vin_upper_limit_updated)
        self.temp_limit_textentry.textChanged.connect(self.temp_limit_updated)
        self.servo_mode_radio_button.toggled.connect(
            self.servo_mode_radio_button_toggled)
        self.motor_mode_radio_button.toggled.connect(
            self.motor_mode_radio_button_toggled)
        self.motor_speed_slider.valueChanged.connect(
            self.motor_speed_slider_updated)
        self.torque_enabled_checkbox.stateChanged.connect(
            self.torque_enabled_checkbox_toggled)
        self.led_enabled_checkbox.stateChanged.connect(
            self.led_enabled_checkbox_toggled)
        self.led_over_temp_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)
        self.led_over_voltage_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)
        self.led_rotor_locked_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)

        self.scan_for_ports()
Exemplo n.º 13
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(800, 410)
        self.setWindowTitle("PyLX16A Servo Testing Software")

        self.port_selection_box = QComboBox(self)
        self.port_selection_box.setFixedSize(200, 27)
        self.port_selection_box.move(30, 65)
        port_selection_box_label = QLabel("Select Port:", self)
        port_selection_box_label.move(30, 35)

        self.port_selection_box_refresh_button = QPushButton("Refresh", self)
        self.port_selection_box_refresh_button.setFixedSize(60, 23)
        self.port_selection_box_refresh_button.move(170, 38)

        self.id_selection_box = QListWidget(self)
        self.id_selection_box.setFixedSize(200, 200)
        self.id_selection_box.move(30, 135)
        id_selection_box_label = QLabel("Connected Servos:", self)
        id_selection_box_label.setFixedWidth(200)
        id_selection_box_label.move(30, 105)

        self.id_selection_box_refresh_button = QPushButton("Refresh", self)
        self.id_selection_box_refresh_button.setFixedSize(60, 23)
        self.id_selection_box_refresh_button.move(170, 108)

        self.set_id_line_edit = QLineEdit(self)
        self.set_id_line_edit.setFixedSize(50, 27)
        self.set_id_line_edit.move(80, 355)
        set_id_line_edit_label = QLabel("Set ID:", self)
        set_id_line_edit_label.move(30, 355)
        set_id_line_edit_label.setFixedSize(50, 27)

        self.set_id_button = QPushButton("Change ID!", self)
        self.set_id_button.setFixedSize(85, 27)
        self.set_id_button.move(145, 355)

        self.position_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.position_slider.setMinimum(0)
        self.position_slider.setMaximum(240)
        self.position_slider.setFixedWidth(200)
        self.position_slider.move(300, 55)
        self.position_slider_readout = QLabel("0.00°", self)
        self.position_slider_readout.setFixedWidth(50)
        self.position_slider_readout.move(450, 30)
        self.position_slider_readout.setAlignment(
            Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        position_slider_label = QLabel("Angle (degrees):", self)
        position_slider_label.move(300, 30)

        self.position_offset_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.position_offset_slider.setMinimum(-30)
        self.position_offset_slider.setMaximum(30)
        self.position_offset_slider.setFixedWidth(200)
        self.position_offset_slider.move(300, 125)
        self.position_offset_slider_readout = QLabel("0.00°", self)
        self.position_offset_slider_readout.setFixedWidth(50)
        self.position_offset_slider_readout.move(450, 100)
        self.position_offset_slider_readout.setAlignment(
            Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        position_offset_slider_label = QLabel("Angle offset (degrees):", self)
        position_offset_slider_label.setFixedWidth(200)
        position_offset_slider_label.move(300, 100)

        self.angle_lower_limit_textentry = QLineEdit(self)
        self.angle_lower_limit_textentry.setFixedWidth(50)
        self.angle_lower_limit_textentry.move(450, 175)
        self.angle_lower_limit_textentry.setValidator(
            QIntValidator(0, 240, self))
        self.angle_upper_limit_textentry = QLineEdit(self)
        self.angle_upper_limit_textentry.setFixedWidth(50)
        self.angle_upper_limit_textentry.move(450, 210)
        self.angle_upper_limit_textentry.setValidator(
            QIntValidator(0, 240, self))
        self.angle_lower_limit_textentry_label = QLabel(
            "Lower Limit (degrees):", self)
        self.angle_lower_limit_textentry_label.move(300, 175)
        self.angle_lower_limit_textentry_label.setFixedWidth(150)
        self.angle_upper_limit_textentry_label = QLabel(
            "Upper Limit (degrees):", self)
        self.angle_upper_limit_textentry_label.move(300, 210)
        self.angle_upper_limit_textentry_label.setFixedWidth(150)

        self.vin_lower_limit_textentry = QLineEdit(self)
        self.vin_lower_limit_textentry.setFixedWidth(50)
        self.vin_lower_limit_textentry.move(450, 265)
        self.vin_lower_limit_textentry.setValidator(
            QIntValidator(4500, 12000, self))
        self.vin_upper_limit_textentry = QLineEdit(self)
        self.vin_upper_limit_textentry.setFixedWidth(50)
        self.vin_upper_limit_textentry.move(450, 300)
        self.vin_upper_limit_textentry.setValidator(
            QIntValidator(4500, 12000, self))
        self.vin_lower_limit_textentry_label = QLabel(
            "Voltage Lower Limit (mV):", self)
        self.vin_lower_limit_textentry_label.move(300, 265)
        self.vin_lower_limit_textentry_label.setFixedWidth(150)
        self.vin_upper_limit_textentry_label = QLabel(
            "Voltage Upper Limit (mV):", self)
        self.vin_upper_limit_textentry_label.move(300, 300)
        self.vin_upper_limit_textentry_label.setFixedWidth(150)

        self.temp_limit_textentry = QLineEdit(self)
        self.temp_limit_textentry.setFixedWidth(50)
        self.temp_limit_textentry.move(450, 355)
        self.temp_limit_textentry.setValidator(QIntValidator(50, 100, self))
        self.temp_limit_textentry_label = QLabel("Temp Limit (°C):", self)
        self.temp_limit_textentry_label.move(300, 355)
        self.temp_limit_textentry_label.setFixedWidth(150)

        self.servo_mode_radio_button = QRadioButton("Servo Mode", self)
        self.servo_mode_radio_button.move(565, 50)
        self.motor_mode_radio_button = QRadioButton("Motor Mode", self)
        self.motor_mode_radio_button.move(565, 75)

        self.motor_speed_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.motor_speed_slider.setMinimum(-1000)
        self.motor_speed_slider.setMaximum(1000)
        self.motor_speed_slider.setFixedWidth(200)
        self.motor_speed_slider.move(565, 125)
        motor_speed_slider_label = QLabel("Motor Speed:", self)
        motor_speed_slider_label.move(565, 100)

        self.torque_enabled_checkbox = QCheckBox("Torque Enabled", self)
        self.torque_enabled_checkbox.move(565, 175)
        self.torque_enabled_checkbox.setFixedWidth(200)

        self.led_enabled_checkbox = QCheckBox("LED Enabled", self)
        self.led_enabled_checkbox.move(565, 210)
        self.led_enabled_checkbox.setFixedWidth(200)

        self.led_over_temp_checkbox = QCheckBox("LED Over Temperature", self)
        self.led_over_temp_checkbox.move(565, 258)
        self.led_over_temp_checkbox.setFixedWidth(200)
        self.led_over_voltage_checkbox = QCheckBox("LED Over Voltage", self)
        self.led_over_voltage_checkbox.move(565, 283)
        self.led_over_voltage_checkbox.setFixedWidth(200)
        self.led_rotor_locked_checkbox = QCheckBox("LED Rotor Locked", self)
        self.led_rotor_locked_checkbox.move(565, 308)
        self.led_rotor_locked_checkbox.setFixedWidth(200)

        self.physical_position_readout = QLabel("--°", self)
        self.physical_position_readout.move(565, 367)
        self.physical_position_readout.setFixedWidth(200)
        self.physical_position_readout_label = QLabel("Position", self)
        self.physical_position_readout_label.move(565, 347)

        self.temperature_readout = QLabel("-- °C", self)
        self.temperature_readout.move(635, 367)
        self.temperature_readout.setFixedWidth(200)
        self.temperature_readout_label = QLabel("Temperature", self)
        self.temperature_readout_label.move(635, 347)

        self.voltage_readout = QLabel("-- V", self)
        self.voltage_readout.move(730, 367)
        self.voltage_readout.setFixedWidth(200)
        self.voltage_readout_label = QLabel("Voltage", self)
        self.voltage_readout_label.move(730, 347)

        self.readout_update_timer = QTimer(self)
        self.readout_update_timer.timeout.connect(self.update_readouts)
        self.readout_update_timer.start(250)

        self.active_servo: LX16A = None

        self.position_slider.setValue(0)
        self.position_offset_slider.setValue(0)
        self.motor_speed_slider.setValue(0)
        self.id_selection_box_refresh_button.setEnabled(False)
        self.disable_widgets()

        self.port_selection_box.currentTextChanged.connect(
            self.port_selection_box_changed)
        self.port_selection_box_refresh_button.clicked.connect(
            self.port_refresh_button_clicked)
        self.id_selection_box.currentTextChanged.connect(
            self.id_selection_box_changed)
        self.id_selection_box_refresh_button.clicked.connect(
            self.id_refresh_button_clicked)
        self.set_id_button.pressed.connect(self.id_updated)
        self.position_slider.sliderMoved.connect(self.position_slider_updated)
        self.position_offset_slider.sliderMoved.connect(
            self.position_offset_slider_updated)
        self.angle_lower_limit_textentry.textChanged.connect(
            self.angle_lower_limit_updated)
        self.angle_upper_limit_textentry.textChanged.connect(
            self.angle_upper_limit_updated)
        self.vin_lower_limit_textentry.textChanged.connect(
            self.vin_lower_limit_updated)
        self.vin_upper_limit_textentry.textChanged.connect(
            self.vin_upper_limit_updated)
        self.temp_limit_textentry.textChanged.connect(self.temp_limit_updated)
        self.servo_mode_radio_button.toggled.connect(
            self.servo_mode_radio_button_toggled)
        self.motor_mode_radio_button.toggled.connect(
            self.motor_mode_radio_button_toggled)
        self.motor_speed_slider.valueChanged.connect(
            self.motor_speed_slider_updated)
        self.torque_enabled_checkbox.stateChanged.connect(
            self.torque_enabled_checkbox_toggled)
        self.led_enabled_checkbox.stateChanged.connect(
            self.led_enabled_checkbox_toggled)
        self.led_over_temp_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)
        self.led_over_voltage_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)
        self.led_rotor_locked_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)

        self.scan_for_ports()

    def disable_widgets(self):
        self.set_id_line_edit.setEnabled(False)
        self.position_slider.setEnabled(False)
        self.position_offset_slider.setEnabled(False)
        self.angle_lower_limit_textentry.setEnabled(False)
        self.angle_upper_limit_textentry.setEnabled(False)
        self.vin_lower_limit_textentry.setEnabled(False)
        self.vin_upper_limit_textentry.setEnabled(False)
        self.temp_limit_textentry.setEnabled(False)
        self.servo_mode_radio_button.setEnabled(False)
        self.motor_mode_radio_button.setEnabled(False)
        self.motor_speed_slider.setEnabled(False)
        self.torque_enabled_checkbox.setEnabled(False)
        self.led_enabled_checkbox.setEnabled(False)
        self.led_over_temp_checkbox.setEnabled(False)
        self.led_over_voltage_checkbox.setEnabled(False)
        self.led_rotor_locked_checkbox.setEnabled(False)

    def enable_widgets(self):
        self.set_id_line_edit.setEnabled(True)
        self.position_slider.setEnabled(True)
        self.position_offset_slider.setEnabled(True)
        self.angle_lower_limit_textentry.setEnabled(True)
        self.angle_upper_limit_textentry.setEnabled(True)
        self.vin_lower_limit_textentry.setEnabled(True)
        self.vin_upper_limit_textentry.setEnabled(True)
        self.temp_limit_textentry.setEnabled(True)
        self.servo_mode_radio_button.setEnabled(True)
        self.motor_mode_radio_button.setEnabled(True)
        self.motor_speed_slider.setEnabled(True)
        self.torque_enabled_checkbox.setEnabled(True)
        self.led_enabled_checkbox.setEnabled(True)
        self.led_over_temp_checkbox.setEnabled(True)
        self.led_over_voltage_checkbox.setEnabled(True)
        self.led_rotor_locked_checkbox.setEnabled(True)

    def clear_servo(self):
        self.active_servo = None

    @catch_disconnection
    def set_servo_id(self, id_):
        if not id_.isdigit():
            return

        self.active_servo = LX16A(int(id_))
        self.active_servo.enable_torque()

        self.position_slider.setValue(
            int(self.active_servo.get_physical_angle()))
        self.position_slider_readout.setText(
            f"{int(self.active_servo.get_physical_angle() * 25 / 6) * 6 / 25:0.2f}°"
        )
        self.position_offset_slider.setValue(
            int(self.active_servo.get_angle_offset()))
        self.position_offset_slider_readout.setText(
            f"{int(self.active_servo.get_angle_offset() * 25 / 6) * 6 / 25:0.2f}°"
        )
        self.angle_lower_limit_textentry.setText(
            str(int(self.active_servo.get_angle_limits()[0])))
        self.angle_upper_limit_textentry.setText(
            str(int(self.active_servo.get_angle_limits()[1])))
        self.vin_lower_limit_textentry.setText(
            str(self.active_servo.get_vin_limits()[0]))
        self.vin_upper_limit_textentry.setText(
            str(self.active_servo.get_vin_limits()[1]))
        self.temp_limit_textentry.setText(
            str(self.active_servo.get_temp_limit()))
        self.motor_speed_slider.setValue(self.active_servo.get_motor_speed(
        ) if self.active_servo.is_motor_mode() else 0)
        if self.active_servo.is_motor_mode():
            self.motor_mode_radio_button.setChecked(True)
        else:
            self.servo_mode_radio_button.setChecked(True)
        self.motor_speed_slider.setEnabled(self.active_servo.is_motor_mode())
        self.torque_enabled_checkbox.setChecked(
            self.active_servo.is_torque_enabled())
        self.led_enabled_checkbox.setChecked(
            self.active_servo.is_led_power_on())
        self.led_over_temp_checkbox.setChecked(
            self.active_servo.get_led_error_triggers()[0])
        self.led_over_voltage_checkbox.setChecked(
            self.active_servo.get_led_error_triggers()[1])
        self.led_rotor_locked_checkbox.setChecked(
            self.active_servo.get_led_error_triggers()[2])

    @catch_disconnection
    def scan_for_servos(self, port):
        self.setCursor(Qt.CursorShape.WaitCursor)

        LX16A.initialize(port)

        self.id_selection_box.clear()

        for i in range(0, 254):
            try:
                servo = LX16A(i)
                self.id_selection_box.addItem(str(i))
            except:
                pass

        self.setCursor(Qt.CursorShape.ArrowCursor)

    @catch_disconnection
    def scan_for_ports(self):
        ports = serial.tools.list_ports.comports()
        for port in ports:
            self.port_selection_box.addItem(port.device)

    @catch_disconnection
    def update_readouts(self):
        if self.active_servo is None:
            return

        try:
            self.physical_position_readout.setText(
                f"{self.active_servo.get_physical_angle():0.2f}°")
            self.temperature_readout.setText(
                f"{self.active_servo.get_temp()} °C")
            self.voltage_readout.setText(
                f"{self.active_servo.get_vin() / 1000} V")
        except (ServoTimeoutError, ServoChecksumError):
            pass

    @catch_disconnection
    def id_updated(self):
        new_id = self.set_id_line_edit.text()

        try:
            servo = LX16A(int(new_id))
        except ServoTimeoutError:
            # Meaning this ID is not taken
            self.active_servo.set_id(int(new_id))
            self.id_selection_box.item(
                self.id_selection_box.currentRow()).setText(new_id)

            return

        QMessageBox.warning(None, "Error", "ID already taken")

    @catch_disconnection
    def position_slider_updated(self, pos):
        if float(self.voltage_readout.text()[:-2]) < 5:
            QMessageBox.warning(
                None,
                "Error",
                "The voltage going through the servo is too low. Is your battery powered on?",
            )

            return
        self.active_servo.move(pos)
        self.position_slider_readout.setText(
            f"{int(pos * 25 / 6) * 6 / 25:0.2f}°")

    @catch_disconnection
    def position_offset_slider_updated(self, pos):
        self.active_servo.set_angle_offset(pos)
        self.position_offset_slider_readout.setText(
            f"{int(pos * 25 / 6) * 6 / 25:0.2f}°")

    @catch_disconnection
    def angle_lower_limit_updated(self, text):
        if (QIntValidator(0, 240, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) > int(self.angle_upper_limit_textentry.text()):
            return

        self.active_servo.set_angle_limits(
            int(text), int(self.angle_upper_limit_textentry.text()))

    @catch_disconnection
    def angle_upper_limit_updated(self, text):
        if (QIntValidator(0, 240, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) < int(self.angle_lower_limit_textentry.text()):
            return

        self.active_servo.set_angle_limits(
            int(self.angle_lower_limit_textentry.text()), int(text))

    @catch_disconnection
    def vin_lower_limit_updated(self, text):
        if (QIntValidator(4500, 12000, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) > int(self.vin_upper_limit_textentry.text()):
            return

        self.active_servo.set_vin_limits(
            int(text), int(self.vin_upper_limit_textentry.text()))

    @catch_disconnection
    def vin_upper_limit_updated(self, text):
        if (QIntValidator(4500, 12000, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) < int(self.vin_lower_limit_textentry.text()):
            return

        self.active_servo.set_vin_limits(
            int(self.vin_lower_limit_textentry.text()), int(text))

    @catch_disconnection
    def temp_limit_updated(self, text):
        if (QIntValidator(50, 100, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        self.active_servo.set_temp_limit(int(text))

    @catch_disconnection
    def servo_mode_radio_button_toggled(self, checked):
        if checked:
            self.active_servo.servo_mode()
            self.motor_speed_slider.setEnabled(False)
            self.position_slider.setEnabled(True)
            self.position_offset_slider.setEnabled(True)
        else:
            self.active_servo.motor_mode(int(self.motor_speed_slider.value()))
            self.motor_speed_slider.setEnabled(True)
            self.position_slider.setEnabled(False)
            self.position_offset_slider.setEnabled(False)

    @catch_disconnection
    def motor_mode_radio_button_toggled(self, checked):
        if checked:
            self.active_servo.motor_mode(int(self.motor_speed_slider.value()))
            self.motor_speed_slider.setEnabled(True)
            self.position_slider.setEnabled(False)
            self.position_offset_slider.setEnabled(False)
        else:
            self.active_servo.servo_mode()
            self.motor_speed_slider.setEnabled(False)
            self.position_slider.setEnabled(True)
            self.position_offset_slider.setEnabled(True)

    @catch_disconnection
    def motor_speed_slider_updated(self, pos):
        self.active_servo.motor_mode(pos)

    @catch_disconnection
    def torque_enabled_checkbox_toggled(self, checked):
        if checked:
            self.active_servo.enable_torque()
        else:
            self.active_servo.disable_torque()

        self.position_slider.setEnabled(checked)
        self.position_offset_slider.setEnabled(checked)
        self.servo_mode_radio_button.setEnabled(checked)
        self.motor_mode_radio_button.setEnabled(checked)
        self.motor_speed_slider.setEnabled(checked)

    @catch_disconnection
    def led_enabled_checkbox_toggled(self, checked):
        if checked:
            self.active_servo.led_power_on()
        else:
            self.active_servo.led_power_off()

    @catch_disconnection
    def led_error_triggers_checkbox_toggled(self):
        self.active_servo.set_led_error_triggers(
            self.led_over_voltage_checkbox.isChecked(),
            self.led_over_temp_checkbox.isChecked(),
            self.led_rotor_locked_checkbox.isChecked(),
        )

    @catch_disconnection
    def port_refresh_button_clicked(self, value):
        self.id_selection_box_refresh_button.setEnabled(False)
        self.disable_widgets()
        self.port_selection_box.clear()
        self.id_selection_box.clear()
        self.scan_for_ports()

    @catch_disconnection
    def id_refresh_button_clicked(self, value):
        self.disable_widgets()
        self.id_selection_box.clear()
        self.scan_for_servos(self.port_selection_box.currentText())

    @catch_disconnection
    def port_selection_box_changed(self, text):
        if text == "":
            return

        self.id_selection_box_refresh_button.setEnabled(True)
        self.disable_widgets()
        self.id_selection_box.clear()
        self.clear_servo()
        self.scan_for_servos(text)

    @catch_disconnection
    def id_selection_box_changed(self, text):
        if text == "":
            return

        self.enable_widgets()
        self.set_servo_id(text)
Exemplo n.º 14
0
    def __init__(self, parent = None):
        super(MainWindow, self).__init__()

        D = self.screen().availableGeometry()
        self.move(0,0)#center.x() + .25*D.width() , center.y() - .5*D.height() )
        self.resize( int(.95*D.width()), int(6*D.height()) )
        
		#qr = self.frameGeometry()
        #cp = self.screen().availableGeometry().center()
        #qr.moveCenter(cp)
        #self.move(qr.topLeft())
		
        self.setWindowState(self.windowState() & ~QtCore.Qt.WindowState.WindowMinimized
                            | QtCore.Qt.WindowState.WindowActive)
        self.activateWindow()

        self.subWin = Window()
        self.iw = imwin()
        self.Manual = Manual()
        self.setCentralWidget(self.iw)

        #Stacked dock widgets
        docked1 = QDockWidget("", self)
        docked2 = QDockWidget("", self)
        self.addDockWidget(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea, docked1)
        self.addDockWidget(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea, docked2)
        docked1.setWidget(self.subWin)
        docked2.setWidget(self.Manual)
        docked1.setFeatures(QDockWidget.DockWidgetFeature.DockWidgetFloatable)

        self.setCorner(QtCore.Qt.Corner.TopLeftCorner, QtCore.Qt.DockWidgetArea.LeftDockWidgetArea);
        self.setCorner(QtCore.Qt.Corner.TopRightCorner, QtCore.Qt.DockWidgetArea.RightDockWidgetArea)
        self.setCorner(QtCore.Qt.Corner.BottomLeftCorner, QtCore.Qt.DockWidgetArea.LeftDockWidgetArea);
        self.setCorner(QtCore.Qt.Corner.BottomRightCorner, QtCore.Qt.DockWidgetArea.RightDockWidgetArea)
        self.resizeDocks( (docked1,docked2), (400,400), QtCore.Qt.Orientation.Horizontal )

        self.exportButton = QPushButton("Export Measurements", self)
        self.exportButton.clicked.connect(self.export_measurements)
        self.exportButton.setEnabled(False)

        self.importImage = QPushButton("New Image", self)
        self.importImage.clicked.connect(self.file_open)

        self.lengthButton = QPushButton("Measure Length", self)
        self.lengthButton.clicked.connect(self.measure_length)
        self.lengthButton.setEnabled(False)
        self.lengthButton.setCheckable(True)
        self.lengthNames = []

        self.widthsButton = QPushButton("Measure Widths", self)
        self.widthsButton.clicked.connect(self.iw.measure_widths)
        self.widthsButton.setEnabled(False)
        self.widthsButton.setCheckable(True)

        self.areaButton = QPushButton("Measure Area", self)
        self.areaButton.clicked.connect(self.measure_area)
        self.areaButton.setEnabled(False)
        self.areaButton.setCheckable(True)
        self.areaNames = []

        self.angleButton = QPushButton("Measure Angle", self)
        self.angleButton.clicked.connect(self.measure_angle)
        self.angleButton.setEnabled(False)
        self.angleButton.setCheckable(True)
        self.angleNames = []

        shortcut_polyClose = QShortcut(QtGui.QKeySequence(QtCore.Qt.Key.Key_Tab), self)
        shortcut_polyClose.activated.connect(self.iw.polyClose) 
        
        self.undoButton = QPushButton("Undo", self)
        self.undoButton.clicked.connect(self.undo)
        self.undoButton.setEnabled(False)
        
        shortcut_undo = QShortcut(QtGui.QKeySequence('Ctrl+Z'), self)
        shortcut_undo.activated.connect(self.undo)

        self.bezier = QRadioButton("Bezier fit", self)
        self.bezier.setEnabled(True)
        self.bezier.setChecked(True)
	#self.bezier.toggled.connect(self.onClicked)
	
        self.piecewise = QRadioButton("Piecewise", self)
	
        self.statusbar = self.statusBar()
        self.statusbar.showMessage('Select new image to begin')

        self.tb = QToolBar('Toolbar')
        #self.addToolBar(QtCore.Qt.RightToolBarArea,self.tb)
        spacer = QWidget(self)
        spacer.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        self.tb.addWidget(spacer)
        self.addToolBar(self.tb)
        self.tb.addWidget(self.importImage)
        self.tb.addWidget(self.exportButton)
        self.tb.addWidget(self.lengthButton)
        self.tb.addWidget(self.widthsButton)
        self.tb.addWidget(self.areaButton)
        self.tb.addWidget(self.angleButton)
        self.tb.addWidget(self.undoButton)
        self.tb.addWidget(self.bezier)
        self.tb.addWidget(self.piecewise)
Exemplo n.º 15
0
class MainWindow(QMainWindow):

    def __init__(self, parent = None):
        super(MainWindow, self).__init__()

        D = self.screen().availableGeometry()
        self.move(0,0)#center.x() + .25*D.width() , center.y() - .5*D.height() )
        self.resize( int(.95*D.width()), int(6*D.height()) )
        
		#qr = self.frameGeometry()
        #cp = self.screen().availableGeometry().center()
        #qr.moveCenter(cp)
        #self.move(qr.topLeft())
		
        self.setWindowState(self.windowState() & ~QtCore.Qt.WindowState.WindowMinimized
                            | QtCore.Qt.WindowState.WindowActive)
        self.activateWindow()

        self.subWin = Window()
        self.iw = imwin()
        self.Manual = Manual()
        self.setCentralWidget(self.iw)

        #Stacked dock widgets
        docked1 = QDockWidget("", self)
        docked2 = QDockWidget("", self)
        self.addDockWidget(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea, docked1)
        self.addDockWidget(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea, docked2)
        docked1.setWidget(self.subWin)
        docked2.setWidget(self.Manual)
        docked1.setFeatures(QDockWidget.DockWidgetFeature.DockWidgetFloatable)

        self.setCorner(QtCore.Qt.Corner.TopLeftCorner, QtCore.Qt.DockWidgetArea.LeftDockWidgetArea);
        self.setCorner(QtCore.Qt.Corner.TopRightCorner, QtCore.Qt.DockWidgetArea.RightDockWidgetArea)
        self.setCorner(QtCore.Qt.Corner.BottomLeftCorner, QtCore.Qt.DockWidgetArea.LeftDockWidgetArea);
        self.setCorner(QtCore.Qt.Corner.BottomRightCorner, QtCore.Qt.DockWidgetArea.RightDockWidgetArea)
        self.resizeDocks( (docked1,docked2), (400,400), QtCore.Qt.Orientation.Horizontal )

        self.exportButton = QPushButton("Export Measurements", self)
        self.exportButton.clicked.connect(self.export_measurements)
        self.exportButton.setEnabled(False)

        self.importImage = QPushButton("New Image", self)
        self.importImage.clicked.connect(self.file_open)

        self.lengthButton = QPushButton("Measure Length", self)
        self.lengthButton.clicked.connect(self.measure_length)
        self.lengthButton.setEnabled(False)
        self.lengthButton.setCheckable(True)
        self.lengthNames = []

        self.widthsButton = QPushButton("Measure Widths", self)
        self.widthsButton.clicked.connect(self.iw.measure_widths)
        self.widthsButton.setEnabled(False)
        self.widthsButton.setCheckable(True)

        self.areaButton = QPushButton("Measure Area", self)
        self.areaButton.clicked.connect(self.measure_area)
        self.areaButton.setEnabled(False)
        self.areaButton.setCheckable(True)
        self.areaNames = []

        self.angleButton = QPushButton("Measure Angle", self)
        self.angleButton.clicked.connect(self.measure_angle)
        self.angleButton.setEnabled(False)
        self.angleButton.setCheckable(True)
        self.angleNames = []

        shortcut_polyClose = QShortcut(QtGui.QKeySequence(QtCore.Qt.Key.Key_Tab), self)
        shortcut_polyClose.activated.connect(self.iw.polyClose) 
        
        self.undoButton = QPushButton("Undo", self)
        self.undoButton.clicked.connect(self.undo)
        self.undoButton.setEnabled(False)
        
        shortcut_undo = QShortcut(QtGui.QKeySequence('Ctrl+Z'), self)
        shortcut_undo.activated.connect(self.undo)

        self.bezier = QRadioButton("Bezier fit", self)
        self.bezier.setEnabled(True)
        self.bezier.setChecked(True)
	#self.bezier.toggled.connect(self.onClicked)
	
        self.piecewise = QRadioButton("Piecewise", self)
	
        self.statusbar = self.statusBar()
        self.statusbar.showMessage('Select new image to begin')

        self.tb = QToolBar('Toolbar')
        #self.addToolBar(QtCore.Qt.RightToolBarArea,self.tb)
        spacer = QWidget(self)
        spacer.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        self.tb.addWidget(spacer)
        self.addToolBar(self.tb)
        self.tb.addWidget(self.importImage)
        self.tb.addWidget(self.exportButton)
        self.tb.addWidget(self.lengthButton)
        self.tb.addWidget(self.widthsButton)
        self.tb.addWidget(self.areaButton)
        self.tb.addWidget(self.angleButton)
        self.tb.addWidget(self.undoButton)
        self.tb.addWidget(self.bezier)
        self.tb.addWidget(self.piecewise)
        #self.tb.setOrientation(QtCore.Qt.Vertical)

    def file_open(self):

        self.iw.scene.clear()
        self.image_name = QFileDialog.getOpenFileName(self, 'Open File')
        self.iw.pixmap = QtGui.QPixmap(self.image_name[0])
        self.iw.pixmap_fit = self.iw.pixmap.scaled(
            self.iw.pixmap.width(),
            self.iw.pixmap.height(),
            QtCore.Qt.AspectRatioMode.KeepAspectRatio,
            transformMode=QtCore.Qt.TransformationMode.SmoothTransformation)
        self.iw.scene.addPixmap(self.iw.pixmap_fit)  #add image
        self.iw.setScene(self.iw.scene)

        #Adjust window size automatically?
        self.iw.fitInView(self.iw.scene.sceneRect(), QtCore.Qt.AspectRatioMode.KeepAspectRatio)
        self.iw.scene.update()
        self.statusbar.showMessage('Select a measurement to make from the toolbar')

        self.lengthButton.setEnabled(True)
        self.areaButton.setEnabled(True)
        self.angleButton.setEnabled(True)
        self.exportButton.setEnabled(True)
        self.undoButton.setEnabled(True)
        self.bezier.setEnabled(True)
        self.bezier.setChecked(True)
        self.widthsButton.setEnabled(False)

        self.angleNames = []
        self.areaNames = []
        self.lengthNames = []
        #self.iw.measurements = [[]]
        self.iw.widths = []
        self.iw.lengths = [[]]
        self.iw.L = posData(
            np.empty(shape=(0, 0)), np.empty(shape=(0, 0)))  #lengths
        self.iw.A = posData(
            np.empty(shape=(0, 0)), np.empty(shape=(0, 0)))  #area
        self.iw.W = posData(
            np.empty(shape=(0, 0)), np.empty(shape=(0, 0)))  #widths
        self.iw.T = angleData(np.empty(shape=(0, 0)))  #angles
        self.iw.angleValues = np.empty((0,0))
        self.iw.areaValues = np.empty((0,0))
        self.iw._lastpos = None
        self.iw._thispos = None
        self.iw.measuring_length = False
        self.iw.measuring_area = False
        self.iw.measuring_widths = False
        self.iw.measuring_angle = False
        self.iw._zoom = 0
        self.iw.factor = 1.0
        self.iw.d = {}  #dictionary for line items
        self.iw.k = 0  #initialize counter so lines turn yellow
        self.iw.m = None
        self.iw.scene.realline = None
        self.iw.scene.testline = None
        self.iw.scene.ellipseItem = None
        self.iw.scene.area_ellipseItem = None
        self.iw.scene.polyItem = None
        self.iw.image_name = None

    def measure_length(self):

        self.lel = QLineEdit(self)
        self.lel.move(130, 22)
        text, ok = QInputDialog.getText(self, 'Input Dialog', 'Length name')

        if ok:
            self.lel.setText(str(text))
            self.lengthNames.append(self.lel.text())
            QApplication.setOverrideCursor(QtCore.Qt.CursorShape.CrossCursor)  #change cursor
            self.widthsButton.setChecked(False)
            self.widthsButton.setEnabled(False)
            self.iw.line_count = 0
            self.iw.measuring_length = True
            self.iw.L = posData(
                np.empty(shape=(0, 0)),
                np.empty(shape=(0, 0)))  #preallocate
            self.iw._lastpos = None
            self.iw._thispos = None
            self.statusbar.showMessage('Click initial point for length measurement')
        else:
            self.lengthButton.setChecked(False)

    def measure_angle(self):

        self.lea = QLineEdit(self)
        self.lea.move(130, 22)
        text, ok = QInputDialog.getText(self, 'Input Dialog', 'Angle name')

        if ok:
            self.lea.setText(str(text))
            self.angleNames.append(self.lea.text())
            QApplication.setOverrideCursor(QtCore.Qt.CrossCursor)  #change cursor
            self.bezier.setEnabled(False)
            self.iw.measuring_angle = True
            self.iw._lastpos = None
            self.iw._thispos = None
            self.statusbar.showMessage('Click initial point for angle measurement')
        else:
            self.angleButton.setChecked(False)

    def measure_area(self):

        self.lea = QLineEdit(self)
        self.lea.move(130, 22)
        text, ok = QInputDialog.getText(self, 'Input Dialog', 'Area name')

        if ok:
            self.lea.setText(str(text))
            self.areaNames.append(self.lea.text())
            QApplication.setOverrideCursor(QtCore.Qt.CrossCursor)  #change cursor
            self.bezier.setEnabled(False)
            self.iw.line_count = 0
            self.iw.measuring_area = True
            self.iw._lastpos = None
            self.iw._thispos = None
            self.iw.A = posData(
                np.empty(shape=(0, 0)),
                np.empty(shape=(0, 0)))  #preallocate
            self.statusbar.showMessage('Click initial point for area measurement')
        else:
            self.areaButton.setChecked(False)

    def undo(self):

        if self.iw.measuring_length:
            self.iw._thispos = self.iw._lastpos
            self.iw.L.downdate()  #remove data
            self.iw.line_count += -1
            self.iw.scene.removeItem(self.iw.scene.realline)  #remove graphic
            self.iw.scene.realline = False

        if self.iw.measuring_area:
            self.iw._thispos = self.iw._lastpos
            self.iw.A.downdate()  #remove data
            self.iw.line_count += -1
            self.iw.scene.removeItem(self.iw.scene.realline)  #remove graphic
            self.iw.scene.realline = False

        if self.iw.measuring_widths:
            self.iw.W.downdate()  #remove data
            self.iw.scene.removeItem(self.iw.scene.ellipseItem)  #remove graphic
            self.iw.scene.ellipseItem = False
            self.iw.d[str(self.iw.k)].setPen(
                QtGui.QPen(QtGui.QColor('black')))  #un-highlight next spine
            self.iw.k += -1  #reduce count

        if self.iw.measuring_angle:
            self.iw.T.downdate()  #remove data
            self.iw._thispos = self.iw_lastpos
            self.iw.scene.removeItem(self.iw.scene.realline)  #remove graphic
            self.iw.scene.realline = False

    def export_measurements(self):

        fac = max(self.iw.pixmap.width(), self.iw.pixmap.height()) / max(
            self.iw.pixmap_fit.width(),
            self.iw.pixmap_fit.height())  #scale pixel -> m by scaled image
        name = QFileDialog.getSaveFileName(
            self, 'Save File', self.image_name[0].split('.', 1)[0])[0]
        self.pixeldim = float(self.subWin.pixeldim.text())
        self.altitude = float(self.subWin.altitude.text())
        self.focal = float(self.subWin.focal.text())
        #okay in mm https://www.imaging-resource.com/PRODS/sony-a5100/sony-a5100DAT.HTM
        if name:

            #Convert pixels to meters
            #measurements = [ f * fac * self.pixeldim * self.altitude / self.focal for f in self.iw.measurements]
            #lengths = [ f * fac * self.pixeldim * self.altitude / self.focal for f in self.iw.lengths]
            #print(self.iw.widths)
            areas = self.iw.areaValues * (
                fac * self.pixeldim * self.altitude / self.focal)**2
            values_optical = np.array([
                self.subWin.id.text(), self.image_name[0], self.focal,
                self.altitude, self.pixeldim
            ])
            names_optical = [
                'Image ID', 'Image Path', 'Focal Length', 'Altitude',
                'Pixel Dimension'
            ]
            names_widths = ['Object'] +  ['Length (m)'] + ['Widths (%)'] # + self.iw.widthNames[0]
            #names_widths.append([self.iw.widthNames[0]])

	    #Write .csv file
            print(f"Writing {name} to file")
            with open(name + '.csv', 'w') as csvfile:
                writer = csv.writer(csvfile)
                for (f, g) in zip(names_optical, values_optical):
                    writer.writerow([f, g])
                writer.writerow(['Notes', self.subWin.notes.toPlainText()])

                writer.writerow([''])
                writer.writerow(names_widths)

                for k,m in enumerate(self.lengthNames):
                    #format and convert pixel length measurement
                    l =  "{0:.2f}".format( self.iw.lengths[k] * fac * self.pixeldim * self.altitude / self.focal )

                    if any(self.iw.widths[k]): #check if width measurement exists for length
                        n = self.iw.widthNames[k]
                        writer.writerow( [''] + [''] + n )
                        #format and convert pixel width measurement
                        vals = [ "{0:.2f}".format(g * fac * self.pixeldim * self.altitude / self.focal) for g in self.iw.widths[k]]
                        line = [m] + [l] + list(vals)
                    else:
                        #vals = l #f.copy()
                        line = [m] + [l]

                    writer.writerow(line)

                writer.writerow([''])
                writer.writerow(['Object'] + ['Angle'])

                for k, f in enumerate(self.angleNames):  #write angles
                    line = [[f] + ["{0:.3f}".format(self.iw.angleValues[k])]]  #need to convert NaNs to empty
                    writer.writerows(line)

                writer.writerow([''])
                writer.writerow(['Object'] + ['Area (m\u00B2)'])

                for k, f in enumerate(self.areaNames):  #write areas
                    line = [[f] + ["{0:.3f}".format(areas[k])]]  #need to convert NaNs to empty
                    writer.writerows(line)

            #Export image
            self.iw.fitInView(self.iw.scene.sceneRect(), QtCore.Qt.AspectRatioMode.KeepAspectRatio)
            pix = QtGui.QPixmap(self.iw.viewport().size())
            self.iw.viewport().render(pix)
            pix.save(name + '-measurements.png')
Exemplo n.º 16
0
    def questionBankPageUI(self):
        layout = QFormLayout()

        subLayout = QHBoxLayout()
        self.questionBankPage.questionList = QListWidget()
        self.questionBankPage.questionList.currentRowChanged.connect(
            self.displayQuestionOnQuestionBankPage)
        self.questionBankPage.questionTextDisplay = QLabel()
        self.questionBankPage.questionTextDisplay.setFixedSize(500, 100)
        self.questionBankPage.questionAnswersList = QListWidget()
        self.questionBankPage.definedCorrectAnswerDisplay = QLabel()
        self.questionBankPage.definedCorrectAnswerDisplay.setFixedSize(50, 10)
        self.questionBankPage.questionCodeParserDisplay = QLabel()
        self.questionBankPage.questionCodeParserDisplay.setFixedSize(100, 50)
        subLayout.addWidget(self.questionBankPage.questionList)
        subLayout.addWidget(self.questionBankPage.questionTextDisplay)
        subLayout.addWidget(self.questionBankPage.questionAnswersList)
        subLayout.addWidget(self.questionBankPage.definedCorrectAnswerDisplay)
        subLayout.addWidget(self.questionBankPage.questionCodeParserDisplay)
        layout.addRow(subLayout)

        self.questionBankPage.newQuestionTitle = QLineEdit()
        self.questionBankPage.newQuestionContent = QPlainTextEdit()
        layout.addRow(self.questionBankPage.newQuestionTitle,
                      self.questionBankPage.newQuestionContent)

        self.questionBankPage.newQuestionAnswerInput = QLineEdit()
        self.questionBankPage.newQuestionAnswerList = QListWidget()
        layout.addRow(self.questionBankPage.newQuestionAnswerInput,
                      self.questionBankPage.newQuestionAnswerList)

        colorLayout = QFormLayout()
        colorButtonGroup = QButtonGroup(self.questionBankPage)
        self.questionBankPage.yellowRadio = QRadioButton()
        self.questionBankPage.blueRadio = QRadioButton()
        self.questionBankPage.redRadio = QRadioButton()
        self.questionBankPage.yellowRadio.toggled.connect(
            self.colorRadioToggle)
        self.questionBankPage.blueRadio.toggled.connect(self.colorRadioToggle)
        self.questionBankPage.redRadio.toggled.connect(self.colorRadioToggle)
        colorButtonGroup.addButton(self.questionBankPage.yellowRadio)
        colorButtonGroup.addButton(self.questionBankPage.blueRadio)
        colorButtonGroup.addButton(self.questionBankPage.redRadio)
        colorLayout.addRow("Yellow", self.questionBankPage.yellowRadio)
        colorLayout.addRow("Blue", self.questionBankPage.blueRadio)
        colorLayout.addRow("Red", self.questionBankPage.redRadio)

        combLayout = QHBoxLayout()
        combLayout.addLayout(colorLayout)
        layout.addRow(combLayout)

        self.questionBankPage.definedNewCorrectAnswerDisplay = QLabel()
        layout.addRow(self.questionBankPage.definedNewCorrectAnswerDisplay)

        self.questionBankPage.defineCorrectAnswerButton = QPushButton(
            "&Define Correct Answer")
        self.questionBankPage.defineCorrectAnswerButton.clicked.connect(
            self.defineCorrectAnswer)
        self.questionBankPage.submitNewAnswerButton = QPushButton(
            "Submit &Answer")
        self.questionBankPage.submitNewAnswerButton.clicked.connect(
            self.submitNewAnswer)
        layout.addRow(self.questionBankPage.defineCorrectAnswerButton,
                      self.questionBankPage.submitNewAnswerButton)

        self.questionBankPage.submitNewQuestionButton = QPushButton(
            "Submit New &Question")
        self.questionBankPage.submitNewQuestionButton.clicked.connect(
            self.submitNewQuestion)
        layout.addRow(self.questionBankPage.submitNewQuestionButton)

        self.questionBankPage.backButton = QPushButton("&Back")
        self.questionBankPage.backButton.clicked.connect(
            self.goTo_FacilStartPage)
        self.questionBankPage.refreshButton = QPushButton("&Refresh")
        self.questionBankPage.refreshButton.clicked.connect(
            self.goTo_QuestionBankPage)
        layout.addRow(self.questionBankPage.backButton,
                      self.questionBankPage.refreshButton)

        self.questionBankPage.setLayout(layout)