チュートリアル

1、PaPeRo i 及びPaPeRo i シミュレータについて

PaPeRo(Partner-Type Personal Robot)とは、NECにより開発されたコミュニケーションロボットです。
2005年のPaPeRo 2005は、チャイルドケアロボットとして愛知万博に出展され、子供たちの人気を集めました。
また、2009年にはPaPeRo R500が世界初のベビーシッターロボット・ソムリエロボットという2つのギネス認定を受けました。

シリーズ最新機種となるPaPeRo i は、2016年7月よりレンタルが開始される予定です。
PaPeRo i は、NECプラットフォームズの製品です。
PaPeRo i は、ユーザの開発するPythonスクリプトに従って動作する事ができます。
PaPeRo i シミュレータは、PaPeRo i を制御する為のPythonスクリプトの開発を支援する為のツールです。

2、Pythonについて

Pythonは、オランダ人のグイド・ヴァンロッサム氏によって開発された汎用スクリプト言語です。
オープンソース、マルチプラットホーム、豊富な組み込みデータ型、豊富な拡張ライブラリ等の特長を持っております。
また「シンプル」で「習得が容易」という目標に重点を置いて設計された言語でもあります。
ロボットのプログラミングにはC言語を用いるのが一般的ですが、そこにPythonを用いる事により、プログラミングの難易度低減、生産性向上、参入障壁低減等のメリットが期待できます。

3、シミュレータの画面を理解する

PaPeRo i シミュレータは、PaPeRo i の動きを再現するシミュレータの他に、モーションを作成するためのモーションエディタの機能も備えております。
画面左側の3DエリアにPaPeRo i が表示されております。3Dエリアの上でマウスの左ボタンを押しながら動かすと、空間上の1点を注視点として視点が回転します。
シフトキーを押しながら同様の操作をすると、視点と注視点が平行移動します。
3Dエリアの下にあるボタンで背景を変更できます。
画面右側の上の方にある「シミュレータ」と書かれたボタンをクリックすると、ロボットの位置を変更したり、テキスト入力により話しかけたり、センサーへの入力を与える為のUIが出現します。
画面右側中央付近に見えるタイムチャート(黒い背景に白い線の入った部分)はモーションエディタで編集中のロボットの動作を時系列で表示しています。
その下にある各種UIにより、PaPeRo i のモーションを編集したり、そのモーションを再現する為のPythonスクリプトを生成したりする事ができます。
生成されたコードをテキストエディタ等を使って組み合わせたり、条件判断等を追加する事により、ロボットに複雑な動作や様々な作業を行わせるためのPythonスクリプトを開発する事ができます。

その他、画面の各部の詳細につきましては、下図をご参照下さい。

  1. 3D画面です。PaPeRo i の動きを様々な視点から見る事ができます。
  2. モーションの編集に用いる各種ボタンです。
  3. タイムチャートです。モーションを構成するシーケンスが時系列で表示されます。マウスで左右にスクロールさせたり、シーケンスを選択したりする事ができます。シーケンスを選択すると、その内容がパラメータ入力欄に表示されます。
  4. ダウンロードリンク及びファイル選択ボタンです。作成中のモーションデータをダウンロード(保存)したり、作業再開時に読み込ませたり追加したりする事ができます。
  5. プリセットされたモーションです。名前をクリックすると動作をプレビューでき、「追加」をクリックすると追加されます。
  6. シミュレータの情報表示画面です。ロボットの位置や角度を変えたり、ロボットに話しかけたり、気温・湿度・照度を設定したり、人感センサー・顔検知・振動検知を動作させる事ができます。スクリプトとの通信による最終受信メッセージを確認する事もできます。
  7. パラメータ入力欄です。パラメータを入力し、「追加」ボタンを押すと、シーケンスが追加されます。また、タイムチャートでシーケンスを選択すると、当該パラメータの「追加」ボタンが「更新」ボタンに変わります。
  8. コード生成エリアです。入力したシーケンスに従ってPaPeRo i を動かすためのPyhtonスクリプトがここに生成されます。生成されたコードをテキストエディタに貼り付け、保存して、Pythonスクリプトとして実行する事により、PaPeRo i を動かす事ができます。

4、挨拶をさせてみる

人のコミュニケーションは通常、挨拶から始まるものです。
そこで、まずはシミュレータの中のPaPeRo i に朝の挨拶をさせてみたいと思います。
(1)、[首]縦目標角のテキストボックスに-15、秒数に1と入力し、その隣の「追加」ボタンを押します。

(2)、そのままもう一度「追加」ボタンを押します。
(3)、[首]縦目標角のテキストボックスに0、秒数に1と入力し、その隣の「追加」ボタンを押します。
(4)、[話]のテキストボックスに「おはようございます」と入力し、その隣の「追加」ボタンを押します。

(5)、ここまでの作業が終わったら、画面左上にある再生ボタンをクリックしてみて下さい。
3D画面上のPaPeRo i が「おはようございます」と言いながら首を上下に回しておじぎをます。

※首を動かす際、上記の説明ではテキストボックスに直接数値を入力しましたが、その隣にある「回転ハンドル」ボタンを押すと、3D画面上のPaPeRo i の頭の周りに現れるハンドルをマウスでドラッグする事で、回転角を指定できるようになります。

5、モーションデータを保存してみる

上記の手順で作成したモーションデータは、ブラウザを閉じると消えてしまいます。
しかし、モーション作成の途中で作業を中断し、後ほど続きの作業をしたい場合もあるでしょう。
そのような場合、タイムチャートのすぐ下にある「モーションの保存」というリンクをクリックすると、現在作成中のモーションデータをファイルとしてダウンロードする事ができます。
作業を再開する時は、隣にある「ファイルを選択」と書かれたボタンを押し、表示されるダイアログで先ほどのファイルを指定すれば、データが読み込まれます。
この時、読み込んだデータで既存のデータを上書きするか、後ろに追加するかを選択する事ができます。

6、Pythonで動かしてみる

シミュレータ上のPaPeRo i はシミュレータの操作だけでも動かす事ができますが、特定の条件が成立した時にのみ動かしたり、条件によって動かし方を変えたりしたい場合や、実機を動かしたい場合は、Pythonを使う必要があります。
Pythonで動かすためには、準備として以下の作業が必要です。
・Pythonのインストール(推奨バージョンはPython3.4です)
https://www.python.org/から必要なファイルをダウンロードし、インストール作業を行います。
・Python用パッケージ管理ツール(pip)のインストール
→コマンドプロンプトから以下のコマンドを入力する事によりインストールします。

python -m ensurepip

・通信ライブラリ(tornado及びws4py)のインストール
→コマンドプロンプトから以下のコマンドを入力する事によりインストールします。

pip install tornado
pip install ws4py

・PaPeRo i 制御用ライブラリのダウンロード
こちらから「PaPeRo i 制御用Pythonライブラリ」をダウンロードします。

 上記の作業を実施後、以下の手順を実行すればシミュレータのPaPeRo i をPythonにより動かす事ができます。
 (1)、PaPeRo i 制御用ライブラリのzipファイル(pypapero.zip)からpypapero.pyを取り出し、任意のフォルダに置きます。
 (2)、「生成コード」をクリックして現れるテキストエリアのすぐ上にある「生成範囲」のリストボックスが「全体」となっている事を確認します。
 (3)、テキストエリアの内容をコピーします。
 (4)、メモ帳又は任意のテキストエディタを起動し、コピーした内容を張り付け、文字コードをUTF-8として(1)のフォルダに保存します。
 (5)、コマンドプロンプトを立ち上げ、カレントディレクトリを(1)のフォルダにします。
 (6)、スクリプト実行の為のコマンドを入力します。
   ((4)で保存したファイル名を”tmp.py”と仮定した場合、「python tmp.py -sim シミュレータID」と入力します)

※「python tmp.py」の後ろに「-sim シミュレータID」のようにしてシミュレータIDを指定する必要があります。
 シミュレータIDは、3D画面の左下に表示されています。

7、ボタン操作に反応させてみる

ボタン操作に従って作業を行う為には、PaPeRo i から送られてくるイベントをPythonスクリプトで監視し、イベントの内容に従った処理を行う必要があります。
例として、中ボタンが押されたらPaPeRo i が挨拶をし、他のボタンが押されたらスクリプトが終了するようにする為には、6で作成したPythonスクリプトを以下のように修正します。

# -*- coding:utf-8 -*-
import sys

import pypapero


def my_func(papero):
    papero.send_move_head(["A-15T1000L", "R0T1000L", "A0T1000L"],
                          ["A0T1000L", "R0T2000L"])
    papero.send_start_speech("おはようございます")


if __name__ == "__main__":
    simulator_id, robot_name, ws_server_addr = pypapero.get_params_from_commandline(sys.argv)
    papero = pypapero.Papero(simulator_id, robot_name, ws_server_addr)
    if papero.errOccurred == 0:
        while True:
            messages = papero.papero_robot_message_recv(1.0)
            if (messages is not None) and (messages[0]["Name"] == "detectButton"):
                if messages[0]["Status"]=="C":
                    my_func(papero)
                else:
                    break;
    papero.papero_cleanup()

18行目の「messages = papero.papero_robot_message_recv(1.0)」で、PaPeRo i からのメッセージを受け取っています。
引数の1.0はタイムアウト(秒)で、この時間内にメッセージが受け取れない場合、messagesにはNoneが入ります。
PaPeRo i のボタンが押されると、detectButtonイベントがメッセージとして送られ、押されたボタンの種類を表す文字列が”Status”という項目の値として設定されます。
この値が”C”であれば中ボタン、それ以外であれば他のボタンが押された事になります。

イベントについては他にも様々なものがあり、それらを活用する事により、PaPeRo i によって検知される様々な事象に応じた動作をさせる事ができます。
イベントの詳細については、Pythonライブラリ(pypapero.py)リファレンスマニュアルをご参照下さい。

8、自分の方を向かせてみる

人が話をする際に相手に顔を向けるのは、コミュニケーションの基本であると言われています。
そこで、イベント処理のもう一つの例として、ここではPaPeRo i の顔認識機能を使って、PaPeRo i にこちらを向かせてみたいと思います。

# -*- coding:utf-8 -*-
import sys
import math
from enum import Enum

import pypapero


class State(Enum):
    st0 = 10
    st1 = 11
    st2 = 12                                                           # 2019/05/27 首動作完了待ちの為追加
    end = 999


def main(papero):
    state = State.st0
    while state != State.end:
        messages = papero.papero_robot_message_recv(1.0)
        if messages is not None:
            msg_dic_rcv = messages[0]
        else:
            msg_dic_rcv = None
        if papero.errOccurred != 0:
            print("------Error occured(main()). Detail : " + papero.errDetail)
            break
        if state == State.st0:
            papero.send_start_face_detection("30")
            state = State.st1
        elif state == State.st1:
            if msg_dic_rcv is not None:
                if msg_dic_rcv["Name"] == "detectFace":
                    left_eye_pos = pypapero.get_numstr_list_from_coord(msg_dic_rcv["LeftEyePos"])
                    right_eye_pos = pypapero.get_numstr_list_from_coord(msg_dic_rcv["RightEyePos"])
                    frame_size = pypapero.get_numstr_list_from_coord(msg_dic_rcv["Framesize"])
                    head_pos = pypapero.get_numstr_list_from_coord(msg_dic_rcv["HeadPos"])
                    x = (int(left_eye_pos[0]) + int(right_eye_pos[0])) / 2
                    y = (int(left_eye_pos[1]) + int(right_eye_pos[1])) / 2
                    xc = int(frame_size[0]) / 2
                    yc = int(frame_size[1]) / 2
                    angle_v = int(head_pos[0])
                    angle_h = int(head_pos[1])
                    angle_v2 = int(angle_v + (240.0 - y) * 18.5 / 240.0)
                    angle_h2 = int(angle_h + (320.0 - x) * 24.4 / 320.0)
                    if angle_v2 < (-15):
                        angle_v2 = (-15)
                    elif angle_v2 > 50:
                        angle_v2 = 50
                    if angle_h2 < (-120):
                        angle_h2 = (-120)
                    elif angle_h2 > 120:
                        angle_h2 = 120
                    seq_v = ["A" + str(angle_v2) + "S120L"]
                    seq_h = ["A" + str(angle_h2) + "S120L"]
                    papero.send_move_head(seq_v, seq_h)
                    state = State.st2                                  # 2019/05/27 首動作完了待ちの為追加
               #elif msg_dic_rcv["Name"] == "detectButton":            # 2019/05/27 首動作完了待ちの為削除
               #    papero.send_stop_face_detection()                  # 2019/05/27 首動作完了待ちの為削除
               #    state = State.end                                  # 2019/05/27 首動作完了待ちの為削除
        elif state == State.st2:                                       # 2019/05/27 首動作完了待ちの為追加
            if msg_dic_rcv["Name"] == "moveFinish":                    # 2019/05/27 首動作完了待ちの為追加
                state = State.st1                                      # 2019/05/27 首動作完了待ちの為追加
        if msg_dic_rcv is not None:                                    # 2019/05/27 首動作完了待ちの為追加
            if msg_dic_rcv["Name"] == "detectButton":                  # 2019/05/27 首動作完了待ちの為追加
                papero.send_stop_face_detection()                      # 2019/05/27 首動作完了待ちの為追加
                state = State.end                                      # 2019/05/27 首動作完了待ちの為追加


if __name__ == "__main__":
    simulator_id, robot_name, ws_server_addr = pypapero.get_params_from_commandline(sys.argv)
    papero = pypapero.Papero(simulator_id, robot_name, ws_server_addr)
    if papero.errOccurred == 0:
        main(papero)
    papero.papero_cleanup()

69行目の if name == “main“: の部分は、直接スクリプトとして呼び出した時のみ実行されて、別のモジュールから呼び出された時には実行されないようにするための記述です。
70行目でコマンドライン引数から接続先のシミュレータ・ロボット・WebSocketサーバに関する情報をコマンドライン引数から抽出し、71行目でPaperoオブジェクトを生成しています。
72行目でエラーが起きていない事を確認し、エラーが起きていなければ本体処理であるmain関数を呼び出しています。
ロボット制御の大まかな流れは、
・ロボットの状況の把握
・状況に応じた動作の実行
の2つを繰り返すというものになります。
PaPeRo i の場合、状況を知る手がかりとしては通信で送られてくるイベント等が挙げられますが、それ以外にも時間の経過や過去の通信に関する記憶等が利用できる場合もあります。
今回の例では、状況把握に用いる記憶の一部を「状態」として変数stateに記憶しており、その値の表現の為にEnumクラスを使用しています。
初期状態はst0となっており、この状態では無条件で顔認識開始コマンドを送信し、st1になります。
st1の状態でdetectFaceイベントを受信したら、イベントに含まれる情報に基づいて首を動かすためのパラメータを計算し、moveHeadコマンドを送信します。
MoveHeadコマンドのパラメータは、53~54行目で組み立てています。
moveHeadコマンドを送信したら、状態をst2に変えます。
st2の状態でmoveFinishイベントを受信したら、状態をst1に戻します。
いずれの状態でも、detectButtonイベントを受信したら、顔認識終了のコマンドを送信し、スクリプト自体も終了します。

※本スクリプトをシミュレータで動かす場合、スクリプトの起動後、シミュレータ内のPaPeRo i に顔を見せるために、画面右上の「シミュレータ」をクリックして現れる枠の中ほど右側付近にある「顔」ボタンを押して下さい。その後、3D画面上でマウスを動かし視点を変えると、顔が動きます。顔の動きに反応してPaPeRo i の首が動く事を確認してみて下さい。

9、いくつかの文言を連続でしゃべらせる

首振り動作やLEDの点灯動作は、PaPeRo i から送られるイベントを監視する事によって完了を知る事ができます。
しかし、発話動作の完了を伝えるイベントはありません。
それでは発話の完了はどのようにして確認するかというと、getSpeechStatusコマンドを使います。
以下に例を示します。

# -*- coding:utf-8 -*-
import sys
import time
from enum import Enum

import pypapero


class State(Enum):
    st0 = 10
    st1 = 11
    st2 = 12
    st3 = 13
    st4 = 14
    st5 = 15
    end = 999


def main(papero):
    state = State.st0
    last_time = time.monotonic()
    past_time = 0
    speech_idx = 0
    speech_words = ["あいうえおかきくけこ",
                    "さしすせそたちつてと",
                    "となりのきゃくはよくかきくうきゃくだ",
                    "あかまきがみあおまきがみきまきがみ"]
    left_right=0
    head_moving = False                                                    # 2019/05/27 首動作完了待ちの為追加
    finish_requested = False                                               # 2019/05/27 首動作完了待ちの為追加
    while state != State.end:
        messages = papero.papero_robot_message_recv(1.0)
        now_time = time.monotonic()
        delta_time = now_time - last_time
        last_time = now_time
        if messages is not None:
            msg_dic_rcv = messages[0]
        else:
            msg_dic_rcv = None
        if papero.errOccurred != 0:
            print("------Error occured(main()). Detail : " + papero.errDetail)
            break
        # 連続発話
        if state == State.st0:
            papero.send_turn_led_on("mouth", 
                                    ["G3G3G3G3G3G3G3G3G3", "2", "NNG3G3G3G3G3NN", "2",
                                     "NNNG3G3G3NNN", "2", "NNG3G3G3G3G3NN", "2"], repeat=True)
            state = State.st1
        elif state == State.st1:
           #if(left_right==0):                                             # 2019/05/27 首動作完了待ちの為削除
           #    papero.send_move_head(["A0S120L"],["A50S120L"])            # 2019/05/27 首動作完了待ちの為削除
           #else:                                                          # 2019/05/27 首動作完了待ちの為削除
           #    papero.send_move_head(["A0S120L"],["A-50S120L"])           # 2019/05/27 首動作完了待ちの為削除
           #left_right = 1-left_right;                                     # 2019/05/27 首動作完了待ちの為削除
           #papero.send_start_speech(speech_words[speech_idx])             # 2019/05/27 首動作完了待ちの為削除
           #speech_idx += 1                                                # 2019/05/27 首動作完了待ちの為削除
           #if speech_idx >= len(speech_words):                            # 2019/05/27 首動作完了待ちの為削除
           #    speech_idx = 0                                             # 2019/05/27 首動作完了待ちの為削除
           #past_time = 0                                                  # 2019/05/27 首動作完了待ちの為削除
           #state = State.st2                                              # 2019/05/27 首動作完了待ちの為削除
            if not head_moving:                                            # 2019/05/27 首動作完了待ちの為追加
                if finish_requested:                                       # 2019/05/27 首動作完了待ちの為追加
                    state = State.st4                                      # 2019/05/27 首動作完了待ちの為追加
                else:                                                      # 2019/05/27 首動作完了待ちの為追加
                    if(left_right==0):                                     # 2019/05/27 首動作完了待ちの為追加
                        papero.send_move_head(["A0S120L"],["A50S120L"])    # 2019/05/27 首動作完了待ちの為追加
                    else:                                                  # 2019/05/27 首動作完了待ちの為追加
                        papero.send_move_head(["A0S120L"],["A-50S120L"])   # 2019/05/27 首動作完了待ちの為追加
                    head_moving = True                                     # 2019/05/27 首動作完了待ちの為追加
                    left_right = 1-left_right;                             # 2019/05/27 首動作完了待ちの為追加
                    papero.send_start_speech(speech_words[speech_idx])     # 2019/05/27 首動作完了待ちの為追加
                    speech_idx += 1                                        # 2019/05/27 首動作完了待ちの為追加
                    if speech_idx >= len(speech_words):                    # 2019/05/27 首動作完了待ちの為追加
                        speech_idx = 0                                     # 2019/05/27 首動作完了待ちの為追加
                    past_time = 0                                          # 2019/05/27 首動作完了待ちの為追加
                    state = State.st2                                      # 2019/05/27 首動作完了待ちの為追加
        elif state == State.st2:
            past_time += delta_time
            if past_time >= 1.0:
                papero.send_get_speech_status()
                state = State.st3
        elif state == State.st3:
            if msg_dic_rcv is not None:
                if msg_dic_rcv["Name"] == "getSpeechStatusRes":
                    if str(msg_dic_rcv["Return"]) == "0":
                        state = State.st1
                    else:
                        past_time = 0
                        state = State.st2
        elif state == State.st4:
            papero.send_move_head(["A0T500L", "A-15T500L", "R0T1000L", "A0T500L"],
                                  ["A0T500L", "R0T2000L"])
            head_moving = True                                             # 2019/05/27 首動作完了待ちの為追加
            papero.send_start_speech("どうも、おそまつさまでした")
            state = State.st5
        elif state == State.st5:
           #if msg_dic_rcv is not None:                                    # 2019/05/27 首動作完了待ちの為削除
           #    if msg_dic_rcv["Name"] == "moveFinish":                    # 2019/05/27 首動作完了待ちの為削除
           #        papero.send_turn_led_off("mouth")                      # 2019/05/27 首動作完了待ちの為削除
           #        state = State.end                                      # 2019/05/27 首動作完了待ちの為削除
            if not head_moving:                                            # 2019/05/27 首動作完了待ちの為追加
                papero.send_turn_led_off("mouth")                          # 2019/05/27 首動作完了待ちの為追加
                state = State.end                                          # 2019/05/27 首動作完了待ちの為追加
        # 首動作完了監視                                                   # 2019/05/27 首動作完了待ちの為追加
        if msg_dic_rcv is not None:                                        # 2019/05/27 首動作完了待ちの為追加
            if msg_dic_rcv["Name"] == "moveFinish":                        # 2019/05/27 首動作完了待ちの為追加
                head_moving = False                                        # 2019/05/27 首動作待完了ちの為追加
        # ボタンの監視
        if msg_dic_rcv is not None:
           #if msg_dic_rcv is not None:                                    # 2019/05/27 首動作完了待ちの為削除
           #    if msg_dic_rcv["Name"] == "detectButton":                  # 2019/05/27 首動作完了待ちの為削除
           #        state = State.st4                                      # 2019/05/27 首動作完了待ちの為削除
            if msg_dic_rcv["Name"] == "detectButton":                      # 2019/05/27 首動作完了待ちの為追加
                finish_requested = True                                    # 2019/05/27 首動作完了待ちの為追加


if __name__ == "__main__":
    simulator_id, robot_name, ws_server_addr = pypapero.get_params_from_commandline(sys.argv)
    papero = pypapero.Papero(simulator_id, robot_name, ws_server_addr)
    if papero.errOccurred == 0:
        main(papero)
    papero.papero_cleanup()

このスクリプトは、頭を左右に回しながら、24~27行目に記載したテキストを順番に繰り返し発話するものです。

43行目から103行目までが読み上げ動作本体です。
stateがState.st0の時に口パクのためのLED点灯動作コマンドを送信しています。repeat=Trueとしていますので、この口パクのLED動作は消灯コマンドを発行するまで繰り返されます。
stateがState.st1の時に、首が動いていなければ、首を左右に回すコマンドと、発話のコマンドを発行し、状態をState.st2に変えています。
State.st2で時間を監視し、80行目でgetSpeechStatusコマンドを発行しています。
State.st3で応答メッセージの内容を確認し、getSpeechStatusResのReturnの値が”0″であれば発話完了と見なして次の発話に移るため、stateをState.st1に戻しますが、Returnの値が”0″でなければ再度の時間監視及びgetSpeechStatusコマンド発行のため、stateをState.st2に戻します。
104~107行目でmoveFinishイベントを監視し、首が動いているかどうかを把握できるようにしています。
ボタンの監視は108行目から114行目で行っており、detectButtonイベント受信時にfinish_requestedをTrueにしています。
State.st1でfinish_requestedがTrueの場合は、stateをState.st4に変更します。
stateがState.st4の時、91行目から95行目でお辞儀と挨拶文発話のコマンドを発行してState.st5に移ります。
stateがState.st5の時、首が停止したらLEDの消灯コマンドを発行して終了します。

10、留意事項

・発話の際の各音の出るタイミング等、シミュレータ上のPaPeRo i の動きが実機のそれと完全には一致しない場合があります。
・シミュレータでの発話には、言語・高程音・速度・音量・文章間ポーズ時間・カンマポーズ時間等の変更は反映されません。
・モーター動作シーケンスの位置・速度・加速度の指定にはいくつかの指定方法がありますが、シミュレータのコード生成機能では角度は絶対位置、速度は時間指定、加速度は低速指定となります。
・シミュレータによる加速度センサーによる揺れ検知の再現は、簡易的なものとなっております。
・シミュレータでは、カメラによる写真撮影に関する通信を再現する事はできますが、画像を取得する事はできません。
・録音・再生機能について、シミュレータでは通信のみの再現となります。

11、シミュレータの動作環境

推奨環境:
①Google Chrome 50.0.2661.102m 以上
 (ビデオカードがOpenGL3.2以上に対応している場合)
②Internet Explorer 11 以上
 (Google Chrome で動作しない場合)

 シミュレータでは、PaPeRo i の発話の表現に、WebSpeechAPIを使用しております。
 Internet Explorer ではWebSpeechAPIが使用できない為、発話の表現はテロップのみとなります。

 まずは、Google Chrome でお試し下さい。
 Google Chrome でシミュレータが動かない場合は、以下をお試し下さい。

・Chromeのメニュー→詳細設定
 で表示されるページの「詳細設定を表示」をクリック→
 「ハードウェアアクセラレーションが使用可能な場合は使用する」にチェックを入れる
・アドレスバーに about:flags と入力し、表示される項目の中で、
 「ソフトウェア レンダリング リストをオーバーライド」
 を有効にする
・アドレスバーに about:flags と入力し、表示される項目の中で、
 「WebGL ドラフト拡張機能」
 「WebGL 2.0 プロトタイプ」
 の二つを有効にする

上記を試してもChromeで動作しない場合は、Internet Explorer 11でご使用下さい。

12、Pythonスクリプトで実機を動かす

 本チュートリアルで作成したPythonスクリプトで実機で動かす為には、準備としてこちらから「PaPeRo i 制御用WebSocket通信アドオンシナリオ」をダウンロードし、PaPeRo i の実機にセットアップする必要があります。
 (セットアップ方法に関しましては、PaPeRo iをRaspberry Pi上のpythonから操作するの「PaPeRo iにアドオンシナリオをインストール」をご参照下さい)

 準備ができたらコマンドプロンプトからPythonスクリプトを実行するのですが、その際、接続先としてPaPeRo i の実機のWebSocketアドレスを与える必要があります。
 WebSocketアドレスは「-wssvr ws://実機のIPアドレス:8088/papero」の形でコマンドライン引数により指定します。
 例えば、スクリプトのファイル名がtmp.pyで、実機のIPアドレスが192.168.1.187の場合、コマンドプロンプトで「python tmp.py -wssvr ws://192.168.1.187:8088/papero」とします。