~shadowrobot/sr-ros-interface-ethercat/electric

« back to all changes in this revision

Viewing changes to sr_hand/python_lib/shadowhand_ros.py

  • Committer: Ugo Cupcic
  • Date: 2012-08-08 10:17:21 UTC
  • mfrom: (1.1.552 shadow_robot_ethercat)
  • Revision ID: ugo@shadowrobot.com-20120808101721-lutmwmwmt06srqya
1.0.0 stable release for the etherCAT hardware

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
import roslib; roslib.load_manifest('sr_control_gui')
3
 
import time
4
 
import os
5
 
import math
6
 
import rospy
7
 
import subprocess
8
 
import threading
9
 
import rosgraph.masterapi
10
 
from sr_hand.msg import sendupdate, joint, joints_data
11
 
from sensor_msgs.msg import *
12
 
 
13
 
class Joint():
14
 
    def __init__(self, name="", motor="", min=0, max=90):
15
 
        self.name = name
16
 
        self.motor = motor
17
 
        self.min = min
18
 
        self.max = max
19
 
 
20
 
class ShadowHand_ROS():
21
 
    """
22
 
    This is a python library used to easily access the shadow hand ROS interface. 
23
 
    """
24
 
    def __init__(self):
25
 
        """
26
 
        Builds the library, creates the communication node in ROS and
27
 
        initializes the hand publisher and subscriber to the default 
28
 
        values of shadowhand_data and sendupdate 
29
 
        """
30
 
        print "Creating good library"
31
 
        self.handJoints = [Joint("THJ1", "smart_motor_th1"), 
32
 
                           Joint("THJ2", "smart_motor_th2", -30, 30), 
33
 
                           Joint("THJ3", "smart_motor_th3",-15, 15),
34
 
                           Joint("THJ4", "smart_motor_th4",0, 75),
35
 
                           Joint("THJ5", "smart_motor_th5",-60, 60),
36
 
                           Joint("FFJ0", "smart_motor_ff2", 0, 180),
37
 
                           Joint("FFJ3", "smart_motor_ff3"),
38
 
                           Joint("FFJ4", "smart_motor_ff4", -25, 25),
39
 
                           Joint("MFJ0", "smart_motor_mf2", 0, 180),
40
 
                           Joint("MFJ3", "smart_motor_mf3"),
41
 
                           Joint("MFJ4", "smart_motor_mf4", -25, 25),
42
 
                           Joint("RFJ0", "smart_motor_rf2", 0, 180),
43
 
                           Joint("RFJ3", "smart_motor_rf3"),
44
 
                           Joint("RFJ4", "smart_motor_rf4", -25,25),
45
 
                           Joint("LFJ0", "smart_motor_lf2", 0, 180),
46
 
                           Joint("LFJ3", "smart_motor_lf3"),
47
 
                           Joint("LFJ4", "smart_motor_lf4", -25, 25), 
48
 
                           Joint("LFJ5", "smart_motor_lf5", 0, 45),
49
 
                           Joint("WRJ1", "smart_motor_wr1", -30, 40), 
50
 
                           Joint("WRJ2", "smart_motor_wr2", -30, 10),
51
 
                           ]
52
 
        self.armJoints = [Joint("trunk_rotation", "", -45, 90),
53
 
                          Joint("shoulder_rotation", "", 0, 90),
54
 
                          Joint("elbow_abduction", "", 0,120),
55
 
                          Joint("forearm_rotation", "", -90,90)
56
 
                         ]
57
 
        self.lastMsg = 0;
58
 
        self.lastArmMsg = 0;
59
 
        self.cyberglove_pub = 0
60
 
        self.cyberglove_sub = 0
61
 
        self.cybergrasp_pub = 0
62
 
        self.cyberglove_sub = 0
63
 
        self.sub = rospy.Subscriber('srh/shadowhand_data', joints_data ,self.callback)
64
 
        self.pub = rospy.Publisher('srh/sendupdate',sendupdate)
65
 
        self.sub_arm = rospy.Subscriber('sr_arm/shadowhand_data', joints_data,self.callback_arm)
66
 
        self.pub_arm = rospy.Publisher('sr_arm/sendupdate',sendupdate)
67
 
        self.isFirstMessage = True
68
 
        self.isFirstMessageArm = True
69
 
        self.isReady = False
70
 
        self.toRecord=0
71
 
        self.liste = 0
72
 
        self.hasarm = 0
73
 
        self.jointToRecord = 'None'
74
 
        self.dict_pos = {}
75
 
        self.dict_tar = {}
76
 
        self.dict_arm_pos = {}
77
 
        self.dict_arm_tar = {}
78
 
        self.dict_record_pos = {}
79
 
        self.dict_record_tar={}
80
 
        self.dict_record_time={}
81
 
        rospy.init_node('python_hand_library')
82
 
        threading.Thread(None, rospy.spin)
83
 
 
84
 
    def callback(self, data):
85
 
        """
86
 
        @param data: The ROS message received which called the callback
87
 
        If the message is the first received, initializes the dictionnaries
88
 
        Else, it updates the lastMsg    
89
 
        """
90
 
        self.lastMsg = data;        
91
 
        if self.isFirstMessage : 
92
 
            for joint in self.lastMsg.joints_list : 
93
 
                self.dict_pos[joint.joint_name]=joint.joint_position
94
 
                self.dict_tar[joint.joint_name]=joint.joint_target
95
 
            self.dict_record_pos[joint.joint_name]=[]
96
 
            self.dict_record_tar[joint.joint_name]=[]
97
 
            self.isFirstMessage = False
98
 
            self.isReady = True
99
 
        if self.toRecord > 0 : 
100
 
            self.dict_record_pos[self.jointToRecord].append(self.dict_pos[self.jointToRecord])
101
 
            self.dict_record_tar[self.jointToRecord].append(self.dict_tar)
102
 
            self.dict_record_time[self.jointToRecord].append(rospy.Time.now())
103
 
            toRecord = toRecord - 1
104
 
 
105
 
    def callback_arm(self, data):
106
 
        """
107
 
        @param data: The ROS message received which called the callback
108
 
        If the message is the first received, initializes the dictionnaries
109
 
        Else, it updates the lastMsg    
110
 
        """
111
 
        self.lastArmMsg = data    
112
 
        if self.isFirstMessageArm :
113
 
            for joint in self.lastArmMsg.joints_list : 
114
 
                self.dict_arm_pos[joint.joint_name]=joint.joint_position
115
 
                self.dict_arm_tar[joint.joint_name]=joint.joint_target
116
 
        
117
 
 
118
 
    def __del__(self):
119
 
        print('Library deleted')
120
 
 
121
 
    def close_connections(self):
122
 
        print('Connection closed')
123
 
    
124
 
    def setShadowhand_data_topic(self, topic):
125
 
        """
126
 
        @param topic: The new topic to be set as the hand publishing topic
127
 
        Set the library to listen to a new topic
128
 
        """
129
 
        print 'Changing subscriber to ' + topic 
130
 
        self.sub = rospy.Subscriber(topic, joints_data ,self.callback)
131
 
    
132
 
    def setSendUpdate_topic(self, topic):
133
 
        """
134
 
        @param topic: The new topic to be set as the hand subscribing topic
135
 
        Set the library to publish to a new topic
136
 
        """
137
 
        print 'Changing publisher to ' + topic 
138
 
        self.pub = rospy.Publisher(topic,sendupdate)
139
 
 
140
 
    def sendupdate_from_dict(self, dicti):
141
 
        """
142
 
        @param dicti: Dictionnary containing all the targets to send, mapping the name of the joint to the value of its target
143
 
        Sends new targets to the hand from a dictionnary
144
 
        """
145
 
        #print(dicti)
146
 
        message = []
147
 
        for join in dicti.keys():
148
 
            message.append(joint(joint_name=join, joint_target=dicti[join]))
149
 
        self.pub.publish(sendupdate(len(message), message))
150
 
 
151
 
    def sendupdate(self, jointName, angle=0):
152
 
        """
153
 
        @param jointName: Name of the joint to update
154
 
        @param angle: Target of the joint, 0 if not set
155
 
        Sends a new target for the specified joint
156
 
        """
157
 
        message = [joint(joint_name=jointName, joint_target=angle)]
158
 
        self.pub.publish(sendupdate(len(message), message))
159
 
 
160
 
    def sendupdate_arm_from_dict(self, dicti):
161
 
        """
162
 
        @param dicti: Dictionnary containing all the targets to send, mapping the name of the joint to the value of its target
163
 
        Sends new targets to the hand from a dictionnary
164
 
        """
165
 
        #print(dicti)
166
 
        #print(dicti)
167
 
        message = []
168
 
        for join in dicti.keys():
169
 
            message.append(joint(joint_name=join, joint_target=dicti[join]))
170
 
        self.pub_arm.publish(sendupdate(len(message), message))
171
 
 
172
 
    def sendupdate_arm(self, jointName, angle=0):
173
 
        """
174
 
        @param jointName: Name of the joint to update
175
 
        @param angle: Target of the joint, 0 if not set
176
 
        Sends a new target for the specified joint
177
 
        """
178
 
        message = [joint(joint_name=jointName, joint_target=angle)]
179
 
        self.pub_arm.publish(sendupdate_arm(len(message), message))
180
 
 
181
 
    def valueof(self, jointName):
182
 
        """
183
 
        @param jointName: Name of the joint to read the value
184
 
        @return: 'NaN' if the value is not correct, the actual position of the joint else
185
 
        """
186
 
        for joint in self.lastMsg.joints_list:
187
 
            if joint.joint_name == jointName:
188
 
                return float(joint.joint_position)
189
 
        for joint in self.lastArmMsg.joints_list:
190
 
            if joint.joint_name == jointName:
191
 
                return float(joint.joint_position)
192
 
        return 'NaN'        
193
 
 
194
 
    def has_arm(self):
195
 
        """
196
 
        @return : True if an arm is detected on the roscore
197
 
        """
198
 
        if not self.hasarm == 0:
199
 
            return self.hasarm
200
 
        self.hasarm = False
201
 
        if self.liste == 0:
202
 
            #process = subprocess.Popen("rostopic list -p".split(), stdout=subprocess.PIPE)
203
 
            #self.liste =  process.communicate()[0]
204
 
            #self.liste = self.liste.split('\n')
205
 
            master = rosgraph.masterapi.Master('/rostopic')
206
 
            self.liste = master.getPublishedTopics('/')
207
 
        for topic_typ in self.liste : 
208
 
            for topic in topic_typ: 
209
 
                if 'sr_arm/shadowhand_data' in topic :
210
 
                    self.hasarm = True
211
 
        return self.hasarm
212
 
        
213
 
    def record_step_to_file(self, filename, grasp_as_xml):
214
 
        """
215
 
        @param filename: name (or path) of the file to save to
216
 
        @param grasp_as_xml: xml-formatted grasp
217
 
        Write the grasp at the end of the file, creates the file if does not exist
218
 
        """    
219
 
        if os.path.exists(filename) :
220
 
            obj = open(filename, 'r')
221
 
            text = obj.readlines()
222
 
            obj.close()
223
 
            objWrite = open(filename,'w')
224
 
            for index in range(0,len(text)-1):
225
 
                objWrite.write(text[index])
226
 
            objWrite.write(grasp_as_xml)
227
 
            objWrite.write('</root>')
228
 
            objWrite.close()
229
 
        else :
230
 
            objWrite = open(filename,'w')
231
 
            objWrite.write('<root>\n')
232
 
            objWrite.write(grasp_as_xml)
233
 
            objWrite.write('</root>')
234
 
            objWrite.close()
235
 
 
236
 
    def save_hand_position_to_file(self, filename):
237
 
        objFile=open(filename,'w')
238
 
        for key, value in self.dict_pos:
239
 
            objFile.write(key + ' ' + value + '\n')
240
 
        objFile.close()    
241
 
 
242
 
    def read_all_current_positions(self):
243
 
        """
244
 
        @return: dictionnary mapping joint names to actual positions
245
 
        Read all the positions in the lastMsg
246
 
        """
247
 
        for joint in self.lastMsg.joints_list:
248
 
            self.dict_pos[joint.joint_name] = joint.joint_position
249
 
        return self.dict_pos
250
 
 
251
 
    def read_all_current_targets(self):
252
 
        """
253
 
        @return: dictionnary mapping joint names to current targets
254
 
        Read all the targets in the lastMsg
255
 
        """
256
 
        for joint in self.lastMsg.joints_list:
257
 
            self.dict_tar[joint.joint_name] = joint.joint_position
258
 
        return self.dict_tar
259
 
 
260
 
    def read_all_current_arm_positions(self):
261
 
        """
262
 
        @return: dictionnary mapping joint names to actual positions
263
 
        Read all the positions in the lastMsg
264
 
        """
265
 
        for joint in self.lastArmMsg.joints_list:
266
 
            self.dict_arm_pos[joint.joint_name] = joint.joint_position
267
 
        return self.dict_arm_pos
268
 
 
269
 
    def read_all_current_arm_targets(self):
270
 
        """
271
 
        @return: dictionnary mapping joint names to actual targets
272
 
        Read all the targets in the lastMsg
273
 
        """
274
 
        for joint in self.lastArmMsg.joints_list:
275
 
            self.dict_arm_tar[joint.joint_name] = joint.joint_target
276
 
        return self.dict_arm_tar
277
 
 
278
 
    def resend_targets(self):
279
 
        """
280
 
        Resend the targets read in the lastMsg to the hand
281
 
        """
282
 
        for key, value in self.dict_tar.items():
283
 
            self.sendupdate(jointName=key, angle=value)
284
 
 
285
 
    def replay_hand_position_from_file(self, filename):
286
 
        """
287
 
        Depreciated, should not be used
288
 
        """
289
 
        dict_temp={}
290
 
        objFile=open(filename,'r')
291
 
        result = objFile.readlines()
292
 
        for line in result : 
293
 
            split=line.split()
294
 
            name=split[0]
295
 
            angle=split[1]
296
 
            dict_temp[name]=angle
297
 
        objFile.close()
298
 
        self.sendupdate_from_dict(dict_temp)
299
 
 
300
 
    def readRecordedData(self, jointName, recordingTimeInSeconds):
301
 
        """
302
 
        Depreciated, should not be used
303
 
        """
304
 
        ret = []
305
 
        self.fileIsComplete(recordingTimeInSeconds*100)
306
 
        """ Getting through only when ready"""
307
 
        positions = dict_record_pos[jointName]
308
 
        targets = dict_record_tar[jointName]
309
 
        times = dict_record_time[jointName]            
310
 
        for index in range(0, len(targets)) :
311
 
            ret.append([int(times[i]), float(positions[i]), float(targets[i])])
312
 
        minTime = ret[0][0]
313
 
        for index in range(0, len(ret)) : 
314
 
            ret[index][0] = float((ret[index][0]-minTime))/1000000000.0
315
 
 
316
 
        return ret
317
 
 
318
 
 
319
 
    def tune(self):
320
 
        print('TODO')
321
 
 
322
 
    def initializeJointsPosition(self):
323
 
        print('TODO')
324
 
 
325
 
    def saveContrlrSettings(self):
326
 
        print('TODO')
327
 
 
328
 
    def stepFunction(self):
329
 
        self.sendupdate(joint.name, joint.min + 0.6*(joint.max - joint.min))
330
 
 
331
 
    def smoothSinFunction(self, joint):
332
 
        numberOfSteps = 500
333
 
        for index in range(numberOfSteps):
334
 
            theta = (float(index)/float(numberOfSteps)) * math.pi
335
 
            mysinvalue = math.sin(theta)
336
 
            self.sendupdate(joint.name, joint.min + mysinvalue*(joint.max - joint.min))
337
 
            time.sleep(0.01)
338
 
        return 0
339
 
 
340
 
 
341
 
    def staircaseFunction(self):
342
 
        for percentage in [0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80,     0.90, 1.00, 0.90 , 0.80, 0.70, 0.60, 0.50, 0.40, 0.30, 0.20, 0.10, 0]:
343
 
            self.sendupdate(joint.name, joint.min + percentage*(joint.max - joint.min))
344
 
            time.sleep(0.25)
345
 
        return 0
346
 
 
347
 
    def callVisualisationService(self, callList=0, reset = 0):
348
 
        """
349
 
        @param callList: dictionnary mapping joint names to information that should be displayed
350
 
        @param reset: flag used to tell if the parameters should be replaced by the new ones or just added to the previous ones
351
 
        Calls a ROS service to display various information in Rviz
352
 
        """
353
 
        if reset == 0:
354
 
            print 'no reset'
355
 
 
356
 
        if reset == 1:
357
 
            print 'reset'
358