[Pepper] Pepperアプリケーション開発 ~通信してみよう~

前回は、Pepperに現在時刻を答えてもらいました。
今回は前回から発展させて、Pepper自ら通信を行って、その結果に応じて答えて貰おうと思います。

具体的には、以下の様な動作を作ろうと思います。
1)Pepperに名前を伝えます
2)その名前に応じたURLに接続してもらい、テキストデータを取得してもらいます
3)テキストデータの内容に応じて、Pepperに「在席中です」「外出中です」「帰宅しました」と答えてもらいます

これまでご紹介して来た内容とは違い、目の前に居る人とのコミュニケーションの最中に、通信を挟んでいます。
こういった動きは、ロボット(機械)ならではですね。

■前準備 サーバにテキストデータを準備
今回、サーバ側には簡単なテキストファイルを5つ用意しました。
satou.html

在籍中

tanaka. html

在籍中

sasaki. html

外出中

itoh. html

外出中

yamazaki. html

帰宅         

佐藤さん、田中さんは「在籍中」
佐々木さん、伊藤さんは「外出中」
伊藤さんは「帰宅」
です。これらのファイルを、Pepperが通信出来る場所に設置します。
今回は、「http://<アライト内サーバ>/pepper/」の下に、ファイルを保存しました。

■Pepperに人物名を伝える
前回の記事で紹介させて頂いている通り、Pepperに訪ねる場合には、SpeechRecoを利用します



図1 SpeechRecoを配置
■通信を行う部品を配置
Pepperで通信を行う際に便利な部品が、InternetConnection です
まずはこの部品を配置してみます


図2 InternetConnectionを配置

しかし、この部品は外部からの入力情報をトリガーに動く口がありません
また、通信処理を行った後、その情報を出力する口もありません

今回は、「Pepperに人物名を訪ねて」(それを入力としたい)、「通信結果をもとに動作」(通信結果を出力としたい)したいので、この2つの口が必要になります

そこで、この部品を拡張して、
・SpeechReco からの入力を受け付けて通信する
・通信結果を次の部品へ渡す
という2つの口を用意しようと思います

■ SpeechRecoからの入力を受け付けるように、InternetConnectionを拡張しよう
配置した InternetConnection のメニューを開き(図3)、「ボックスの編集」を選択すると、図4の画面になります
Pepper の部品は、この「ボックスの編集」から、部品の入出力契機を増やす事が出来ます


図3 メニューを開く

図4 ボックスの編集画面

画面下の、「入力/出力」-「入力」にある「+」ボタンを押下すると、図5のようになります


図5 入力の接続口追加画面

ここで、以下の様に設定して、「inputVoice」というイベントを追加します(図6)
Name inputVoice
Type 文字列
Nature onEvent


図6 入力の接続口を追加する

■通信結果を出力するように、InternetConnectionを拡張しよう
同じ要領で、今度は「入力/出力」-「出力」にある「+」ボタンから、通信結果を出力する為のイベントを追加します
以下の様に設定して、「outputConnectData」というイベントを追加します(図7)
Name outputConnectData
Type 文字列
Nature 即時


図7 出力の接続口を追加する

ここまでで、部品に2つ、口が増えています(図8)


図8 InternetConnectionに接続口が2つ増えました

■部品のプログラムを拡張しよう
これで InternetConnection に2つのイベントを追加しましたが、未だプログラムを書いていないので、口だけがある状態で動きません
プログラムを書いて、イベントの処理を追記します

InternetConnection でメニューを開き(図9)、「ボックスのスクリプトを編集」を選択します


図9 スクリプトを追加する

以下のメソッドを追加します(図10)


図10 文字列を入力→通信→通信結果を出力のプログラムを追加


#図6で「input」に「inputVoice」という口を作成したため
#onInput + _ + inputVoice
#という関数名にする
#入力値は文字列で、inputData に設定される

def onInput_inputVoice(self, inputData):
    #pepperが聞いた人物名に応じて通信先を振り分ける

    if (inputData == "satou") :
        inputURLData = "http://<サーバのアドレス>/pepper/satou.html"
    elif (inputData == "tanaka") :
        inputURLData = "http://<サーバのアドレス>/pepper/tanaka.html"
    elif (inputData == "sasaki") :
        inputURLData = "http://<サーバのアドレス>/pepper/sasaki.html"
    elif (inputData == "itoh") :
        inputURLData = "http://<サーバのアドレス>/pepper/itoh.html"
    elif (inputData == "yamazaki") :
        inputURLData = "http://<サーバのアドレス>/pepper/yamazaki.html"

    if( self.bIsRunning ):
        return

    self.bIsRunning = True
    self.bMustStop = False
    
    previousTimeout = socket.getdefaulttimeout()

    while( not self.bMustStop ):
        nTimeout = self.getParameter("Time to refresh (s)")
        tempReqs = self.getParameter("URLs").split(';')
        reqs = []
        
        for tempReq in tempReqs:
            reqs.append(tempReq.strip(" ¥n"))

        socket.setdefaulttimeout(nTimeout * 1. / len(reqs))

        bOk = False

        for req in reqs:
            try:
                #今回は通信した結果、「在席中」「外出中」「帰宅」の
                #いずれかの文字列を取得する
                #その文字列を、そのまま出力する
                #
                #図7で「output」に「outputConnectData」という口を作成したため
                #outputConnectDataを実行する
                
                self.outputConnectData(str(urllib2.urlopen(inputURLData).read()))
                bOk = True
                break

            except:
                pass

        if( self.bConnected == None ):
            self.bConnected = not bOk

        if( bOk and not self.bConnected ):
            self.bConnected = True
            self.connected()
            time.sleep(nTimeout)

        if( not bOk and self.bConnected ):
            self.bConnected = False
            self.notconnected()

    socket.setdefaulttimeout(previousTimeout)
    self.bIsRunning = False

この追加したプログラムは、「inputVoice」の口にシーケンスが流れて来た際に実行されます
入力値が「inputData」に格納されてきますが、今回の場合は、 SpeechRecoの部品で聞いた人物名が入ってきます
人物名に応じて、接続先のURLを切り替えて、urllib2.urlopenを用いて通信処理を行っています
さらに、その結果をもとに、「outputConnectData」イベントを発行して、次のシーケンスにデータを送信しています

■通信結果に応じて、Pepperに答えてもらう
これまでの記事で紹介させて頂いている通り、Pepperに答えてもらうには、Sayという部品を使います
今回は、通信結果の「在籍中」「外出中」「帰宅」に応じて、それぞれに合った受け答えをしてもらうようにしました
完成したシーケンスは、図11のようになりました


図11 人物名を聞いて、その人の状況をサーバに問い合わせ、結果を応えてくれるシーケンス

■実行
このシーケンスを実行すると、名前の受付に入ります
ここでは、試しに「tanaka」と入力しました(図12)
すると、通信処理が行われて「在席中」という文字を受信し、「在席してるよ」とPepperが答えてくれました(図13)


図12 tanakaと入力


図13 「在席してるよ」と答えてくれました

■まとめ
以上で、Pepperによる通信と、通信結果に応じた挙動の変化に関する紹介は終了です。
今回実施した内容を発展させると、たとえば社内システムから、誰かの予定を確認して、それに従った応対をしてくれる受付プログラムを作ることが出来るのではないでしょうか?
最後までご覧頂き、ありがとうございました。

次回も引き続き、Pepperアプリケーションに触れて行く予定です


弊社では全国各地の請負い(ご自宅)で作業協力頂ける、フリーランスエンジニアの方を常時探しております。
ご興味ある方は、お気軽にお問い合わせ下さい。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*