slider_simple.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import math
00004 import new
00005 import os
00006 import random
00007 import signal
00008 from StringIO import StringIO
00009 import sys
00010 import tempfile
00011 
00012 import roslib
00013 roslib.load_manifest('python_qt_binding')
00014 roslib.load_manifest('rviz')
00015 roslib.load_manifest('rviz_backdrop')
00016 roslib.load_manifest('slider_gui')
00017 import rospy;
00018 
00019 #setattr(sys, 'SELECT_QT_BINDING', 'pyside')
00020 from python_qt_binding.QtBindingHelper import loadUi
00021 from QtCore import QEvent, qFatal, QModelIndex, QObject, QRect, QRegExp, QSignalMapper, Qt, QTimer, Signal
00022 from QtGui import QApplication, QColor, QDialog, QFileDialog, QIcon, QItemSelectionModel, QKeyEvent, QMainWindow, QMessageBox, QPalette, QPixmap, QSplitter, QTableView, QVBoxLayout, QWidget
00023 from actions.DefaultAction import DefaultAction
00024 from CollisionChecker import CollisionChecker
00025 from DoubleSpinBoxDelegate import DoubleSpinBoxDelegate
00026 from KontrolSubscriber import KontrolSubscriber
00027 from PosesDataModel import PosesDataModel
00028 from actions.ActionSet import ActionSet
00029 from actions.Pr2LookAtFace import Pr2LookAtFace
00030 from actions.Pr2MoveHeadAction import Pr2MoveHeadAction
00031 from actions.Pr2MoveLeftArmAction import Pr2MoveLeftArmAction
00032 from actions.Pr2MoveRightArmAction import Pr2MoveRightArmAction
00033 from pr2_controllers_msgs.msg import *
00034 import pr2_mechanism_msgs.srv._ListControllers
00035 import pr2_mechanism_msgs.srv._LoadController
00036 import pr2_mechanism_msgs.srv._SwitchController
00037 from ProgramQueue import ProgramQueue
00038 from Ps3Subscriber import Ps3Subscriber
00039 import rviz
00040 from sensor_msgs.msg import CompressedImage
00041 from sensor_msgs.msg import Image
00042 from sensor_msgs.msg import JointState 
00043 from SimpleFormat import SimpleFormat
00044 import std_srvs.srv._Empty
00045 from trajectory_msgs.msg import *
00046 
00047 app = QApplication(sys.argv)
00048 
00049 check_collisions = '--no-collision' not in sys.argv
00050 show_point_clouds = '--with-point-clouds' in sys.argv
00051 
00052 main_window = QMainWindow()
00053 ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'src', 'slider_simple.ui')
00054 loadUi(ui_file, main_window)
00055 
00056 # set icons for tabs
00057 icons = {
00058     0: 'square.png',
00059     1: 'triangle.png',
00060     2: 'circle.png',
00061     3: 'cross.png',
00062 }
00063 for index, filename in icons.iteritems():
00064     filename = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'icons', filename))
00065     icon = QIcon(filename)
00066     if not icon.isNull():
00067         main_window.PoseList_tabWidget.setTabText(index, '')
00068         main_window.PoseList_tabWidget.setTabIcon(index, icon)
00069 
00070 # hide design-only widgets
00071 #main_window.square_tableWidget.setVisible(False)
00072 
00073 sigint_called = False
00074 def sigint_handler(*args):
00075     global sigint_called
00076     print('\nsigint_handler()')
00077     sigint_called = True
00078     main_window.close()
00079 signal.signal(signal.SIGINT, sigint_handler)
00080 # the timer enables triggering the sigint_handler
00081 timer = QTimer()
00082 timer.start(500)
00083 timer.timeout.connect(lambda: None)
00084 
00085 # replace placeholder with rviz visualization panel
00086 index = main_window.robot_view_verticalLayout.indexOf(main_window.robot_view_widget)
00087 stretch = main_window.robot_view_verticalLayout.stretch(index)
00088 main_window.robot_view_verticalLayout.removeWidget(main_window.robot_view_widget)
00089 robot_view = rviz.VisualizationPanel()
00090 # hide rviz display list
00091 robot_view.children()[1].hide()
00092 main_window.robot_view_verticalLayout.insertWidget(index, robot_view, stretch)
00093 robot_view.setSizes([0])
00094 
00095 config = tempfile.NamedTemporaryFile('w')
00096 if not show_point_clouds:
00097     config.write("""Backdrop.Enabled=1
00098 Backdrop.Scale=4
00099 Backdrop.Topic=/backdrop
00100 Background\ ColorB=0
00101 Background\ ColorG=0
00102 Background\ ColorR=0
00103 Camera\ Config=0.905202 5.83579 18.0278 0 -1.90735e-06 1.90735e-06
00104 Camera\ Type=rviz::OrbitViewController
00105 Fixed\ Frame=/base_link
00106 Grid.Alpha=0.5
00107 Grid.Cell\ Size=1
00108 Grid.ColorB=0.5
00109 Grid.ColorG=0.5
00110 Grid.ColorR=0.5
00111 Grid.Enabled=1
00112 Grid.Line\ Style=0
00113 Grid.Line\ Width=0.03
00114 Grid.Normal\ Cell\ Count=0
00115 Grid.OffsetX=0
00116 Grid.OffsetY=0
00117 Grid.OffsetZ=0
00118 Grid.Plane=0
00119 Grid.Plane\ Cell\ Count=8
00120 Grid.Reference\ Frame=<Fixed Frame>
00121 RobotModel.Alpha=1
00122 RobotModel.Collision\ Enabled=0
00123 RobotModel.Enabled=1
00124 RobotModel.Robot\ Description=robot_description
00125 RobotModel.TF\ Prefix=
00126 RobotModel.Update\ Interval=0
00127 RobotModel.Visual\ Enabled=1
00128 Target\ Frame=<Fixed Frame>
00129 [Display0]
00130 ClassName=rviz::GridDisplay
00131 Name=Grid
00132 [Display1]
00133 ClassName=rviz_backdrop::BackdropDisplay
00134 Name=Backdrop
00135 [Display2]
00136 ClassName=rviz::RobotModelDisplay
00137 Name=RobotModel
00138 """)
00139 else:
00140     config.write("""Backdrop.Enabled=1
00141 Backdrop.Scale=4
00142 Backdrop.Topic=/backdrop
00143 Background\ ColorB=0
00144 Background\ ColorG=0
00145 Background\ ColorR=0
00146 Camera\ Config=0.905202 5.83579 18.0278 0 -1.90735e-06 1.90735e-06
00147 Camera\ Type=rviz::OrbitViewController
00148 Fixed\ Frame=/base_link
00149 Grid.Alpha=0.5
00150 Grid.Cell\ Size=1
00151 Grid.ColorB=0.5
00152 Grid.ColorG=0.5
00153 Grid.ColorR=0.5
00154 Grid.Enabled=1
00155 Grid.Line\ Style=0
00156 Grid.Line\ Width=0.03
00157 Grid.Normal\ Cell\ Count=0
00158 Grid.OffsetX=0
00159 Grid.OffsetY=0
00160 Grid.OffsetZ=0
00161 Grid.Plane=0
00162 Grid.Plane\ Cell\ Count=8
00163 Grid.Reference\ Frame=<Fixed Frame>
00164 PointCloud2..AxisColorAutocompute\ Value\ Bounds=1
00165 PointCloud2..AxisColorAxis=2
00166 PointCloud2..AxisColorMax\ Value=0.919509
00167 PointCloud2..AxisColorMin\ Value=-0.0470135
00168 PointCloud2..AxisColorUse\ Fixed\ Frame=1
00169 PointCloud2..FlatColorColorB=1
00170 PointCloud2..FlatColorColorG=1
00171 PointCloud2..FlatColorColorR=1
00172 PointCloud2..IntensityAutocompute\ Intensity\ Bounds=1
00173 PointCloud2..IntensityChannel\ Name=intensity
00174 PointCloud2..IntensityMax\ ColorB=1
00175 PointCloud2..IntensityMax\ ColorG=1
00176 PointCloud2..IntensityMax\ ColorR=1
00177 PointCloud2..IntensityMax\ Intensity=4096
00178 PointCloud2..IntensityMin\ ColorB=0
00179 PointCloud2..IntensityMin\ ColorG=0
00180 PointCloud2..IntensityMin\ ColorR=0
00181 PointCloud2..IntensityMin\ Intensity=0
00182 PointCloud2..IntensityUse\ full\ RGB\ spectrum=0
00183 PointCloud2.Alpha=1
00184 PointCloud2.Billboard\ Size=0.003
00185 PointCloud2.Color\ Transformer=RGB8
00186 PointCloud2.Decay\ Time=0
00187 PointCloud2.Enabled=1
00188 PointCloud2.Position\ Transformer=XYZ
00189 PointCloud2.Queue\ Size=10
00190 PointCloud2.Selectable=1
00191 PointCloud2.Style=1
00192 PointCloud2.Topic=/head_mount_kinect/depth_registered/points
00193 RobotModel.Alpha=1
00194 RobotModel.Collision\ Enabled=0
00195 RobotModel.Enabled=1
00196 RobotModel.Robot\ Description=robot_description
00197 RobotModel.TF\ Prefix=
00198 RobotModel.Update\ Interval=0
00199 RobotModel.Visual\ Enabled=1
00200 Target\ Frame=<Fixed Frame>
00201 [Display0]
00202 ClassName=rviz::GridDisplay
00203 Name=Grid
00204 [Display1]
00205 ClassName=rviz_backdrop::BackdropDisplay
00206 Name=Backdrop
00207 [Display2]
00208 ClassName=rviz::RobotModelDisplay
00209 Name=RobotModel
00210 [Display3]
00211 ClassName=rviz::PointCloud2Display
00212 Name=PointCloud2
00213 """)
00214     
00215 config.flush()
00216 robot_view.loadDisplayConfig(config.name)
00217 config.close
00218 
00219 
00220 # set up viewports for camera
00221 views = []
00222 view_mapper = QSignalMapper(main_window)
00223 def set_view(index):
00224     robot_view.setViewString(views[index])
00225 view_mapper.mapped.connect(set_view)
00226 def view_selected(checked):
00227     if checked:
00228         view_mapper.map()
00229 def add_view(button, view_str):
00230     view_mapper.setMapping(button, len(views))
00231     views.append(view_str)
00232     if button.isChecked():
00233         set_view(len(views) - 1)
00234     button.clicked.connect(view_mapper.map)
00235 add_view(main_window.front_view_radioButton, '0.0402028 6.2758 2.24508 0.00208002 -0.0024735 0.753009')
00236 add_view(main_window.side_view_radioButton, '-0.0747972 4.83578 2.81623 -0.0104112 -0.00416593 0.984444')
00237 add_view(main_window.angled_view_radioButton, '0.175202 5.59079 2.81623 -0.0104112 -0.00416593 0.984444')
00238 
00239 rospy.init_node('proto_simple', disable_signals=True)
00240 try:
00241     use_sim_time = rospy.get_param('use_sim_time')
00242 except KeyError:
00243     use_sim_time = False
00244 
00245 
00246 # publish image for backdrop
00247 
00248 # Note: this is not doing a complete proper ROS image transport
00249 # publisher.  That doesn't support Python.  Instead, I'm publishing
00250 # directly on the /backdrop/compressed topic a
00251 # sensor_msgs/CompressedImage message, with the raw jpeg data just
00252 # loaded into it.  This way my python file doesn't have to decode or
00253 # convert the image data at all.  It does mean when you ask RViz for
00254 # the available image topics, this won't show up, you'll have to type
00255 # "/backdrop" directly into the topic field.  (RViz adds
00256 # "/compressed".)
00257 
00258 backdrop_publisher = rospy.Publisher('/backdrop/compressed', CompressedImage, latch=True)
00259 scenes = []
00260 def set_scene(index):
00261     image = CompressedImage()
00262     # image.header.frame_id = '/odom_combined'
00263     # If you ever want to drive the base, you will want to use the line above, or /map or something.
00264     # Using /base_link means the robot will always stay exactly in the middle of the backdrop.
00265     image.header.frame_id = '/base_link'
00266     image.format = 'jpeg'
00267     try:
00268         scene = scenes[index]
00269     except TypeError:
00270         index = main_window.scene_comboBox.findText(index)
00271         scene = scenes[index]
00272     image.data = open(scene).read()
00273     image.header.stamp = rospy.Time.now()
00274     backdrop_publisher.publish(image)
00275 path = os.path.join(os.path.dirname(__file__), '..', 'images')
00276 for filename in os.listdir(path):
00277     (root, ext) = os.path.splitext(filename)
00278     if ext in ['.jpg']:
00279         filename = os.path.join(path, filename)
00280         scenes.append(filename)
00281 scenes.sort()
00282 for index, filename in enumerate(scenes):
00283     (root, ext) = os.path.splitext(filename)
00284     text = os.path.basename(root)
00285     main_window.scene_comboBox.insertItem(index, text)
00286 main_window.scene_comboBox.currentIndexChanged.connect(set_scene)
00287 index = main_window.scene_comboBox.findText('None')
00288 if index != -1:
00289     main_window.scene_comboBox.setCurrentIndex(index)
00290 
00291 
00292 
00293 def reset_sim():
00294     print 'reset_sim()'
00295     service = '/gazebo/reset_simulation'
00296     rospy.wait_for_service(service)
00297     reset_sim_service = rospy.ServiceProxy(service, std_srvs.srv._Empty.Empty)
00298     try:
00299         reset_sim_service()
00300     except rospy.ServiceException, e:
00301         print "Service did not process request: %s" % str(e)
00302 
00303 main_window.reset_sim_pushButton.clicked.connect(reset_sim)
00304 if not show_point_clouds:
00305     main_window.reset_sim_pushButton.setVisible(False)
00306 
00307 def autosave_program():
00308     print 'autosave_program()'
00309     save_to_filename(os.path.expanduser('~/_autosave.pt'))
00310 
00311 def update_sequence_duration():
00312     print 'update_sequence_duration()'
00313     model = get_current_model()
00314     main_window.sequence_duration_label.setText('%.1f' % model.action_sequence().get_duration())
00315 
00316 def current_tab_changed(index):
00317     update_sequence_duration()
00318 main_window.PoseList_tabWidget.currentChanged.connect(current_tab_changed)
00319 
00320 
00321 class TrajectoryLock():
00322     def __init__(self, ns, joint_bounds):
00323         self._ns = ns
00324         self._subscriber = None
00325         self._joint_bounds = [float(x) for x in joint_bounds]
00326         self._publisher = rospy.Publisher('/%s/command' % ns, trajectory_msgs.msg.JointTrajectory)
00327 
00328     def start(self):
00329         print 'TrajectoryLock.start()'
00330         if self._subscriber is not None:
00331             self._subscriber.unregister()
00332         self._subscriber = rospy.Subscriber('/%s/state' % self._ns, pr2_controllers_msgs.msg.JointTrajectoryControllerState, self._receive_state)
00333 
00334     def stop(self):
00335         print 'TrajectoryLock.stop()'
00336         if self._subscriber is not None:
00337             self._subscriber.unregister()
00338             self._subscriber = None
00339 
00340     def _receive_state(self, msg):
00341         max_error = max([abs(x) for x in msg.error.positions])
00342 
00343         exceeded = [abs(x) > y for x,y in zip(msg.error.positions, self._joint_bounds)]
00344 
00345         #print "All: %s" % "  ".join(["% .4f" % x for x in msg.error.positions] )
00346 
00347         if any(exceeded):
00348             #print "Exceeded: %.4f" % max_error
00349 
00350             # Copy our current state into the commanded state
00351             cmd = trajectory_msgs.msg.JointTrajectory()
00352             cmd.header.stamp = msg.header.stamp
00353             cmd.joint_names = msg.joint_names
00354             cmd.points.append(trajectory_msgs.msg.JointTrajectoryPoint())
00355             cmd.points[0].time_from_start = rospy.Duration(.125)
00356             cmd.points[0].positions = msg.actual.positions
00357             self._publisher.publish(cmd)
00358         #else:
00359             #print "Small: %.4f" % max_error
00360 
00361 # pass signal across thread boundaries
00362 class JointObserver(QObject):
00363     current_values_changed = Signal(str)
00364     _update_current_value_signal = Signal()
00365     def __init__(self):
00366         super(JointObserver, self).__init__()
00367         self.action_set = None
00368         self._latest_joint_state = None
00369         self._update_current_value_signal.connect(self._update_current_value)
00370         self._subscriber = None
00371         self._trajectory_locks = []
00372         self._trajectory_locks.append(TrajectoryLock('head_traj_controller_loose', [.08, .08]))
00373         self._trajectory_locks.append(TrajectoryLock('l_arm_controller_loose', [.02, .02, .02, .02, .02, .06, .06]))
00374         self._trajectory_locks.append(TrajectoryLock('r_arm_controller_loose', [.02, .02, .02, .02, .02, .06, .06]))
00375 
00376     def start(self):
00377         print 'JointObserver.start()'
00378         if self._subscriber is not None:
00379             self._subscriber.unregister()
00380         self._subscriber = rospy.Subscriber('/joint_states', JointState, self._receive_joint_states)
00381         for trajectory_lock in self._trajectory_locks:
00382             trajectory_lock.start()
00383 
00384     def stop(self):
00385         print 'JointObserver.stop()'
00386         if self._subscriber is not None:
00387             self._subscriber.unregister()
00388             self._subscriber = None
00389         for trajectory_lock in self._trajectory_locks:
00390             trajectory_lock.stop()
00391 
00392     def _receive_joint_states(self, joint_state_msg):
00393         self._latest_joint_state = joint_state_msg
00394         self._update_current_value_signal.emit()
00395 
00396     def _update_current_value(self):
00397         self.action_set = ActionSet()
00398         self.action_set.add_action(Pr2MoveHeadAction())
00399         self.action_set.add_action(Pr2MoveLeftArmAction())
00400         self.action_set.add_action(Pr2MoveRightArmAction())
00401 
00402         labels = self.action_set.get_labels()
00403 
00404         for label in labels:
00405             value = self._latest_joint_state.position[self._latest_joint_state.name.index(label)]
00406             value *= 180.0 / math.pi
00407             try:
00408                 self.action_set.update_value(label, value)
00409             except KeyError, e:
00410                 print 'JointObserver._update_current_value() label "%s" not found' % label
00411                 pass
00412 
00413         value = self.action_set.to_string()
00414         self.current_values_changed.emit(value)
00415 
00416 joint_observer = JointObserver()
00417 joint_observer.current_values_changed.connect(main_window.lineEdit.setText)
00418 
00419 
00420 INPUT_METHOD_SLIDERS = 0
00421 INPUT_METHOD_INTERACTIVE_MARKERS = 1
00422 INPUT_METHOD_ROBOT = 2
00423 main_window.input_method_comboBox.addItem('Sliders', INPUT_METHOD_SLIDERS)
00424 #main_window.input_method_comboBox.addItem('Interactive Markers', INPUT_METHOD_INTERACTIVE_MARKERS)
00425 if not use_sim_time:
00426     main_window.input_method_comboBox.addItem('Robot', INPUT_METHOD_ROBOT)
00427 def is_in_slider_mode():
00428     return main_window.input_method_comboBox.currentIndex() == INPUT_METHOD_SLIDERS
00429 
00430 def load_controllers(controllers):
00431     service = '/pr2_controller_manager/list_controllers'
00432     rospy.wait_for_service(service)
00433     service_proxy = rospy.ServiceProxy(service, pr2_mechanism_msgs.srv._ListControllers.ListControllers)
00434     try:
00435         request = pr2_mechanism_msgs.srv._ListControllers.ListControllersRequest()
00436         response = service_proxy(request)
00437         loaded_controllers = response.controllers
00438     except rospy.ServiceException, e:
00439         print 'Service did not process request: %s' % str(e)
00440         return False
00441 
00442     service = '/pr2_controller_manager/load_controller'
00443     rospy.wait_for_service(service)
00444     for name in controllers:
00445         if name in loaded_controllers:
00446             print 'load_controllers()', 'skip already loaded', name
00447             continue
00448         print 'load_controllers()', name
00449         service_proxy = rospy.ServiceProxy(service, pr2_mechanism_msgs.srv._LoadController.LoadController)
00450         try:
00451             request = pr2_mechanism_msgs.srv._LoadController.LoadControllerRequest()
00452             request.name = name
00453             response = service_proxy(request)
00454             if not response.ok:
00455                 return False
00456         except rospy.ServiceException, e:
00457             print 'Service did not process request: %s' % str(e)
00458             return False
00459     return True
00460 
00461 def switch_controllers(start_controllers, stop_controllers):
00462     print 'switch_controllers()'
00463     service = '/pr2_controller_manager/switch_controller'
00464     rospy.wait_for_service(service)
00465     service_proxy = rospy.ServiceProxy(service, pr2_mechanism_msgs.srv._SwitchController.SwitchController)
00466     try:
00467         request = pr2_mechanism_msgs.srv._SwitchController.SwitchControllerRequest()
00468         request.start_controllers = start_controllers
00469         request.stop_controllers = stop_controllers
00470         response = service_proxy(request)
00471         if not response.ok:
00472             return False
00473     except rospy.ServiceException, e:
00474         print 'Service did not process request: %s' % str(e)
00475         return False
00476     return True
00477 
00478 manniquin_controllers_loaded = False
00479 def change_input_method():
00480     global manniquin_controllers_loaded
00481     global joint_observer
00482     index = main_window.input_method_comboBox.currentIndex()
00483     input_method = main_window.input_method_comboBox.itemData(index)
00484     print 'change_input_method()', index
00485 
00486     manniquin_controllers = ['r_arm_controller_loose', 'l_arm_controller_loose', 'head_traj_controller_loose']
00487     standard_controllers = ['r_arm_controller', 'l_arm_controller', 'head_traj_controller']
00488     if input_method == INPUT_METHOD_ROBOT:
00489         # setup controllers for manniquin mode
00490         if not manniquin_controllers_loaded:
00491             # load controllers once
00492             print 'change_input_method()', 'load manniquin controllers'
00493             manniquin_controllers_loaded = load_controllers(manniquin_controllers)
00494             if not manniquin_controllers_loaded:
00495                 QMessageBox.critical(main_window, main_window.tr('Loading controllers failed'), main_window.tr('Could not load manniquin controllers.'))
00496         # switch to manniquin controllers
00497         success = switch_controllers(manniquin_controllers, standard_controllers)
00498         if success:
00499             joint_observer.start()
00500     else:
00501         # restore standard controllers
00502         success = switch_controllers(standard_controllers, manniquin_controllers)
00503         if success:
00504             joint_observer.stop()
00505     if not success:
00506         QMessageBox.critical(main_window, main_window.tr('Switching controllers failed'), main_window.tr('Could not switch controllers.'))
00507 
00508 main_window.input_method_comboBox.setCurrentIndex(INPUT_METHOD_SLIDERS)
00509 main_window.input_method_comboBox.currentIndexChanged.connect(change_input_method)
00510 if main_window.input_method_comboBox.count() <= 1:
00511     main_window.input_method_label.setVisible(False)
00512     main_window.input_method_comboBox.setVisible(False)
00513     main_window.input_method_horizontalLayout.parent().removeItem(main_window.input_method_horizontalLayout)
00514 
00515 
00516 kontrol_subscriber = KontrolSubscriber()
00517 if check_collisions:
00518     collision_checker = CollisionChecker()
00519 currently_in_collision = False
00520 default_color = main_window.lineEdit.palette().text().color()
00521 
00522 # pass signal across thread boundaries
00523 class Foo(QObject):
00524     current_values_changed = Signal(str)
00525     current_duration_changed = Signal(float)
00526     _update_current_value_signal = Signal()
00527     _show_input_notification_signal = Signal()
00528     _hide_input_notification_signal = Signal()
00529     _show_scene_notification_signal = Signal()
00530     _hide_scene_notification_signal = Signal()
00531     _update_color_of_line_edit_signal = Signal()
00532     def __init__(self):
00533         super(Foo, self).__init__()
00534         self._action_set = None
00535         self._update_current_value_signal.connect(self._update_current_value)
00536 
00537         self._scene_notification = QDialog(main_window)
00538         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'src', 'wrong_scene_dialog.ui')
00539         loadUi(ui_file, self._scene_notification)
00540         self._scene_notification_timer = QTimer(main_window)
00541         self._scene_notification_timer.setInterval(5000)
00542         self._scene_notification_timer.setSingleShot(True)
00543         self._scene_notification_timer.timeout.connect(self._hide_scene_notification)
00544         self._scene_notification.finished.connect(self._hide_scene_notification)
00545 
00546         self._input_notification = QDialog(main_window)
00547         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'src', 'wrong_input_method_dialog.ui')
00548         loadUi(ui_file, self._input_notification)
00549         self._input_notification_timer = QTimer(main_window)
00550         self._input_notification_timer.setInterval(5000)
00551         self._input_notification_timer.setSingleShot(True)
00552         self._input_notification_timer.timeout.connect(self._hide_input_method_notification)
00553         self._input_notification.finished.connect(self._hide_input_method_notification)
00554 
00555         self._show_input_notification_signal.connect(self._show_input_notification)
00556         self._hide_input_notification_signal.connect(self._hide_input_method_notification)
00557         self._show_input_notification_signal.connect(self._show_scene_notification)
00558         self._hide_input_notification_signal.connect(self._hide_scene_notification)
00559         self._update_color_of_line_edit_signal.connect(self._update_color_of_line_edit)
00560 
00561     def _hide_scene_notification(self, result=None):
00562         self._scene_notification_timer.stop()
00563         self._scene_notification.hide()
00564 
00565     def _hide_input_method_notification(self, result=None):
00566         self._input_notification_timer.stop()
00567         self._input_notification.hide()
00568 
00569     # this method is call by ROS, all UI interaction is delayed via signals
00570     def update_current_value(self):
00571         global check_collisions
00572         global currently_in_collision
00573 
00574         if self._action_set is not None:
00575             self._action_set.stop()
00576         self._action_set = kontrol_subscriber.get_action_set()
00577         if self._action_set is not None:
00578             self.current_duration_changed.emit(self._action_set.get_duration())
00579 
00580         if not is_in_slider_mode():
00581             currently_in_collision = False
00582             self._show_input_notification_signal.emit()
00583             return
00584         if self._input_notification_timer.isActive():
00585             self._hide_input_notification_signal.emit()
00586 
00587         #print('update_current_value()')
00588         if not kontrol_subscriber.is_valid_action_set():
00589             self._show_scene_notification_signal.emit()
00590             return
00591         if self._scene_notification_timer.isActive():
00592             self._hide_scene_notification_signal.emit()
00593 
00594         joint_values = kontrol_subscriber.get_joint_values()
00595         if check_collisions:
00596             in_collision = collision_checker.is_in_collision(joint_values)
00597         else:
00598             in_collision = False
00599 
00600         collision_toggled = (currently_in_collision != in_collision)
00601         currently_in_collision = in_collision
00602 
00603         if collision_toggled:
00604             self._update_color_of_line_edit_signal.emit()
00605 
00606         self._update_current_value_signal.emit()
00607 
00608     def _show_input_notification(self):
00609         # open dialog which closes after some s_hide_scene_notification_hide_scene_notificationeconds or when confirmed manually
00610         self._input_notification.show()
00611         self._input_notification_timer.start()
00612 
00613     def _show_scene_notification(self):
00614         # open dialog which closes after some seconds or when confirmed manually
00615         self._scene_notification.show()
00616         self._scene_notification_timer.start()
00617 
00618     def _update_color_of_line_edit(self):
00619         global currently_in_collision
00620         palette = main_window.lineEdit.palette()
00621         if currently_in_collision:
00622             palette.setColor(QPalette.Text, QColor(255, 0, 0))
00623         else:
00624             palette.setColor(QPalette.Text, default_color)
00625         main_window.lineEdit.setPalette(palette)
00626 
00627     def _update_current_value(self):
00628         global currently_in_collision
00629         main_window.append_pushButton.setEnabled(not currently_in_collision)
00630         main_window.insert_before_pushButton.setEnabled(not currently_in_collision)
00631 
00632         value = self._action_set.to_string()
00633         self.current_values_changed.emit(value)
00634         for action in self._action_set._actions:
00635             action._duration = 0.1 if use_sim_time else 0.5
00636         self._action_set.execute()
00637 foo = Foo()
00638 
00639 kontrol_subscriber.axes_changed.connect(foo.update_current_value)
00640 foo.current_values_changed.connect(main_window.lineEdit.setText)
00641 foo.current_duration_changed.connect(main_window.duration_doubleSpinBox.setValue)
00642 
00643 def get_tab_widget(index):
00644     return main_window.PoseList_tabWidget.widget(index)
00645 
00646 def get_table_view(index):
00647     tab_widget = get_tab_widget(index)
00648     return tab_widget.findChildren(QTableView, QRegExp('.*_tableView'))[0]
00649 
00650 def get_current_tab_index():
00651     return main_window.PoseList_tabWidget.currentIndex()
00652 
00653 def test_clicked(index):
00654     try:
00655         row = index.row()
00656     except:
00657         row = int(index)
00658     model = get_current_model()
00659     print 'execute %d' % row
00660     model.action_sequence().actions()[row].execute()
00661 
00662 # override tab order by ignoring non-editable cells
00663 def custom_focusNextPrevChild(self, next, old_focusNextPrevChild=QTableView.focusNextPrevChild):
00664     rc = old_focusNextPrevChild(self, next)
00665     if self.tabKeyNavigation() and self.currentIndex().isValid() and not(self.currentIndex().flags() & Qt.ItemIsEditable):
00666         # repeat same key press when cell is not editable
00667         event = QKeyEvent(QEvent.KeyPress, Qt.Key_Tab, Qt.ShiftModifier if next else Qt.NoModifier)
00668         self.keyPressEvent(event)
00669         if event.isAccepted():
00670             return True
00671     return rc
00672 
00673 # override key press event to handle delete key pressed
00674 def custom_keyPressEvent(self, event, old_keyPressEvent=QTableView.keyPressEvent):
00675     if event.key() == Qt.Key_Delete and event.modifiers() == Qt.NoModifier:
00676         if delete_selected():
00677             print 'custom_keyPressEvent()', 'delete row'
00678             event.accept()
00679             return True
00680     return old_keyPressEvent(self, event)
00681 
00682 for i in range(main_window.PoseList_tabWidget.count()):
00683     table_view = get_table_view(i)
00684     table_view.focusNextPrevChild = new.instancemethod(custom_focusNextPrevChild, table_view, None)
00685     table_view.keyPressEvent = new.instancemethod(custom_keyPressEvent, table_view, None)
00686 
00687 # create models for each table view in the tabs
00688 models = []
00689 # keep reference to delegates to prevent being garbaged
00690 delegates = []
00691 for i in range(main_window.PoseList_tabWidget.count()):
00692     table_view = get_table_view(i)
00693     model = PosesDataModel(main_window.edit_model_radioButton.isChecked())
00694     model.actions_changed.connect(autosave_program)
00695     model.duration_modified.connect(update_sequence_duration)
00696     table_view.setModel(model)
00697     table_view.resizeColumnsToContents()
00698     duration_delegate = DoubleSpinBoxDelegate()
00699     duration_delegate.setMinimum(main_window.duration_doubleSpinBox.minimum())
00700     duration_delegate.setMaximum(main_window.duration_doubleSpinBox.maximum())
00701     duration_delegate.setSuffix(main_window.duration_doubleSpinBox.suffix())
00702     duration_delegate.setSingleStep(main_window.duration_doubleSpinBox.singleStep())
00703     table_view.setItemDelegateForColumn(0, duration_delegate)
00704     delegates.append(duration_delegate)
00705     model.add_delegates(table_view)
00706     table_view.clicked.connect(test_clicked)
00707     table_view.verticalHeader().sectionClicked.connect(test_clicked)
00708     models.append(model)
00709 
00710 def toggle_model_editable():
00711     for i in range(main_window.PoseList_tabWidget.count()):
00712         models[i].set_editable(main_window.edit_model_radioButton.isChecked())
00713         table_view = get_table_view(i)
00714         table_view.resizeColumnsToContents()
00715 
00716 main_window.read_only_model_radioButton.clicked.connect(toggle_model_editable)
00717 main_window.edit_model_radioButton.clicked.connect(toggle_model_editable)
00718 
00719 def get_current_model():
00720     index = get_current_tab_index()
00721     return models[index]
00722 
00723 
00724 def get_action_set():
00725     if is_in_slider_mode():
00726         action_set = kontrol_subscriber.get_action_set()
00727         if action_set is not None:
00728             action_set.set_duration(main_window.duration_doubleSpinBox.value())
00729     else:
00730         action_set = joint_observer.action_set.deepcopy()
00731     return action_set
00732 
00733 def append_current():
00734     if currently_in_collision:
00735         return
00736 
00737     model = get_current_model()
00738 
00739     action_set = get_action_set()
00740     if action_set is None:
00741         return
00742     model.add_action(action_set)
00743 
00744     table_view = get_table_view(get_current_tab_index())
00745     rows = len(model.action_sequence().actions())
00746     table_view.resizeColumnsToContents()
00747     table_view.selectRow(rows - 1)
00748 
00749 main_window.append_pushButton.clicked.connect(append_current)
00750 
00751 
00752 def insert_current_before_selected():
00753     if currently_in_collision:
00754         return
00755 
00756     row = get_selected_row()
00757     if row is None:
00758         append_current()
00759         return
00760 
00761     model = get_current_model()
00762 
00763     action_set = get_action_set()
00764     if action_set is None:
00765         return
00766     model.add_action(action_set, row)
00767 
00768     table_view = get_table_view(get_current_tab_index())
00769     table_view.resizeColumnsToContents()
00770     table_view.selectRow(row + 1)
00771 
00772 main_window.insert_before_pushButton.clicked.connect(insert_current_before_selected)
00773 
00774 
00775 def insert_find_face():
00776     model = get_current_model()
00777     action_set = ActionSet()
00778     action = Pr2LookAtFace()
00779     action_set.add_action(action)
00780     action_set.set_duration(main_window.duration_doubleSpinBox.value())
00781     model.add_action(action_set)
00782 
00783 main_window.find_face_pushButton.clicked.connect(insert_find_face)
00784 
00785 
00786 def delete_selected():
00787     row = get_selected_row()
00788     if row is None:
00789         return False
00790 
00791     model = get_current_model()
00792     model.remove_action(row)
00793 
00794     table_view = get_table_view(get_current_tab_index())
00795     rows = len(model.action_sequence().actions())
00796     if row >= rows:
00797         row = row - 1
00798     table_view.resizeColumnsToContents()
00799     table_view.selectRow(row)
00800     return True
00801 
00802 main_window.delete_selected_pushButton.clicked.connect(delete_selected)
00803 
00804 
00805 def clone_selected():
00806     row = get_selected_row()
00807     if row is None:
00808         return
00809 
00810     model = get_current_model()
00811     action = model.action_sequence().actions()[row]
00812     clone = action.deepcopy()
00813     model.add_action(clone, row + 1)
00814 
00815 main_window.clone_selected_pushButton.clicked.connect(clone_selected)
00816 
00817 
00818 def get_row_count():
00819     model = get_current_model()
00820     return model.rowCount()
00821 def get_selected_row():
00822     table_view = get_table_view(get_current_tab_index())
00823     selection_model = table_view.selectionModel()
00824     if selection_model.hasSelection():
00825         row = selection_model.selectedRows()[0].row()
00826         #print 'get_selected_row() %d' % row
00827         return row
00828     #print 'get_selected_row() None'
00829     return None
00830 def execute_selected():
00831     row = get_selected_row()
00832     if row is not None:
00833         model = get_current_model()
00834         print 'execute %d' % row
00835         model.action_sequence().actions()[row].execute()
00836 
00837 
00838 def set_selected_row(row):
00839     #print 'set_selected_row(%d)' % row
00840     rows = get_row_count()
00841     if rows == 0:
00842         return
00843     if row < 0:
00844         row = 0
00845     if row >= rows:
00846         row = rows - 1
00847     table_view = get_table_view(get_current_tab_index())
00848     #print 'set_selected_row() row %d' % row
00849     table_view.selectRow(row)
00850 
00851 class RelaySignalInt(QObject):
00852     relay_signal = Signal(int)
00853     def __init__(self):
00854         super(RelaySignalInt, self).__init__()
00855     def emit(self, row):
00856         self.relay_signal.emit(row)
00857 
00858 set_selected_row_signal = RelaySignalInt()
00859 set_selected_row_signal.relay_signal.connect(set_selected_row)
00860 
00861 running_sequence = None
00862 
00863 def set_tab(index):
00864     if get_current_tab_index() != index:
00865         main_window.PoseList_tabWidget.setCurrentIndex(index)
00866 
00867 def finished_executing_current_sequence():
00868     global running_sequence
00869     print 'finished_executing_current_sequence()'
00870     model = get_current_model()
00871     action_sequence = model.action_sequence()
00872     action_sequence.executing_action_signal.disconnect(set_selected_row_signal.emit)
00873     action_sequence.execute_sequence_finished_signal.disconnect(finished_executing_current_sequence)
00874     running_sequence = None
00875 
00876 def stop_sequence():
00877     global running_sequence
00878     if running_sequence is None:
00879         print 'stop_sequence() skipped - not running'
00880         return
00881     print 'stop_sequence()', running_sequence
00882     model = models[running_sequence]
00883     action_sequence = model.action_sequence()
00884     action_sequence.executing_action_signal.disconnect(set_selected_row_signal.emit)
00885     action_sequence.execute_sequence_finished_signal.disconnect(finished_executing_current_sequence)
00886     action_sequence.stop()
00887     running_sequence = None
00888 
00889 def execute_sequence(index, first_action = None):
00890     global running_sequence
00891     if running_sequence == -1:
00892         print 'execute_sequence() skip execute due to running sequence'
00893         return
00894     if running_sequence is not None:
00895         stop_sequence()
00896     print 'execute_sequence()', index
00897     running_sequence = index
00898     set_tab(index)
00899     model = models[index]
00900     action_sequence = model.action_sequence()
00901     action_sequence.executing_action_signal.connect(set_selected_row_signal.emit)
00902     action_sequence.execute_sequence_finished_signal.connect(finished_executing_current_sequence)
00903     action_sequence.execute_all(first_action)
00904 
00905 def execute_current_sequence():
00906     execute_sequence(get_current_tab_index())
00907 
00908 def execute_current_sequence_from_selection():
00909     row = get_selected_row()
00910     if row == get_row_count() - 1:
00911         row = None
00912     execute_sequence(get_current_tab_index(), row)
00913 
00914 main_window.run_sequence_from_selection_pushButton.clicked.connect(execute_current_sequence_from_selection)
00915 
00916 
00917 select_row_signal = RelaySignalInt()
00918 select_row_signal.relay_signal.connect(set_selected_row)
00919 
00920 collision_notification = QDialog(main_window)
00921 ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'src', 'collision_dialog.ui')
00922 loadUi(ui_file, collision_notification)
00923 collision_notification_timer = QTimer(main_window)
00924 collision_notification_timer.setInterval(3000)
00925 collision_notification_timer.setSingleShot(True)
00926 def hide_collision_notification(result=None):
00927     collision_notification_timer.stop()
00928     collision_notification.hide()
00929 collision_notification_timer.timeout.connect(hide_collision_notification)
00930 collision_notification.finished.connect(hide_collision_notification)
00931 
00932 def check_buttons():
00933     triggered_buttons = kontrol_subscriber.get_triggered_buttons()
00934 
00935     if KontrolSubscriber.previous_button in triggered_buttons:
00936         if get_selected_row() is not None:
00937             select_row_signal.emit(get_selected_row() - 1)
00938         else:
00939             select_row_signal.emit(0)
00940     elif KontrolSubscriber.play_button in triggered_buttons:
00941         execute_selected()
00942     elif KontrolSubscriber.next_button in triggered_buttons:
00943         if get_selected_row() is not None:
00944             select_row_signal.emit(get_selected_row() + 1)
00945         else:
00946             select_row_signal.emit(get_row_count() - 1)
00947 
00948     elif KontrolSubscriber.repeat_button in triggered_buttons:
00949         execute_current_sequence()
00950     elif KontrolSubscriber.stop_button in triggered_buttons:
00951         stop_sequence()
00952     elif KontrolSubscriber.record_button in triggered_buttons:
00953         if currently_in_collision:
00954             # open dialog which closes after some seconds or when confirmed manually
00955             collision_notification.show()
00956             collision_notification_timer.start()
00957         append_current()
00958 
00959     elif KontrolSubscriber.top1_button in triggered_buttons:
00960         set_tab(0)
00961     elif KontrolSubscriber.bottom1_button in triggered_buttons:
00962         set_tab(3)
00963     elif KontrolSubscriber.top2_button in triggered_buttons:
00964         set_tab(1)
00965     elif KontrolSubscriber.bottom2_button in triggered_buttons:
00966         set_tab(2)
00967 
00968     elif KontrolSubscriber.top6_button in triggered_buttons:
00969         execute_sequence(0)
00970     elif KontrolSubscriber.bottom6_button in triggered_buttons:
00971         execute_sequence(3)
00972     elif KontrolSubscriber.top7_button in triggered_buttons:
00973         execute_sequence(1)
00974     elif KontrolSubscriber.bottom7_button in triggered_buttons:
00975         execute_sequence(2)
00976 
00977 class RelaySignal(QObject):
00978     relay_signal = Signal()
00979     def __init__(self):
00980         super(RelaySignal, self).__init__()
00981     def emit(self):
00982         self.relay_signal.emit()
00983 
00984 check_buttons_signal = RelaySignal()
00985 check_buttons_signal.relay_signal.connect(check_buttons)
00986 kontrol_subscriber.buttons_changed.connect(check_buttons_signal.emit)
00987 
00988 
00989 def check_ps3_buttons():
00990     triggered_buttons = ps3_subscriber.get_triggered_buttons()
00991 
00992     if Ps3Subscriber.select_button in triggered_buttons:
00993         #sys.exit(0)
00994         pass
00995     elif Ps3Subscriber.start_button in triggered_buttons:
00996         #default_pose()
00997         pass
00998 
00999     elif Ps3Subscriber.square_button in triggered_buttons:
01000         execute_sequence(0)
01001     elif Ps3Subscriber.triangle_button in triggered_buttons:
01002         execute_sequence(1)
01003     elif Ps3Subscriber.circle_button in triggered_buttons:
01004         execute_sequence(2)
01005     elif Ps3Subscriber.cross_button in triggered_buttons:
01006         execute_sequence(3)
01007 
01008 ps3_subscriber = Ps3Subscriber()
01009 check_ps3_buttons_signal = RelaySignal()
01010 check_ps3_buttons_signal.relay_signal.connect(check_ps3_buttons)
01011 ps3_subscriber.buttons_changed.connect(check_ps3_buttons_signal.emit)
01012 
01013 
01014 current_name = None
01015 
01016 def load_from_file():
01017     global current_name
01018     file_name, _ = QFileDialog.getOpenFileName(main_window, main_window.tr('Load program from file'), None, main_window.tr('Puppet Talk (*.pt)'))
01019     if file_name is None or file_name == '':
01020         return
01021 
01022     print 'load_from_file', file_name
01023     handle = open(file_name, 'rb')
01024     storage = SimpleFormat(handle)
01025 
01026     count = storage.deserialize_data()
01027     tabs = main_window.PoseList_tabWidget.count()
01028     for index in range(tabs):
01029         model = models[index]
01030         if index < count:
01031             model.action_sequence().deserialize(storage)
01032             model.reset()
01033         else:
01034             model.remove_all_actions()
01035     handle.close()
01036 
01037     current_name = os.path.splitext(os.path.basename(file_name))[0]
01038 
01039     update_sequence_duration()
01040 
01041 main_window.actionOpen.triggered.connect(load_from_file)
01042 
01043 
01044 def serialize(storage):
01045     count = main_window.PoseList_tabWidget.count()
01046     storage.serialize_data(count)
01047     for index in range(count):
01048         model = models[index]
01049         model.action_sequence().serialize(storage)
01050 
01051 def save_to_file():
01052     file_name, _ = QFileDialog.getSaveFileName(main_window, main_window.tr('Save program to file'), 'example.pt', main_window.tr('Puppet Talk (*.pt)'))
01053     if file_name is None or file_name == '':
01054         return False
01055 
01056     save_to_filename(file_name)
01057     return True
01058 
01059 def save_to_filename(file_name):
01060     global current_name
01061     print 'save_to_filename', file_name
01062     handle = open(file_name, 'wb')
01063     storage = SimpleFormat(handle)
01064     serialize(storage)
01065     handle.close()
01066 
01067     current_name = os.path.splitext(os.path.basename(file_name))[0]
01068 
01069 main_window.actionSave_As.triggered.connect(save_to_file)
01070 
01071 
01072 def save_screenshot():
01073     path = os.path.expanduser('~')
01074     filename_template = 'robot-%d.png'
01075     serial = 1
01076     while True:
01077         filename = os.path.join(path, filename_template % serial)
01078         if not os.path.exists(filename):
01079             break
01080         serial += 1
01081     widget = robot_view.children()[0]
01082     pixmap = QPixmap.grabWindow(widget.winId())
01083     rc = pixmap.save(filename)
01084     if rc:
01085         QMessageBox.information(main_window, main_window.tr('Saved screenshot'), main_window.tr('Screenshot saved in file: %s') % filename)
01086     else:
01087         QMessageBox.critical(main_window, main_window.tr('Saving screenshot failed'), main_window.tr('Could not save screenshot.'))
01088 
01089 main_window.actionSave_Screenshot.triggered.connect(save_screenshot)
01090 
01091 
01092 def clear_all():
01093     global current_name
01094     confirmed = True
01095     if current_name is None:
01096         button = QMessageBox.question(main_window, main_window.tr('Clear all poses'), main_window.tr('Do you really want to delete all poses?'), QMessageBox.No | QMessageBox.Yes)
01097         confirmed = button == QMessageBox.Yes
01098     if confirmed:
01099         print 'clear_all()'
01100         for index in range(main_window.PoseList_tabWidget.count()):
01101             model = models[index]
01102             model.remove_all_actions()
01103         current_name = None
01104         set_tab(0)
01105         main_window.angled_view_radioButton.click()
01106 
01107 main_window.actionClear_All.triggered.connect(clear_all)
01108 
01109 
01110 default_pose = DefaultAction()
01111 default_pose.set_duration(8.0)
01112 
01113 def finished_executing_default_pose():
01114     global running_sequence
01115     print 'finished_executing_default_pose()'
01116     running_sequence = None
01117 
01118 def execute_default_pose():
01119     global running_sequence
01120     if running_sequence is not None:
01121         stop_sequence()
01122     print 'execute_default_pose()'
01123     running_sequence = -1
01124     default_pose.execute()
01125 
01126 default_pose.execute_finished_signal.connect(finished_executing_default_pose)
01127 
01128 def add_default_pose():
01129     model = get_current_model()
01130     action_set = ActionSet()
01131     action = DefaultAction()
01132     action_set.add_action(action)
01133     action_set.set_duration(main_window.duration_doubleSpinBox.value())
01134     model.add_action(action_set)
01135 
01136     table_view = get_table_view(get_current_tab_index())
01137     rows = len(model.action_sequence().actions())
01138     table_view.resizeColumnsToContents()
01139     table_view.selectRow(rows - 1)
01140 
01141 main_window.actionDefault_Pose.triggered.connect(add_default_pose)
01142 
01143 
01144 main_window.actionTest_Program.triggered.connect(execute_current_sequence)
01145 
01146 
01147 queue_default_username = 'admin'
01148 queue_default_password = 'admin'
01149 
01150 def queue_dialog():
01151     dialog = QDialog()
01152     ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'src', 'queue_dialog.ui')
01153     loadUi(ui_file, dialog)
01154 
01155     if current_name is not None:
01156         dialog.label_lineEdit.setText(current_name)
01157     dialog.username_lineEdit.setText(queue_default_username)
01158     dialog.password_lineEdit.setText(queue_default_password)
01159 
01160     rc = dialog.exec_()
01161     if rc == QDialog.Rejected:
01162         return
01163 
01164     queue_program(dialog.username_lineEdit.text(), dialog.password_lineEdit.text(), dialog.label_lineEdit.text())
01165 
01166 def save_and_queue_program():
01167     rc = save_to_file()
01168     if rc:
01169         queue_program(queue_default_username, queue_default_password, current_name)
01170 
01171 def queue_program(username, password, label):
01172     queue = ProgramQueue(username, password)
01173     try:
01174         rc = queue.login()
01175     except:
01176         rc = False
01177     if not rc:
01178         QMessageBox.critical(main_window, main_window.tr('Login failed'), main_window.tr('Could not log in to the program queue.'))
01179         return
01180 
01181     output = StringIO()
01182     storage = SimpleFormat(output)
01183     serialize(storage)
01184     program_data = output.getvalue()
01185     output.close()
01186 
01187     try:
01188         id = queue.upload_program(program_data, label)
01189     except:
01190         id = False
01191     if not id:
01192         QMessageBox.critical(main_window, main_window.tr('Upload failed'), main_window.tr('Could not upload program to queue.'))
01193         return
01194     try:
01195         queue.logout()
01196     except:
01197         pass
01198     QMessageBox.information(main_window, main_window.tr('Uploaded program'), main_window.tr('Uploaded program (%d) successfully.') % id)
01199 
01200 main_window.actionQueue_Program.triggered.connect(queue_dialog)
01201 main_window.save_and_queue_program_pushButton.clicked.connect(save_and_queue_program)
01202 
01203 
01204 main_window.actionExit.triggered.connect(main_window.close)
01205 
01206 # confirm closing of application
01207 def closeEvent(event):
01208     if not sigint_called:
01209         button = QMessageBox.question(main_window, main_window.tr('Close application'), main_window.tr('Do you really want to close the application?'), QMessageBox.Cancel | QMessageBox.Close)
01210     else:
01211         button = QMessageBox.Close
01212     if button == QMessageBox.Close:
01213         event.accept()
01214     else:
01215         event.ignore()
01216 main_window.closeEvent = closeEvent
01217 
01218 
01219 #main_window.show()
01220 main_window.showMaximized()
01221 
01222 execute_default_pose()
01223 
01224 sys.exit(app.exec_())


slider_gui
Author(s): Dirk Thomas
autogenerated on Thu Jun 6 2019 20:32:11