Exemple #1
0
    def say(self, text, lang):
        # SSML tags for english TTS only.
        if lang in ['en-US']:
            text = self._add_ssml(text)

        text = self.replace_variables_text(text)
        self.runner.topics['tts'].publish(TTS(text, lang))
Exemple #2
0
    def _request_callback(self, chat_message):
        if not self.enable:
            logger.info("Chatbot is disabled")
            return
        if self.speech:
            logger.info("In speech, ignore the question")
            return
        if 'shut up' in chat_message.utterance.lower():
            logger.info("Robot's talking wants to be interruptted")
            self.tts_ctrl_pub.publish("shutup")
            rospy.sleep(0.5)
            self._affect_publisher.publish(String('sad'))
            if not self.mute:
                self._response_publisher.publish(
                    TTS(text='Okay', lang=chat_message.lang))
            return

        # Handle chatbot command
        cmd, arg, line = self.client.parseline(chat_message.utterance)
        func = None
        try:
            if cmd is not None:
                func = getattr(self.client, 'do_' + cmd)
        except AttributeError as ex:
            pass
        if func:
            try:
                func(arg)
            except Exception as ex:
                logger.error("Executing command {} error {}".format(func, ex))
            return

        chat_message.utterance = self.handle_control(chat_message.utterance)

        # blink that we heard something, request, probability defined in
        # callback
        self._blink_publisher.publish('chat_heard')

        if self.delay_response:
            logger.info("Add input: {}".format(chat_message.utterance))
            self.input_stack.append((time.clock(), chat_message))
            self._gesture_publisher.publish(SetGesture('nod-2', 0, 1, 1))
            self._gesture_publisher.publish(
                SetGesture('blink-relaxed', 0, 1, 1))
            self.reset_timer()
        else:
            self.ask([chat_message])
Exemple #3
0
    def _response_callback(self, msg):
        logger.info("Get response msg %s", msg)
        text = msg.text
        text = re.sub(r"""\[callback.*\]""", '', text)
        logger.warn('Send to TTS "%s"', text)
        self._response_publisher.publish(TTS(text=text, lang=msg.lang))
        if self.client.last_response and self.client.last_response_time:
            request_id = self.client.last_response.get('RequestId')
            elapse = dt.datetime.utcnow() - self.client.last_response_time
            if elapse.total_seconds(
            ) > 10:  # don't record request id for late coming msg
                request_id = ''
            try:
                self.write_response(request_id, msg)
            except Exception as ex:
                logger.exception(ex)
        else:
            logger.warn("No last response")

        # send the response back to chat server so it's aware of what's been
        # actually said
        self.client.feedback(msg.text, msg.label, msg.lang)
Exemple #4
0
    def on_response(self, sid, response):
        if response is None:
            logger.error("No response")
            return

        if sid != self.client.session:
            logger.error("Session id doesn't match")
            return

        logger.info("Get response {}".format(response))

        for k, v in response.iteritems():
            rospy.set_param('{}/response/{}'.format(self.node_name, k), v)

        text = response.get('text')
        emotion = response.get('emotion')
        lang = response.get('lang', 'en-US')

        orig_text = response.get('orig_text')
        if orig_text:
            try:
                self.handle_control(orig_text)
            except Exception as ex:
                logger.error(ex)
        #elif self.recover:
        #    param = {
        #        'delay_response': False
        #    }
        #    update_parameter('chatbot', param, timeout=2)
        #    self.recover = False
        #    logger.info("Recovered delay response")

        # Add space after punctuation for multi-sentence responses
        text = text.replace('?', '? ')
        text = text.replace('_', ' ')
        if self.insert_behavior:
            # no
            pattern = r"(\bnot\s|\bno\s|\bdon't\s|\bwon't\s|\bdidn't\s)"
            text = re.sub(pattern, '\g<1>|shake3| ', text, flags=re.IGNORECASE)

            # yes
            pattern = r'(\byes\b|\byeah\b|\byep\b)'
            text = re.sub(pattern, '\g<1>|nod|', text, flags=re.IGNORECASE)

            # question
            # pattern=r'(\?)'
            # thinks = ['thinkl', 'thinkr', 'thinklu', 'thinkld', 'thinkru', 'thinkrd']
            # random.shuffle(thinks)
            # text = re.sub(pattern, '|{}|\g<1>'.format(thinks[0]), text, flags=re.IGNORECASE)

        # if sentiment active save state and wait for affect_express to publish response
        # otherwise publish and let tts handle it
        if self._sentiment_active:
            emo = String()
            if emotion:
                emo.data = emotion
                self._affect_publisher.publish(emo)
                rospy.loginfo('[#][PERCEIVE ACTION][EMOTION] {}'.format(
                    emo.data))
                logger.info('Chatbot perceived emo: {}'.format(emo.data))
            else:
                p = self.polarity.get_polarity(text)
                logger.debug('Polarity for "{}" is {}'.format(
                    text.encode('utf-8'), p))
                # change emotion if polarity magnitude exceeds threshold defined in constructor
                # otherwise let top level behaviors control
                if p > self._polarity_threshold:
                    emo.data = 'happy'
                    self._affect_publisher.publish(emo)
                    rospy.loginfo('[#][PERCEIVE ACTION][EMOTION] {}'.format(
                        emo.data))
                    logger.info('Chatbot perceived emo: {}'.format(emo.data))
                    # Currently response is independant of message received so no need to wait
                    # Leave it for Opencog to handle responses later on.
                elif p < 0 and abs(p) > self._polarity_threshold:
                    emo.data = 'frustrated'
                    self._affect_publisher.publish(emo)
                    rospy.loginfo('[#][PERCEIVE ACTION][EMOTION] {}'.format(
                        emo.data))
                    logger.info('Chatbot perceived emo: {}'.format(emo.data))
                    # Currently response is independant of message received so no need to wait
                    # Leave it for Opencog to handle responses later on.

        if not self.mute:
            self._blink_publisher.publish('chat_saying')
            self._response_publisher.publish(TTS(text=text, lang=lang))

        if rospy.has_param('{}/context'.format(self.node_name)):
            rospy.delete_param('{}/context'.format(self.node_name))
        context = self.client.get_context()
        logger.warn("Get context %s" % context)
        context['sid'] = self.client.session
        for k, v in context.iteritems():
            rospy.set_param('{}/context/{}'.format(self.node_name, k), v)
            logger.info("Set param {}={}".format(k, v))

        # Assign known name to the percepted faces
        face_id = self.client.user
        if face_id in self.perception_users:
            uid = self.perception_users[face_id].uid
            context_firstname = context.get('firstname')
            context_lastname = context.get('lastname')
            firstname = self.perception_users[face_id].first_name
            if not uid:
                self.assign_name(face_id, context_firstname, context_lastname)
            elif uid and firstname != context_firstname:
                logger.warn("Update the name of face id %s from %s to %s" %
                            (face_id, firstname, context_firstname))
                self.forget_name(uid)
                self.assign_name(face_id, context_firstname, context_lastname)
            else:
                logger.warn(
                    "Failed to update name of face id %s from %s to %s" %
                    (face_id, firstname, context_firstname))
        else:
            logger.warn("Face %s is out of scene" % face_id)
            logger.warn("Perception face %s" %
                        str(self.perception_users.keys()))
Exemple #5
0
 def Say(self, text):
     # publish TTS message
     msg = TTS()
     msg.text = text
     msg.lang = 'en-US'
     self.tts_pub.publish(msg)
Exemple #6
0
 def publish_tts(self, text):
     msg = TTS()
     msg.text = text
     msg.lang = 'en-US'
     self.tts_pub.publish(msg)
     rospy.logdebug("published tts: '{}', '{}'".format(msg.text, msg.lang))
Exemple #7
0
 def respond(self, response):
     self.runner.topics['events'].publish(Event('chat_end', 0))
     self.talking = True
     self.runner.topics['tts'].publish(TTS(response, 'en-US'))