1. UMasaU

    No comment

    UMasaU
Changes in body
Source | HTML | Preview
@@ -1,188 +1,195 @@
世の中は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)
````
としてしまっても動きます。
+とりあえずほかの人が開発してる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](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」を連発してうるさいから、というだけで、
発生するイベントによっては不要です。
+
+-----------
+