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
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()
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])