Pepper

技術のない人向け それでも複数台動かしたい

More than 1 year has passed since last update.

世の中はAzureを使って、とかWebsocketを使って、とか色々な方法でPepperを複数台動かす方法が世にあふれてますが、
「とりあえず動けば何でもいいよ。」という人たちに贈るtipsです。

環境:choregraphe2.4.3.28

ALProxyについての復習

http://doc.aldebaran.com/2-4/dev/python/making_nao_speak.html
こちらのリンクを見ると

from naoqi import ALProxy
tts = ALProxy("ALTextToSpeech", "<IP of your robot>", 9559)
tts.say("Hello, world!")

このような形でロボットのIPとportnumber(9559)をALProxyの引数に入れてあげると、自分の接続しているPepperからほかのPepperのサービスを使うことができます。
要は、ほかのPepperをしゃべらせたり、動かしたりすることができる。という事ですね。

具体的にいうと、Sayボックスをダブルクリックして中にあるSay Textボックスの

    def __init__(self):
        GeneratedClass.__init__(self, False)
        self.tts = ALProxy('ALTextToSpeech')
        self.ttsStop = ALProxy('ALTextToSpeech', True) #Create another proxy as wait is blocking if audioout is remote

    def __init__(self):
        GeneratedClass.__init__(self, False)
        self.tts = ALProxy('ALTextToSpeech',"192.168.100.xxx",9559)
        self.ttsStop = ALProxy('ALTextToSpeech', True) #Create another proxy as wait is blocking if audioout is remote


というように変えてあげればいいだけです。
"192.168.100.xxx"の部分は、自分が接続している機体以外で動かしたいPepperのIPを指定してください。


session、serviceは無視しよう。

技術がない人向け(自分含む)なので、難しいことは飛ばします。
後で時間があるときにでも調べましょう。

何かというと、Show Imageボックスなどの中身がちょっと前から変わってるんですね。
どういう効果があるのかはいまだによく知らないのですが、

tabletService = self.session().service("ALTabletService")

なんていう書き方に変わってます。

なんだか難しそうですね。

ただ、とりあえず

tabletService = ALProxy("ALTabletService")

としてしまっても動くんですね。これ。

もっと言うと、

tabletService = ALProxy("ALTabletService","192.168.100.xxx",9559)

としてしまっても動きます。

とりあえずほかの人が開発してるPepperのタブレットをガンガン動かしてみましょう。
たぶん、すごく怒られます。


他のロボットのALMemoryをのぞいてみたい

とはいっても、先ほどまでのALProxyにIPを足す方法では難しいようです。
Raise Eventは可能なのですが、Subscribe to EventやGet Dataができないようです。
このあたりは、非同期処理に対応してないんじゃないかな、とか思いますが、正直、プログラミングの知識がないんでよくわからないですね。
なので、とりあえず小細工で何とかします。

要は
・Pepper AからPepper BのALMemoryが覗ければよい。
・Subscribe to EventやGet DataはできないがRaise Eventは可能。

ということなので、
Pepper Bが自分のALMemoryの内容をPepper AのALMemoryに書き込んであげれば、よさそうですね。
そうすれば、Pepper Aは自身のALMemoryをsubscribeするだけでPepper BのALMemoryを覗くことができそうです。

まずは、例として、Pepper AにPepper Bの首関節のモーターの温度を言ってもらいましょう。

Pepper A
 ①Raise Eventボックス:レンチマークを押してeventのところにtestと記入。pythonスクリプトを編集。ALProxy の引数にPepper BのIPを記入
 ②Subscribe to Eventボックス:レンチマークを押してeventのところにother/testと記入
 ③Say Textボックス:Subscribe to EventボックスのonEvent端子(グレーの出力端子)に入力を接続
image

Pepper B
 ④Subscribe to Eventボックス:レンチマークを押してeventのところにtestと記入。
 ⑤Get Dataボックス:レンチマークを押してeventのところに「Device/SubDeviceList/HeadYaw/Temperature/Sensor/Value」と記入
 ⑥Raise Eventボックス:レンチマークを押してeventのところにother/testと記入。pythonスクリプトを編集。ALProxy の引数にPepper AのIPを記入
image

Pepper Bに接続したChoregrapheで実行した後にPepper Aに接続したChoregrapheで実行してみましょう。

これで「340」とか言ったら成功です。
pepperは小数点を飛ばして発音するので3桁の数字を言ってますが、Pepper Aのダイアログビューなどを見て確認すれば、納得できる数字のはずです。

流れとしては
①で作ったPepper AのRaise EventボックスがPepper BのALMemory の「test」にevent をRaiseします。
④のPepper BのSubscribe to Event ボックスがPepper AからのRaise Eventを検知します。
⑤のGetData ボックスがPepper Bの頭の関節の温度データを取得します。
⑥のRaise EventボックスがPepper AのALMemory「other/test」にeventをRaiseします。
②のPepper AのSubscribe to EventボックスがPepper BからのRaise Eventを検知します。
③Pepper AのALMemory「other/test」の内容を発話します。

というものになります。


他のロボットで発生したeventを検知してみたい。

たとえば、Pepperを防犯に使ってみる。みたいなデモをするときによいかもしれません。

Pepper Aで実行することは変わりませんが
Pepper Bでは
 ④Basic Awarenessボックスを配置。
 ⑤ALMemoryからのイベントを追加。「ALBasicAwareness/HumanTracked」
image
image
 ⑥ifボックスの出力端子を右クリックで編集。数値へ。レンチマークを押して「value to compare」を-1に。
image
pythonスクリプトも変更。入力された数値を出力するように改造する。

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

    def onLoad(self):
        #~ puts code for box initialization here
        pass

    def onUnload(self):
        #~ puts code for box cleanup here
        pass

    def onInput_onData(self, p):
        param = self.getParameter("Value to compare")
        try:
            p = float(p)
            param = float(param)
        except:
            p = str(p)
            param = str(param)
        operator = self.getParameter("Condition operator")
        if( operator == "<" ):
            self.outputTrueOrFalse( p < param ,p)
        elif( operator == "< or =" ):
            self.outputTrueOrFalse( p <= param ,p)
        elif( operator == "=" ):
            self.outputTrueOrFalse( p == param ,p)
        elif( operator == "> or =" ):
            self.outputTrueOrFalse( p >= param ,p)
        elif( operator == ">" ):
            self.outputTrueOrFalse( p > param ,p)
        elif( operator == "≠" ):
            self.outputTrueOrFalse( p != param ,p)
        else:
            raise Exception( "Operator not known: " + str(operator) )

    def outputTrueOrFalse(self, condition,p):
        if( condition ):
            self.output_then(p)
        else:
            self.output_else(p)

image
ちなみに、ifボックスの追加や、改造は、BasicAwarenessがHumanLostした時などに、「-1」を連発してうるさいから、というだけで、
発生するイベントによっては不要です。


ちなみに、この複数台、というのは「実機複数台」だけでなく「バーチャルロボット+実機」でもできる。というのがポイント。
モーションとALMemory周りを人工夫してPEpper開発の最大の障害「複数人がChoregrapheでつなげない」が何とかできないかなー。と
思う今日この頃。