LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

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

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

缶コーヒーのテレビ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くんと人の会話ができるようになります!
人力でやってどーする!と思うかもしれませんが、人力でもそれはそれで楽しいのでやってみてください。