Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 import os
00036 try:  
00037     from urlparse import urlparse
00038 except ImportError:  
00039     from urllib.parse import urlparse
00040 
00041 from hironx_ros_bridge.hironx_client import HIRONX
00042 from hrpsys import rtm
00043 from hrpsys_ros_bridge.hrpsys_dashboard import HrpsysDashboard
00044 from python_qt_binding import loadUi
00045 from python_qt_binding.QtCore import Qt, Signal
00046 
00047 try: 
00048     from python_qt_binding.QtGui import (QHeaderView, QItemSelectionModel,
00049                                          QWidget)
00050 except: 
00051     from python_qt_binding.QtWidgets import (QHeaderView, QWidget)
00052     from python_qt_binding.QtCore import QItemSelectionModel
00053 
00054 from rosgraph import Master
00055 from rospkg import RosPack
00056 import rospy
00057 from rospy.exceptions import ROSException
00058 import rosservice
00059 from rqt_robot_dashboard.widgets import MenuDashWidget
00060 
00061 PKG_NAME = 'hironx_ros_bridge'
00062 
00063 
00064 class HironxoCommandPanel(QWidget):
00065     '''
00066     Design decisions:
00067 
00068     - joint_state_publisher is dropped, since hrpsys_ros_bridge seems to set
00069     `robot_description` param using COLLADA (see https://goo.gl/aLpILa)
00070     instead of URDF, which joint_state_publisher is not capable of.
00071     '''
00072 
00073     def __init__(self, parent, guicontext):
00074         '''
00075         A GUi panel to list common operation commands for Hironx / NEXTAGE Open robot.
00076 
00077         @param guicontext: The plugin context to create the monitor in.
00078         @type guicontext: qt_gui.plugin_context.PluginContext
00079         '''
00080         super(HironxoCommandPanel, self).__init__()
00081         self._parent = parent
00082         self._guicontext = guicontext
00083 
00084         
00085         rtm.nshost = rospy.get_param('rtmnameserver_host', 'localhost')
00086         rtm.nsport = rospy.get_param('rtmnameserver_port', '15005')
00087         robotname = rospy.get_param('rtmnameserver_robotname', 'HiroNX(Robot)0')
00088         rospy.loginfo('Connecting to RTM nameserver. host={}, port={}, robotname={} using rtmnameserver_{{host,port,robotname}} ROS param'.format(rtm.nshost, rtm.nsport, robotname))
00089 
00090         self._rtm = HIRONX()
00091         self._rtm.init(robotname=robotname, url='')
00092 
00093         rospack = RosPack()
00094         ui_file = os.path.join(rospack.get_path(PKG_NAME), 'resource',
00095                                'hironx_commandpanel_main.ui')
00096         loadUi(ui_file, self, {'HironxoCommandPanel': HironxoCommandPanel})
00097 
00098         self._precision_output = 4  
00099 
00100         
00101         self.pushButton_checkEncoders.clicked[bool].connect(self._check_encoders)
00102         self.pushButton_goInitial.clicked[bool].connect(self._go_initial)
00103         self.pushButton_goInitial_factoryval.clicked[bool].connect(self._go_initial_factoryval)
00104         self.pushButton_goOffPose.clicked[bool].connect(self._go_offPose)
00105         self.pushButton_startImpedance.clicked[bool].connect(self._impedance_on)
00106         self.pushButton_stopImpedance.clicked[bool].connect(self._impedance_off)
00107         self.pushButton_actualPose_l.clicked[bool].connect(self._actual_pose_l)
00108         self.pushButton_actualPose_r.clicked[bool].connect(self._actual_pose_r)
00109         self.spinBox_precision_output.valueChanged[int].connect(self._get_precision_output)
00110         self.pushButton_groups.clicked[bool].connect(self._show_groups)
00111 
00112     def get_rosmaster_domain(self):
00113         '''
00114         Workaround for rosgraph.Master.getUri() that does NOT return
00115         a domain name with ".local".
00116         '''
00117         master = Master('/hironxo_command_widget')
00118         
00119                                            
00120         masteruri_http = os.environ['ROS_MASTER_URI']
00121         urlparsed = urlparse(masteruri_http)
00122         return urlparsed
00123 
00124     def _print_command(self, command_str):
00125         self.textBrowser_output.append('***Command used***\n\t' + command_str)
00126 
00127     def _get_duration(self):
00128         '''
00129         @rtype float
00130         '''
00131         return float(self.doubleSpinBox_duration.text())
00132 
00133     def _get_precision_output(self):
00134         self._precision_output = self.spinBox_precision_output.value()
00135 
00136     def _get_arm_impedance(self):
00137         '''
00138         @rtype str
00139         @return: Returns a name of arm group that is checked on GUI. None by default.
00140         '''
00141         checked_arm = None
00142         if self.radioButton_impedance_left.isChecked():
00143             checked_arm = 'larm'
00144         elif self.radioButton_impedance_right.isChecked():
00145             checked_arm = 'rarm'
00146         return checked_arm
00147 
00148     def _check_encoders(self):
00149         self._print_command('checkEncoders()')
00150         self._rtm.checkEncoders()
00151 
00152     def _go_initial(self):
00153         self._print_command('goInitial(tm={})'.format(self._get_duration()))
00154         self._rtm.goInitial(tm=self._get_duration())
00155 
00156     def _go_initial_factoryval(self):
00157         self._print_command('goInitial(init_pose_type=1, tm={})'.format(self._get_duration()))
00158         self._rtm.goInitial(init_pose_type=self._rtm.INITPOS_TYPE_FACTORY,
00159                             tm=self._get_duration())
00160 
00161     def _go_offPose(self):
00162         self._print_command('goOffPose(tm={})'.format(self._get_duration()))
00163         self._rtm.goOffPose(tm=self._get_duration())
00164 
00165     def _impedance_on_off(self, do_on=True):
00166         '''
00167         Start/stop impedance control for the specified arm group.
00168         Arm group to operate impedance control is automatically obtained from
00169         GUI internally within this method.
00170         @raise AttributeError: When no arm group is specified.
00171         @type do_on: bool
00172         @param do_on: On/off of impedance control
00173         '''
00174         armgroup = self._get_arm_impedance()
00175         if not armgroup:
00176             raise AttributeError('No arm is specified for impedance control to start.')
00177         if do_on:
00178             self._print_command('startImpedance({})'.format(armgroup))
00179             self._rtm.startImpedance(armgroup)
00180         elif not do_on:
00181             self._print_command('stopImpedance({})'.format(armgroup))
00182             self._rtm.stopImpedance(armgroup)
00183 
00184     def _impedance_on(self):
00185         self._impedance_on_off()
00186 
00187     def _impedance_off(self):
00188         self._impedance_on_off(do_on=False)
00189 
00190     def _show_actual_pose(self, list_pose):
00191         '''
00192         @type list_pose: [str]
00193         @param list_pose: list of str that represent angles (in radian)
00194         '''
00195         
00196         section_line_piece = '-'
00197         text_single_line = section_line_piece * self._precision_output + '\t'
00198         self.textBrowser_output.append(text_single_line * 4)
00199 
00200         text_single_line = ''
00201         i = 0
00202         for fl in list_pose:
00203             val = str(round(fl, self._precision_output))
00204 
00205             
00206             text_single_line += val
00207             print('DEBUG) #{}: text_single_line: {}'.format(i, text_single_line))
00208             
00209             
00210             
00211             if (i != 0 and i % 4 == 3) or i+1 == len(list_pose):
00212                 self.textBrowser_output.append(text_single_line)
00213                 text_single_line = ''  
00214             else:
00215                 text_single_line += '\t'
00216             i += 1
00217 
00218     def _actual_pose_l(self):
00219         target_joint = 'LARM_JOINT5'
00220         self._print_command('getCurrentPose({})'.format(target_joint))
00221         self._show_actual_pose(self._rtm.getCurrentPose(target_joint))
00222 
00223     def _actual_pose_r(self):
00224         target_joint = 'LARM_JOINT5'
00225         self._print_command('getCurrentPose({})'.format(target_joint))
00226         self._show_actual_pose(self._rtm.getCurrentPose(target_joint))
00227 
00228     def _show_groups(self):
00229         groups = self._rtm.Groups
00230         text = ''
00231         for g in groups:
00232             text += g[0]
00233             str_elems = ''.join(str('\t' + e + '\n') for e in g[1])
00234             text += str_elems
00235 
00236         self._print_command('Groups')
00237         self.textBrowser_output.append(text)