Choregrapheには Take Pictureというボックスがあり、Pepperが見ている画像をファイルとしてPepper内のファイルシステムに保存することができます。
このファイルをどう処理するかとしては、Eメール送信ボックスでの添付ファイルとしたり、タブレットに画像表示するボックスで参照するなどさまざまなことが考えられますが、それぞれのボックスでファイルを参照するときに重要になるのが、Pepper内でのパスの考え方です。
ここでは、画像を撮影して、それをタブレットに表示する例の作成を通じて、パスの考え方をいくつか説明していきます。
#Take Pictureボックスにおける画像保存先パス
Choregrapheの[ボックスライブラリ]パネルで、standardボックスライブラリ > Vision > Take Pictureボックスを選択すると、以下のような説明が表示されます。
store it in his memory in ~/recordings/cameras.
とあるので、撮影された画像はPepper内のファイルシステムの (ホームディレクトリ)/recordings/cameras/
に保存されます。画像ファイル名はパラメータに File Name
という項目があり、ここで指定することができます。
#タブレットShow Imageボックスにおける画像読み込み元パス
タブレットに画像を表示するためには tabletボックスライブラリ > tablet > Show Imageボックスが利用できますが、このボックスのImage Urlの説明は以下のようになっています。
Pepperチュートリアル (5):タブレットを使う で詳しく説明していますが、アプリケーションを構成するファイル([プロジェクトの内容]パネルで示されるファイル構成ツリ)ーのうち、 html
ディレクトリ以下のファイルがタブレットに表示することができるようになっています。
つまり、Take Pictureボックスで撮影した内容を、アプリケーションの html
ディレクトリに保存することができれば、Show Imageボックスで表示できるようになります。
#実装例
では、Take Pictureボックスで画像を撮影し、Show Imageボックスでタブレットに表示するアプリケーションを作ってみます。
なお、Pepperのタブレットに動的に作成したファイルを表示する際は、キャッシュを回避する工夫が必要になりますので、これは別に説明します。
##つくってみる
-
以下のボックスを配置します
- standardボックスライブラリ > Vision > Take Picture
- tabletボックスライブラリ > tablet > Show Image
-
ボックスを以下のように接続します
-
Take Pictureボックスの保存先が、アプリケーションの
html
ディレクトリになるように変更します。Take Pictureボックスをダブルクリックし、以下のようにコードを変更します。
a.onLoad
メソッドの先頭にALFrameManager
へのアクセス用オブジェクトを生成するコードを追加しますdef onLoad(self): # 追加コード: ここから self.framemanager = ALProxy("ALFrameManager") # 追加コード: ここまで self.bIsRunning = False ...
b.
onInput_onStart
メソッドの先頭に、htmlディレクトリのパスを取得するコードを追加しますdef onInput_onStart(self): # 追加コード: ここから import os self.recordFolder = os.path.join( self.framemanager.getBehaviorPath(self.behaviorId), "../html") # 追加コード: ここまで if( self.bIsRunning ): return ...
-
Show Imageボックスのパス問題回避のため、Show Imageボックスをダブルクリックし、
_getAppName
メソッドに以下のコードを追加しますdef _getAppName(self): import os if self.frameManager: behaviorPath = os.path.normpath(self.frameManager.getBehaviorPath(self.behaviorId)) appsFolderFragment = os.path.join("PackageManager", "apps") if not (appsFolderFragment in behaviorPath): self.logger.error("appsFolderFragment is not in behaviorPath") fragment = behaviorPath.split(appsFolderFragment, 1)[1] # 追加コード: ここから fragment = fragment.split('/')[1] # 追加コード: ここまで return fragment.lstrip("\\/") else: self.logger.warning("No ALFrameManager")
-
各ボックスの保存先ファイル名を設定します。Take Pictureボックスのほうは拡張子なし、Show Imageボックスのほうは拡張子あり(.jpg)である必要があります
-
画像の保存先となる
html
ディレクトリを作成し、適当なダミーファイルをインポートしておきます
a. プロジェクトの内容パネルの追加ボタンをクリックし、[ディレクトリの作成...] をクリックします
b. [ファイルのインポート...] をクリックすると、ファイル選択ダイアログが開きます。適当なダミーファイルを選択します。
c. ダミーファイルをドラッグし、htmlディレクトリ内に移動します
これで画像ファイルがタブレットで表示可能な状態になりました。
これで、タブレット表示用の html
ディレクトリに対して撮影したデータを保存するTake Pictureボックス、この撮影したデータを表示するShow Imageボックスの準備ができました。
##動作確認
Pepperに接続し、[ロボットにアップロードして再生]ボタンを押すと、Pepperのカメラが撮影した内容がタブレットに表示されます。
##タブレットのキャッシュの回避
このアプリケーションを複数回実行しても、タブレットの内容が更新されないという現象が発生します。
これは、タブレットのWebブラウザが画像をキャッシュしてしまっているためです。これを回避する方法としては、実行時の時間をURLのクエリに含めてあげる方法があります。
Show Imageボックスの onInput_onStart
メソッドに以下のようなコードを追加することで、この問題を回避することができます。
def onInput_onStart(self):
# 追加コード: ここから
import time
# 追加コード: ここまで
# We create TabletService here in order to avoid
# problems with connections and disconnections of the tablet during the life of the application
tabletService = self._getTabletService()
if tabletService:
try:
url = self.getParameter("ImageUrl")
if url == '':
self.logger.error("URL of the image is empty")
if not url.startswith('http'):
url = self._getAbsoluteUrl(url)
# 追加コード: ここから
url += "?" + str(time.time())
# 追加コード: ここまで
tabletService.showImage(url)