More than 1 year has passed since last update.

会話入門 (Pepper TechFes技術セッション)では、QiChat Scriptの機能をいくつか見てきました。
QiChatが備える便利な機能として、メモリイベントとの連携があります。ここでは、その例についていくつか見ていきます。

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

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

このチュートリアルに関するプロジェクトファイルはGitHub https://github.com/Atelier-Akihabara/pepper-dialog-example にて公開しています。
GitHubにあるコードの取得方法にはいくつかありますが、[Download ZIP]リンクからアーカイブを取得するのが簡単な方法のひとつです。他にもgit関連ツールを利用する方法などさまざまな方法がありますので、状況に応じて調べてみてください。

QiChatでのメモリイベントの監視

Choregrapheのドキュメント NAOqi Developer guide > NAOqi Framework > NAOqi API > NAOqi Audio > ALDialog > QiChat - Table of Content > QiChat - Syntax を読むと、 Robot events: e:eventName という記述があります。
この e:イベント名 の記述を用いると、以下のように、聞いたことに対する返答と全く同じ形式で、あるイベントが発火されたことに対する反応を実装することができます。

u:(こんにちは)こんにちは、お元気ですか?
u:(e:イベント名)イベントを検出しました。

この記述方法を利用することで、言われた言葉に対してだけでなく、Pepperのセンサーなどにより発火するイベントに対する反応をDialogで記述することができます。

Face Characteristicsイベントの利用

e:イベント名 の記述を用いることで、笑顔認識で利用した FaceCharacteristics/PersonSmiling イベントに対する反応をDialog中で記述することが可能です。

この記述例がサンプルプロジェクト handle-person-smiling です。GitHubから取得したファイルのうち、 handle-person-smiling フォルダ内の handle-person-smiling.pml をダブルクリックするなどして開くことができます。
以下のような手順で作成しています。

  1. Dialogの作成手順を参考に、トピック test を作成します
  2. トピック test に以下のようなQiChat Scriptを記述します

    topic: ~test()
    language: jpj
    
    u:(こんにちは) こんにちは、僕に向かって笑ってもらえますか?
    
    u:(e:FaceCharacteristics/PersonSmiling) 楽しそうですねー
    
  3. トピック test を実行するボックスを作成し、接続します

    handle-person-smiling-dialog.png

このサンプルを実行してみてください。これまでのDialogのサンプルと同様に、「こんにちは」としゃべると、「こんにちは、僕に向かって笑ってもらえますか?」と応答してきます。これに加えて、Pepperの前で笑顔を作ると「楽しそうですねー」としゃべります。
これは、e:FaceCharacteristics/PersonSmilingが発火されたことで、u:(e:FaceCharacteristics/PersonSmiling)~のルールが実行されるためです。

この記述では、任意のメモリイベントを処理することができますので、たとえばタッチセンサーによるやり取りを組み込むことも可能です。また、サブルールと組み合わせることで、言葉だけでなく、カメラの処理などを複雑に組み合わせた会話の構成が可能です。

Dialog/NotUnderstoodイベントの利用

Dialog自身もその状況に応じてイベントを発火させるため、これをDialog中で利用することで、より高度な制御が可能になります。
たとえば、Choregrapheのドキュメント NAOqi Developer guide > NAOqi Framework > NAOqi API > NAOqi Audio > ALDialog > ALDialog API をみると、Dialog/NotUnderstood というイベントが定義されていることがわかります。
これは、u:で定義したルールのいずれにもマッチしなかった場合に発火するイベントで、このイベントを活用することで、「Aに対する反応」「Bに対する反応」「AB以外に対する反応」といった記述をおこなうことが可能です。

この記述例が、サンプルプロジェクト handle-not-understood です。GitHubから取得したファイルのうち、 handle-not-understood フォルダ内の handle-not-understood.pml をダブルクリックするなどして開くことができます。
以下のような手順で作成しています。

  1. Dialogの作成手順を参考に、トピック test を作成します
  2. トピック test に以下のようなQiChat Scriptを記述します

    topic: ~test()
    language: jpj
    
    u:(こんにちは)こんにちは、突然ですが、犬と猫、どちらが好きですか?
        u1:(犬)わん
        u1:(猫)にゃー
        u1:(e:Dialog/NotUnderstood)犬か猫でお願いします ^stayInScope
    

    今回は、サブルールを取り入れた例になっています。「こんにちは」と言われると、質問を投げかけサブルールの処理に入ります。「犬」「猫」の場合は適当な反応を返してこのサブルールを終了し、それ以外の場合は ^stayInScope によりこのサブルールにとどまることで、引き続き「犬」「猫」のいずれかを言われるのを待ちます。

  3. トピック test を実行するボックスを作成し、接続します

    handle-not-understood.png

    このサンプルについては、バーチャルロボットでも動作するように、Set Languageボックスを追加しています。Pepper実機の場合はデフォルトが日本語になっているため不要です。

このサンプルを実行し、「こんにちは」と話しかけ、Pepperの質問に答えてみてください。「犬」「猫」に対する反応と、それ以外の言葉(たとえば、「ライオン」)に対する反応をみてください。
また、質問を受けた状態で「イルカ」などとしゃべると「犬」と解釈されるような現象も確認できるかと思います。これは、Dialogがルールに定義された言葉に対して反応しやすくなっているためと考えられます。

他にも、 Dialog/NotSpeaking5 Dialog/NotSpeaking10 イベントを用いて一定の時間話しかけられなかったら反応するようなDialogを記述することもできます(末尾の数字は秒数を示す)。ぜひ、試してみてください。

ボックスでDialogのイベントを取得

Dialogにより発火されたイベントは、他のメモリイベントと同様、Dialogボックスの外側で利用することも可能です。
「Pepperに任意の言葉を聞き取らせることはできる?」と質問いただくことがありますが、実はPepperはDialog起動中、ルールに記述された以外の言葉もある程度聞き取っており、これは Dialog/LastInput イベントによって取得することができます。ここでは Dialog/LastInput イベントを使って、Dialogが取得した任意のキーワードを取得するようなフローを実験的に記述してみましょう。

サンプルプロジェクトとして、はじめに「僕が何でも答えてあげましょう。何か単語を言ってください。」としゃべり、話しかけられた言葉に対して、「(話しかけられた言葉)ですか。うーん、僕のデータベースにはありませんね。残念。」としゃべるアプリケーションを作成してみます。

なお、サンプルプロジェクトは subscribe-last-input です。GitHubから取得したファイルのうち、 subscribe-last-input フォルダ内の subscribe-last-input.pml をダブルクリックするなどして開くことができます。
以下のような手順で作成しています。

  1. ダミーのDialogを実行するためのトピックファイルとして、Dialogの作成手順を参考に、トピック dummy を作成します。トピックファイルは、以下のように空のままにしておきます

    topic: ~dummy()
    language: jpj
    
  2. 実験用ボックスは、わかりやすさのため、フローダイアグラムボックスとしてまとめます。以下のような空のSubscribe LastInputダイアグラムボックスを作成します

    subscribe-last-input-box.png

  3. Subscribe LastInputボックスの中のフローを以下のように構成します。ボックスは dummy ダイアログのほか、以下のものを利用しています

    • standardボックスライブラリ
      • Flow Control > Time > Wait
    • advancedボックスライブラリ
      • Memory > Subscribe to event

    inside-subscribe-last-input.png

    ここでは、Subscribe LastInput開始時にdummyダイアログを起動し、これと時間差でSubscribe to Eventボックスで Dialog/LastInput イベントの監視を開始しています。これにより、Dialogにより Dialog/LastInput イベントが発火されると、Subscribe to EventボックスのonEvent出力を通じて値がSubscribe LastInputボックスのlastInputとして出力される形にしてあります。

  4. 実験用のフローを以下のように構成します

    subscribe-last-input-flow.png

    フローのポイントは以下の通りです。

    • 先の例と同様に、バーチャルロボットでも実行できるよう、Set Languageボックスを追加しています。
    • 自身が言ったことをLastInputで拾ってしまうことを防ぐため、LastInputで出力された内容をAnimated Say Textボックスに入力する前に、Subscribe LastInputボックスを停止しています。この際、Wait For Signalsボックスを改造したボックスを使い、Subscribe LastInputがonStoppedを出力してからAnimated Say Textボックスの実行を開始する形にしています。
    • デモとして、人間のほうを向き続けるように、Basic Awarenessボックスを配置しています。

このアプリケーションの実行例は以下の動画を参考にしてください。

Dialog/LastInputイベント動作例
(再生時間: 1分30秒)

動画中の「アトリエ」という言葉のように、この方法では、期待した結果が得られない場合が多いと思います。これは、Speech Reco.ボックスやDialogボックスが、あらかじめこれから聞き取ることになる言葉をリストアップしておくことで認識精度を高めているためです。

そこで、以下のようにトピックファイル dummy_jpj.top 中に空の(表面上は何もしない)ルールを記述することで単語の候補を与え、特定の単語について精度を高めることも可能です。ただし、列挙した言葉と類似した別の言葉は認識されにくくなる(候補として挙げたもののほうが優先されるようになる)可能性がある点に注意してください。

u:(アトリエ)$DummyVar=1

このようにして、Dialogについても、イベントを用いることでより応用範囲が広がり、深く理解することができると思います。ぜひ、ドキュメントを確認しながら色々な処理を実現してみてください。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.