#!/usr/bin/env python # coding=utf-8 import os import rospy import rospkg import math import datetime from enums.clutch_state import ClutchState as CS from enums.stop_state import StopState as SS from python_qt_binding.QtGui import QPixmap from python_qt_binding.QtGui import QTextCursor from python_qt_binding.QtWidgets import QMessageBox class QtWrapper: def __init__(self,widget): self.widget = widget self.displayed_robots_id_list = [] self.clear_robot_info() ui_directory_path = '{0}/ui'.format(rospkg.RosPack().get_path('safety_user_plugin')) self.distance_pixmap = QPixmap('{0}/Distance.png'.format(ui_directory_path)) self.angular_pixmap = QPixmap('{0}/Angular.png'.format(ui_directory_path)) self.linear_pixmap = QPixmap('{0}/Linear.png'.format(ui_directory_path)) self.widget.distanceImage.setPixmap(self.distance_pixmap.scaled(66,46)) self.widget.angularImage.setPixmap(self.angular_pixmap) self.widget.linearImage.setPixmap(self.linear_pixmap.scaled(20,48)) self.ok_pixmap = QPixmap('{0}/Ok.jpg'.format(ui_directory_path)) self.cancel_pixmap = QPixmap('{0}/Cancel.jpg'.format(ui_directory_path)) def disconnect_signals(self): self.widget.clutchButton.clicked.disconnect() self.widget.stopButton.clicked.disconnect() self.widget.choiceButton.clicked.disconnect() def connect_robot_signals(self): self.widget.clutchButton.clicked.connect(self.handle_clutchButton_clicked_callback) self.widget.stopButton.clicked.connect(self.handle_stopButton_clicked) self.widget.choiceButton.clicked.connect(self.handle_closeButton_clicked) def connect_signals(self): self.widget.clutchButton.clicked.connect(self.handle_not_selected_error) self.widget.stopButton.clicked.connect(self.handle_not_selected_error) self.widget.choiceButton.clicked.connect(self.handle_openButton_clicked) def handle_emitted_signal(self,method_name): exec('self.{0}()'.format(method_name)) def handle_emitted_signal_with_list_argument(self,method_name,argument): if method_name == 'update_selected_robot_info': self.update_selected_robot_info(argument[0]) else: method_with_argument = 'self.{0}({1})'.format(method_name,argument[0]) exec(method_with_argument) def handle_stopButton_clicked(self): if self.robot_state == SS.RUNNING: self.handle_stopButton_clicked_callback() else: reply = QMessageBox.warning(self.widget,"UWAGA","Na pewno chcesz odblokować robota?",QMessageBox.Yes,QMessageBox.No) if reply == QMessageBox.Yes: self.handle_stopButton_clicked_callback() def get_selected_robot_id(self): current_text = self.widget.robotsList.currentText() if 'PIONIER' in current_text: return int(current_text[7:]) else: return None def display_clutch_on(self): # self.widget.clutchLabel.setPixmap(self.ok_pixmap.scaled(40,40)) self.widget.clutchButton.setStyleSheet("QPushButton { color: black; background-color: green; font: bold 20px}") self.widget.clutchButton.setText('Rozłącz sprzęgło') def display_clutch_off(self): # self.widget.clutchLabel.setPixmap(self.cancel_pixmap.scaled(40,40)) self.widget.clutchButton.setStyleSheet("QPushButton { color: black; background-color: red; font: bold 20px}") self.widget.clutchButton.setText('Połącz sprzęgło') def display_state_on(self): self.widget.stateLabel.setPixmap(self.ok_pixmap.scaled(40,40)) self.widget.stopButton.setStyleSheet("QPushButton { color: black; background-color: green; font: bold 20px}") self.widget.stopButton.setText('Zatrzymaj robota') self.robot_state = SS.RUNNING def display_state_off(self): self.widget.stateLabel.setPixmap(self.cancel_pixmap.scaled(40,40)) self.widget.stopButton.setStyleSheet("QPushButton { color: black; background-color: red; font: bold 20px}") self.widget.stopButton.setText('Odblokuj robota') self.robot_state = SS.STOPPED def handle_not_selected_error(self): self.log_error('Najpierw wybierz PIONIERA z listy robotów') def handle_openButton_clicked(self): selected_robot_id = self.get_selected_robot_id() if selected_robot_id != None: self.handle_openButton_clicked_callback(selected_robot_id) else: self.log_error('Najpierw wybierz PIONIERA z listy robotów') def handle_closeButton_clicked(self): self.handle_closeButton_clicked_callback() def set_robot_selection_callback(self,callback): self.handle_openButton_clicked_callback = callback def set_robot_release_callback(self,callback): self.handle_closeButton_clicked_callback = callback def set_user_stop_state_updated_callback(self,callback): self.handle_stopButton_clicked_callback = callback def set_clutch_switched_callback(self,callback): self.handle_clutchButton_clicked_callback = callback def select_robot(self,robot_id): self.disconnect_signals() self.connect_robot_signals() self.log_info('PIONIER{0} wybrany!'.format(robot_id)) self.log_info('Robot zostanie zatrzymany i sprzęgnięty') self.widget.choiceButton.setText('Zwolnij robota') def release_robot(self): self.disconnect_signals() self.connect_signals() self.log_info('Odłączam robota') self.clear_robot_info() def update_robots_list_gui(self,robots_id_list): robots_id_list.sort() id_strings_list = (('PIONIER'+str(x)) for x in robots_id_list) robots_to_add = [] robots_to_remove = [] for robot_id in robots_id_list: if robot_id not in self.displayed_robots_id_list: robots_to_add.append(robot_id) for robot_id in self.displayed_robots_id_list: if robot_id not in robots_id_list: robots_to_remove.append(robot_id) for robot_id in robots_to_remove: self.remove_robot_from_list(robot_id) for robot_id in robots_to_add: self.add_robot_to_list(robot_id) def remove_robot_from_list(self,robot_id): count = self.widget.robotsList.count() for i in range(count): if str(robot_id) in self.widget.robotsList.itemText(i): self.widget.robotsList.removeItem(i) self.displayed_robots_id_list.remove(robot_id) return def add_robot_to_list(self,robot_id): self.widget.robotsList.addItem('PIONIER{0}'.format(robot_id)) self.displayed_robots_id_list.append(robot_id) def update_selected_robot_info(self,robot_info): linear_vel = math.sqrt(robot_info.linear_velocity[0]**2 + robot_info.linear_velocity[1]**2) self.widget.idLabel.setText('PIONIER{0}'.format(robot_info.robot_id)) self.widget.batteryLabel.setText("{:.2f}".format(robot_info.battery_voltage)) self.widget.linearLabel.setText("{:.2f}".format(linear_vel)) self.widget.angularLabel.setText("{:.2f}".format(robot_info.angular_velocity[2])) # self.log_info(str(robot_info.clutch == CS.ENGAGED)) if robot_info.clutch == CS.ENGAGED: self.display_clutch_on() else: self.display_clutch_off() if robot_info.state == SS.RUNNING: self.display_state_on() else: self.display_state_off() if robot_info.obstacle_detected == True: self.widget.obstaclestopLabel.setPixmap(self.cancel_pixmap.scaled(40,40)) else: self.widget.obstaclestopLabel.setPixmap(self.ok_pixmap.scaled(40,40)) def master_stopped(self): self.widget.masterstopLabel.setPixmap(self.cancel_pixmap.scaled(40,40)) self.log_info('Przycisk masterSTOP został naciśnięty. Zatrzymuje roboty') def master_started(self): self.widget.masterstopLabel.setPixmap(self.ok_pixmap.scaled(40,40)) self.log_info('Przycisk masterSTOP odciśnięty. Mozesz uruchomić robota') def user_stopped(self): self.log_info('Robot zatrzymany') self.display_state_off() def user_started(self): self.log_info('Robot wystartował') self.display_state_on() def disengage_clutch(self): self.log_info('Rozprzęgam sprzęgło') self.display_clutch_off() def engage_clutch(self): self.log_info('Sprzęgam sprzegło') self.display_clutch_on() def master_is_stopped_notify(self): self.log_error('Nie można wystartować robota. MasterSTOP wciśnięty!') def obstacle_is_detected_notify(self): self.log_error('Nie mozna wystartować. Przeszkoda w polu działania robota') def robot_selected_by_another_group_notify(self): self.log_error('Nie mozna wybrać robota. Robot został już wybrany przez inną grupę') def update_restrictions_gui(self,restrictions): self.widget.distanceRestrictionLabel.setText("{:.2f}".format(restrictions.distance)) self.widget.linearRestrictionLabel.setText("{:.2f}".format(restrictions.linear_velocity)) self.widget.angularRestrictionLabel.setText("{:.2f}".format(restrictions.angular_velocity)) def log_info(self,info_text): time = datetime.datetime.now().strftime('[%H:%M:%S]') cursor = self.widget.logsBrowser.textCursor() cursor.movePosition(QTextCursor.End) self.widget.logsBrowser.setTextCursor(cursor) self.widget.logsBrowser.insertHtml(' {0} {1}
'.format(time,info_text)) self.scroll_to_bottom() # self.widget.logsBrowser.insertHtml(str(self.logger_counter) + '\t[INFO]\t' + info_text) def log_warning(self,warning_text): time = datetime.datetime.now().strftime('[%H:%M:%S]') cursor = self.widget.logsBrowser.textCursor() cursor.movePosition(QTextCursor.End) self.widget.logsBrowser.setTextCursor(cursor) self.widget.logsBrowser.textCursor().movePosition(QTextCursor.End) self.widget.logsBrowser.insertHtml(' {0} {1}
'.format(time,warning_text)) self.scroll_to_bottom() # self.widget.logsBrowser.append(str(self.logger_counter) + '\t[WARN]\t' + warning_text) def log_error(self,error_text): time = datetime.datetime.now().strftime('[%H:%M:%S]') cursor = self.widget.logsBrowser.textCursor() cursor.movePosition(QTextCursor.End) self.widget.logsBrowser.setTextCursor(cursor) self.widget.logsBrowser.textCursor().movePosition(QTextCursor.End) self.widget.logsBrowser.insertHtml(' {0} {1}
'.format(time,error_text)) self.scroll_to_bottom() # self.widget.logsBrowser.append(str(self.logger_counter) + '\t[ERROR]\t' + error_text) def connection_to_robot_lost(self,lost_robot_id): self.clear_robot_info() self.disconnect_signals() self.connect_signals() self.log_info('Utrata połączenia z robotem PIONIER{0}'.format(lost_robot_id)) def connection_to_master_lost(self): self.log_error('Utrata połączenia z masterstopem. Poproś prowadzącego o jego uruchomienie') def obstacle_detected(self): self.log_error('Przeszkoda wykryta. Zatrzymuję robota') # TODO Zmiana def obstacle_removed(self): self.log_info('Przeszkoda usunięta') def scroll_to_bottom(self): scrollbar = self.widget.logsBrowser.verticalScrollBar() scrollbar.setValue(scrollbar.maximum()) def clear_robot_info(self): self.widget.idLabel.setText('-') self.widget.batteryLabel.setText('-') self.widget.linearLabel.setText('-') self.widget.angularLabel.setText('-') self.widget.stateLabel.setText('-') self.widget.masterstopLabel.setText('-') self.widget.obstaclestopLabel.setText('-') self.widget.choiceButton.setText('Wybierz') self.widget.stopButton.setText('-') self.widget.stopButton.setStyleSheet("") self.widget.clutchButton.setText('-') self.widget.clutchButton.setStyleSheet("")