Pepper開発に向けて、Pythonを理解する。-Pythonボックス入門編-


#前書き
PepperやNAOの開発をするにあたって、Pythonの知識は必須といえるでしょう。
そこで、簡単にですが、NaoqiにおけるPythonボックスの説明をしたいと思います。

#開発環境
機種名 : MacBook Pro
OS : Yosemite 10.10.3
プロセッサ名 : Intel Core i5 2.6 GHz
メモリ : 16 GB
グラフィック : Intel Iris 1536MB
Choreographe : 2.3.1

#本題
##Pythonボックス
###Pythonボックスとは
まずはPythonボックスについて簡単に説明したいと思います。
Pythonボックスは、ボックスライブラリの以下のところにあります。
>なければ虫眼鏡マークから検索かけてください。

**[Programming]->[Template]->Pythonボックス**

![Untitled_-_Choregraphe__バーチャルロボットに接続_.png](https://qiita-image-store.s3.amazonaws.com/0/35860/a801cd92-eb4c-26ed-474e-571252a102d6.png "Untitled_-_Choregraphe__バーチャルロボットに接続_.png")

input  : "onStart" "onStop"
output : "onStopped"

から成るボックスです。

###スクリプト
Choreographe内のボックスは基本的に全て以下の構成を元に作成されています。
スクリプトは以下のようになっています。

```py
#GeneratedClassの派生クラスがMyClassとなっていることがわかります。
class MyClass(GeneratedClass):
	#まずbehaviorが読み込まれた際に初めて呼び出されるのが__init__(self)です。
    def __init__(self):
        #GeneratedClassの__init__(self)をオーバーライドしていることがわかります。
        GeneratedClass.__init__(self)
        #ここにはbehaviorが読み込まれた際に呼び出されるものを入れましょう。

    def onLoad(self):
        #put initialization code here
        #ここでは初期化処理を入れましょう。
        #behaviorが読み込まれ、すべてのinitが呼び出されたあとに呼ばれます。
        pass

    def onUnload(self):
        #put clean-up code here
        #アプリケーション終了時、onInput_onStopに入力があったときに呼ばれます。
        pass

    def onInput_onStart(self):
        #self.onStopped() #activate the output of the box
        #onStartに入力があった時に呼ばれます。
        #self.onStopped()を記述しないと出力がなされません、注意しましょう。
        pass

    def onInput_onStop(self):
    	 #onStopに入力があった時に呼ばれます。
        self.onUnload() #it is recommended to reuse the clean-up as the box is stopped
        self.onStopped() #activate the output of the box
```

###検証
Pythonボックスの呼び出され方を確認します。
それぞれの関数にLoggerを仕込んで実行順序を確認しました。

1. 結線していないボックスを並べました。
![スクリーンショット 2015-07-17 15.44.12.png](https://qiita-image-store.s3.amazonaws.com/0/35860/ea8d4eee-db91-75f1-cdae-0c24e537cd70.png "スクリーンショット 2015-07-17 15.44.12.png")

	```
[INFO] init 0
[INFO] init 1
[INFO] init 2
[INFO] init 3
[INFO] onLoad 0
[INFO] onLoad 1
[INFO] onLoad 2
[INFO] onLoad 3
#ここでrootのonStopをダブルクリック
[INFO] onUnload 0
[INFO] onUnload 1
[INFO] onUnload 2
[INFO] onUnload 3
	```
initが呼ばれ、onLoadが呼ばれていることがわかります。
そののちに、onUnloadが順番に呼ばれ終了します。
2. 直列で結線してみました。
	![スクリーンショット 2015-07-17 15.54.44.png](https://qiita-image-store.s3.amazonaws.com/0/35860/67ca376d-ba4c-b133-54ac-7026731f3bd6.png "スクリーンショット 2015-07-17 15.54.44.png")
		
	```
[INFO] init 0
[INFO] init 1
[INFO] init 2
[INFO] init 3
[INFO] onLoad 0
[INFO] onLoad 1
[INFO] onLoad 2
[INFO] onLoad 3
[INFO] onInput_onStart 0
	```
	上でも書きましたが"onInput_onStart"メソッドにself.onStopped()を追記しないとアウトプットがなされません。
	なので、次はself.onStopped()を入れたもので検証します。
3. 2にself.onStopped()を入れたもの。
"onInput_onStart"メソッドにself.onStopped()を追記しました。
	
	```
[INFO] init 0
[INFO] init 1
[INFO] init 2
[INFO] init 3
[INFO] onLoad 0
[INFO] onLoad 1
[INFO] onLoad 2
[INFO] onLoad 3
[INFO] onInput_onStart 0
[INFO] onInput_onStart 1
[INFO] onInput_onStart 2
[INFO] onInput_onStart 3
[INFO] onUnload 0
[INFO] onUnload 1
[INFO] onUnload 2
[INFO] onUnload 3
	```
正しく最後まで出力されました。
4. スクリプトはそのままで、☓に結線しました。
	![スクリーンショット 2015-07-17 16.05.47.png](https://qiita-image-store.s3.amazonaws.com/0/35860/5f77991e-73e2-b8f8-6834-f3626f4fb381.png "スクリーンショット 2015-07-17 16.05.47.png")
	
	```
[INFO] init 0
[INFO] init 1
[INFO] init 2
[INFO] init 3
[INFO] onLoad 0
[INFO] onLoad 1
[INFO] onLoad 2
[INFO] onLoad 3
[INFO] onInput_onStop 0
[INFO] onUnload 0
[INFO] onInput_onStop 1
[INFO] onUnload 1
[INFO] onInput_onStop 2
[INFO] onUnload 2
#注目
[INFO] onUnload 3
[INFO] onInput_onStop 3
[INFO] onUnload 0
[INFO] onUnload 1
[INFO] onUnload 2
[INFO] onUnload 3
	```
	注目と記述したところですが、onInput_onStopとonUnloadの順番が逆転して呼び出されていることがわかります。
	何度か繰り返してみましたが、書きだされる順序が逆転するのか、呼び出される順序が逆転するのかわかりませんが、0~2の時のように正しい順序で動くときもあれば、3の時のように逆転する場合もあります。
	**原因は不明です。**Choreographeのバグかもしれませんね。
	
	またonUnloadが二回呼び出されていることにも注目です。☓にinputした時とbehaviorが終了するときの2度呼び出されます。

#感想
続きの記事として、自作関数の活用方と外部ライブラリを利用する方法を書いていきたいと思います。