bhand_node.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2014, Robotnik Automation SLL
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of Robotnik Automation SSL nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 
34 import rospy
35 from pyHand_api import *
36 
37 from std_msgs.msg import String
38 from bhand_controller.msg import State, TactileArray, Service, ForceTorque
39 from bhand_controller.srv import Actions, SetControlMode
40 from sensor_msgs.msg import JointState
41 
42 import time, threading
43 import math
44 
45 DEFAULT_FREQ = 100.0
46 MAX_FREQ = 300.0
47 
48 
49 CONTROL_MODE_POSITION = "PID"
50 CONTROL_MODE_VELOCITY = "VELOCITY"
51 CONTROL_MODE_IDLE = "IDLE"
52 
53 WATCHDOG_VELOCITY = 0.1 # Max time (seconds) between velocity commands before stopping the velocity
54 
55 # class to save the info of each joint
56 class JointHand:
57 
58  def __init__(self, id, name):
59  self.id = id
60  self.joint_name = name
61  self.desired_position = 0.0
62  self.desired_velocity = 0.0
63  self.real_position = 0.0
64  self.real_velocity = 0.0
65 
66 
67 # Class control the Barrett Hand
68 class BHand:
69 
70  def __init__(self, args):
71 
72  self.port = args['port']
73  self.topic_state_name = args['topic_state']
74  self.desired_freq = args['desired_freq']
75  if self.desired_freq <= 0.0 or self.desired_freq > MAX_FREQ:
76  rospy.loginfo('%s::init: Desired freq (%f) is not possible. Setting desired_freq to %f'%(rospy.get_name(), self.desired_freq, DEFAULT_FREQ))
77  self.desired_freq = DEFAULT_FREQ
78  self.tactile_sensors = args['tactile_sensors']
79  self.ft_sensor = args['ft_sensor']
80  self.ft_sensor_frame_id = args['ft_sensor_frame_id']
81  self.real_freq = 0.0
82 
83  joint_ids_arg = args['joint_ids']
84  joint_names_arg = args['joint_names']
85  # Control mode
86  self.control_mode = args['control_mode']
87  if self.control_mode != CONTROL_MODE_POSITION and self.control_mode != CONTROL_MODE_VELOCITY:
88  rospy.loginfo('%s: init: setting control mode by default to %s'%(rospy.get_name(), CONTROL_MODE_POSITION))
89  self.control_mode = CONTROL_MODE_POSITION
90 
91  self.state = State.INIT_STATE
92  # flag to control the initialization of CAN device
93  self.can_initialized = False
94  # flag to control the initialization of the hand
95  self.hand_initialized = False
96  # flag to control the initialization of ROS stuff
97  self.ros_initialized = False
98  # flag to control that the control loop is running
99  self.running = False
100 
101  self.time_sleep = 1.0
102  # BHand library object
103  self.hand = pyHand(self.port)
104  # Current state of the joints
105  self.joint_state = JointState()
106  # Msg to publish the tactile array
107  self.msg_tact_array = TactileArray()
108  # State msg to publish
109  self.msg_state = State()
110  # Timer to publish state
112  # Flag active after receiving a new command
113  self.new_command = False
114  # Flag active for reading temperature
115  self.temp_command = False
116  # Used to read one temperature sensor every time
118  # Total number of temperature sensors
120  # Frequency to read temperature
121  self.temp_read_timer = 5# seconds
122  # Counts the number of CAN errors before switching to FAILURE
123  self.can_errors = 0
124  # Max. number of CAN errors
125  self.max_can_errors = 5
126  # Flag to perform a failure recover
127  self.failure_recover = False
128  # Timer to try the FAILURE RECOVER
130  # Timer to save the last command
131  self.timer_command = time.time()
132  self.watchdog_command = float(WATCHDOG_VELOCITY)
133 
134  # List where saving the required actions
135  self.actions_list = []
136  # Mode of the hand to perform the grasp
137  self.grasp_mode = Service.SET_GRASP_1
138 
139  #print 'Control mode = %s'%self.control_mode
140 
141  # Data structure to link assigned joint names with every real joint
142  # {'ID': ['joint_name', index], ...}
143  #self.joint_names = {'F1': ['j12_joint', 0], 'F1_TIP': ['j13_joint', 1] , 'F2': ['j22_joint', 2], 'F2_TIP': ['j23_joint', 3], 'F3': ['j32_joint', 4], 'F3_TIP': ['j33_joint', 5], 'SPREAD_1': ['j11_joint', 6], 'SPREAD_2': ['j21_joint', 7]}
144  # {'ID': ['joint_name'], ...}
145  #'j33_joint' -> F3-Fingertip
146  #'j32_joint' -> F3-Base
147  #
148  #'j11_joint' -> F1-Spread
149  #'j12_joint' -> F1-Base
150  #'j13_joint' -> F1-Fingertip
151  #
152  #'j21_joint' -> F2-Spread
153  #'j22_joint' -> F2-Base
154  #'j23_joint' -> F2-Fingertip
155 
156  self.joint_names = {}
157 
158  for i in range(len(joint_ids_arg)):
159  self.joint_names[joint_ids_arg[i]] = [joint_names_arg[i], i]
160 
161  print self.joint_names
162 
163  # {'ID': [Puck_temp, motor_temp], ..}
164  self.temperatures = {'F1': [0.0, 0.0], 'F2': [0.0, 0.0], 'F3': [0.0, 0.0], 'SPREAD': [0.0, 0.0]}
165 
166  # Inits joint state (FOR PUBLISHING)
167  k = 0
168  for i in self.joint_names:
169  self.joint_state.name.append(self.joint_names[i][0])
170  self.joint_names[i][1] = k # Updates the index
171  k = k + 1
172  #self.joint_state.name = ['j33_joint', 'j32_joint', 'j21_joint', 'j22_joint', 'j23_joint', 'j11_joint', 'j12_joint', 'j13_joint']
173  self.joint_state.position.append(0.0)
174  self.joint_state.velocity.append(0.0)
175  self.joint_state.effort.append(0.0)
176 
177  # Saves the desired position of the joints {'joint_name': value, ...}
178  self.desired_joints_position = {self.joint_names['F1'][0]: 0.0, self.joint_names['F2'][0]: 0.0, self.joint_names['F3'][0]: 0.0, self.joint_names['SPREAD_1'][0]: 0.0, self.joint_names['SPREAD_2'][0]: 0.0}
179  self.desired_joints_velocity = {self.joint_names['F1'][0]: 0.0, self.joint_names['F2'][0]: 0.0, self.joint_names['F3'][0]: 0.0, self.joint_names['SPREAD_1'][0]: 0.0, self.joint_names['SPREAD_2'][0]: 0.0}
180  # Saves the last sent velocity
181  self.sent_joints_velocity = {self.joint_names['F1'][0]: 0.0, self.joint_names['F2'][0]: 0.0, self.joint_names['F3'][0]: 0.0, self.joint_names['SPREAD_1'][0]: 0.0, self.joint_names['SPREAD_2'][0]: 0.0}
182 
183  self.t_publish_state = threading.Timer(self.publish_state_timer, self.publishROSstate)
184  self.t_read_temp = threading.Timer(self.temp_read_timer, self.readTemp)
185  self.msg_ft = ForceTorque()
186  self.msg_ft.header.frame_id = self.ft_sensor_frame_id
187 
188  rospy.loginfo('%s: port %s, freq = %d, topic = %s, tactile_sensors = %s'%(rospy.get_name() , self.port, self.desired_freq, self.topic_state_name, self.tactile_sensors))
189 
190 
191  def setup(self):
192  '''
193  Initializes de hand
194  @return: True if OK, False otherwise
195  '''
196  if self.can_initialized or self.hand.initialize() == True:
197  if self.ft_sensor:
198  rospy.loginfo('%s:setup: initializing FT sensor'%rospy.get_name() )
199  self.hand.initialize_fts()
200  rospy.loginfo('%s:setup: ok'%rospy.get_name() )
201  self.can_initialized = True
202  return 0
203  else:
204  self.hand.can_uninit()
205  rospy.logerr('%s:setup: Error initializing the hand'%rospy.get_name() )
206  return -1
207 
208 
209  def rosSetup(self):
210  '''
211  Creates and inits ROS components
212  '''
213  if self.ros_initialized:
214  return 0
215 
216  #self._enable_disable_service = rospy.Service('%s/enable_disable'%rospy.get_name(), enable_disable, self.enableDisable)
217  # PUBLISHERS
218  self._state_publisher = rospy.Publisher('%s/state'%rospy.get_name(), State, queue_size=5)
219  self._joints_publisher = rospy.Publisher('/joint_states', JointState, queue_size=5)
220  self._tact_array_publisher = rospy.Publisher('%s/tact_array'%rospy.get_name(), TactileArray, queue_size=5)
221  self._ft_sensor_publisher = rospy.Publisher('~force_torque', ForceTorque, queue_size=5)
222  # SUBSCRIBERS
223  self._joints_subscriber = rospy.Subscriber('%s/command'%rospy.get_name(), JointState, self.commandCallback)
224 
225  # SERVICES
226  self._hand_service = rospy.Service('%s/actions'%rospy.get_name(), Actions, self.handActions)
227  self._set_control_mode_service = rospy.Service('%s/set_control_mode'%rospy.get_name(), SetControlMode, self.setControlModeServiceCb)
228 
229  self.ros_initialized = True
230 
231  self.publishROSstate()
232 
233  return 0
234 
235 
236  def shutdown(self):
237  '''
238  Shutdowns device
239  @return: 0 if it's performed successfully, -1 if there's any problem or the component is running
240  '''
241  if self.running or not self.can_initialized:
242  return -1
243  rospy.loginfo('%s::shutdown'%rospy.get_name())
244  self.setControlMode(CONTROL_MODE_POSITION)
245  # Performs Hand shutdown
246  self.hand.can_uninit()
247  # Cancels current timers
248  self.t_publish_state.cancel()
249  self.t_read_temp.cancel()
250 
251 
252  self.can_initialized = False
253  self.hand_initialized = False
254 
255  return 0
256 
257 
258  def rosShutdown(self):
259  '''
260  Shutdows all ROS components
261  @return: 0 if it's performed successfully, -1 if there's any problem or the component is running
262  '''
263  if self.running or not self.ros_initialized:
264  return -1
265 
266  # Performs ROS topics & services shutdown
267  self._state_publisher.unregister()
268  self._joints_publisher.unregister()
269  self._tact_array_publisher.unregister()
270  self._joints_subscriber.unregister()
271  self._ft_sensor_publisher.unregister()
272  self._set_control_mode_service.shutdown()
273  self._hand_service.shutdown()
274 
275  self.ros_initialized = False
276 
277  return 0
278 
279 
280  def stop(self):
281  '''
282  Creates and inits ROS components
283  '''
284  self.running = False
285 
286  return 0
287 
288 
289  def start(self):
290  '''
291  Runs ROS configuration and the main control loop
292  @return: 0 if OK
293  '''
294  self.rosSetup()
295 
296  if self.running:
297  return 0
298 
299  self.running = True
300 
301  self.controlLoop()
302 
303  return 0
304 
305 
306  def controlLoop(self):
307  '''
308  Main loop of the component
309  Manages actions by state
310  '''
311 
312  while self.running and not rospy.is_shutdown():
313  t1 = time.time()
314 
315  if self.state == State.INIT_STATE:
316  self.initState()
317 
318  elif self.state == State.STANDBY_STATE:
319  self.standbyState()
320 
321  elif self.state == State.READY_STATE:
322  self.readyState()
323 
324  elif self.state == State.EMERGENCY_STATE:
325  self.emergencyState()
326 
327  elif self.state == State.FAILURE_STATE:
328  self.failureState()
329 
330  elif self.state == State.SHUTDOWN_STATE:
331  self.shutdownState()
332 
333  self.allState()
334 
335  t2 = time.time()
336  tdiff = (t2 - t1)
337 
338 
339  t_sleep = self.time_sleep - tdiff
340  #print 't_sleep = %f secs'%(t_sleep)
341  if t_sleep > 0.0:
342  #print 't_sleep = %f secs'%(self.time_sleep)
343  rospy.sleep(t_sleep)
344 
345  t3= time.time()
346  self.real_freq = 1.0/(t3 - t1)
347 
348  self.running = False
349  # Performs component shutdown
350  self.shutdownState()
351  # Performs ROS shutdown
352  self.rosShutdown()
353  rospy.loginfo('%s::controlLoop: exit control loop'%rospy.get_name())
354 
355  return 0
356 
357 
358 
359  def rosPublish(self):
360  '''
361  Publish topics at standard frequency
362  '''
363  #self._state_publisher.publish(self.getState())
364 
365 
366  t = rospy.Time.now()
367 
368  self.joint_state.header.stamp = t
369  self._joints_publisher.publish(self.joint_state)
370 
371  if self.tactile_sensors:
372  self.msg_tact_array.header.stamp = t
373  self._tact_array_publisher.publish(self.msg_tact_array)
374 
375  if self.ft_sensor:
376  self.msg_ft.header.stamp = t
377  self._ft_sensor_publisher.publish(self.msg_ft)
378 
379  return 0
380 
381 
382 
383  def initState(self):
384  '''
385  Actions performed in init state
386  '''
387  error = 0
388  if not self.can_initialized:
389  ret = self.setup()
390  if ret == -1:
391  error = 1
392 
393  if self.hand_initialized and self.can_initialized:
394  self.switchToState(State.STANDBY_STATE)
395 
396  self.canError(error)
397 
398  return
399 
400  def standbyState(self):
401  '''
402  Actions performed in standby state
403  '''
404  #self.hand.close_grasp()
405  self.switchToState(State.READY_STATE)
406 
407  return
408 
409 
410  def readyState(self):
411  '''
412  Actions performed in ready state
413  '''
414  f1_index = self.joint_names['F1'][1]
415  f2_index = self.joint_names['F2'][1]
416  f3_index = self.joint_names['F3'][1]
417  f1_tip_index = self.joint_names['F1_TIP'][1]
418  f2_tip_index = self.joint_names['F2_TIP'][1]
419  f3_tip_index = self.joint_names['F3_TIP'][1]
420  spread1_index = self.joint_names['SPREAD_1'][1]
421  spread2_index = self.joint_names['SPREAD_2'][1]
422  errors = 0
423 
424 
425  try:
426  # Reads position
427  self.hand.read_packed_position(HAND_GROUP)
428 
429  # Reads strain
430  self.hand.read_strain(HAND_GROUP)
431  #self.hand.read_strain(FINGER2)
432  #self.hand.read_strain(FINGER3)
433 
434  # Reads temperature
435  if self.temp_command:
436  self.hand.read_temp(HAND_GROUP)
437  self.hand.read_therm(HAND_GROUP)
438  self.initReadTempTimer()
439 
440  # Reads tactile sensor cells
441  if self.tactile_sensors:
442 
443  self.hand.read_full_tact(FINGER1)
444  self.hand.read_full_tact(FINGER2)
445  self.hand.read_full_tact(FINGER3)
446  self.hand.read_full_tact(SPREAD)
447 
448 
449  # Reads ft sensors
450  if self.ft_sensor:
451  self.hand.read_full_force_torque()
452 
453 
454  except Exception, e:
455  rospy.logerr('%s::readyState: error getting info: %s'%(rospy.get_name(), e))
456  errors = errors + 1
457 
458  # Predefined actions
459  if len(self.actions_list) > 0:
460  action = self.actions_list[0]
461  # Removes action from list
462  self.actions_list.remove(action)
463 
464  # Actions performed in CONTROL POSITION
465  if self.control_mode == CONTROL_MODE_VELOCITY:
466  self.setControlMode(CONTROL_MODE_POSITION)
467 
468  if action == Service.CLOSE_GRASP:
469  self.closeFingers(3.14)
470 
471  if action == Service.CLOSE_HALF_GRASP:
472  self.closeFingers(1.57)
473 
474  elif action == Service.OPEN_GRASP:
475  self.openFingers()
476 
477  elif action == Service.SET_GRASP_1:
478  if self.joint_state.position[f1_index] > 0.1 or self.joint_state.position[f2_index] > 0.1 or self.joint_state.position[f3_index] > 0.1:
479  #rospy.logerr('BHand::ReadyState: Service SET_GRASP 1 cannot be performed. Rest of fingers have to be on zero position')
480  self.openFingers()
481  time.sleep(2.0)
482 
483  self.desired_joints_position['SPREAD_1'] = 0.0
484  self.desired_joints_position['SPREAD_2'] = 0.0
485  self.hand.move_to(SPREAD, self.hand.rad_to_enc(self.desired_joints_position['SPREAD_1'], BASE_TYPE), False)
486  self.grasp_mode = action
487 
488  elif action == Service.SET_GRASP_2:
489  if self.joint_state.position[f1_index] > 0.1 or self.joint_state.position[f2_index] > 0.1 or self.joint_state.position[f3_index] > 0.1:
490  #rospy.logerr('BHand::ReadyState: Service SET_GRASP 2 cannot be performed. Rest of fingers have to be on zero position')
491  self.openFingers()
492  time.sleep(2.0)
493  #else:
494  self.desired_joints_position['SPREAD_1'] = 3.14
495  self.desired_joints_position['SPREAD_2'] = 3.14
496  self.hand.move_to(SPREAD, self.hand.rad_to_enc(self.desired_joints_position['SPREAD_1'], BASE_TYPE), False)
497  self.grasp_mode = action
498 
499  elif action == Service.TARE_FTS:
500  if self.ft_sensor:
501  self.hand.tare_fts()
502 
503  # NO pre-defined actions
504  else:
505  if self.control_mode == CONTROL_MODE_POSITION:
506 
507  # Moves joints to desired pos
508  if self.new_command:
509  try:
510  f1_joint = self.joint_names['F1'][0]
511  if self.desired_joints_position[f1_joint] != self.joint_state.position[f1_index]:
512  #rospy.loginfo_throttle(2,'moving joint %s to position %f'%(f1_joint, self.desired_joints_position[f1_joint]))
513  self.hand.move_to(FINGER1, self.hand.rad_to_enc(self.desired_joints_position[f1_joint], BASE_TYPE), False)
514 
515  f2_joint = self.joint_names['F2'][0]
516  if self.desired_joints_position[f2_joint] != self.joint_state.position[f2_index]:
517  #rospy.loginfo_throttle(2,'moving joint %s to position %f'%(f2_joint, self.desired_joints_position[f2_joint]))
518  self.hand.move_to(FINGER2, self.hand.rad_to_enc(self.desired_joints_position[f2_joint], BASE_TYPE), False)
519 
520  f3_joint = self.joint_names['F3'][0]
521  if self.desired_joints_position[f3_joint] != self.joint_state.position[f3_index]:
522  #rospy.loginfo_throttle(2,'moving joint %s to position %f'%(f3_joint, self.desired_joints_position[f3_joint]))
523  self.hand.move_to(FINGER3, self.hand.rad_to_enc(self.desired_joints_position[f3_joint], BASE_TYPE), False)
524 
525  spread1_joint = self.joint_names['SPREAD_1'][0]
526  spread2_joint = self.joint_names['SPREAD_2'][0]
527  if self.desired_joints_position[spread1_joint] != self.joint_state.position[spread1_index]:
528  #rospy.loginfo_throttle(2,'moving joint %s to position %f'%(spread1_joint, self.desired_joints_position[spread1_joint]))
529  self.hand.move_to(SPREAD, self.hand.rad_to_enc(self.desired_joints_position[spread1_joint], SPREAD_TYPE), False)
530  elif self.desired_joints_position[spread2_joint] != self.joint_state.position[spread2_index]:
531  #rospy.loginfo_throttle(2,'moving joint %s to position %f'%(spread2_joint, self.desired_joints_position[spread2_joint]))
532  self.hand.move_to(SPREAD, self.hand.rad_to_enc(self.desired_joints_position[spread2_joint], SPREAD_TYPE), False)
533 
534  except Exception, e:
535  rospy.logerr('%s::readyState: error sending command: %s'%(rospy.get_name(), e))
536  errors = errors + 1
537 
538  self.new_command = False
539 
540  else:
541  # VELOCITY CONTROL
542  if ((time.time() - self.timer_command) >= self.watchdog_command):
543  try:
544  #rospy.loginfo('BHand::readyState: Watchdog velocity')
545  self.desired_joints_velocity[self.joint_names['F1'][0]] = 0.0
546  self.desired_joints_velocity[self.joint_names['F2'][0]] = 0.0
547  self.desired_joints_velocity[self.joint_names['F3'][0]] = 0.0
548  self.desired_joints_velocity[self.joint_names['SPREAD_1'][0]] = 0.0
549  self.desired_joints_velocity[self.joint_names['SPREAD_2'][0]] = 0.0
550  self.setJointVelocity('F1')
551  self.setJointVelocity('F2')
552  self.setJointVelocity('F3')
553  self.setJointVelocity('SPREAD_1')
554  except Exception, e:
555  rospy.logerr('%s::readyState: error sending command: %s'%(rospy.get_name(), e))
556  errors = errors + 1
557  # Moves joints to desired pos
558  if self.new_command:
559 
560  try:
561  self.setJointVelocity('F1')
562  self.setJointVelocity('F2')
563  self.setJointVelocity('F3')
564  self.setJointVelocity('SPREAD_1')
565 
566 
567  except Exception, e:
568  rospy.logerr('%s::readyState: error sending command: %s'%(rospy.get_name(), e))
569  errors = errors + 1
570 
571  self.new_command = False
572 
573  time.sleep(0.002)
574 
575  # Reads messages from CAN bus
576  if self.hand.process_can_messages() != 0:
577  # If it doesn't read any msg, counts as error
578  self.canError(1)
579 
580  # Updating variables
581  # Position
582  self.joint_state.position[f1_index], self.joint_state.position[f1_tip_index] = self.hand.get_packed_position(FINGER1)
583  self.joint_state.position[f2_index], self.joint_state.position[f2_tip_index] = self.hand.get_packed_position(FINGER2)
584  self.joint_state.position[f3_index], self.joint_state.position[f3_tip_index] = self.hand.get_packed_position(FINGER3)
585  self.joint_state.position[spread1_index], e = self.hand.get_packed_position(SPREAD)
586  self.joint_state.position[spread2_index] = self.joint_state.position[spread1_index]
587 
588  # Strain
589  self.joint_state.effort[f1_index] = self.joint_state.effort[f1_tip_index] = self.strain_to_nm(self.hand.get_strain(FINGER1))
590  self.joint_state.effort[f2_index] = self.joint_state.effort[f2_tip_index] = self.strain_to_nm(self.hand.get_strain(FINGER2))
591  self.joint_state.effort[f3_index] = self.joint_state.effort[f3_tip_index] = self.strain_to_nm(self.hand.get_strain(FINGER3))
592 
593  # Temperature
594  self.msg_state.temp_f1[1] = self.hand.get_temp(FINGER1)
595  self.msg_state.temp_f2[1] = self.hand.get_temp(FINGER2)
596  self.msg_state.temp_f3[1] = self.hand.get_temp(FINGER3)
597  self.msg_state.temp_spread[1] = self.hand.get_temp(SPREAD)
598  self.msg_state.temp_f1[0] = self.hand.get_therm(FINGER1)
599  self.msg_state.temp_f2[0] = self.hand.get_therm(FINGER2)
600  self.msg_state.temp_f3[0] = self.hand.get_therm(FINGER3)
601  self.msg_state.temp_spread[0] = self.hand.get_therm(SPREAD)
602 
603  # Tactile Sensors
604  if self.tactile_sensors:
605  self.msg_tact_array.finger1 = self.hand.get_full_tact(FINGER1)
606  self.msg_tact_array.finger2 = self.hand.get_full_tact(FINGER2)
607  self.msg_tact_array.finger3 = self.hand.get_full_tact(FINGER3)
608  self.msg_tact_array.palm = self.hand.get_full_tact(SPREAD)
609 
610  if self.ft_sensor:
611  fts = self.hand.get_fts()
612  self.msg_ft.force.x = fts['force'][0]
613  self.msg_ft.force.y = fts['force'][1]
614  self.msg_ft.force.z = fts['force'][2]
615  self.msg_ft.torque.x = fts['torque'][0]
616  self.msg_ft.torque.y = fts['torque'][1]
617  self.msg_ft.torque.z = fts['torque'][2]
618 
619  # Check the CAN bus status
620  self.canError(errors)
621 
622  return
623 
624 
625  def setJointVelocity(self, finger):
626  '''
627  Sets the joint velocity of the desired joint
628  Takes the velocity value from the attribute desired_joints_velocity
629  @param joint: finger of the hand (F1, F2, F3, SPREAD)
630  @type joint: string
631  '''
632  if self.joint_names.has_key(finger):
633  joint = self.joint_names[finger][0]
634 
635  if self.desired_joints_velocity[joint] != self.sent_joints_velocity[joint]:
636 
637  value = self.hand.rad_to_enc(self.desired_joints_velocity[joint], BASE_TYPE) / 1000
638  self.sent_joints_velocity[joint] = self.desired_joints_velocity[joint] # Saves the last sent ref
639  #print 'Moving Joint %s at %f rad/s (%d conts/sec)'%(joint, self.desired_joints_velocity[joint], value)
640 
641  if finger == 'F1':
642  self.hand.set_velocity(FINGER1, value)
643  elif finger == 'F2':
644  self.hand.set_velocity(FINGER2, value)
645  elif finger == 'F3':
646  self.hand.set_velocity(FINGER3, value)
647  elif finger == 'SPREAD_1' or finger == 'SPREAD_2':
648  self.hand.set_velocity(SPREAD, value)
649 
650 
651  def shutdownState(self):
652  '''
653  Actions performed in shutdown state
654  '''
655  rospy.loginfo('%s:shutdownState', rospy.get_name())
656  if self.shutdown() == 0:
657  self.switchToState(State.INIT_STATE)
658 
659  return
660 
661  def emergencyState(self):
662  '''
663  Actions performed in emergency state
664  '''
665 
666  return
667 
668  def failureState(self):
669  '''
670  Actions performed in failure state
671  '''
672  if self.failure_recover:
673  # Performs Hand shutdown
674  self.hand.can_uninit()
675  self.can_initialized = False
676  self.switchToState(State.INIT_STATE)
677  self.failure_recover = False
678  self.can_errors = 0
679 
680  return
681 
682  def switchToState(self, new_state):
683  '''
684  Performs the change of state
685  '''
686  if self.state != new_state:
687  self.state = new_state
688  rospy.loginfo('BHand::switchToState: %s', self.stateToString(self.state))
689 
690  if self.state == State.READY_STATE:
691  # On ready state it sets the desired freq.
692  self.time_sleep = 1.0 / self.desired_freq
693  self.initReadTempTimer()
694  elif self.state == State.FAILURE_STATE:
695  # On other states it set 1 HZ frequency
696  self.time_sleep = 1.0
698  else:
699  # On other states it set 1 HZ frequency
700  self.time_sleep = 1.0
701 
702  return
703 
704  def allState(self):
705  '''
706  Actions performed in all states
707  '''
708  self.rosPublish()
709 
710  return
711 
712 
713  def stateToString(self, state):
714  '''
715  @param state: state to convert
716  @type state: bhand_controller.msg.State
717  @returns the equivalent string of the state
718  '''
719  if state == State.INIT_STATE:
720  return 'INIT_STATE'
721 
722  elif state == State.STANDBY_STATE:
723  return 'STANDBY_STATE'
724 
725  elif state == State.READY_STATE:
726  return 'READY_STATE'
727 
728  elif state == State.EMERGENCY_STATE:
729  return 'EMERGENCY_STATE'
730 
731  elif state == State.FAILURE_STATE:
732  return 'FAILURE_STATE'
733 
734  elif state == State.SHUTDOWN_STATE:
735  return 'SHUTDOWN_STATE'
736  else:
737  return 'UNKNOWN_STATE'
738 
739 
740  def actionsToString(self, action):
741  '''
742  @param action: action to convert
743  @type state: bhand_controller.msg.Service
744  @returns the equivalent string of the action
745  '''
746  if action == Service.INIT_HAND:
747  return 'INIT_HAND'
748 
749  elif action == Service.CLOSE_GRASP:
750  return 'CLOSE_GRASP'
751 
752  elif action == Service.OPEN_GRASP:
753  return 'OPEN_GRASP'
754 
755  elif action == Service.SET_GRASP_1:
756  return 'SET_GRASP_1'
757 
758  elif action == Service.SET_GRASP_2:
759  return 'SET_GRASP_2'
760 
761  elif action == Service.CLOSE_HALF_GRASP:
762  return 'CLOSE_HALF_GRASP'
763 
764  else:
765  return 'UNKNOWN_ACTION'
766 
767 
768  def commandCallback(self, data):
769  '''
770  Function called when receive a new value
771  @param data: state to convert
772  @type data: sensor_msgs.JointState
773  '''
774  bingo = False
775 
776  for i in range(len(data.name)):
777  if self.desired_joints_position.has_key(data.name[i]):
778  self.desired_joints_position[data.name[i]] = data.position[i]
779  self.desired_joints_velocity[data.name[i]] = data.velocity[i]
780  bingo = True
781 
782 
783  if bingo:
784  self.new_command = True
785  self.timer_command = time.time()
786  #print 'commandCallback'
787 
788 
789  def readTemp(self):
790  '''
791  Function periodically to enable the read of temperature
792  '''
793 
795 
797  self.temp_current_sensor = 1
798 
799  self.temp_command = True
800 
801 
802  def initReadTempTimer(self):
803  '''
804  Function to start the timer to read the temperature
805  '''
806  self.temp_command = False
807 
808  self.t_read_temp = threading.Timer(self.temp_read_timer, self.readTemp)
809  self.t_read_temp.start()
810 
811 
812  def publishROSstate(self):
813  '''
814  Publish the State of the component at the desired frequency
815  '''
816  self.msg_state.state = self.state
817  self.msg_state.state_description = self.stateToString(self.state)
818  self.msg_state.desired_freq = self.desired_freq
819  self.msg_state.real_freq = self.real_freq
820  self.msg_state.hand_initialized = self.hand_initialized
821  self.msg_state.control_mode = self.control_mode
822  self._state_publisher.publish(self.msg_state)
823 
824  self.t_publish_state = threading.Timer(self.publish_state_timer, self.publishROSstate)
825  self.t_publish_state.start()
826 
827 
828  def strain_to_nm(self, x):
829  '''
830  Converts from raw encoder unit reading to Newton-meters.
831 
832  @param x: value to convert
833 
834  @returns nm: the torque value in Newton-meters.
835  '''
836  p1 = 2.754e-10
837  p2 = -1.708e-06
838  p3 = 0.003764
839  p4 = -2.85
840  nm= p1*x**3 + p2*x**2 + p3*x + p4
841 
842  return nm
843 
844 
845  def handActions(self, req):
846  '''
847  Handles the callback to Actions ROS service. Allows a set of predefined actions like init_hand, close_grasp, ...
848 
849  @param req: action id to perform
850  @type req: bhand_controller.srv.Actions
851 
852  @returns: True or false depending on the result
853  '''
854  if req.action == Service.INIT_HAND:
855  if self.state != State.INIT_STATE:
856  rospy.logerr('%s::handActions: action INIT_HAND not allowed in state %s'%(rospy.get_name() ,self.stateToString(self.state)))
857 
858  return False
859  else:
860  ret = self.hand.init_hand()
861  if ret:
862  self.hand_initialized = True
863  #self.setControlMode(self.control_mode, force = True)
864  rospy.loginfo('%s::handActions: INIT HAND service OK'%rospy.get_name() )
865 
866  return True
867  else:
868  rospy.logerr('%s::handActions: error on INIT_HAND service'%rospy.get_name() )
869  # Set the max number of errors to perform the CAN reinitialization
870  self.canError(self.max_can_errors + 1)
871  return False
872 
873  if self.state != State.READY_STATE:
874  rospy.logerr('%s::handActions: action not allowed in state %s'%(rospy.get_name(), self.stateToString(self.state)))
875  return False
876  else:
877  rospy.loginfo('%s::handActions: Received new action %s'%(rospy.get_name(), self.actionsToString(req.action)))
878  self.actions_list.append(req.action)
879 
880  return True
881 
882 
883  def canError(self, n):
884  '''
885  Manages the CAN errors ocurred
886 
887  @param n: number of produced
888  @type n: int
889 
890  @returns: True or false depending on the result
891  '''
892 
893  self.can_errors = self.can_errors + n
894 
895  #rospy.loginfo('%s::canError: %d errors on CAN bus'%(rospy.get_name(),self.can_errors))
896 
897  if self.can_errors > self.max_can_errors:
898  rospy.logerr('%s::canError: Errors on CAN bus'%rospy.get_name())
899  self.switchToState(State.FAILURE_STATE)
900 
901 
902  def initFailureRecoverTimer(self, timer = 5):
903  '''
904  Function to start the timer to recover from FAILURE STATE
905  '''
906  t = threading.Timer(timer, self.failureRecover)
907  t.start()
908 
909 
910  def failureRecover(self):
911  '''
912  Sets the recovery flag TRUE. Function called after timer
913  '''
914  self.failure_recover = True
915 
916 
917  def setControlModeServiceCb(self, req):
918  '''
919  Sets the hand control mode
920  @param req: Requested service
921  @type req: bhand_controller.srv.SetControlMode
922  '''
923  if self.state != State.READY_STATE:
924  rospy.logerr('%s:setControlModeServiceCb: bhand is not in a valid state to change the mode'%rospy.get_name() )
925  return False
926 
927  if req.mode != CONTROL_MODE_POSITION and req.mode != CONTROL_MODE_VELOCITY:
928  rospy.logerr('%s:setControlModeServiceCb: invalid control mode %s'%(rospy.get_name(), req.mode))
929  return False
930 
931  else:
932  if self.setControlMode(req.mode):
933  rospy.loginfo('%s:setControlModeServiceCb: control mode %s set successfully'%(rospy.get_name(), req.mode))
934  return True
935 
936  else:
937  return False
938 
939 
940  def setControlMode(self, mode, force = False):
941  '''
942  Configures the hand to work under the desired control mode
943  @param mode: new mode
944  @type mode: string
945  '''
946  if force == False and self.control_mode == mode:
947  return True
948 
949  if mode == CONTROL_MODE_POSITION:
950  self.hand.set_mode(HAND_GROUP, 'PID')
951  elif mode == CONTROL_MODE_VELOCITY:
952  self.hand.set_mode(HAND_GROUP, 'VEL')
953  elif mode == CONTROL_MODE_IDLE:
954  self.hand.set_mode(HAND_GROUP, 'IDLE')
955 
956  self.control_mode = mode
957 
958 
959  def openFingers(self):
960  '''
961  Opens all the fingers
962  '''
963  self.desired_joints_position['F1'] = 0.0
964  self.desired_joints_position['F2'] = 0.0
965  self.desired_joints_position['F3'] = 0.0
966  self.hand.move_to(FINGER1, self.hand.rad_to_enc(self.desired_joints_position['F1'], BASE_TYPE), False)
967  self.hand.move_to(FINGER2, self.hand.rad_to_enc(self.desired_joints_position['F2'], BASE_TYPE), False)
968  self.hand.move_to(FINGER3, self.hand.rad_to_enc(self.desired_joints_position['F3'], BASE_TYPE), False)
969 
970 
971  def closeFingers(self, value):
972  '''
973  Closes all the fingers
974  '''
975  self.desired_joints_position['F1'] = value
976  self.desired_joints_position['F2'] = value
977  self.desired_joints_position['F3'] = value
978  self.hand.move_to(FINGER1, self.hand.rad_to_enc(self.desired_joints_position['F1'], BASE_TYPE), False)
979  self.hand.move_to(FINGER2, self.hand.rad_to_enc(self.desired_joints_position['F2'], BASE_TYPE), False)
980  self.hand.move_to(FINGER3, self.hand.rad_to_enc(self.desired_joints_position['F3'], BASE_TYPE), False)
981 
982 
983 
984 def main():
985 
986  rospy.init_node("bhand_node")
987 
988 
989  _name = rospy.get_name()
990 
991  arg_defaults = {
992  'port': '/dev/pcan32',
993  'topic_state': 'state',
994  'desired_freq': DEFAULT_FREQ,
995  'tactile_sensors': True,
996  'ft_sensor': False,
997  'control_mode': 'POSITION',
998  'joint_ids': [ 'F1', 'F1_TIP', 'F2', 'F2_TIP', 'F3', 'F3_TIP', 'SPREAD_1', 'SPREAD_2'],
999  'joint_names': ['bh_j12_joint', 'bh_j13_joint', 'bh_j22_joint', 'bh_j23_joint', 'bh_j32_joint', 'bh_j31_joint', 'bh_j11_joint', 'bh_j21_joint'],
1000  'ft_sensor_frame_id': 'bhand_ft_sensor_link'
1001  }
1002 
1003  args = {}
1004 
1005  for name in arg_defaults:
1006  try:
1007  if rospy.search_param(name):
1008  args[name] = rospy.get_param('%s/%s'%(_name, name)) # Adding the name of the node, because the para has the namespace of the node
1009  else:
1010  args[name] = arg_defaults[name]
1011  #print name
1012  except rospy.ROSException, e:
1013  rospy.logerror('bhand_node: %s'%e)
1014 
1015  #print args
1016  bhand_node = BHand(args)
1017 
1018  rospy.loginfo('bhand_node: starting')
1019 
1020  bhand_node.start()
1021 
1022 
1023 if __name__ == "__main__":
1024  main()
def switchToState(self, new_state)
Definition: bhand_node.py:682
def main()
Definition: bhand_node.py:984
def stop(self)
Definition: bhand_node.py:280
def allState(self)
Definition: bhand_node.py:704
def setup(self)
Definition: bhand_node.py:191
def shutdown(self)
Definition: bhand_node.py:236
def handActions(self, req)
Definition: bhand_node.py:845
def emergencyState(self)
Definition: bhand_node.py:661
def strain_to_nm(self, x)
Definition: bhand_node.py:828
def closeFingers(self, value)
Definition: bhand_node.py:971
def readyState(self)
Definition: bhand_node.py:410
def rosShutdown(self)
Definition: bhand_node.py:258
def stateToString(self, state)
Definition: bhand_node.py:713
def initFailureRecoverTimer(self, timer=5)
Definition: bhand_node.py:902
def standbyState(self)
Definition: bhand_node.py:400
def __init__(self, args)
Definition: bhand_node.py:70
def failureState(self)
Definition: bhand_node.py:668
def setControlMode(self, mode, force=False)
Definition: bhand_node.py:940
def setControlModeServiceCb(self, req)
Definition: bhand_node.py:917
def __init__(self, id, name)
Definition: bhand_node.py:58
def rosPublish(self)
Definition: bhand_node.py:359
def rosSetup(self)
Definition: bhand_node.py:209
def commandCallback(self, data)
Definition: bhand_node.py:768
def initReadTempTimer(self)
Definition: bhand_node.py:802
def readTemp(self)
Definition: bhand_node.py:789
def controlLoop(self)
Definition: bhand_node.py:306
def publishROSstate(self)
Definition: bhand_node.py:812
def openFingers(self)
Definition: bhand_node.py:959
def actionsToString(self, action)
Definition: bhand_node.py:740
def start(self)
Definition: bhand_node.py:289
def failureRecover(self)
Definition: bhand_node.py:910
def setJointVelocity(self, finger)
Definition: bhand_node.py:625
def initState(self)
Definition: bhand_node.py:383
def shutdownState(self)
Definition: bhand_node.py:651
def canError(self, n)
Definition: bhand_node.py:883


bhand_controller
Author(s): Román Navarro , Jorge Ariño
autogenerated on Thu Aug 1 2019 03:30:51