calibrate_hand_finder.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright 2014, 2020 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 sys
18 import rospy
19 import rosservice
20 from sr_utilities.hand_finder import HandFinder
21 from std_msgs.msg import Bool
22 from std_srvs.srv import Empty
23 
24 
25 class CalibrateHand(object):
26  """
27  This class resets all the motor boards of the Shadow Hand E present in the system.
28  On reset, the motor board firmware causes a jiggle and zeroes the tendon strain gauges.
29  Once the hands have been successfully reset, this class publishes True on the topic /calibrated
30  """
31 
32  def __init__(self):
33  rospy.wait_for_service("controller_manager/load_controller", timeout=120.0)
34  self.pub_calibrated = rospy.Publisher('calibrated', Bool, queue_size=1, latch=True)
35 
37  reset_service_list = []
38  generated_reset_service_list = []
39  service_list = []
40 
41  # We first read the list of available motor reset services in this namespace
42  # this will allow us to avoid having to know the name of the robot driver node
43  ns = rospy.get_namespace()
44  while not reset_service_list:
45  rospy.sleep(0.5)
46  service_list = rosservice.get_service_list(namespace=ns)
47  reset_service_list = [srv for srv in service_list if '/reset_motor_' in srv]
48  if not reset_service_list:
49  rospy.loginfo("Waiting for motor reset services")
50 
51  # We generate a list of the services that we expect to find
52  # and merely throw a warning if some of them didn't turn up in the available service list
53  hand_finder = HandFinder()
54  joints = hand_finder.get_hand_joints()
55  mapping = hand_finder.get_hand_parameters().mapping
56  for hand in mapping:
57  prefix = mapping[hand]
58  for joint in joints[prefix]:
59  if not (joint[3:5].lower() == 'th' or joint[3:5].lower() == 'wr' or
60  (joint[6] != '1' and joint[6] != '2')):
61  joint = joint[:6] + '0'
62 
63  joint_reset_service = joint[:2] + '/reset_motor_' + joint[3:].upper()
64 
65  if joint_reset_service not in generated_reset_service_list:
66  generated_reset_service_list.append(joint_reset_service)
67  for gen_srv in generated_reset_service_list:
68  gen_srv_match_list = [srv for srv in reset_service_list if gen_srv in srv]
69  if not gen_srv_match_list:
70  rospy.logwarn("Expected service not found: %s", gen_srv)
71 
72  return reset_service_list
73 
74  def calibrate(self, services):
75  success = True
76  for srv in services:
77  rospy.wait_for_service(srv, timeout=4.0)
78  try:
79  reset_motor = rospy.ServiceProxy(srv, Empty)
80  reset_motor()
81  except rospy.ServiceException as exc:
82  success = False
83  rospy.logerr("Motor reset failed: %s Exception: %s", srv, str(exc))
84  return success
85 
86 
87 def main():
88  if rospy.is_shutdown():
89  return
90 
91  rospy.init_node('calibration', anonymous=True)
92  calibrate_class = CalibrateHand()
93 
94  services = calibrate_class.generate_reset_services_list()
95 
96  calibrate_class.pub_calibrated.publish(False)
97 
98  if not calibrate_class.calibrate(services):
99  sys.exit(3)
100 
101  calibrate_class.pub_calibrated.publish(True)
102 
103  print("Hand calibration complete")
104  rospy.spin()
105 
106 if __name__ == '__main__':
107  main()


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