hand_finder.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright 2014 Shadow Robot Company Ltd.
4 #
5 # This program is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation version 2 of the License.
8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 # more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 import rospy
18 import rospkg
19 from urdf_parser_py.urdf import URDF
20 import time
21 
22 DEFAULT_TIMEOUT = 60.0
23 
24 
25 class HandControllerTuning(object):
26  def __init__(self, mapping):
27  """
28 
29  """
30  ros_pack = rospkg.RosPack()
31  ethercat_path = ros_pack.get_path('sr_ethercat_hand_config')
33  self.host_control = {}
34  self.motor_control = {}
35  for hand in mapping:
36  self.friction_compensation[mapping[hand]] = \
37  ethercat_path + '/controls/' + 'friction_compensation.yaml'
38  host_path = ethercat_path + '/controls/host/' + mapping[hand] + '/'
39  self.host_control[mapping[hand]] = \
40  [host_path + 'sr_edc_calibration_controllers.yaml',
41  host_path + 'sr_edc_joint_velocity_controllers_PWM.yaml',
42  host_path + 'sr_edc_effort_controllers_PWM.yaml',
43  host_path + 'sr_edc_joint_velocity_controllers.yaml',
44  host_path + 'sr_edc_effort_controllers.yaml',
45  host_path + 'sr_edc_mixed_position_velocity_'
46  'joint_controllers_PWM.yaml',
47  host_path + 'sr_edc_joint_position_controllers_PWM.yaml',
48  host_path + 'sr_edc_mixed_position_velocity_'
49  'joint_controllers.yaml',
50  host_path + 'sr_edc_joint_position_controllers.yaml']
51 
52  self.motor_control[mapping[hand]] = \
53  ethercat_path + '/controls/motors/' +\
54  mapping[hand] + '/motor_board_effort_controllers.yaml'
55 
56 
57 class HandCalibration(object):
58  def __init__(self, mapping):
59  """
60 
61  """
62  ros_pack = rospkg.RosPack()
63  ethercat_path = ros_pack.get_path('sr_ethercat_hand_config')
64  self.calibration_path = {}
65  for hand in mapping:
66  self.calibration_path[mapping[hand]] = \
67  ethercat_path + '/calibrations/' + mapping[hand] + '/' \
68  + "calibration.yaml"
69 
70 
71 class HandConfig(object):
72 
73  def __init__(self, mapping, joint_prefix):
74  """
75 
76  """
77  # handle possibly empty mapping
78  self.mapping = {}
79  for serial_id in mapping:
80  if mapping[serial_id] == '':
81  self.mapping[serial_id] = str(serial_id)
82  else:
83  self.mapping[serial_id] = mapping[serial_id]
84  self.joint_prefix = joint_prefix
85 
86 
87 class HandJoints(object):
88 
89  @classmethod
91  joints = ['FFJ1', 'FFJ2', 'FFJ3', 'FFJ4', 'MFJ1', 'MFJ2', 'MFJ3',
92  'MFJ4', 'RFJ1', 'RFJ2', 'RFJ3', 'RFJ4', 'LFJ1', 'LFJ2',
93  'LFJ3', 'LFJ4', 'LFJ5', 'THJ1', 'THJ2', 'THJ3', 'THJ4',
94  'THJ5', 'WRJ1', 'WRJ2']
95  return joints
96 
97  def __init__(self, mapping, joint_prefix, timeout=DEFAULT_TIMEOUT):
98  """
99 
100  """
101  self.joints = {}
102  hand_joints = []
103  joints = self.get_default_joints()
104  TIMEOUT_WAIT_FOR_PARAMS_IN_SECS = timeout
105  start_time = rospy.get_time()
106  while not rospy.has_param("robot_description"):
107  if (rospy.get_time() - start_time > TIMEOUT_WAIT_FOR_PARAMS_IN_SECS):
108  rospy.logwarn("No robot_description found on parameter server."
109  "Joint names are loaded for 5 finger hand")
110  # concatenate all the joints with prefixes
111  for hand in mapping:
112  hand_joints = []
113  if hand in joint_prefix:
114  for joint in joints:
115  hand_joints.append(joint_prefix[hand] + joint)
116  else:
117  rospy.logwarn("Cannot find serial " + hand +
118  "in joint_prefix parameters")
119  self.joints[mapping[hand]] = hand_joints
120  return
121  else:
122  time.sleep(1)
123 
124  robot_description = rospy.get_param('robot_description')
125 
126  # concatenate all the joints with prefixes
127  for hand in mapping:
128  if hand in joint_prefix:
129  for joint in joints:
130  hand_joints.append(joint_prefix[hand] + joint)
131  else:
132  rospy.logwarn("Cannot find serial " + hand +
133  "in joint_prefix parameters")
134 
135  # add the prefixed joints to each hand but remove fixed joints
136  hand_urdf = URDF.from_xml_string(robot_description)
137  for hand in mapping:
138  joints_tmp = []
139  self.joints[mapping[hand]] = []
140  for joint in hand_urdf.joints:
141  if joint.type != 'fixed':
142  prefix = joint.name[:3]
143  # is there an empty prefix ?
144  if "" in joint_prefix.values():
145  joints_tmp.append(joint.name)
146  elif prefix not in joint_prefix.values():
147  rospy.logdebug("joint " + joint.name + " has invalid "
148  "prefix:" + prefix)
149  elif prefix == joint_prefix[hand]:
150  joints_tmp.append(joint.name)
151  for joint_unordered in hand_joints:
152  if joint_unordered in joints_tmp:
153  self.joints[mapping[hand]].append(joint_unordered)
154 
155 
156 class HandFinder(object):
157  """
158  The HandFinder is a utility library for detecting Shadow Hands running on
159  the system. The idea is to make it easier to write generic code,
160  using this library to handle prefixes, joint prefixes etc...
161  """
162 
163  def __init__(self, timeout=DEFAULT_TIMEOUT):
164  """
165  Parses the parameter server to extract the necessary information.
166  """
167  self._hand_e = False
168  self._hand_parameters = {'joint_prefix': {}, 'mapping': {}}
169  self._hand_h = False
171 
172  TIMEOUT_WAIT_FOR_PARAMS_IN_SECS = timeout
173  self.wait_for_hand_params(TIMEOUT_WAIT_FOR_PARAMS_IN_SECS)
174 
175  self.hand_config = HandConfig(self._hand_parameters["mapping"],
176  self._hand_parameters["joint_prefix"])
177  self.hand_joints = HandJoints(self.hand_config.mapping, self.hand_config.joint_prefix, timeout).joints
178  self.calibration_path = HandCalibration(self.hand_config.mapping).calibration_path
180 
181  def wait_for_hand_params(self, timeout_in_secs):
182  start_time = rospy.get_time()
183  while not rospy.has_param("/hand") and not rospy.has_param("/fh_hand"):
184  if (rospy.get_time() - start_time > timeout_in_secs):
185  rospy.logerr("No hand is detected")
186  break
187  else:
188  time.sleep(1)
189  if rospy.has_param("/hand"):
190  rospy.loginfo("Found hand E")
191  self._hand_e = True
192  self._hand_parameters = rospy.get_param("/hand")
193  elif rospy.has_param("/fh_hand"):
194  rospy.loginfo("Found hand H")
195  self._hand_h = True
196  self._hand_h_parameters = rospy.get_param("/fh_hand")
197 
199  if not self._hand_e:
200  rospy.logerr("No Hand E present - can't get calibration path")
201  return self.calibration_path
202 
203  def get_hand_joints(self):
204  # TODO(@anyone): update HandJoints to work with Hand H. Didn't seem necessary yet, so left for now - dg
205  if not self._hand_e:
206  rospy.logerr("No Hand E present - can't get hand joints")
207  return self.hand_joints
208 
210  if not self._hand_e:
211  rospy.logerr("No Hand E present - can't get hand parameters")
212  return self.hand_config
213 
215  if not self._hand_e:
216  rospy.logerr("No Hand E present - can't get hand control_tuning")
217  return self.hand_control_tuning
218 
219  def hand_e_available(self):
220  return self._hand_e
221 
222  def hand_h_available(self):
223  return self._hand_h
224 
225  def get_hand_e(self, number=0, serial=None):
226  hand_parameters = self.get_hand_parameters()
227  if serial is None:
228  serial = sorted(hand_parameters.mapping.keys())[number]
229  name = "right_hand" if hand_parameters.mapping[serial] == "rh" else "left_hand"
230  prefix = hand_parameters.joint_prefix[serial]
231  return name, prefix, serial
232 
233  def get_hand_h(self, number=0, name=None):
234  if name is None:
235  name = sorted(self._hand_h_parameters.keys())[number]
236  prefix = self._hand_h_parameters[name]['controller_prefix']
237  serial = self._hand_h_parameters[name]['palm']['serial_number']
238  return "hand_h", prefix, serial
239  # TODO(@anyone): replace "hand_h" with name once moveit config is auto-generated with correct movegroup name
240 
241  def get_available_prefix(self, number=0, serial=None, name=None):
242  if self._hand_e:
243  hand_parameters = self.get_hand_parameters()
244  if serial is None:
245  serial = sorted(hand_parameters.mapping.keys())[number]
246  return hand_parameters.joint_prefix[serial]
247  elif self._hand_h:
248  if name is None:
249  name = sorted(self._hand_h_parameters.keys())[number]
250  return self._hand_h_parameters[name]['controller_prefix']
def __init__(self, mapping, joint_prefix, timeout=DEFAULT_TIMEOUT)
Definition: hand_finder.py:97
def get_available_prefix(self, number=0, serial=None, name=None)
Definition: hand_finder.py:241


sr_utilities
Author(s): Ugo Cupcic
autogenerated on Mon Feb 28 2022 23:52:19