PaPeRoにおける終話検知について

アプリ開発に関する質問 PaPeRoにおける終話検知について

5件の投稿を表示中 - 1 - 5件目 (全5件中)
  • 投稿者
    投稿
  • #1274
    yokkun
    参加者

    お世話になっております。
    掲題の件、PythonライブラリのAPIを使用し、PaPeRoの発話終了をリアルタイムに取得したいと考えております。
    簡単なサンプルを作成したのですが、長い文章を発話する場合は発話終了を取得できるのですが、短い文章を発話する場合失敗します。
    サンプルコードを添付しますのでご確認いただけますでしょうか。

    35~36行目でPaPeRoの発話状態を取得し、38~39行目で発話させています。
    サンプルのようにある程度長い言葉だと「getSpeechStatusRes」の値が「0⇒1⇒0」と変化するのですが、短い言葉だと常に「0」になってしまいます。

    お手数をおかけしますが宜しくお願い致します。

    #1275
    yokkun
    参加者

    連投失礼します。
    ソースのアップロードに失敗しましたので貼り付けさせていただきます。

    
    import pypapero
    from enum import Enum
    import time
    import threading
    from logging import (getLogger, StreamHandler, INFO, Formatter)
    from datetime import datetime
    import logging
    import random
    
    # ログの設定
    handler = StreamHandler()
    handler.setLevel(INFO)
    handler.setFormatter(Formatter("[%(asctime)s] [%(threadName)s] %(message)s"))
    
    logFileName = datetime.now()
    logging.basicConfig(level=logging.INFO,
    filename=str(logFileName.month) + str(logFileName.day) + "_" + str(logFileName.hour) + str(
    logFileName.minute) + "_" + str(logFileName.second) + ".log",
    format="%(asctime)s %(levelname)-7s %(message)s")
    logger = logging.getLogger("logger")
    logger.addHandler(handler)
    logger.setLevel(INFO)
    
    class WelcomePaPeRo():
        # PaPeRoオブジェクト
        papero = None
    
        def __init__(self):
            if (self.papero is None):
                self.papero = pypapero.Papero("", "", "ws://192.168.1.1:8088/papero")
                if (self.papero.errOccurred == 0):
                    self.papero.send_turn_led_on("ear", ["W3W3", "1"], repeat=True, priority="normal")
                    # 
                    t = threading.Timer(0, self.sayTextWait)
                    t.start()
                    time.sleep(3)
                    t2 = threading.Timer(0, self.sayText, args=("おはようございます。PaPeRo起動したよ。今日も一日よろしくお願いします。",))
                    t2.start()
    
        def sayTextWait(self):
            # 耳を消灯する
            self.papero.send_turn_led_off("ear", "normal")
    
            # 会話状態取得指示
            self.papero.send_get_speech_status(priority="higher")
    
            speak_start_time = time.time()
            while ((time.time() - speak_start_time) < 30):
                # 状態取得
                msgs = self.papero.papero_robot_message_recv(0.1)
                if (msgs is not None) and (msgs[0] is not None) and (msgs[0]["Name"] == "getSpeechStatusRes"):
                    # 会話状態取得イベント
                    # 戻り値(Return)に0(停止中)、1(発話中)、2(一時停止中)
                    logger.warn("SPEECH 1ST STATUS " + str(msgs[0]["Return"]))
                    if msgs[0]["Return"] == 1:
                        # 発話終了
                        logger.warn("SPEECH 1ST END")
                        break
                    else:
                        # 発話中、ポーズ中
                        logger.warn("SPEECH 1ST REPEAT")
                        self.papero.send_get_speech_status(priority="higher")
            else:
                logger.info("sayTextWait speak timeout!")
    
            self.papero.send_get_speech_status(priority="higher")
    
            speak_start_time = time.time()
            while ((time.time() - speak_start_time) < 30):
                # 状態取得
                msgs = self.papero.papero_robot_message_recv(0.1)
                if (msgs is not None) and (msgs[0] is not None) and (msgs[0]["Name"] == "getSpeechStatusRes"):
                    # 会話状態取得イベントo
                    logger.warn("SPEECH 2ND STATUS " + str(msgs[0]["Return"]))
                    if msgs[0]["Return"] == 0:
                        # 発話終了
                        logger.warn("SPEECH 2ST END")
                        break
                    else:
                        # 発話中、ポーズ中
                        logger.warn("SPEECH 2ST REPEAT")
                        self.papero.send_get_speech_status(priority="higher")
            else:
                logger.info("sayTextWait speak timeout!")
    
            self.papero.send_move_head(["A15T500L"], ["A0T500L"])
            self.papero.send_turn_led_on("ear", ["W3W3", "1"], repeat=True, priority="normal")
            logger.info("sayTextWait#OUT")
    
        # 発話
        def sayText(self, mes):
            logger.info ("sayText#IN mes = " + mes)
    
            if self.papero is not None:
                self.papero.send_stop_speech()
                self.papero.send_start_speech(mes, priority="higher")
    
            logger.info ("sayText#OUT")
    
    if __name__ == '__main__':
        WelcomePaPeRo()
    
    • この返信は4年、 9ヶ月前にyokkunが編集しました。
    #1278
    takahashi@spi
    参加者

    一つのスレッドでしゃべらせ、もう一つのスレッドで
    状態をポーリングする方法ですと検出出来ない場合が
    発生してしまうのは回避できないと思います。

    状態を一カ所で管理して回避するならこんな感じかと
    思うのですが、いかがでしょうか?

    import pypapero
    from enum import Enum
    import time
    import threading
    from logging import (getLogger, StreamHandler, INFO, Formatter)
    from datetime import datetime
    import logging
    import random
    import queue
    
    # ログの設定
    handler = StreamHandler()
    handler.setLevel(INFO)
    handler.setFormatter(Formatter("[%(asctime)s] [%(threadName)s] %(message)s"))
    
    logFileName = datetime.now().strftime("%m%d_%H%M_%S.log")
    logging.basicConfig(level=logging.INFO, filename=logFileName,
                        format="%(asctime)s %(levelname)-7s %(message)s")
    logger = logging.getLogger("logger")
    logger.addHandler(handler)
    logger.setLevel(INFO)
    
    class State(Enum):
        init = 0
        stop_speech = 1
        start_speech = 2
        get_speech_status = 3
        end_speech = 4
    
    class Event(Enum):
        start_speech = 1
        end_speech = 2
    
    class WelcomePaPeRo():
        # PaPeRoオブジェクト
        papero = None
    
        def __init__(self):
            self.state = State.init
            self.que = queue.Queue()
            if (self.papero is None):
                self.papero = pypapero.Papero("", "", "ws://192.168.1.1:8088/papero")
                if (self.papero.errOccurred == 0):
                    self.papero.send_turn_led_on("ear", ["W3W3", "1"], repeat=True, priority="normal")
                    t = threading.Timer(0, self.sayTextWait)
                    t.start()
                    time.sleep(3)
                    #t2 = threading.Timer(0, self.sayText, args=("おはようございます。PaPeRo起動したよ。今日も一日よろしくお願いします。",))
                    t2 = threading.Timer(0, self.sayText, args=("おは",))
                    t2.start()
    
        def sayTextWait(self):
            # 耳を消灯する
            self.papero.send_turn_led_off("ear", "normal")
    
            def loop(name, wait_event):
                logger.info(name)
                speak_start_time = time.time()
                while (time.time() - speak_start_time) < 30:
                    # イベント受信
                    try:
                        msgs = self.que.get(block=True, timeout=1)
                    except queue.Empty:
                        continue
                    if msgs is not None:
                        if msgs == wait_event:
                            logger.warn("SPEECH " + name + " END " + str(msgs))
                            break
                else:
                    logger.info("sayTextWait speak timeout!")
    
            loop("1ST", Event.start_speech)
            loop("2ND", Event.end_speech)
    
            self.papero.send_move_head(["A15T500L"], ["A0T500L"])
            self.papero.send_turn_led_on("ear", ["W3W3", "1"], repeat=True, priority="normal")
            logger.info("sayTextWait#OUT")
    
        # 発話
        def sayText(self, mes):
            logger.info ("sayText#IN mes = " + mes)
    
            if self.papero is None:
                logger.info("sayText#OUT fatal")
                return
    
            # 発話停止
            self.papero.send_stop_speech()
            self.state = State.stop_speech
            while True:
                msgs = self.papero.papero_robot_message_recv(1.0)
                if msgs is None:
                    continue
                msg_dic = msgs[0]
                if "Name" not in msg_dic:
                    continue
                name = msg_dic["Name"]
                state = self.state
                if state == State.stop_speech:
                    if name == "stopSpeechRes":
                        # 発話
                        self.papero.send_start_speech(mes)
                        self.state = State.start_speech
                        self.que.put(Event.start_speech)
                elif state == State.start_speech:
                    if name == "startSpeechRes":
                        self.papero.send_get_speech_status()
                        # 会話状態取得指示
                        self.state = State.get_speech_status
                elif state == State.get_speech_status:
                    if name == "getSpeechStatusRes":
                        if "Return" in msg_dic:
                            res = msg_dic["Return"]
                            logger.warn("SPEECH STATUS " + str(res))
                            if res == 0:
                                # 発話終了
                                self.state = State.end_speech
                                logger.warn("SPEECH END")
                                self.que.put(Event.end_speech)
                                break
                        logger.warn("SPEECH REPEAT")
                        time.sleep(0.1)
                        self.papero.send_get_speech_status()
    
            logger.info ("sayText#OUT")
    
    if __name__ == '__main__':
        WelcomePaPeRo()
    
    • この返信は4年、 9ヶ月前にtakahashi@spiが編集しました。
    #1280
    yokkun
    参加者

    お世話になっております。

    早速のご返信ありがとうございます。
    投稿いただいたコードを実機にて動作させました。
    まさに実現したかった挙動になりました。

    ありがとうございます。
    また何かありましたら宜しくお願い致します。

    #1281
    takahashi@spi
    参加者

    お世話になっております。

    ご要望を満たせたのなら良かったです。
    ちょっとしたことでも是非また書き込みをお願いします。

    書き忘れてしまったのですが、もしもPaPeRo上でPythonを
    動かすのであれば、ログファイルの様な更新頻度が多い
    ファイルをフラッシュ領域(/Extension以下)に置いてしまうと
    フラッシュが傷みますので、/tmp以下に変更する必要があります。

    商用利用でエラーログを残したい場合、/tmp以下で電源OFFで
    消えてしまうのも困りますが、USBメモリを外付けする
    くらいしか方法はなさそうです。
    (傷むのは同じですが本体フラッシュと違って取り替え可能なので)

5件の投稿を表示中 - 1 - 5件目 (全5件中)
  • このトピックに返信するにはログインが必要です。