move_head_tool.py
Go to the documentation of this file.
00001 import rospy
00002 from PyQt4.QtGui import *
00003 from PyQt4.QtCore import *
00004 import rcommander.tool_utils as tu
00005 import actionlib_msgs.msg as am
00006 import numpy as np
00007 import smach
00008 import roslib
00009 import os.path as pt
00010 
00011 class MoveHeadTool(tu.ToolBase):
00012 
00013     def __init__(self, rcommander):
00014         tu.ToolBase.__init__(self, rcommander, 'move_head_ang', 'Move Head (ang)', MoveHeadState)
00015         self.head_angs_list = None
00016         self.joint_names = ["head_pan_joint", "head_tilt_joint"]
00017         self.status_bar_timer = QTimer()
00018         self.rcommander.connect(self.status_bar_timer, SIGNAL('timeout()'), self.get_current_joint_angles_cb)
00019 
00020     def fill_property_box(self, pbox):
00021         formlayout = pbox.layout()
00022         
00023         joint_names = self.rcommander.robot.head.get_joint_names()
00024         self.joint_boxes = []
00025         for jname in joint_names:
00026             #joint_box = QDoubleSpinBox(pbox)
00027             exec("self.%s = QDoubleSpinBox(pbox)" % jname)
00028             exec('box = self.%s' % jname)
00029             box.setMinimum(-9999.)
00030             box.setMaximum(9999.)
00031             box.setSingleStep(1.)
00032             self.joint_boxes.append(box)
00033             formlayout.addRow('&%s' % jname, box)
00034 
00035         self.head_angs_list = []
00036         self.time_box = QDoubleSpinBox(pbox)
00037         self.time_box.setMinimum(0)
00038         self.time_box.setMaximum(1000.)
00039         self.time_box.setSingleStep(.5)
00040         formlayout.addRow('&Time', self.time_box)
00041 
00042         self.update_checkbox = QCheckBox(pbox) 
00043         self.update_checkbox.setTristate(False)
00044         formlayout.addRow('&Live Update', self.update_checkbox)
00045         self.rcommander.connect(self.update_checkbox, SIGNAL('stateChanged(int)'), self.update_selected_cb)
00046 
00047         self.current_pose_button = QPushButton(pbox)
00048         self.current_pose_button.setText('Current Pose')
00049         self.rcommander.connect(self.current_pose_button, 
00050                 SIGNAL('clicked()'), self.get_current_joint_angles_cb)
00051         formlayout.addRow(self.current_pose_button)
00052      
00053 #widet box 
00054         self.list_box = QWidget(pbox)
00055         self.list_box_layout = QHBoxLayout(self.list_box)
00056         self.list_box_layout.setMargin(0)
00057 
00058         self.list_widget = QListWidget(self.list_box)
00059         self.rcommander.connect(self.list_widget, SIGNAL('itemSelectionChanged()'), self.item_selection_changed_cb)
00060         self.list_box_layout.addWidget(self.list_widget)
00061 
00062         #self.movement_buttons_widget = QWidget(self.list_box)
00063         #self.movement_buttons_widgetl = QVBoxLayout(self.movement_buttons_widget)
00064         #self.movement_buttons_widgetl.setMargin(0)
00065 
00066         self.list_widget_buttons = QWidget(pbox)
00067         self.list_widget_buttons2 = QWidget(pbox)
00068         self.lbb_hlayout = QHBoxLayout(self.list_widget_buttons)
00069         #self.lbb_hlayout2 = QHBoxLayout(self.list_widget_buttons2)
00070 
00071 #UP
00072 
00073         #self. = QPushButton(self.list_widget_buttons)
00074         #self.move_up_button.setText('Up')
00075         #self.rcommander.connect(self.move_up_button, SIGNAL('clicked()'), self.move_up_cb)
00076         #self.lbb_hlayout.addWidget(self.move_up_button)
00077 #DOWN
00078         #self.move_down_button = QPushButton(self.list_widget_buttons)
00079         #self.move_down_button.setText('Down')
00080         #self.rcommander.connect(self.move_down_button, SIGNAL('clicked()'), self.move_down_cb)
00081         #self.lbb_hlayout.addWidget(self.move_down_button)
00082         #self.lbb_hlayout.addSpacing(50)
00083 
00084         #spacer = QSpacerItem(40, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
00085         #self.lbb_hlayout.addItem(spacer)
00086 
00087             #formlayout.addRow('&Create a Joint Sequence', self.time_box)
00088 
00089         self.move_up_button = QPushButton(self.list_widget_buttons)
00090         self.move_up_button.setText("")
00091         icon = QIcon()
00092         base_path = roslib.packages.get_pkg_dir('rcommander_pr2_gui')
00093         icon.addPixmap(QPixmap(pt.join(base_path, "icons/UpButton.png")), QIcon.Normal, QIcon.Off)
00094         self.move_up_button.setIcon(icon)
00095         self.move_up_button.setObjectName("up_button")
00096         #self. = QPushButton(self.list_widget_buttons)
00097         #self.move_up_button.setText('Up')
00098         self.rcommander.connect(self.move_up_button, SIGNAL('clicked()'), self.move_up_cb)
00099         #self.lbb_hlayout.addWidget(self.move_up_button)
00100         self.move_up_button.setToolTip('Move Up')
00101 
00102         self.move_down_button = QPushButton(self.list_widget_buttons)
00103         self.move_down_button.setText("")
00104         icon = QIcon()
00105         icon.addPixmap(QPixmap(pt.join(base_path,"icons/DownButton.png")), QIcon.Normal, QIcon.Off)
00106         self.move_down_button.setIcon(icon)
00107         self.move_down_button.setObjectName("down_button")
00108         #self.move_down_button = QPushButton(self.list_widget_buttons)
00109         #self.move_down_button.setText('Down')
00110         self.rcommander.connect(self.move_down_button, SIGNAL('clicked()'), self.move_down_cb)
00111         #self.lbb_hlayout.addWidget(self.move_down_button)
00112         #self.lbb_hlayout.addSpacing(50)
00113         self.move_down_button.setToolTip('Move Down')
00114 
00115         self.add_head_set_button = QPushButton(self.list_widget_buttons)
00116         self.add_head_set_button.setText("")
00117         icon = QIcon()
00118         icon.addPixmap(QPixmap(pt.join(base_path, "icons/AddButton.png")), QIcon.Normal, QIcon.Off)
00119         self.add_head_set_button.setIcon(icon)
00120         self.add_head_set_button.setObjectName("add_button")
00121         #self.add_head_set_button = QPushButton(self.list_widget_buttons2)
00122         #self.add_head_set_button.setText('Add Head Position')
00123         self.rcommander.connect(self.add_head_set_button, SIGNAL('clicked()'), self.add_head_set_cb)
00124         self.add_head_set_button.setToolTip('Add')
00125 
00126         self.remove_head_set_button = QPushButton(self.list_widget_buttons)
00127         self.remove_head_set_button.setText("")
00128         icon = QIcon()
00129         icon.addPixmap(QPixmap(pt.join(base_path, "icons/RemoveButton.png")), QIcon.Normal, QIcon.Off)
00130         self.remove_head_set_button.setIcon(icon)
00131         self.remove_head_set_button.setObjectName("remove_button")
00132         #self.remove_head_set_button = QPushButton(self.list_widget_buttons2)
00133         #self.remove_head_set_button.setText('Remove Head Position')
00134         self.rcommander.connect(self.remove_head_set_button, SIGNAL('clicked()'), self.remove_pose_cb)
00135         self.remove_head_set_button.setToolTip('Remove')
00136 
00137         self.save_button = QPushButton(self.list_widget_buttons)
00138         self.save_button.setText("")
00139         icon = QIcon()
00140         icon.addPixmap(QPixmap(pt.join(base_path, "icons/SaveButton.png")), QIcon.Normal, QIcon.Off)
00141         self.save_button.setIcon(icon)
00142         self.save_button.setObjectName("save_button")
00143         #self.save_button = QPushButton(self.list_widget_buttons2)
00144         #self.save_button.setText('Save Sequence')
00145         self.rcommander.connect(self.save_button, SIGNAL('clicked()'), self.save_button_cb)
00146         self.save_button.setToolTip('Save')
00147         
00148         spacer = QSpacerItem(40, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
00149         self.lbb_hlayout.addWidget(self.add_head_set_button)
00150         self.lbb_hlayout.addWidget(self.remove_head_set_button)
00151         self.lbb_hlayout.addWidget(self.save_button)
00152         self.lbb_hlayout.addItem(spacer)
00153         self.lbb_hlayout.addWidget(self.move_up_button)
00154         self.lbb_hlayout.addWidget(self.move_down_button)
00155         self.lbb_hlayout.setContentsMargins(2, 2, 2, 2)
00156 
00157         formlayout.addRow('\n', self.list_box)      
00158         formlayout.addRow('&Sequence:', self.list_box)
00159         formlayout.addRow(self.list_box)
00160         formlayout.addRow(self.list_widget_buttons)
00161         #formlayout.addRow(self.list_widget_buttons2)
00162         self.reset()
00163 
00164     def _refill_list_widget(self, joints_list):
00165         self.list_widget.clear()
00166         for d in joints_list:
00167             self.list_widget.addItem(d['name'])
00168 
00169     def get_current_joint_angles_cb(self):
00170         poses = self.rcommander.robot.head.pose()
00171         self.joint_boxes[0].setValue(np.degrees(poses[0,0]))
00172         self.joint_boxes[1].setValue(np.degrees(poses[1,0]))
00173 
00174     def set_node_properties(self, my_node):
00175         self.joint_boxes[0].setValue(np.degrees(my_node.poses[0,0]))
00176         self.joint_boxes[1].setValue(np.degrees(my_node.poses[1,0]))
00177         #self.time_box.setValue(my_node.mot_time) 
00178         self.head_angs_list = my_node.joint_waypoints
00179         self._refill_list_widget(my_node.joint_waypoints)
00180         self.list_widget.setCurrentItem(self.list_widget.item(0))
00181 
00182 #added   
00183     def item_selection_changed_cb(self):
00184         selected = self.list_widget.selectedItems()
00185         if len(selected) == 0:
00186             return
00187         idx = self._find_index_of(str(selected[0].text()))
00188         head_angs = self.head_angs_list[idx]['angs']
00189         self._set_joints_to_fields(head_angs)
00190         self.time_box.setValue(self.head_angs_list[idx]['time'])
00191 #added
00192     def _set_joints_to_fields(self, joints):
00193         for idx, name in enumerate(self.joint_names):
00194             deg = np.degrees(joints[idx])
00195             exec('line_edit = self.%s' % name)
00196             line_edit.setValue(deg)
00197 
00198 #added
00199     def _has_name(self, test_name):
00200         for rec in self.head_angs_list:
00201             if rec['name'] == test_name:
00202                 return True
00203             else:
00204                 return False
00205 
00206 #added
00207     def move_up_cb(self):
00208         #get the current index
00209         idx = self._selected_idx()
00210         if idx == None:
00211             return
00212 
00213         #pop & insert it
00214         item = self.head_angs_list.pop(idx)
00215         self.head_angs_list.insert(idx-1, item)
00216 
00217         #refresh
00218         self._refill_list_widget(self.head_angs_list)
00219         self.list_widget.setCurrentItem(self.list_widget.item(idx-1))
00220 
00221 #added
00222     def move_down_cb(self):
00223         #get the current index
00224         idx = self._selected_idx()
00225         if idx == None:
00226             return
00227 
00228         #pop & insert it
00229         item = self.head_angs_list.pop(idx)
00230         self.head_angs_list.insert(idx+1, item)
00231 
00232         #refresh
00233         self._refill_list_widget(self.head_angs_list)
00234         self.list_widget.setCurrentItem(self.list_widget.item(idx+1))
00235 
00236 #added
00237     def add_head_set_cb(self):
00238         #Create a new string, check to see whether it's in the current list
00239         name = self._create_name()
00240         #self.list_widget.addItem(name)
00241         self.head_angs_list.append({'name':name, 'time': self.time_box.value(), 'angs': self._read_head_position_from_fields()})
00242         self._refill_list_widget(self.head_angs_list)
00243 
00244 #added
00245     def save_button_cb(self):
00246         idx = self._selected_idx()
00247         if idx == None:
00248             return
00249         el = self.head_angs_list[idx]
00250         self.head_angs_list[idx] = {'name': el['name'],
00251             'time': self.time_box.value(), 
00252             'angs': self._read_head_position_from_fields()}
00253 
00254 #added
00255     def _read_head_position_from_fields(self):
00256         headPos = []
00257         for name in self.joint_names:
00258             #exec('rad = np.radians(float(str(self.%s.text())))' % name)
00259             exec('rad = np.radians(self.%s.value())' % name)
00260             headPos.append(rad)
00261         return headPos
00262 
00263 #added
00264     def remove_pose_cb(self):
00265         idx = self._selected_idx()
00266         if idx == None:
00267             return
00268         #self.list_widget.takeItem(idx)
00269         #self.list_widget.removeItemWidget(selected[0])
00270         if idx == None:
00271             raise RuntimeError('Inconsistency detected in list')
00272         else:
00273             self.head_angs_list.pop(idx)
00274         self._refill_list_widget(self.head_angs_list)
00275 
00276 #added
00277     def _create_name(self):
00278         idx = len(self.head_angs_list)
00279         tentative_name = 'point%d' % idx 
00280 
00281         while self._has_name(tentative_name):
00282             idx = idx + 1
00283             tentative_name = 'point%d' % idx 
00284 
00285         return tentative_name
00286 
00287 #added
00288     def _selected_idx(self):
00289         #Get currently selected
00290         selected = self.list_widget.selectedItems()
00291         if len(selected) == 0:
00292             return None
00293         sname = str(selected[0].text())
00294 
00295         #Remove it from list_widget and head_angs_list
00296         idx = self._find_index_of(sname)
00297         return idx
00298 
00299 #added
00300     def _find_index_of(self, name):
00301         for idx, tup in enumerate(self.head_angs_list):
00302             if tup['name'] == name:
00303                 return idx
00304         return None
00305 
00306     def reset(self):
00307         for box in self.joint_boxes:
00308             box.setValue(0)
00309         self.time_box.setValue(1.)
00310         self.update_checkbox.setCheckState(False)
00311         self.status_bar_timer.stop()
00312         self.current_pose_button.setEnabled(True)
00313 
00314     def new_node(self, name=None):
00315         if name == None:
00316             nname = self.name + str(self.counter)
00317         else:
00318             nname = name
00319 
00320         poses = np.matrix([np.radians(self.joint_boxes[0].value()),
00321                            np.radians(self.joint_boxes[1].value())]).T
00322         return MoveHeadState(nname, poses, self.head_angs_list)
00323 
00324 #added
00325     def save_button_cb(self):
00326         idx = self._selected_idx()
00327         if idx == None:
00328             return
00329         el = self.head_angs_list[idx]
00330         self.head_angs_list[idx] = {'name': el['name'],
00331             'time': self.time_box.value(), 
00332             'angs': self._read_head_position_from_fields()}
00333 #added
00334     def update_selected_cb(self, state):
00335         # checked
00336         if state == 2:
00337             self.status_bar_timer.start(30)
00338             self.current_pose_button.setEnabled(False)
00339             self.get_current_joint_angles_cb()
00340         # unchecked
00341         if state == 0:
00342             self.status_bar_timer.stop()
00343             self.current_pose_button.setEnabled(True)
00344 
00345 #added
00346     def move_up_cb(self):
00347         #get the current index
00348         idx = self._selected_idx()
00349         if idx == None:
00350             return
00351 
00352         #pop & insert it
00353         item = self.head_angs_list.pop(idx)
00354         self.head_angs_list.insert(idx-1, item)
00355 
00356         #refresh
00357         self._refill_list_widget(self.head_angs_list)
00358         self.list_widget.setCurrentItem(self.list_widget.item(idx-1))
00359 #added
00360     def get_current_joint_angles(self):
00361         pose_mat = rcommander.robot.head.pose()
00362 
00363         for idx, name in enumerate(self.joint_name_fields):
00364             deg = np.degrees(pose_mat[idx, 0])
00365             exec('line_edit = self.%s' % name)
00366             #line_edit.setText('%.2f' % deg)
00367             line_edit.setValue(deg)
00368 
00369     def move_down_cb(self):
00370         #get the current index
00371         idx = self._selected_idx()
00372         if idx == None:
00373             return
00374 
00375         #pop & insert it
00376         item = self.head_angs_list.pop(idx)
00377         self.head_angs_list.insert(idx+1, item)
00378 
00379         #refresh
00380         self._refill_list_widget(self.head_angs_list)
00381         self.list_widget.setCurrentItem(self.list_widget.item(idx+1))
00382 
00383 
00384 class MoveHeadState(tu.StateBase):
00385 
00386     def __init__(self, name, poses, joint_waypoints):
00387         tu.StateBase.__init__(self, name)
00388         self.poses = poses 
00389         self.joint_waypoints = joint_waypoints
00390 
00391     def get_smach_state(self):
00392         return MoveHeadStateSmach(self.poses, self.joint_waypoints)
00393 
00394 
00395 class MoveHeadStateSmach(smach.State):
00396 
00397     TIME_OUT_FACTOR = 3.
00398 
00399     def __init__(self, poses, joint_waypoints):
00400         smach.State.__init__(self, outcomes=['preempted', 'done', 'None'], 
00401                              input_keys=[], output_keys=[])
00402         self.joint_waypoints = joint_waypoints
00403         self.poses = poses
00404 
00405     def set_robot(self, robot):
00406         if robot != None:
00407             self.head_obj = robot.head
00408             self.controller_manager = robot.controller_manager
00409 
00410     def execute(self, userdata):
00411         #status, started, stopped = self.controller_manager.joint_mode(self.head_obj)
00412 
00413         #Construct trajectory command
00414         times = []
00415         wps = []
00416         for x in self.joint_waypoints:
00417             wps.append(np.matrix(x['angs']).T)
00418             times.append(x['time'])
00419 
00420         self.head_obj.set_poses(np.column_stack(wps), np.cumsum(np.array(times)))
00421         #client = self.head_obj.client
00422         #state = client.get_state()
00423 
00424         #Monitor execution
00425         trajectory_time_out = MoveHeadStateSmach.TIME_OUT_FACTOR * np.sum(times)
00426         succeeded = False
00427         preempted = False
00428         r = rospy.Rate(30)
00429         start_time = rospy.get_time()
00430         while (rospy.get_time() - start_time) < trajectory_time_out:
00431             r.sleep()
00432             if self.preempt_requested():
00433                 self.services_preempt()
00434                 return 'preempted'
00435         return 'done'
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 


rcommander_pr2_gui
Author(s): Hai Nguyen
autogenerated on Thu Dec 12 2013 12:09:58