Posted at

PepperタブレットにおけるJavaScript活用コンテンツ(QiMessaging JavaScript)

More than 3 years have passed since last update.

Pepperのタブレットで画像や動画を表示する方法についてみてきましたが、JavaScriptなどを含むHTMLコンテンツをタブレットで実行することで、よりリッチなコミュニケーションを実現することができます。

ここでは、HTMLコンテンツの基本的な表示方法と、QiMessaging JavaScriptライブラリによる、HTMLコンテンツとビヘイビアとを連携する方法について紹介します。

なお、このサンプルはバーチャルロボットでの動作確認手段はなく、Pepper実機が必要になります。アルデバラン・アトリエ秋葉原などでPepper実機を使って実験などおこなってみていただければと思います。 (予約URL:http://pepper.doorkeeper.jp/events)


Pepperとタブレット

Pepperでタブレットアプリケーションを作成するにあたり、Pepperで動作しているNAOqi OSとタブレットで動作しているソフトウェアの関係を簡単に説明していきます。


NAOqiでのアプリケーション実行

これまで紹介してきたサンプルの多くが、Choregraphe上でボックスをつないで振る舞いを作成し、実行する形式のサンプルでした。

これらの実行時には、接続されているPepperのNAOqi OS上にアプリケーションのファイル一式がアップロードされたのち、NAOqi OS上でアプリケーションのビヘイビアが実行されるという処理がおこなわれています。

ビヘイビアは、その中に配置されたボックスがNAOqi API(ALMemory, ALTextToSpeech など)にアクセスすることで、さまざまな処理を実現することができます。

このように、Choregrapheで作成したアプリケーションはPepper上で実行される形になります。


タブレットでの画像や動画の表示

PepperのタブレットではAndroid OSが動作しており、Pepperで動作しているNAOqi OSとは独立したものとして動作しています。

NAOqi OSとAndroid OSは内部的なネットワークで接続されており、ビヘイビアからは ALTabletService API を通じてタブレットに対してブラウザを起動するなどの指示を出したり、タッチイベントを取得したりといったことが可能になっています。

たとえば、tabletボックスライブラリはこれらのAPIを用いることで、NAOqi上からタブレットへの画像表示や動画表示を指示している形になります。

また、タブレット内のブラウザはALTabletService経由で受けた指示に従い、アプリケーションの画像ファイルやHTMLファイルを取得し、表示をおこないます。

これまで「タブレットに表示したいコンテンツはプロジェクト中の html ディレクトリに配置する」と説明してきましたが、これはNAOqiが、タブレットのようなNAOqi外のシステムに対してはhtmlディレクトリ内のファイルにのみアクセスを許可するような構造になっているためです。


QiMessaging JavaScript

タブレットのブラウザでは、通常のWebのコンテンツと同様にJavaScriptを記述し、実行させることができます。

加えて、NAOqiが提供するQiMessaging JavaScriptライブラリをHTMLコンテンツ内で読み込むことで、JavaScriptからNAOqiのAPIに対して操作をおこなうことが可能になります。

つまり、QiMessaging JavaScriptを用いることで、HTMLコンテンツからもNAOqiの各機能にアクセスできるようになります。

今回は例として、ALMemory を介したビヘイビアとHTMLコンテンツの連携についてみていきます。


試してみる

ここでは、ChoregrapheでのHTMLコンテンツの作成方法から、QiMessaging JavaScriptの利用までを、簡単な例を追ってみていきます。


プロジェクトファイルの入手方法

このチュートリアルに関するプロジェクトファイルはGitHub https://github.com/Atelier-Akihabara/pepper-qimessaging-examples にて公開しています。

GitHubにあるコードの取得方法にはいくつかありますが、[Download ZIP]リンクからアーカイブを取得するのが簡単な方法のひとつです。他にもgit関連ツールを利用する方法などさまざまな方法がありますので、状況に応じて調べてみてください。


簡単なHTMLをタブレットに表示

まずは、プロジェクト内にHTMLで単純なコンテンツを作成し、タブレットに表示させてみます。

サンプルプロジェクトは show-app です。GitHubから取得したファイルのうち、 show-app フォルダ内の show-app.pml をダブルクリックするなどして開くことができます。



  1. htmlディレクトリを作成する

    プロジェクトの内容パネルの追加ボタンをクリックし、[ディレクトリの作成...] をクリックします。

    名前を html として作成すると、プロジェクトファイルとして html ディレクトリが作成されます。




  2. index.htmlファイルを作成する

    以下のようなファイルをテキストエディタで作成し、適当な場所に保存します。なお、保存する際の文字コードはUTF-8を指定してください。

    <!DOCTYPE html>
    
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>タブレットに表示したいページ</title>
    </head>
    <body>
    <div style="font-size: 6em">
    タブレットに表示したいページ
    </div>
    </body>
    </html>



  3. index.htmlファイルをインポートし、htmlディレクトリ内に配置します

    プロジェクトの内容パネルの追加ボタンをクリックし、[ファイルのインポート...] をクリックします。

    インポートするファイルを問い合わせるダイアログが開きますので、2.で作成した index.html を選択します。すると、プロジェクトファイルに index.html がインポートされます。

    index.htmlhtmlディレクトリにマウスドラッグして移動します。

    これでHTMLコンテンツの準備は完了です。



  4. ビヘイビアにShow Appボックスを配置する

    tabletボックスライブラリ > Show Appボックスをフローダイアグラムにドラッグ&ドロップし、以下のように接続します。




  5. Show Appボックスを修正する

    Show AppボックスはShow Imageボックスと同様のパス問題を持っています。そのため、Show Appボックスの _getAppName 関数のコードを修正します。

            fragment = behaviorPath.split(appsFolderFragment, 1)[1]
    
    # 以下の1行を追加
    fragment = fragment.split("/")[1]
    return fragment.lstrip("\\/")


これで、index.htmlの内容をタブレットに表示するアプリケーションの完成です。


実行する

ChoregrapheでPepperに接続し、[ロボットにアップロードして再生]をおこないます。

以下のようにタブレットに index.html の内容が表示されれば成功です。


簡単なJavaScriptを実行

次に、HTML中に簡単なJavaScriptを記述してみます。JavaScriptの例として、HTMLコンテンツ上のボタンが押されたらログメッセージを表示することをおこなってみます。

一般にブラウザ上のJavaScriptでは console.log APIを用いてログ出力をおこなうことができますが、PepperのタブレットでもこのAPIが提供されており、出力したログメッセージはALMemoryのメモリイベント ALTabletService/message から取得することが可能です。

サンプルプロジェクトは simple-js です。GitHubから取得したファイルのうち、 simple-js フォルダ内の simple-js.pml をダブルクリックするなどして開くことができます。


  1. 先ほど作成した [簡単なHTMLをタブレットに表示] と同じ手順でhtmlディレクトリ、Show Appボックスを準備する


  2. 以下のような index.html ファイルを作成する

    先と同様の手順で htmlディレクトリ内に配置します。

    <!DOCTYPE html>
    
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>単純なJavaScript (ログ出力)</title>
    <script>
    // ログを出力するだけの関数
    // <button>が押されると、onclick属性に指定されたスクリプトが実行され、この関数が
    // 実行されます。
    function sampleButtonClicked() {
    console.log("sampleButtonClicked")
    }
    </script>
    </head>
    <body>
    <div style="font-size: 6em">
    単純なJavaScript (ログ出力)
    </div>
    <button style="font-size: 6em" type="button" onclick="sampleButtonClicked();">ログ出力</button>
    </body>
    </html>

    script 要素に関数 sampleButtonClicked を記述し、これを[ログ出力]ボタンクリック時に実行(onclick属性で指定)する形にしています。




  3. ALTabletService/message メモリイベントをLogボックスにつなぐ

    メモリイベント追加[+]ボタンをクリック[A]し、フィルターにALTabletServiceと入力[B]し、ALTabletService/messageをチェック[C] し[OK]ボタンを押します。

    standardボックスライブラリ > System > Logボックスをフローダイアグラムに配置し、以下のように ALTabletService/message 入力とつなぎ[A]ます。また、ログがタブレットからのものとわかりやすいように、パラメータのMessage prefixをTabletに変更[B]します。



このようにして、HTMLで呼び出した console.log によるメッセージをメモリイベントとして取得し、Choregrapheのログ出力で確認することが可能になります。


実行する

ログビューアを開いてログが確認可能な状態にして、プロジェクトを実行してみてください。

まず、タブレットでのブラウザの起動処理などが動作し、以下のようなログが表示されます。

[INFO ] behavior.box :onInput_message:27 _Behavior__lastUploadedChoregrapheBehaviorbehavior_11027515016__root__Log_1: Tablet: [INFO] TabletService : Loading application .lastUploadedChoregrapheBehavior

[INFO ] behavior.box :onInput_message:27 _Behavior__lastUploadedChoregrapheBehaviorbehavior_11027515016__root__Log_1: Tablet: [INFO] TabletService : Loading url: 'http://198.18.0.1/apps/.lastUploadedChoregrapheBehavior'
[INFO ] behavior.box :onInput_message:27 _Behavior__lastUploadedChoregrapheBehaviorbehavior_11027515016__root__Log_1: Tablet: [INFO] TabletService : Ping url : http://198.18.0.1/apps/.lastUploadedChoregrapheBehavior response : 200
[INFO ] behavior.box :onInput_onStart:56 _Behavior__lastUploadedChoregrapheBehaviorbehavior_11027515016__root__ShowApp_2: Successfully set application: .lastUploadedChoregrapheBehavior
[INFO ] behavior.box :onInput_message:27 _Behavior__lastUploadedChoregrapheBehaviorbehavior_11027515016__root__Log_1: Tablet: [INFO] TabletService : Show web view

この後、タブレットに [ログ出力] というボタンがあらわれますので、タブレットをタッチしてボタンを押してみてください。以下のようなログメッセージが表示されるはずです。

[INFO ] behavior.box :onInput_message:27 _Behavior__lastUploadedChoregrapheBehaviorbehavior_11027515016__root__Log_1: Tablet: [INFO] WebView : onConsoleMessage : sampleButtonClicked

これは、Pepperのタブレット内でJavaScriptが実行され、そこで実行された console.log の内容が ALTabletService/message メモリイベントを通じてログに出力されたことを意味しています。

JavaScriptでの開発の際は、console.logを活用することでスクリプトの動作の把握がしやすくなります。


アプリケーションとの連携

JavaScriptが動作することが確認できたので、QiMessaging JavaScriptを用いてJavaScriptからNAOqi APIにアクセスしてみましょう。

今回は ALMemory を介して、ビヘイビアとHTMLコンテンツを連携させてみます。


タブレット→アプリケーション

まず、タブレットのJavaScript側からイベントを発行し、これをビヘイビア側で取得してみます。

簡単な例として、タブレットのボタンが押されたら独自メモリイベント PepperQiMessaging/fromtablet を発行し、ビヘイビア側で渡された値をしゃべる ということをやってみます。

サンプルプロジェクトは memory-from-tablet です。GitHubから取得したファイルのうち、 memory-from-tablet フォルダ内の memory-from-tablet.pml をダブルクリックするなどして開くことができます。


  1. 先ほど作成した [簡単なJavaScriptを実行] と同じ手順でhtmlディレクトリ、Show Appボックス、console.logの確認用Logボックスを配置する


  2. PepperQiMessaging/fromtablet メモリイベント入力を作成する

    今回は独自のキーを持つメモリイベントを利用します。フローダイアグラム上でメモリイベント追加[+]ボタンをクリックし、[メモリイベントの選択]ダイアログを開き、[新しいキーの追加...]をクリックします。

    新しいメモリキー名として、PepperQiMessaging/fromtabletを入力します。

    メモリキーの一覧に PepperQiMessaging/fromtablet が追加されるので、これをチェックします。




  3. PepperQiMessaging/fromtabletメモリイベント入力をSay Textボックスに出力する

    advancedボックスライブラリ > Audio > Voice > Say Textボックスを配置し、以下のように接続します。




  4. index.htmlを修正する

    今回は以下のようなHTMLを記述します。

    <!DOCTYPE html>
    
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>QiMessaging (メモリに出力)</title>
    <script src="/libs/qimessaging/1.0/qimessaging.js"></script>
    <script>
    var session = new QiSession();

    function sampleButtonClicked() {
    session.service("ALMemory").done(function (ALMemory) {
    console.log("ALMemory取得成功");
    ALMemory.raiseEvent("PepperQiMessaging/fromtablet", "押したね");
    });
    }
    </script>
    </head>
    <body>
    <div style="font-size: 6em">
    QiMessaging (メモリに出力)
    </div>
    <button style="font-size: 6em" type="button" onclick="sampleButtonClicked();">メモリイベント発生</button>
    </body>
    </html>

    重要なのは以下の3点です。



    • qimessaging.jsの読み込み

      以下のscript要素により、タブレットにqimessaging.jsをダウンロード・実行します。

      <script src="/libs/qimessaging/1.0/qimessaging.js"></script>
      



    • QiSessionオブジェクトの作成

      ページのロード時に、qimessaging.jsに定義されたQiSessionオブジェクトを初期化しています。JavaScriptは、このオブジェクトを介してNAOqi APIにアクセスできるようになります。

      var session = new QiSession();
      



    • QiSessionからのALMemory取得、ALMemory.raiseEvent呼び出し

      ボタンが押された際の処理で、sessionオブジェクトに対してservice関数を通じて ALMemory へのアクセス用オブジェクトを要求します。

      この取得処理は非同期的に実行され、取得完了時に function (ALMemory) { ... } 関数がアクセス用オブジェクト ALMemory をともなって呼び出されます。

          session.service("ALMemory").done(function (ALMemory) {
      
      console.log("ALMemory取得成功");
      ALMemory.raiseEvent("PepperQiMessaging/fromtablet", "押したね");
      });




このようにして、JavaScript側でボタンが押された際に、ALMemory.raiseEvent を実行することで、独自メモリイベント PepperQiMessaging/fromtablet押したね という値をつけて発火させています。

ビヘイビア側ではPepperQiMessaging/fromtabletの値をSay Textボックスに入力することで、JavaScriptで指定された文字列(押したね)をしゃべらせています。


実行する

このアプリケーションをPepperで再生してみてください。

タブレットに[メモリイベント発生]ボタンが表示されるので、これを押すとPepperが「押したね」としゃべります。

このように、ALMemory.raiseEvent により、メモリイベントを介してタブレットからビヘイビアへと処理を伝達することができます。


アプリケーション→タブレット

今度は逆に、アプリケーションで発火したイベントをJavaScript側で取得してみます。

簡単な例として、Basic Awarenessで得られた人のIDをメモリイベントを介してタブレットに渡す ということをやってみます。

サンプルプロジェクトは memory-to-tablet です。GitHubから取得したファイルのうち、 memory-to-tablet フォルダ内の memory-to-tablet.pml をダブルクリックするなどして開くことができます。


  1. [簡単なJavaScriptを実行] と同じ手順でhtmlディレクトリ、Show Appボックス、console.logの確認用Logボックスを配置する

  2. Basic Awarenessボックスを配置する

    standardボックスライブラリ > Trackers > Basic Awarenessボックスをドラッグ&ドロップします。


  3. Raise Eventボックスを配置する

    ビヘイビア側でイベントを発火させるため、 advancedボックスライブラリ > Memory > Raise Eventボックスを配置し、パラメータkeyにPepperQiMessaging/totabletを設定します。



  4. ボックスをつなげる

    以下のようにボックスをつなげます。なお、Show AppボックスとBasic Awarenessボックスの間は3秒程度のWaitボックスを挿入しています。今回の例では、タブレットでのコンテンツがロードされたのちにBasic Awarenessが起動するように制御する必要があったのですが、例として単純化するためにWaitで実現しています。




  5. index.htmlを修正する

    HTMLは以下のようにします。

    <!DOCTYPE html>
    
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>QiMessaging (メモリを監視)</title>
    <script src="/libs/qimessaging/1.0/qimessaging.js"></script>
    <script>
    var session = new QiSession();

    function toTabletHandler(value) {
    console.log("PepperQiMessaging/totabletイベント発生: " + value);
    document.getElementById("memory").innerHTML = value;
    }

    function startSubscribe() {
    session.service("ALMemory").done(function (ALMemory) {
    console.log("ALMemory取得成功");
    ALMemory.subscriber("PepperQiMessaging/totablet").done(function(subscriber) {
    subscriber.signal.connect(toTabletHandler);
    });
    });
    }
    </script>
    </head>
    <body onLoad="startSubscribe();">
    <div style="font-size: 6em">
    QiMessaging (メモリを監視)
    </div>
    <div style="font-size: 4em">
    現在のPepperQiMessaging/totabletの値: <span id="memory">不明</span>
    </div>
    </body>
    </html>

    先の例に加えて重要なのは ALMemory.subscriberによるイベントの監視部分です。以下の処理により、PepperQiMessaging/totabletメモリイベントが発生した際にJavaScriptで定義した toTabletHandler 関数が呼び出されるように設定しています。

              ALMemory.subscriber("PepperQiMessaging/totablet").done(function(subscriber) {
    
    subscriber.signal.connect(toTabletHandler);
    });



実行する

このアプリケーションをPepperで再生してみて、Pepperに近づいたり、離れたりしてみてください。

Pepperのビヘイビア内、Basic Awarenessボックスが検出した人のIDがタブレットに表示されるはずです。

このように、ALMemory.subscriber により、ビヘイビアからタブレットへとメモリイベントを伝達することができるようになります。

以上のように、QiMessaging JavaScriptを利用することで、Choregrapheのボックスとタブレットを密接に連携させたアプリケーションを実現することが可能になります。

また、QiMessaging JavaScriptでは、ALMemory以外に他にもALMotionなどのさまざまなAPIにアクセスすることが可能です。今後は、QiMessagingからAPIへとアクセスする例も扱っていく予定です。