Exemplo n.º 1
0
class ControlFrame(QFrame):
    def __init__(self, dataset, display_panel, threads):
        super().__init__()
        if isinstance(display_panel, DisplayFrame):
            self.display_panel = display_panel
        else:
            raise TypeError("'display_panel' must be the instance of "
                            "'DisplayFrame'")
        self.dataset = dataset
        self.threads = threads

        self.__layout = QVBoxLayout()
        self.setLayout(self.__layout)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        self.__set_running_options_ui()
        self.__set_fuzzy_set_operation_types_ui()
        self.__set_fuzzy_variables_ui()
        self.__set_fuzzy_rules_ui()
        self.__set_console_ui()

    def __set_running_options_ui(self):
        group_box = QGroupBox("Running Options")
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.data_selector = QComboBox()
        self.data_selector.addItems(list(self.dataset.keys()))
        self.data_selector.setStatusTip("Select the road map case.")
        self.data_selector.currentIndexChanged.connect(self.__change_map)

        self.fps = QSpinBox()
        self.fps.setMinimum(1)
        self.fps.setMaximum(60)
        self.fps.setValue(20)
        self.fps.setStatusTip(
            "The re-drawing rate for car simulator. High fps "
            "may cause the plot shows discontinuously.")

        self.start_btn = QPushButton("Run")
        self.start_btn.setStatusTip("Run the car.")
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton("Stop")
        self.stop_btn.setStatusTip("Force the simulation stop running.")
        self.stop_btn.setDisabled(True)

        self.save_btn = QPushButton()
        self.save_btn.setIcon(QIcon(':/icons/save_icon.png'))
        self.save_btn.setStatusTip("Save every details for the last time "
                                   "running.")
        self.save_btn.clicked.connect(self.__save_results)
        self.save_btn.setDisabled(True)

        self.__change_map()
        inner_layout.addWidget(self.data_selector, 1)
        inner_layout.addWidget(QLabel("FPS:"))
        inner_layout.addWidget(self.fps)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)
        inner_layout.addWidget(self.save_btn)

        self.__layout.addWidget(group_box)

    def __set_fuzzy_set_operation_types_ui(self):
        group_box = QGroupBox("Fuzzy Sets Operation Types")
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.implication_selections = RadioButtonSet([
            ("imp_dr", QRadioButton("Dienes-Rescher")),
            ("imp_l", QRadioButton("Lukasieweicz")),
            ("imp_z", QRadioButton("Zadel")), ("imp_g", QRadioButton("Godel")),
            ("imp_m", QRadioButton("Mamdani")),
            ("imp_p", QRadioButton("Product"))
        ])
        self.combination_vars_selections = RadioButtonSet([
            ("tn_min", QRadioButton("Minimum")),
            ("tn_ap", QRadioButton("Algebraic Product")),
            ("tn_bp", QRadioButton("Bounded Product")),
            ("tn_dp", QRadioButton("Drastic Product"))
        ])
        self.combination_rules_selections = RadioButtonSet([
            ("tc_max", QRadioButton("Maximum")),
            ("tc_as", QRadioButton("Algebraic Sum")),
            ("tc_bs", QRadioButton("Bounded Sum")),
            ("tc_ds", QRadioButton("Drastic Sum"))
        ])
        self.defuzzifier_selections = RadioButtonSet([
            ("gravity_center", QRadioButton("Center of Gravity")),
            ("maxima_mean", QRadioButton("Mean of Maxima")),
            ("modified_maxima_mean", QRadioButton("Modified Mean of Maxima"))
        ])

        self.implication_selections.set_selected('imp_m')
        self.combination_vars_selections.set_selected('tn_min')
        self.combination_rules_selections.set_selected('tc_max')
        self.defuzzifier_selections.set_selected('gravity_center')

        self.implication_selections.setStatusTip("Choose the method for fuzzy "
                                                 "implication.")
        self.combination_vars_selections.setStatusTip(
            "Choose the method of "
            "combination of multiple "
            "fuzzy variables.")
        self.combination_rules_selections.setStatusTip("Choose the method of "
                                                       "combination of "
                                                       "multiple fuzzy rules.")
        self.defuzzifier_selections.setStatusTip("Choose the method for the "
                                                 "defuzifier.")

        inner_layout.addRow(QLabel("Implication:"),
                            self.implication_selections)
        inner_layout.addRow(QLabel("Combination of Variables:"),
                            self.combination_vars_selections)
        inner_layout.addRow(QLabel("Combination of Rules:"),
                            self.combination_rules_selections)
        inner_layout.addRow(QLabel("Defuzzifier:"),
                            self.defuzzifier_selections)

        self.__layout.addWidget(group_box)

    def __set_fuzzy_variables_ui(self):
        group_box = QGroupBox("Fuzzy Variables Settings")
        group_box.setStatusTip("Set the membership functions for each fuzzy "
                               "variable.")
        inner_layout = QVBoxLayout()
        self.fuzzyvar_setting_stack = QStackedWidget()
        self.fuzzyvar_ui_selection = RadioButtonSet([
            ("front", QRadioButton("Front Distance Radar")),
            ("lrdiff", QRadioButton("(Left-Right) Distance Radar")),
            ("consequence", QRadioButton("Consequence"))
        ])
        self.fuzzyvar_setting_dist_front = FuzzierVarSetting()
        self.fuzzyvar_setting_dist_front.small.mean.setValue(5)
        self.fuzzyvar_setting_dist_front.medium.mean.setValue(12)
        self.fuzzyvar_setting_dist_front.large.mean.setValue(20)

        self.fuzzyvar_setting_dist_lrdiff = FuzzierVarSetting()
        self.fuzzyvar_setting_dist_lrdiff.small.mean.setValue(-10)
        self.fuzzyvar_setting_dist_lrdiff.medium.mean.setValue(0)
        self.fuzzyvar_setting_dist_lrdiff.large.mean.setValue(10)

        self.fuzzyvar_setting_consequence = FuzzierVarSetting()
        self.fuzzyvar_setting_consequence.small.mean.setValue(-12)
        self.fuzzyvar_setting_consequence.small.sd.setValue(20)
        self.fuzzyvar_setting_consequence.medium.mean.setValue(0)
        self.fuzzyvar_setting_consequence.medium.sd.setValue(20)
        self.fuzzyvar_setting_consequence.large.mean.setValue(12)
        self.fuzzyvar_setting_consequence.large.sd.setValue(20)

        inner_layout.addWidget(self.fuzzyvar_ui_selection)
        inner_layout.addWidget(self.fuzzyvar_setting_stack)
        group_box.setLayout(inner_layout)

        self.fuzzyvar_setting_stack.addWidget(self.fuzzyvar_setting_dist_front)
        self.fuzzyvar_setting_stack.addWidget(
            self.fuzzyvar_setting_dist_lrdiff)
        self.fuzzyvar_setting_stack.addWidget(
            self.fuzzyvar_setting_consequence)

        self.fuzzyvar_ui_selection.sig_rbtn_changed.connect(
            self.__change_fuzzyvar_setting_ui_stack)

        self.__layout.addWidget(group_box)

    def __set_fuzzy_rules_ui(self):
        antecedents = ('small', 'medium', 'large')

        group_box = QGroupBox("Fuzzy Rules Setting")
        inner_layout = QVBoxLayout()
        group_box.setStatusTip("Set the rules for the fuzzy system.")

        self.rules_setting = FuzzyRulesSetting(
            [p for p in itertools.product(antecedents, repeat=2)])
        self.rules_setting.set_consequence_fuzzysets(
            ('large', 'small', 'small', 'large', 'small', 'small', 'large',
             'small', 'small'))

        inner_layout.addWidget(self.rules_setting)
        group_box.setLayout(inner_layout)
        self.__layout.addWidget(group_box)

    def __set_console_ui(self):
        self.__console = QTextEdit()
        self.__console.setReadOnly(True)
        self.__console.setStatusTip("Show the logs of status changing.")
        self.__layout.addWidget(self.__console)

    @Slot(str)
    def __change_fuzzyvar_setting_ui_stack(self, name):
        if name == 'front':
            self.fuzzyvar_setting_stack.setCurrentIndex(0)
        elif name == 'lrdiff':
            self.fuzzyvar_setting_stack.setCurrentIndex(1)
        else:
            self.fuzzyvar_setting_stack.setCurrentIndex(2)

    @Slot()
    def __change_map(self):
        self.__current_data = self.dataset[self.data_selector.currentText()]
        self.__car = Car(self.__current_data['start_pos'],
                         self.__current_data['start_angle'], 3,
                         self.__current_data['route_edge'])
        self.display_panel.change_map(self.__current_data)

    @Slot(str)
    def __print_console(self, text):
        self.__console.append(text)

    @Slot(list)
    def __get_results(self, results):
        """Get the results of last running and draw the path of it."""
        self.results = results
        self.display_panel.show_path([d['x'] for d in results],
                                     [d['y'] for d in results])

    @Slot()
    def __save_results(self):
        save_dir = QFileDialog.getExistingDirectory(self,
                                                    'Select Saving Directory')
        file4d_filepath = os.path.join(save_dir, 'train4D.txt')
        file6d_filepath = os.path.join(save_dir, 'train6D.txt')
        with open(file4d_filepath, 'w') as file4d:
            for result in self.results:
                file4d.write('{:.7f} {:.7f} {:.7f} {:.7f}\n'.format(
                    result['front_dist'], result['right_dist'],
                    result['left_dist'], result['wheel_angle']))
        with open(file6d_filepath, 'w') as file6d:
            for result in self.results:
                file6d.write(
                    '{:.7f} {:.7f} {:.7f} {:.7f} {:.7f} {:.7f}\n'.format(
                        result['x'], result['y'], result['front_dist'],
                        result['right_dist'], result['left_dist'],
                        result['wheel_angle']))
        self.__print_console('Note: Detailed results have been saved in both'
                             ' "%s" and "%s".' %
                             (file4d_filepath, file6d_filepath))

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.save_btn.setDisabled(True)
        self.fps.setDisabled(True)
        self.data_selector.setDisabled(True)
        self.implication_selections.setDisabled(True)
        self.combination_vars_selections.setDisabled(True)
        self.combination_rules_selections.setDisabled(True)
        self.defuzzifier_selections.setDisabled(True)
        self.fuzzyvar_setting_dist_front.setDisabled(True)
        self.fuzzyvar_setting_dist_lrdiff.setDisabled(True)
        self.fuzzyvar_setting_consequence.setDisabled(True)
        self.rules_setting.setDisabled(True)

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.save_btn.setEnabled(True)
        self.fps.setEnabled(True)
        self.data_selector.setEnabled(True)
        self.implication_selections.setEnabled(True)
        self.combination_vars_selections.setEnabled(True)
        self.combination_rules_selections.setEnabled(True)
        self.defuzzifier_selections.setEnabled(True)
        self.fuzzyvar_setting_dist_front.setEnabled(True)
        self.fuzzyvar_setting_dist_lrdiff.setEnabled(True)
        self.fuzzyvar_setting_consequence.setEnabled(True)
        self.rules_setting.setEnabled(True)

    @Slot()
    def __run(self):
        # reset the map
        self.__change_map()
        # create a QThread
        self.thread = RunCar(self.__car, self.__create_fuzzy_system(),
                             (self.__current_data['end_area_lt'],
                              self.__current_data['end_area_rb']),
                             self.fps.value())
        # Record the new created threads for the closeEvent in gui_base.py
        # By doing this, user can destroy the QMainWindow elegantly when there
        # are threads still running.
        self.threads.append(self.thread)
        self.stop_btn.clicked.connect(self.thread.stop)
        self.thread.started.connect(self.__init_widgets)
        self.thread.finished.connect(self.__reset_widgets)
        self.thread.sig_console.connect(self.__print_console)
        self.thread.sig_car.connect(self.display_panel.move_car)
        self.thread.sig_car_collided.connect(
            self.display_panel.show_car_collided)
        self.thread.sig_dists.connect(self.display_panel.show_dists)
        self.thread.sig_results.connect(self.__get_results)
        self.thread.start()

    def __create_fuzzy_system(self):
        """Create a fuzzy system with the parameter given in control panel."""
        dist_front = FuzzyVariable()
        dist_front.add_membershipf(
            'small',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_front.small.get_values()))
        dist_front.add_membershipf(
            'medium',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_front.medium.get_values()))
        dist_front.add_membershipf(
            'large',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_front.large.get_values()))

        dist_lrdiff = FuzzyVariable()
        dist_lrdiff.add_membershipf(
            'small',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_lrdiff.small.get_values()))
        dist_lrdiff.add_membershipf(
            'medium',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_lrdiff.medium.get_values()))
        dist_lrdiff.add_membershipf(
            'large',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_lrdiff.large.get_values()))

        consequence = FuzzyVariable()
        consequence.add_membershipf(
            'small',
            get_gaussianf(
                *self.fuzzyvar_setting_consequence.small.get_values()))
        consequence.add_membershipf(
            'medium',
            get_gaussianf(
                *self.fuzzyvar_setting_consequence.medium.get_values()))
        consequence.add_membershipf(
            'large',
            get_gaussianf(
                *self.fuzzyvar_setting_consequence.large.get_values()))

        fuzzy_system = FuzzySystem(consequence, dist_front, dist_lrdiff)
        fuzzy_system.set_operation_types(
            self.implication_selections.get_selected_name(),
            self.combination_vars_selections.get_selected_name(),
            self.combination_rules_selections.get_selected_name(),
            self.defuzzifier_selections.get_selected_name())

        for antecendent_names, consequence_name in self.rules_setting.rules.items(
        ):
            fuzzy_system.add_rule(consequence_name, antecendent_names)

        return fuzzy_system
Exemplo n.º 2
0
class TrainingPanel(Panel):

    def __init__(self, datasets, testing_panel, threads):
        super().__init__()
        if isinstance(testing_panel, TestingPanel):
            self.testing_panel = testing_panel
        else:
            raise TypeError('"testing_panel" must be the instance of '
                            '"TestingPanel"')
        self.datasets = datasets
        self.threads = threads

        self.__set_execution_ui()
        self.__set_options_ui()
        self.__set_outputs_ui()
        self.__set_graphic_ui()

    def __set_execution_ui(self):
        group_box = QGroupBox('Training Execution')
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.data_selector = QComboBox()
        self.data_selector.addItems(list(self.datasets.keys()))
        self.data_selector.setStatusTip('Select the training dataset.')

        self.start_btn = QPushButton('Train')
        self.start_btn.setStatusTip('Start training.')
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton('Stop')
        self.stop_btn.setStatusTip('Force the training stop running.')
        self.stop_btn.setDisabled(True)

        self.multicore_cb = QCheckBox('Multicore')
        self.multicore_cb.setStatusTip('Use multiprocessing in calculating '
                                       'fitting for populations.')
        self.multicore_cb.setChecked(True)

        inner_layout.addWidget(self.data_selector, 1)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)
        inner_layout.addWidget(self.multicore_cb)

        self._layout.addWidget(group_box)

    def __set_options_ui(self):
        group_box = QGroupBox('Training Options')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.iter_times = QSpinBox()
        self.iter_times.setRange(1, 1000000)
        self.iter_times.setValue(200)
        self.iter_times.setStatusTip('The total iterating times for training.')

        self.population_size = QSpinBox()
        self.population_size.setRange(1, 100000)
        self.population_size.setValue(100)
        self.population_size.setStatusTip('The population size for the PSO.')

        self.inertia_weight = QDoubleSpinBox()
        self.inertia_weight.setRange(0, 50)
        self.inertia_weight.setValue(1)
        self.inertia_weight.setSingleStep(0.1)
        self.inertia_weight.setStatusTip('The inertia weight of the velocity '
                                         ' for each individual.')

        self.cognitive_const_rand_upper = QDoubleSpinBox()
        self.cognitive_const_rand_upper.setRange(0, 50)
        self.cognitive_const_rand_upper.setValue(2)
        self.cognitive_const_rand_upper.setSingleStep(0.1)
        self.cognitive_const_rand_upper.setStatusTip(
            'The random upper bound for cognitive accelerate constant.')

        self.social_const_rand_upper = QDoubleSpinBox()
        self.social_const_rand_upper.setRange(0, 50)
        self.social_const_rand_upper.setValue(3)
        self.social_const_rand_upper.setSingleStep(0.1)
        self.social_const_rand_upper.setStatusTip(
            'The random upper bound for social accelerate constant.')

        self.v_max = QDoubleSpinBox()
        self.v_max.setRange(0.5, 100)
        self.v_max.setValue(5)
        self.v_max.setSingleStep(1)
        self.v_max.setStatusTip('The maximum of velocity for each individual.')

        self.nneuron = QSpinBox()
        self.nneuron.setRange(1, 100)
        self.nneuron.setValue(6)
        self.nneuron.setStatusTip('The number of RBFN neuron.')

        self.sd_max = QDoubleSpinBox()
        self.sd_max.setRange(0.01, 20)
        self.sd_max.setValue(10)
        self.sd_max.setSingleStep(0.1)
        self.sd_max.setStatusTip('The random range maximum of standard '
                                 'deviation of each neuron in RBFN (only for '
                                 'initialization).')

        inner_layout.addRow('Iterating Times:', self.iter_times)
        inner_layout.addRow('Population Size:', self.population_size)
        inner_layout.addRow('Inertia Weight:', self.inertia_weight)
        inner_layout.addRow('Cognitive Const Upper:',
                            self.cognitive_const_rand_upper)
        inner_layout.addRow('Social Const Upper:',
                            self.social_const_rand_upper)
        inner_layout.addRow('Maximum of Velocity:', self.v_max)
        inner_layout.addRow('Number of Neuron:', self.nneuron)
        inner_layout.addRow('Maximum of SD:', self.sd_max)

        self._layout.addWidget(group_box)

    def __set_outputs_ui(self):
        group_box = QGroupBox('Training Details')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.current_iter_time = QLabel('--')
        self.current_error = QLabel('--')
        self.avg_error = QLabel('--')
        self.global_best_error = QLabel('--')
        self.total_best_error = QLabel('--')
        self.progressbar = QProgressBar()

        self.current_iter_time.setAlignment(Qt.AlignCenter)
        self.current_error.setAlignment(Qt.AlignCenter)
        self.avg_error.setAlignment(Qt.AlignCenter)
        self.global_best_error.setAlignment(Qt.AlignCenter)
        self.total_best_error.setAlignment(Qt.AlignCenter)

        self.current_iter_time.setStatusTip('The current iterating time of '
                                            'the PSO.')
        self.current_error.setStatusTip('The current error from the fitting '
                                        'function. ("( )": normalized error)')
        self.avg_error.setStatusTip('The average error from the fitting '
                                    'function in current iteration.  ("( )": '
                                    'normalized error)')
        self.global_best_error.setStatusTip(
            'The error of global best individual from the fitting function in '
            'current iteration.  ("( )": normalized error)')
        self.total_best_error.setStatusTip(
            'The error of total best individual from the fitting function in '
            'training.  ("( )": normalized error)')

        inner_layout.addRow('Current Iterating Time:', self.current_iter_time)
        inner_layout.addRow('Current Error:', self.current_error)
        inner_layout.addRow('Average Error:', self.avg_error)
        inner_layout.addRow('Global Best Error:', self.global_best_error)
        inner_layout.addRow('Total Best Error:', self.total_best_error)
        inner_layout.addRow(self.progressbar)

        self._layout.addWidget(group_box)

    def __set_graphic_ui(self):
        group_box = QGroupBox('Error Line Charts:')
        inner_layout = QVBoxLayout()
        group_box.setLayout(inner_layout)

        self.err_chart = ErrorLineChart(1)
        self.err_chart.setStatusTip('The history of error from the fitting '
                                    'of the PSO for each data.')
        self.__err_x = 1

        self.iter_err_chart = ErrorLineChart(
            3, ('Avg', 'Global Best', 'Total Best'))
        self.iter_err_chart.setStatusTip('The history of average and least '
                                         'error from the fitting of the PSO '
                                         'for each iteration.')
        self.iter_err_chart.setMinimumHeight(150)

        inner_layout.addWidget(QLabel('Current Error'))
        inner_layout.addWidget(self.err_chart)
        inner_layout.addWidget(QLabel('Average Error'))
        inner_layout.addWidget(self.iter_err_chart)
        self._layout.addWidget(group_box)

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.multicore_cb.setDisabled(True)
        self.data_selector.setDisabled(True)
        self.iter_times.setDisabled(True)
        self.population_size.setDisabled(True)
        self.inertia_weight.setDisabled(True)
        self.cognitive_const_rand_upper.setDisabled(True)
        self.social_const_rand_upper.setDisabled(True)
        self.v_max.setDisabled(True)
        self.nneuron.setDisabled(True)
        self.sd_max.setDisabled(True)
        self.err_chart.clear()
        self.iter_err_chart.clear()
        self.__err_x = 1

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.multicore_cb.setEnabled(True)
        self.data_selector.setEnabled(True)
        self.iter_times.setEnabled(True)
        self.population_size.setEnabled(True)
        self.inertia_weight.setEnabled(True)
        self.cognitive_const_rand_upper.setEnabled(True)
        self.social_const_rand_upper.setEnabled(True)
        self.v_max.setEnabled(True)
        self.nneuron.setEnabled(True)
        self.sd_max.setEnabled(True)
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)

    @Slot()
    def __indicate_busy(self):
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(0)

    @Slot(int)
    def __show_current_iter_time(self, value):
        self.current_iter_time.setText(str(value + 1))
        self.progressbar.setValue(value + 1)

    @Slot(float)
    def __show_current_error(self, value):
        self.current_error.setText('{:.5f} ({:.5f})'.format(value, value / 40))
        self.err_chart.append_point(self.__err_x, value)
        self.__err_x += 1

    @Slot(float, float, float)
    def __show_iter_error(self, avg, glob, total):
        self.avg_error.setText('{:.5f} ({:.5f})'.format(avg, avg / 40))
        self.global_best_error.setText(
            '{:.5f} ({:.5f})'.format(glob, glob / 40))
        self.total_best_error.setText(
            '{:.5f} ({:.5f})'.format(total, total / 40))
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), total, 2)
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), glob, 1)
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), avg, 0)

    def __run(self):
        self.progressbar.setMaximum(self.iter_times.value())

        self.__current_dataset = self.datasets[
            self.data_selector.currentText()]

        self.__pso = PSO(self.iter_times.value(), self.population_size.value(),
                         self.inertia_weight.value(),
                         self.cognitive_const_rand_upper.value(),
                         self.social_const_rand_upper.value(),
                         self.v_max.value(), self.nneuron.value(),
                         self.__current_dataset, self.sd_max.value(),
                         is_multicore=self.multicore_cb.isChecked())
        self.threads.append(self.__pso)
        self.stop_btn.clicked.connect(self.__pso.stop)
        self.__pso.started.connect(self.__init_widgets)
        self.__pso.finished.connect(self.__reset_widgets)
        self.__pso.sig_current_iter_time.connect(self.__show_current_iter_time)
        self.__pso.sig_current_error.connect(self.__show_current_error)
        self.__pso.sig_iter_error.connect(self.__show_iter_error)
        self.__pso.sig_indicate_busy.connect(self.__indicate_busy)
        self.__pso.sig_console.connect(self.testing_panel.print_console)
        self.__pso.sig_rbfn.connect(self.testing_panel.load_rbfn)
        self.__pso.start()
Exemplo n.º 3
0
class TestingPanel(Panel):
    def __init__(self, maps, threads):
        super().__init__()
        self.maps = maps
        self.rbfn = None
        self.threads = threads

        self.__set_execution_ui()
        self.__set_outputs_ui()
        self.__set_graphic_ui()
        self.__set_console_ui()

    def __set_execution_ui(self):
        group_box = QGroupBox('Testing Execution')
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.map_selector = QComboBox()
        self.map_selector.addItems(list(self.maps.keys()))
        self.map_selector.setStatusTip('Select the training dataset.')
        self.map_selector.currentIndexChanged.connect(self.__change_map)

        self.start_btn = QPushButton('Test')
        self.start_btn.setStatusTip(
            'Start testing. (available after training)')
        self.start_btn.setDisabled(True)
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton('Stop')
        self.stop_btn.setStatusTip('Force the testing stop running.')
        self.stop_btn.setDisabled(True)

        self.fps = QSpinBox()
        self.fps.setMinimum(1)
        self.fps.setMaximum(60)
        self.fps.setValue(20)
        self.fps.setStatusTip(
            "The re-drawing rate for car simulator. High fps "
            "may cause the plot shows discontinuously.")

        inner_layout.addWidget(self.map_selector, 1)
        inner_layout.addWidget(QLabel("FPS:"))
        inner_layout.addWidget(self.fps)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)

        self._layout.addWidget(group_box)

    def __set_outputs_ui(self):
        group_box = QGroupBox("Testing Details")
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.car_position = QLabel('--')
        self.car_angle = QLabel('--')
        self.wheel_angle = QLabel('--')
        self.dist_front = QLabel('--')
        self.dist_left = QLabel('--')
        self.dist_right = QLabel('--')

        self.car_position.setAlignment(Qt.AlignCenter)
        self.car_angle.setAlignment(Qt.AlignCenter)
        self.wheel_angle.setAlignment(Qt.AlignCenter)
        self.dist_front.setAlignment(Qt.AlignCenter)
        self.dist_left.setAlignment(Qt.AlignCenter)
        self.dist_right.setAlignment(Qt.AlignCenter)

        inner_layout.addRow('Car Position:', self.car_position)
        inner_layout.addRow('Car Angle:', self.car_angle)
        inner_layout.addRow('Wheel Angle:', self.wheel_angle)
        inner_layout.addRow('Front Distance:', self.dist_front)
        inner_layout.addRow('Left Distance:', self.dist_left)
        inner_layout.addRow('Right Distance:', self.dist_right)

        self._layout.addWidget(group_box)

    def __set_graphic_ui(self):
        self.simulator = CarSimulatorPlot()
        self.simulator.setStatusTip("Show the graphic of the car controled by "
                                    "the result of the PSO in mazz.")
        self.__change_map()
        self._layout.addWidget(self.simulator)

    def __set_console_ui(self):
        self.__console = QTextEdit()
        self.__console.setReadOnly(True)
        self.__console.setStatusTip("Show the logs of status changing.")
        self._layout.addWidget(self.__console)

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.fps.setDisabled(True)
        self.map_selector.setDisabled(True)

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.fps.setEnabled(True)
        self.map_selector.setEnabled(True)

    @Slot(str)
    def print_console(self, text):
        self.__console.append(text)

    @Slot(list, list, list)
    def __show_dists(self, pos, intersections, dists):
        self.simulator.paint_dist(pos, intersections)
        self.dist_front.setText(str(dists[0]))
        self.dist_left.setText(str(dists[1]))
        self.dist_right.setText(str(dists[2]))

    @Slot()
    def __show_car_collided(self):
        self.simulator.paint_car_collided()

    def __show_path(self, xdata, ydata):
        self.simulator.paint_path(xdata, ydata)

    @Slot()
    def __change_map(self):
        self.__current_map = self.maps[self.map_selector.currentText()]
        self.__car = Car(self.__current_map['start_pos'],
                         self.__current_map['start_angle'], 3,
                         self.__current_map['route_edge'])
        self.simulator.paint_map(self.__current_map)
        self.__move_car(self.__current_map['start_pos'],
                        self.__current_map['start_angle'])
        self.__show_dists(self.__current_map['start_pos'],
                          [self.__current_map['start_pos']] * 3, ['--'] * 3)

    @Slot(list, float, float)
    def __move_car(self, pos, angle, wheel_angle=0.0):
        self.simulator.paint_car(pos, angle)
        self.car_position.setText("({:.7f}, {:.7f})".format(*pos))
        self.car_angle.setText(str(angle))
        self.wheel_angle.setText(str(wheel_angle))

    @Slot(RBFN)
    def load_rbfn(self, rbfn):
        self.rbfn = rbfn
        self.print_console('New RBFN model has been loaded.')
        self.start_btn.setEnabled(True)

    @Slot()
    def __run(self):
        # reset the map
        self.__change_map()
        # create a QThread
        if self.rbfn is None:
            raise TypeError('The RBFN model has not yet loaded.')
        self.__thread = RunCar(self.__car, self.rbfn,
                               (self.__current_map['end_area_lt'],
                                self.__current_map['end_area_rb']),
                               self.fps.value())
        self.threads.append(self.__thread)
        self.stop_btn.clicked.connect(self.__thread.stop)
        self.__thread.started.connect(self.__init_widgets)
        self.__thread.finished.connect(self.__reset_widgets)
        self.__thread.sig_console.connect(self.print_console)
        self.__thread.sig_car.connect(self.__move_car)
        self.__thread.sig_car_collided.connect(self.__show_car_collided)
        self.__thread.sig_dists.connect(self.__show_dists)
        self.__thread.sig_results.connect(self.__get_results)
        self.__thread.start()

    @Slot(list)
    def __get_results(self, results):
        """Get the results of last running and draw the path of it."""
        self.simulator.paint_path([d['x'] for d in results],
                                  [d['y'] for d in results])