1. UMasaU

    Posted

    UMasaU
Changes in title
+技術のない人向け それでも複数台動かしたい
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,173 @@
+世の中はAzureを使って、とかWebsocketを使って、とか色々な方法でPepperを複数台動かす方法が世にあふれてますが、
+「とりあえず動けば何でもいいよ。」という人たちに贈るtipsです。
+
+環境:choregraphe2.4.3.28
+------------
+
+#ALProxyについての復習
+http://doc.aldebaran.com/2-4/dev/python/making_nao_speak.html
+こちらのリンクを見ると
+```py
+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ボックスの
+```py
+ 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
+```
+
+```py
+ 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ボックスなどの中身がちょっと前から変わってるんですね。
+何が変わってるのかはいまだによく知らないのですが、
+
+```py
+tabletService = self.session().service("ALTabletService")
+```
+なんていう書き方に変わってます。
+
+なんだか難しそうですね。
+
+ただ、とりあえず
+```py
+tabletService = ALProxy("ALTabletService")
+```
+
+としてしまっても動くんですね。これ。
+
+もっと言うと、
+```py
+tabletService = ALProxy("ALTabletService","192.168.100.xxx",9559)
+````
+
+としてしまっても動きます。
+
+----------
+#他のロボットのALMemoryをのぞいてみたい
+とはいっても、先ほどまでのALProxyにIPを足す方法では難しいようです。
+Raise Eventは可能なのですが、Subscribe to EventやGet Dataができないようです。
+このあたりは、非同期処理に対応してないんじゃないかな、とか思いますが、正直、プログラミングの知識がないんでよくわからないですね。
+なので、とりあえず小細工で何とかします。
+
+要は
+・Pepper AからPepper BのALMemoryが覗ければよい。
+・Subscribe to EventやGet DataはできないがRaise Eventは可能。
+
+ということなので、お互いの機体に向けてRaise Eventで情報を送ってあげれば目的を果たせそうですね。
+
+まずは、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](https://qiita-image-store.s3.amazonaws.com/0/60999/a0da6df9-0fc4-bdb4-7340-19629da5f0bc.png)
+
+
+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](https://qiita-image-store.s3.amazonaws.com/0/60999/28f3b9eb-d733-b055-e7c9-0c28d1481e79.png)
+
+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](https://qiita-image-store.s3.amazonaws.com/0/60999/5a277c2b-5920-8221-3901-ae2844d3129e.png)
+![image](https://qiita-image-store.s3.amazonaws.com/0/60999/43177fbb-4492-0d08-1519-47ce541642c1.png)
+ ⑥ifボックスの出力端子を右クリックで編集。数値へ。レンチマークを押して「value to compare」を-1に。
+![image](https://qiita-image-store.s3.amazonaws.com/0/60999/4d6d7609-cf14-9cbd-819d-4e736e12a566.png)
+pythonスクリプトも変更。入力された数値を出力するように改造する。
+```py
+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](https://qiita-image-store.s3.amazonaws.com/0/60999/370e87e0-c209-dd28-7083-08b9552a8af1.png)
+ちなみに、ifボックスの追加や、改造は、BasicAwarenessがHumanLostした時などに、「-1」を連発してうるさいから、というだけで、
+発生するイベントによっては不要です。
+
+