Revision 70c54617 client/python/hlrc_client/MiddlewareROS.py

View differences:

client/python/hlrc_client/MiddlewareROS.py
28 28
from Middleware import *
29 29
import errno
30 30

  
31
import roslib; 
32
import rospy 
31
import roslib;
32
import rospy
33 33
import actionlib
34 34
from hlrc_server.msg import *
35 35

  
......
39 39

  
40 40
    #######################################################################
41 41
    def __init__(self, scope, loglevel=logging.WARNING):
42
	"""initialise
43
	:param scope: base scope we want to listen on
44
	"""
45
	#init base settings
46
	Middleware.__init__(self,scope,loglevel)
47
	#call mw init
48
	self.init_middleware()
49

  
50
	def __del__(self):
51
	    """destructor
52
	    """
53
	    self.logger.debug("destructor of MiddlewareROS called")
54

  
55
	    #######################################################################
56
	    def init_middleware(self):
57
		"""initialise middleware
58
		"""
59
		self.logger.info("initialising ROS middleware connection on scope %s" % (self.base_scope))
60
		
61
		rospy.init_node('hlrc_client', anonymous=True)
62
		
63
		self.logger.info("creating action clients")
64
		
65
		self.logger.debug("creating speech action client")
66
		self.speech_client = actionlib.SimpleActionClient(self.base_scope + "/set/speech", speechAction)
67
		self.speech_client.wait_for_server()
68
		
69
		self.logger.debug("creating default emotion action client")
70
		self.default_emotion_client = actionlib.SimpleActionClient(self.base_scope + "/set/defaultEmotion", emotionstateAction)
71
		self.default_emotion_client.wait_for_server()
72
		
73
		self.logger.debug("creating current emotion action client")
74
		self.current_emotion_client = actionlib.SimpleActionClient(self.base_scope + "/set/currentEmotion", emotionstateAction)
75
		self.current_emotion_client.wait_for_server()
76
		
77
		self.logger.debug("creating animation action client")
78
		self.animation_client = actionlib.SimpleActionClient(self.base_scope + "/set/animation", animationAction)
79
		self.animation_client.wait_for_server()
80
		
81
		self.logger.debug("creating gazetarget action client")
82
		self.gazetarget_client = actionlib.SimpleActionClient(self.base_scope + "/set/gaze", gazetargetAction)
83
		self.gazetarget_client.wait_for_server()
84
		
85
		self.logger.debug("creating mouthtarget action client")
86
		self.mouthtarget_client = actionlib.SimpleActionClient(self.base_scope + "/set/mouth", mouthtargetAction)
87
		self.mouthtarget_client.wait_for_server()
88
		
89
		self.logger.info("MiddlewareROS initialised")
90
		
91

  
92
		#######################################################################
93
		def publish_emotion(self, em_type, emotion, blocking):
94
		    """publish an emotion via mw
95
		    :param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT)
96
		    :param emotion: emotion to set
97
		    :param blocking: True if this call should block until execution finished on robot
98
		    """
99
		    self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
100

  
101
		    #create a goal to send to the action server.
102
		    goal = emotionstateGoal()
103
		    goal.value    = self.convert_emotiontype_to_rosval(emotion.value)
104
		    goal.duration =  int(emotion.time_ms)
105

  
106
		    #which client do we use?
107
		    if (em_type == RobotEmotion.TYPE_DEFAULT):
108
			client = self.default_emotion_client
109
			else:
110
			    client = self.current_emotion_client
111

  
112
			    #send the goal to the server
113
			    client.send_goal(goal)
114

  
115
			    #wait for the server to finish
116
			    if (blocking):
117
				timed_out = client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
118
				if (timed_out):
119
				    self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
120

  
121
				    def publish_default_emotion(self, emotion, blocking):
122
					self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking)
123

  
124
					def publish_current_emotion(self, emotion, blocking):
125
					    self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking)
126

  
127
					    def publish_head_animation(self, animation, blocking):
128
						"""publish an head animation via mw
129
						:param animation: animation to set
130
						:param blocking: True if this call should block until execution finished on robot
131
						"""
132
						self.logger.debug("calling the animation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
133

  
134
						#create a goal to send to the action server.
135
						goal = animationGoal()
136
						goal.target = self.convert_animationtype_to_rosval(animation.value)
137
						goal.repetitions = animation.repetitions
138
						goal.duration_each =  int(animation.time_ms)
139
						goal.scale = animation.scale
140

  
141
						#send the goal to the server
142
						self.animation_client.send_goal(goal)
143

  
144
						#wait for the server to finish
145
						if (blocking):
146
						    timed_out = self.animation_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
147
						    if (timed_out):
148
							self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
149

  
150
							self.logger.debug("animation rpc done")
151

  
152
							def publish_gaze_target(self, gaze, blocking):
153
							    """publish a gaze target via mw
154
							    :param gaze: gaze to set
155
							    :param blocking: True if this call should block until execution finished on robot
156
							    """
157
							    self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
158

  
159
							    #create a goal to send to the action server.
160
							    goal = gazetargetGoal()
161
							    goal.pan  = gaze.pan
162
							    goal.tilt = gaze.tilt
163
							    goal.roll = gaze.roll
164
							    goal.vergence = gaze.vergence
165
							    goal.pan_offset  = gaze.pan_offset
166
							    goal.tilt_offset = gaze.tilt_offset
167

  
168
							    #type
169
							    if (gaze.gaze_type == RobotGaze.GAZETARGET_ABSOLUTE):
170
								goal.gaze_type = gazetargetGoal.GAZETARGET_ABSOLUTE
171
								else:
172
								    goal.gaze_type = gazetargetGoal.GAZETARGET_RELATIVE
173

  
174
								    goal.timestamp = rospy.Time.from_sec(gaze.timestamp)
175

  
176
								    #send the goal to the server
177
								    self.gazetarget_client.send_goal(goal)
178

  
179
								    #wait for the server to finish
180
								    if (blocking):
181
									timed_out = self.gazetarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
182
									if (timed_out):
183
									    self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
184

  
185

  
186
									    self.logger.debug("gaze rpc done")
187

  
188
									    def publish_mouth_target(self, mouth, blocking):
189
										"""publish a mouth target via mw
190
										:param mouth: mouth value to set
191
										:param blocking: True if this call should block until execution finished on robot
192
										"""
193
										self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
194

  
195
										#create a goal to send to the action server.
196
										goal = mouthtargetGoal()
197
										goal.opening_left  = mouth.opening_left
198
										goal.opening_center = mouth.opening_center
199
										goal.opening_right = mouth.opening_right
200
										goal.position_left = mouth.position_left
201
										goal.position_center  = mouth.position_center
202
										goal.position_right = mouth.position_right
203

  
204
										#send the goal to the server
205
										self.mouthtarget_client.send_goal(goal)
206

  
207
										#wait for the server to finish
208
										if (blocking):
209
										    timed_out = self.mouthtarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
210
										    if (timed_out):
211
											self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
212

  
213
											self.logger.debug("mouth rpc done")
214

  
215
											def publish_speech(self, text_, blocking):
216
											    """publish a tts request via mw
217
											    :param text_: text to synthesize and speak
218
											    :param blocking: True if this call should block until execution finished on robot
219
											    """
220
											    self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
221

  
222
											    #create a goal to send to the action server.
223
											    goal = speechGoal(text=text_)
224

  
225
											    #send the goal to the server
226
											    self.speech_client.send_goal(goal)
227

  
228
											    #wait for the server to finish
229
											    if (blocking):
230
												timed_out = self.speech_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
231
												if (timed_out):
232
												    self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
233

  
234
												    self.logger.debug("speech rpc done")
235

  
236
												    #######################################################################
237
												    # some helpers
238
												    def convert_animationtype_to_rosval(self, value):
239
													"""convert RobotAnimation.value to ROS animation value
240
													:param value: RobotAnimation.* id to convert to rsb id
241
													"""
242
													#NOTE: this convertion is important as the actual integer values of
243
													#      thy python api and the protobuf might be different
244
													if (value == RobotAnimation.IDLE):
245
													    return animationGoal.IDLE
246
													elif (value == RobotAnimation.HEAD_NOD):
247
													    return animationGoal.HEAD_NOD
248
													elif (value == RobotAnimation.HEAD_SHAKE):
249
													    return animationGoal.HEAD_SHAKE
250
													elif (value == RobotAnimation.EYEBLINK_L):
251
													    return animationGoal.EYEBLINK_L
252
													elif (value == RobotAnimation.EYEBLINK_R):
253
													    return  animationGoal.EYEBLINK_R
254
													elif (value == RobotAnimation.EYEBLINK_BOTH):
255
													    return  animationGoal.EYEBLINK_BOTH
256
													elif (value == RobotAnimation.EYEBROWS_RAISE):
257
													    return  animationGoal.EYEBROWS_RAISE
258
													elif (value == RobotAnimation.EYEBROWS_LOWER):
259
													    return  animationGoal.EYEBROWS_LOWER
260
													else:
261
													    self.logger.error("invalid animation type %d\n" % (value))
262
													    return  animationGoal.NEUTRAL
263

  
264
													def convert_emotiontype_to_rosval(self, value):
265
													    """convert RobotEmotion.value to ROS animation value
266
													    :param value: RobotEmotion.* id to convert to ros id
267
													    """
268
													    #NOTE: this convertion is important as the actual integer values of
269
													    #      thy python api and the protobuf might be different
270

  
271
													    if (value == RobotEmotion.NEUTRAL):
272
														return emotionstateGoal.NEUTRAL
273
													    elif (value == RobotEmotion.HAPPY):
274
														return emotionstateGoal.HAPPY
275
													    elif (value == RobotEmotion.SAD):
276
														return emotionstateGoal.SAD
277
													    elif (value == RobotEmotion.ANGRY):
278
														return emotionstateGoal.ANGRY
279
													    elif (value == RobotEmotion.SURPRISED):
280
														return  emotionstateGoal.SURPRISED
281
													    elif (value == RobotEmotion.FEAR):
282
														return emotionstateGoal.FEAR
283
													    else:
284
														self.logger.error("invalid emotion type %d\n" % (value))
285
														return  emotionstateGoal.NEUTRAL
42
        """initialise
43
        :param scope: base scope we want to listen on
44
        """
45
        #init base settings
46
        Middleware.__init__(self,scope,loglevel)
47
        #call mw init
48
        self.init_middleware()
49

  
50
    def __del__(self):
51
        """destructor
52
        """
53
        self.logger.debug("destructor of MiddlewareROS called")
54

  
55
    #######################################################################
56
    def init_middleware(self):
57
        """initialise middleware
58
        """
59
        self.logger.info("initialising ROS middleware connection on scope %s" % (self.base_scope))
60

  
61
        rospy.init_node('hlrc_client', anonymous=True)
62

  
63
        self.logger.info("creating action clients")
64

  
65
        self.logger.debug("creating speech action client")
66
        self.speech_client = actionlib.SimpleActionClient(self.base_scope + "/set/speech", speechAction)
67
        self.speech_client.wait_for_server()
68

  
69
        self.logger.debug("creating default emotion action client")
70
        self.default_emotion_client = actionlib.SimpleActionClient(self.base_scope + "/set/defaultEmotion", emotionstateAction)
71
        self.default_emotion_client.wait_for_server()
72

  
73
        self.logger.debug("creating current emotion action client")
74
        self.current_emotion_client = actionlib.SimpleActionClient(self.base_scope + "/set/currentEmotion", emotionstateAction)
75
        self.current_emotion_client.wait_for_server()
76

  
77
        self.logger.debug("creating animation action client")
78
        self.animation_client = actionlib.SimpleActionClient(self.base_scope + "/set/animation", animationAction)
79
        self.animation_client.wait_for_server()
80

  
81
        self.logger.debug("creating gazetarget action client")
82
        self.gazetarget_client = actionlib.SimpleActionClient(self.base_scope + "/set/gaze", gazetargetAction)
83
        self.gazetarget_client.wait_for_server()
84

  
85
        self.logger.debug("creating mouthtarget action client")
86
        self.mouthtarget_client = actionlib.SimpleActionClient(self.base_scope + "/set/mouth", mouthtargetAction)
87
        self.mouthtarget_client.wait_for_server()
88

  
89
        self.logger.info("MiddlewareROS initialised")
90

  
91

  
92
    #######################################################################
93
    def publish_emotion(self, em_type, emotion, blocking):
94
        """publish an emotion via mw
95
        :param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT)
96
        :param emotion: emotion to set
97
        :param blocking: True if this call should block until execution finished on robot
98
        """
99
        self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
100

  
101
        #create a goal to send to the action server.
102
        goal = emotionstateGoal()
103
        goal.value    = self.convert_emotiontype_to_rosval(emotion.value)
104
        goal.duration =  int(emotion.time_ms)
105

  
106
        #which client do we use?
107
        if (em_type == RobotEmotion.TYPE_DEFAULT):
108
            client = self.default_emotion_client
109
        else:
110
            client = self.current_emotion_client
111

  
112
        #send the goal to the server
113
        client.send_goal(goal)
114

  
115
        #wait for the server to finish
116
        if (blocking):
117
            timed_out = client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
118
            if (timed_out):
119
                self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
120

  
121
    def publish_default_emotion(self, emotion, blocking):
122
        self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking)
123

  
124
    def publish_current_emotion(self, emotion, blocking):
125
        self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking)
126

  
127
    def publish_head_animation(self, animation, blocking):
128
        """publish an head animation via mw
129
        :param animation: animation to set
130
        :param blocking: True if this call should block until execution finished on robot
131
        """
132
        self.logger.debug("calling the animation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
133

  
134
        #create a goal to send to the action server.
135
        goal = animationGoal()
136
        goal.target = self.convert_animationtype_to_rosval(animation.value)
137
        goal.repetitions = animation.repetitions
138
        goal.duration_each =  int(animation.time_ms)
139
        goal.scale = animation.scale
140

  
141
        #send the goal to the server
142
        self.animation_client.send_goal(goal)
143

  
144
        #wait for the server to finish
145
        if (blocking):
146
            timed_out = self.animation_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
147
            if (timed_out):
148
                self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
149

  
150
        self.logger.debug("animation rpc done")
151

  
152
    def publish_gaze_target(self, gaze, blocking):
153
        """publish a gaze target via mw
154
        :param gaze: gaze to set
155
        :param blocking: True if this call should block until execution finished on robot
156
        """
157
        self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
158

  
159
        #create a goal to send to the action server.
160
        goal = gazetargetGoal()
161
        goal.pan  = gaze.pan
162
        goal.tilt = gaze.tilt
163
        goal.roll = gaze.roll
164
        goal.vergence = gaze.vergence
165
        goal.pan_offset  = gaze.pan_offset
166
        goal.tilt_offset = gaze.tilt_offset
167

  
168
        #type
169
        if (gaze.gaze_type == RobotGaze.GAZETARGET_ABSOLUTE):
170
            goal.gaze_type = gazetargetGoal.GAZETARGET_ABSOLUTE
171
        else:
172
            goal.gaze_type = gazetargetGoal.GAZETARGET_RELATIVE
173

  
174
        goal.timestamp = rospy.Time.from_sec(gaze.timestamp)
175

  
176
        #send the goal to the server
177
        self.gazetarget_client.send_goal(goal)
178

  
179
        #wait for the server to finish
180
        if (blocking):
181
            timed_out = self.gazetarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
182
            if (timed_out):
183
                self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
184

  
185

  
186
        self.logger.debug("gaze rpc done")
187

  
188
    def publish_mouth_target(self, mouth, blocking):
189
        """publish a mouth target via mw
190
        :param mouth: mouth value to set
191
        :param blocking: True if this call should block until execution finished on robot
192
        """
193
        self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
194

  
195
        #create a goal to send to the action server.
196
        goal = mouthtargetGoal()
197
        goal.opening_left  = mouth.opening_left
198
        goal.opening_center = mouth.opening_center
199
        goal.opening_right = mouth.opening_right
200
        goal.position_left = mouth.position_left
201
        goal.position_center  = mouth.position_center
202
        goal.position_right = mouth.position_right
203

  
204
        #send the goal to the server
205
        self.mouthtarget_client.send_goal(goal)
206

  
207
        #wait for the server to finish
208
        if (blocking):
209
            timed_out = self.mouthtarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
210
            if (timed_out):
211
                self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
212

  
213
        self.logger.debug("mouth rpc done")
214

  
215
    def publish_speech(self, text_, blocking):
216
        """publish a tts request via mw
217
        :param text_: text to synthesize and speak
218
        :param blocking: True if this call should block until execution finished on robot
219
        """
220
        self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
221

  
222
        #create a goal to send to the action server.
223
        goal = speechGoal(text=text_)
224

  
225
        #send the goal to the server
226
        self.speech_client.send_goal(goal)
227

  
228
        #wait for the server to finish
229
        if (blocking):
230
            timed_out = self.speech_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT))
231
            if (timed_out):
232
                self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name))
233

  
234
        self.logger.debug("speech rpc done")
235

  
236
    #######################################################################
237
    # some helpers
238
    def convert_animationtype_to_rosval(self, value):
239
        """convert RobotAnimation.value to ROS animation value
240
        :param value: RobotAnimation.* id to convert to rsb id
241
        """
242
        #NOTE: this convertion is important as the actual integer values of
243
        #      thy python api and the protobuf might be different
244
        if (value == RobotAnimation.IDLE):
245
            return animationGoal.IDLE
246
        elif (value == RobotAnimation.HEAD_NOD):
247
            return animationGoal.HEAD_NOD
248
        elif (value == RobotAnimation.HEAD_SHAKE):
249
            return animationGoal.HEAD_SHAKE
250
        elif (value == RobotAnimation.EYEBLINK_L):
251
            return animationGoal.EYEBLINK_L
252
        elif (value == RobotAnimation.EYEBLINK_R):
253
            return  animationGoal.EYEBLINK_R
254
        elif (value == RobotAnimation.EYEBLINK_BOTH):
255
            return  animationGoal.EYEBLINK_BOTH
256
        elif (value == RobotAnimation.EYEBROWS_RAISE):
257
            return  animationGoal.EYEBROWS_RAISE
258
        elif (value == RobotAnimation.EYEBROWS_LOWER):
259
            return  animationGoal.EYEBROWS_LOWER
260
        else:
261
            self.logger.error("invalid animation type %d\n" % (value))
262
            return  animationGoal.NEUTRAL
263

  
264
    def convert_emotiontype_to_rosval(self, value):
265
        """convert RobotEmotion.value to ROS animation value
266
        :param value: RobotEmotion.* id to convert to ros id
267
        """
268
        #NOTE: this convertion is important as the actual integer values of
269
        #      thy python api and the protobuf might be different
270

  
271
        if (value == RobotEmotion.NEUTRAL):
272
            return emotionstateGoal.NEUTRAL
273
        elif (value == RobotEmotion.HAPPY):
274
            return emotionstateGoal.HAPPY
275
        elif (value == RobotEmotion.SAD):
276
            return emotionstateGoal.SAD
277
        elif (value == RobotEmotion.ANGRY):
278
            return emotionstateGoal.ANGRY
279
        elif (value == RobotEmotion.SURPRISED):
280
            return  emotionstateGoal.SURPRISED
281
        elif (value == RobotEmotion.FEAR):
282
            return emotionstateGoal.FEAR
283
        else:
284
            self.logger.error("invalid emotion type %d\n" % (value))
285
            return  emotionstateGoal.NEUTRAL

Also available in: Unified diff