Statistics
| Branch: | Tag: | Revision:

hlrc / client / python / hlrc_client / MiddlewareRSB.py @ 909e9261

History | View | Annotate | Download (11.64 KB)

1 0c286af0 Simon Schulz
"""
2
This file is part of hlrc
3

4
Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
5
http://opensource.cit-ec.de/projects/hlrc
6

7
This file may be licensed under the terms of the
8
GNU General Public License Version 3 (the ``GPL''),
9
or (at your option) any later version.
10

11
Software distributed under the License is distributed
12
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13
express or implied. See the GPL for the specific language
14
governing rights and limitations.
15

16
You should have received a copy of the GPL along with this
17
program. If not, go to http://www.gnu.org/licenses/gpl.html
18
or write to the Free Software Foundation, Inc.,
19
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20

21
The development of this software was supported by the
22
Excellence Cluster EXC 277 Cognitive Interaction Technology.
23
The Excellence Cluster EXC 277 is a grant of the Deutsche
24
Forschungsgemeinschaft (DFG) in the context of the German
25
Excellence Initiative.
26
"""
27
28 836f314c Robert Haschke
from .Middleware import *
29 0c286af0 Simon Schulz
import errno
30
31 ba6302b1 Simon Schulz
import rsb
32
import rsb.converter
33 eb08b7c8 Viktor Richter
import rst
34
import rstsandbox
35 c827824f fl
36 eb08b7c8 Viktor Richter
from rst.animation.EmotionExpression_pb2 import EmotionExpression
37
from rst.animation.HeadAnimation_pb2 import HeadAnimation
38
from rst.animation.BinocularHeadGaze_pb2 import BinocularHeadGaze
39
from rst.geometry.SphericalDirectionFloat_pb2 import SphericalDirectionFloat
40 c827824f fl
41 0c286af0 Simon Schulz
42
class MiddlewareRSB(Middleware):
43 3877047d Simon Schulz
    #######################################################################
44
    def __init__(self, scope, loglevel=logging.WARNING):
45 70c54617 Simon Schulz
        """initialise
46
        :param scope: base scope we want to listen on
47
        """
48 e3691d2d fl
        # init base settings
49
        Middleware.__init__(self, scope, loglevel)
50 73f57e84 fl
        self.EmotionExpression_converter = None
51
        self.HeadAnimation_converter = None
52
        self.BinocularHeadGaze_converter = None
53 70c54617 Simon Schulz
        #call mw init
54 ee1e3286 fl
        self.server = None
55 70c54617 Simon Schulz
        self.init_middleware()
56
57
    def __del__(self):
58
        """destructor
59
        """
60
        self.logger.debug("destructor of MiddlewareROS called")
61
62
    #######################################################################
63
    def init_middleware(self):
64
        """initialise middleware
65
        """
66 e3691d2d fl
        # mute rsb logging:
67 70c54617 Simon Schulz
        logging.getLogger("rsb").setLevel(logging.ERROR)
68
69
        #initialise RSB stuff
70 e3691d2d fl
        self.logger.info(
71
            "initialising RSB middleware connection on scope %s, registering rst converters..." % (self.base_scope))
72 70c54617 Simon Schulz
73 e3691d2d fl
        self.EmotionExpression_converter = rsb.converter.ProtocolBufferConverter(messageClass=EmotionExpression)
74 78cc756c Simon Schulz
        rsb.converter.registerGlobalConverter(self.EmotionExpression_converter)
75 70c54617 Simon Schulz
76 e3691d2d fl
        self.HeadAnimation_converter = rsb.converter.ProtocolBufferConverter(messageClass=HeadAnimation)
77 78cc756c Simon Schulz
        rsb.converter.registerGlobalConverter(self.HeadAnimation_converter)
78 70c54617 Simon Schulz
79 e3691d2d fl
        self.BinocularHeadGaze_converter = rsb.converter.ProtocolBufferConverter(messageClass=BinocularHeadGaze)
80 78cc756c Simon Schulz
        rsb.converter.registerGlobalConverter(self.BinocularHeadGaze_converter)
81 70c54617 Simon Schulz
82
        try:
83
            self.server = rsb.createRemoteServer(self.base_scope + '/set')
84
        except ValueError:
85
            self.logger.error("ERROR: invalid scope given. server deactivated")
86
            self.server.deactivate()
87
            sys.exit(errno.EINVAL)
88
89
    #######################################################################
90
    def publish_emotion(self, em_type, emotion, blocking):
91
        """publish an emotion via mw
92
        :param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT)
93
        :param emotion: emotion to set
94
        :param blocking: True if this call should block until execution finished on robot
95
        """
96
97 e3691d2d fl
        # create emotion & fill it with values:
98 78cc756c Simon Schulz
        rsb_em = EmotionExpression()
99 bbd41216 fl
        rsb_em.emotion = self.convert_emotiontype_to_rsbval(emotion.value)
100 70c54617 Simon Schulz
        rsb_em.duration = int(emotion.time_ms)
101
102 4f2f4ba3 sschulz
        # with rsb.createRemoteServer(self.base_scope + '/{current,default}Emotion') as server:
103 041c3638 fl
        self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
104
105
        if (blocking):
106
            #blocking rpc call:
107 4f2f4ba3 sschulz
            if (em_type == EmotionExpression.TYPE_DEFAULT):
108
                result = self.server.defaultEmotion(rsb_em)
109
            else:
110
                result = self.server.currentEmotion(rsb_em)
111 041c3638 fl
            self.logger.debug("server reply: '%s'" % result)
112
        else:
113 4f2f4ba3 sschulz
            if (em_type == EmotionExpression.TYPE_DEFAULT):
114
                future = self.server.defaultEmotion.async(rsb_em)
115
            else:
116
                future = self.server.currentEmotion.async(rsb_em)
117 041c3638 fl
            self.logger.debug("server reply: '%s'" % future)
118
            #we could block here for a incoming result with a timeout in s
119
            #print '> server reply: "%s"' % future.get(timeout = 10);
120
        self.logger.debug("emotion rpc done")
121 70c54617 Simon Schulz
122 11b8a2b5 fl
    def publish_head_animation(self, animation, blocking):
123 78cc756c Simon Schulz
        """publish an head HeadAnimation via mw
124
        :param HeadAnimation: HeadAnimation to set
125 70c54617 Simon Schulz
        :param blocking: True if this call should block until execution finished on robot
126
        """
127
128 78cc756c Simon Schulz
        self.logger.debug("calling the HeadAnimation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
129 70c54617 Simon Schulz
130 e3691d2d fl
        # create HeadAnimation & fill it with values:
131 78cc756c Simon Schulz
        rsb_ani = HeadAnimation()
132 70c54617 Simon Schulz
133
        #select ani
134 11b8a2b5 fl
        rsb_ani.animation = self.convert_HeadAnimationtype_to_rsbval(animation.value)
135
        rsb_ani.repetitions = animation.repetitions
136
        rsb_ani.duration_each = animation.time_ms
137
        rsb_ani.emphasis_scale = animation.scale
138 70c54617 Simon Schulz
139 73f57e84 fl
        if blocking:
140 70c54617 Simon Schulz
            #blocking:
141 c00b9328 fl
            result = self.server.animation(rsb_ani)
142 70c54617 Simon Schulz
            self.logger.debug("server reply: '%s'" % result)
143
        else:
144 c00b9328 fl
            future = self.server.animation.async(rsb_ani)
145 70c54617 Simon Schulz
            #we can block here for a incoming result with a timeout in s
146
            #print '> server reply: "%s"' % future.get(timeout = 10);
147
148 78cc756c Simon Schulz
        self.logger.debug("HeadAnimation rpc done")
149 70c54617 Simon Schulz
150
    def publish_default_emotion(self, emotion, blocking):
151
        self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking)
152
153
    def publish_current_emotion(self, emotion, blocking):
154
        self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking)
155
156
    def publish_gaze_target(self, gaze, blocking):
157
        """publish a gaze target via mw
158
        :param gaze: gaze to set
159
        :param blocking: True if this call should block until execution finished on robot
160
        """
161
        self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
162
163 e3691d2d fl
        # create gaze target & fill it with values:
164 73f57e84 fl
        hg = BinocularHeadGaze()
165 70c54617 Simon Schulz
166 d076942c fl
        hg.target.elevation = gaze.tilt
167
        hg.target.azimuth = gaze.pan
168 73f57e84 fl
        hg.eye_vergence = gaze.vergence
169 78cc756c Simon Schulz
170 d076942c fl
        hg.offset.elevation = gaze.tilt_offset
171
        hg.offset.azimuth = gaze.pan_offset
172 0b6329fb fl
173 73f57e84 fl
        if blocking:
174 e3691d2d fl
            # blocking:
175 73f57e84 fl
            result = self.server.gaze(hg)
176 ee1e3286 fl
            self.logger.debug("server reply blocking: '%s'" % result)
177 70c54617 Simon Schulz
        else:
178 73f57e84 fl
            future = self.server.gaze.async(hg)
179 ee1e3286 fl
            self.logger.debug("server reply non-blocking: '%s'" % future)
180 e3691d2d fl
            # we can block here for a incoming result with a timeout in s
181 70c54617 Simon Schulz
            #print '> server reply: "%s"' % future.get(timeout = 10);
182
183
        self.logger.debug("gaze rpc done")
184
185 5eb9025f fl
    def publish_speech(self, text, blocking):
186
        """publish a tts request via mw
187
        :param text: text to synthesize and speak
188
        :param blocking: True if this call should block until execution finished on robot
189
        """
190 c00b9328 fl
        """
191 5eb9025f fl
        self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
192 70c54617 Simon Schulz

193 5eb9025f fl
        if (blocking):
194
            # blocking:
195
            result = self.server.speech(text)
196
            self.logger.debug("server reply: '%s'" % result)
197
        else:
198
            future = self.server.speech.async(text)
199
            # we can block here for a incoming result with a timeout in s
200
            #print '> server reply: "%s"' % future.get(timeout = 10);
201 70c54617 Simon Schulz

202 5eb9025f fl
        self.logger.debug("speech rpc done")
203 c00b9328 fl
        """
204 836f314c Robert Haschke
        print("WARNING: Not IMPLEMENTED.")
205 70c54617 Simon Schulz
206
207 5eb9025f fl
    #######################################################################
208
    def is_running(self):
209
        return True
210 70c54617 Simon Schulz
211
212 5eb9025f fl
    #######################################################################
213
    # some helpers
214
    def convert_HeadAnimationtype_to_rsbval(self, value):
215
        """convert RobotHeadAnimation.value to RSB HeadAnimation value
216
        :param value: RobotHeadAnimation.* id to convert to rsb id
217
        """
218
        # NOTE: this convertion is important as the actual integer values of
219
        #      thy python api and the protobuf might be different
220
221 11b8a2b5 fl
        if value == HeadAnimation.IDLE:
222 5eb9025f fl
            return HeadAnimation().IDLE
223 11b8a2b5 fl
        elif value == HeadAnimation.HEAD_NOD:
224 5eb9025f fl
            return HeadAnimation().HEAD_NOD
225 11b8a2b5 fl
        elif (value == HeadAnimation.HEAD_SHAKE):
226 5eb9025f fl
            return HeadAnimation().HEAD_SHAKE
227 11b8a2b5 fl
        elif (value == HeadAnimation.EYEBLINK_LEFT):
228
            return HeadAnimation().EYEBLINK_LEFT
229
        elif (value == HeadAnimation.EYEBLINK_RIGHT):
230
            return HeadAnimation().EYEBLINK_RIGHT
231
        elif (value == HeadAnimation.EYEBLINK_BOTH):
232 5eb9025f fl
            return HeadAnimation().EYEBLINK_BOTH
233 11b8a2b5 fl
        elif (value == HeadAnimation.EYEBROWS_RAISE):
234 5eb9025f fl
            return HeadAnimation().EYEBROWS_RAISE
235 11b8a2b5 fl
        elif (value == HeadAnimation.EYEBROWS_LOWER):
236 5eb9025f fl
            return HeadAnimation().EYEBROWS_LOWER
237
        else:
238
            self.logger.error("invalid HeadAnimation type %d\n" % (value))
239
            return HeadAnimation().NEUTRAL
240 70c54617 Simon Schulz
241 5eb9025f fl
    def convert_emotiontype_to_rsbval(self, value):
242
        """convert RobotEmotion.value to RSB HeadAnimation value
243
        :param value: RobotEmotion.* id to convert to rsb id
244
        """
245
        # NOTE: this convertion is important as the actual integer values of
246
        #      thy python api and the protobuf might be different
247
248
        if (value == RobotEmotion.NEUTRAL):
249
            return EmotionExpression().NEUTRAL
250
        elif (value == RobotEmotion.HAPPY):
251
            return EmotionExpression().HAPPY
252
        elif (value == RobotEmotion.SAD):
253
            return EmotionExpression().SAD
254
        elif (value == RobotEmotion.ANGRY):
255
            return EmotionExpression().ANGRY
256
        elif (value == RobotEmotion.SURPRISED):
257
            return EmotionExpression().SURPRISED
258
        elif (value == RobotEmotion.FEAR):
259
            return EmotionExpression().FEAR
260
        else:
261
            self.logger.error("invalid emotion type %d\n" % (value))
262
            return EmotionExpression().NEUTRAL
263 e3691d2d fl
264
    """
265 5eb9025f fl
    def publish_mouth_target(self, mouth, blocking):
266
        publish a mouth target via mw
267
        :param mouth: mouth value to set
268
        :param blocking: True if this call should block until execution finished on robot
269

270
        self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
271

272
        #create mouth state & fill it with values:
273
        rsb_mouth = MouthTarget()
274

275
        #fill proto
276
        rsb_mouth.opening_left   = mouth.opening_left
277
        rsb_mouth.opening_center = mouth.opening_center
278
        rsb_mouth.opening_right  = mouth.opening_right
279
        rsb_mouth.position_left  = mouth.position_left
280
        rsb_mouth.position_center = mouth.position_center
281
        rsb_mouth.position_right = mouth.position_right
282

283
        if (blocking):
284
            #blocking:
285
            result = self.server.mouth(rsb_mouth)
286
            self.logger.debug("server reply: '%s'" % result)
287
        else:
288
            future = self.server.mouth.async(rsb_mouth)
289
            #we can block here for a incoming result with a timeout in s
290
            #print '> server reply: "%s"' % future.get(timeout = 10);
291

292
        self.logger.debug("mouth rpc done")
293 eb08b7c8 Viktor Richter
    """