Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@UMasaU

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

More than 3 years have 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でつなげない」が何とかできないかなー。と
思う今日この頃。

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
UMasaU
プログラミング初心者

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?