synergy_node.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import sys
00004 import argparse
00005 import numpy as np
00006 
00007 import rospy
00008 from sensor_msgs.msg import JointState
00009 from std_msgs.msg import Float32MultiArray, Float32
00010 
00011 from grasp_synergy import GraspSynergy
00012 
00013 """
00014 
00015 This is the synergy ROS node. It deals with receiving grasp synergy commands
00016 (scalars or arrays), computes the resulting grasp, and commands it to the hand.
00017 
00018 For the actual details of the implementation, see grasp_synergy.py.
00019 
00020 Author: Felix Duvallet <felixd@gmail.com>
00021 
00022 """
00023 
00024 
00025 class GraspSynergyNode(object):
00026     """
00027     The grasp synergy node subscribes to low-dimensional synergies
00028     and publishes desired joint state.
00029 
00030     It is hand agnostic.
00031     """
00032 
00033     def __init__(self, joint_cmd_topic,
00034                  synergy_input_topic='grasp_synergy',
00035                  num_synergies=2):
00036 
00037         self._synergy = GraspSynergy()
00038 
00039         self._publisher = rospy.Publisher(
00040             joint_cmd_topic, JointState, queue_size=1)
00041 
00042         self._subscriber_main = None
00043         self._subscriber_components = []
00044         queue_size = 1  # for now we don't expose this as a parameter
00045         self._init_subscribers(synergy_input_topic, num_synergies, queue_size)
00046 
00047     def fit_joint_values(self, joint_values):
00048         return self._synergy.fit_joint_values(joint_values)
00049 
00050     def fit_joint_state_messages(self, joint_state_messages):
00051         return self._synergy.fit_joint_state_messages(joint_state_messages)
00052 
00053     def fit_bag_file(self, bag_filepath):
00054         return self._synergy.fit_bag_file(bag_filepath)
00055 
00056     def command_synergy(self, synergy):
00057 
00058         if not self._synergy.trained:
00059             rospy.logwarn('Synergy is not initialized: did you provide '
00060                           'training data?')
00061             return
00062 
00063         grasp = self._synergy.compute_grasp(synergy)
00064         rospy.logdebug('Commanding synergy: {} -> grasp {}'.format(
00065             synergy, grasp))
00066 
00067         joint_state = JointState()
00068         joint_state.position = grasp
00069         self._publisher.publish(joint_state)
00070 
00071     def _callback_main(self, data):
00072         """
00073         Main callback for a fully-specified coefficient vector.
00074         Commands the synergy.
00075         """
00076         alpha = data.data
00077         self.command_synergy(alpha)
00078 
00079     def _callback_component(self, data, component_number):
00080         """
00081         Component callback (component number & value).
00082 
00083         Creates an alpha vector with all zeros except for the given component,
00084         then commands the synergy.
00085         """
00086         rospy.logdebug('Received data for component {} - {}'.format(
00087             component_number, data.data))
00088         alpha = np.zeros((component_number + 1,))
00089         alpha[component_number] = data.data
00090         self.command_synergy(alpha)
00091 
00092     def _init_subscribers(self, synergy_input_topic, num_synergies=0,
00093                           queue_size=1):
00094         """
00095         Create num_synergies+1 subscribers. The main (top-level) subscriber
00096         listens for an array of floats.
00097 
00098         Each component subscriber only listens to the float corresponding to
00099         its component's singular value. Each component subscriber is nested
00100         under the top-level one: synergy_input_topic/
00101 
00102         :param synergy_input_topic The top-level topic.
00103 
00104         :param num_synergies Number of component subscribers to generate.
00105 
00106         :param queue_size Subscriber queue size. Setting the queue size
00107         small allows dropping older messages when a new one is received,
00108         to prevent a large queue of messages to process. This is useful
00109         because the synergy callback can take some time to compute the
00110         grasp.
00111 
00112         """
00113 
00114         # Main callback for arrays.
00115         self._subscriber_main = rospy.Subscriber(
00116             synergy_input_topic,  Float32MultiArray, self._callback_main,
00117             queue_size=queue_size)
00118         rospy.loginfo('Created main subscriber {}'.format(synergy_input_topic))
00119 
00120         # Component subscriber, using individual (nested) topic names and a
00121         # simple Float.
00122         for idx in range(num_synergies):
00123             topic = '{}/syn_{}'.format(synergy_input_topic, idx)
00124 
00125             subscriber = rospy.Subscriber(
00126                 topic, Float32, self._callback_component, idx,
00127                 queue_size=queue_size)
00128             self._subscriber_components.append(subscriber)
00129             rospy.loginfo('  Created component subscriber {}'.format(topic))
00130         pass
00131 
00132 
00133 def run(arguments):
00134     parser = argparse.ArgumentParser(
00135         description='Command hands in a low-dimensional grasp synergy space.')
00136     parser.add_argument('--hand_control_topic', required=True,
00137                         help='Commanded joint state topic.')
00138     parser.add_argument('--bag_filename', required=True,
00139                         help='Filepath for bag file of grasp data')
00140     parser.add_argument('--num_synergies', default=4,
00141                         type=int,
00142                         help='Number of synergies.')
00143     args = parser.parse_args(rospy.myargv(arguments))
00144 
00145     rospy.init_node('grasp_synergy')
00146 
00147     hand_control_topic = args.hand_control_topic
00148     num_synergies = args.num_synergies
00149     fpath = args.bag_filename
00150 
00151     node = GraspSynergyNode(joint_cmd_topic=hand_control_topic,
00152                             num_synergies=num_synergies)
00153     if not node.fit_bag_file(fpath):
00154         return
00155     rospy.spin()
00156 
00157 
00158 if __name__ == '__main__':
00159     arguments = sys.argv[1:]  # argv[0] is the program name.
00160     run(arguments)


grasp-synergy
Author(s): Felix Duvallet
autogenerated on Sat Jun 8 2019 20:11:26