読者です 読者をやめる 読者になる 読者になる

株式会社ネクスト エンジニアBlog

不動産・住宅情報サイト HOME'Sを運営する株式会社ネクストのエンジニアが提供する技術ブログです。エンジニアに役立つ情報の発信や、弊社エンジニアの活動を中心にお届けします。

PepperとMacをソケット通信でつないでテキストを喋らせてみた

pepper

こんにちは、上津原です。

缶コーヒーのテレビCMでもPepperくんを見るようになって、なんだかPepperくん変なタレントみたいな立ち位置になってきてますね。
というわけでまたPepperの話題です。

遠隔で色々喋らせたい

Pepperの開発をやっていると、インストールしておいたものしか動かせないのにやきもきしてきます。
なので、PepperとMacをつないで、こっちからテキストをを送ればそれを喋るようにしてみました。

pythonで書きます。

基本は普通のソケット通信のコードと同じです。サーバーサイドとクライアントサイドのスクリプトを書きます。

今回はMacをサーバーとして、Pepperをクライアントとして作りました。

サーバーサイド
import os
import sys
import socket

HOST = ''
PORT = 50008

def main():

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    s.bind((HOST, PORT))
    print 'waiting for client...'
    s.listen(1)
    (conn, addr) = s.accept()

    print 'Connected by', addr

    pid = os.fork()

    if pid == 0:
        print "child process"
        while 1:
            msg = raw_input(">> ")
            conn.send('%s' % msg )
            if msg == "quit":
                break;
        sys.exit()

    else:
        print "parent process"
        while 1:
            data = conn.recv(1024)

            if not data:
                print 'End'
                break
            elif data == "":
                print "Client is closed"
                os.kill(pid, 9)
                break

            print "pepper: ", data

        conn.close()
        sys.exit()


if __name__ == '__main__':
    main()
クライアントサイド(Pepper)
import os
import sys
from socket import *

HOST = '192.168.XXX.XXX' #ここは設定に合わせて 
PORT = 50008

class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self)

    def onLoad(self):
        #put initialization code here
        pass

    def onUnload(self):
        #put clean-up code here
        pass

    def onInput_onStart(self):
        # ソケット接続
        try:
            #接続処理
            self.s = socket(AF_INET, SOCK_STREAM)
            self.s.connect((HOST, PORT))

        except:
            #接続失敗したらソケットを閉じて終了へ
            self.s.close()
            self.onStopped()
            return
        
        # 子プロセスの作成
        try:
            pid = os.fork()
        
        except:
            return


        # つながったらテキストの送受信を行う
        self.log("pid :" + str(pid))

        # 子プロセスの場合の処理
        if pid == 0:
            # 一旦未使用
            pass

        # 親プロセスの場合
        else:
            while 1:
                self.log("pid else")
                data = self.s.recv(1024)

                if not data:
                    break
                elif data == "quit":
                    os.kill(pid, 9)
                    break

                self.log(data)
                # Stopの何かがないか確認
                stop = self.stopVerification(data)

                if stop == False:
                    self.outputStringFromServer(data)

            self.s.close()
            self.onStopped()


        pass

    def onInput_inputString(self, p):
        # PCからインプットされたテキストをmsgに入れて、喋らせる
        self.log("Recieve String " + p)
        # Stopの何かがないか確認
        stop = self.stopVerification(p)

        # Stopではなかったらメッセージをサーバに送る
        if stop == False:
            self.s.send(p)
            

    def onInput_onStop(self):
        self.onUnload() #it is recommended to reuse the clean-up as the box is stopped
        self.onStopped() #activate the output of the box

    def stopVerification(self,inputString):
        if inputString == "ストップ":
            self.log("stop!!")
            self.outputStopBehavior()
            return True
        else:
            return False

補足説明

outputStringFromServer()部分がサーバーから受け付けたテキストをノードからアウトプットするものになってます。
ここから先にAnimatedSayなどをつなげればそのとおりに喋ってくれます。

stopVerification()というのも作っていますが、これは「ストップ」という単語が届いたらアプリケーションを停止する挙動なども取り入れています。特定のテキストを送ればこの挙動をする、とかそういった物を簡単に設定することが出来るようになります。

forkを使って、好き勝手やりとりできるように作っているので、pepperのSpeechRecoを使って特定の言葉をサーバ側に送ったりもできます。onInput_inputString()はSpeechRecoから受け付けた単語を得てうごかしてます。

とりあえずコレを使えば、人力でPepperくんと人の会話ができるようになります!
人力でやってどーする!と思うかもしれませんが、人力でもそれはそれで楽しいのでやってみてください。