Pepperに会えない日々が続くので、Google Home MiniとMESHでPepperの自作を試みた

# はじめに
筆者は趣味でコミュニケーションロボットPepperのアプリ開発をやる事があるのですが、自宅にPepperはおらず、いつも[Pepperアトリエ](https://pepper-atelier-akihabara.jp/)を利用させて頂いています。しかしながら、本記事を書いている2020年4月現在、筆者は外出自粛中であり、かつアトリエも休業になってから1ヶ月以上が経っており、ここしばらくPepperに会えていません。
趣味を自粛するのもちょっと疲れてきたので、なんとか自宅にあるものでPepperを自作できないかと模索してみました。

# 材料
<img width="600" alt="ingredient" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/d53a1857-8e6d-f8b7-9187-b04e2afc3707.jpeg">

- Pepperぬいぐるみポシェット
    - 正式名称：[一緒におでかけPepperポシェット](https://www.fantasy.co.jp/company/wp-content/uploads/2018/12/FINAL_FINAL_2018_12_25_Pepper.pdf)
- Google Home Mini
- [MESH](https://meshprj.com/jp/)ブロック「ボタン」と「動き」
    - 旧称：MESHタグ
- MacBook (サービス常駐用。ラズパイに移行予定)
- iPad mini(MESHアプリ対応のスマホやタブレットならなんでもOK)

Pepperポシェットの中にMESHブロック2つとGoogle Home Miniを入れてインタラクションをします。
<img width="450" alt="inside_pepper" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/6c8fe801-008f-8916-b749-06ef1d46325f.png">
センサーブロック2つはちょうどお腹辺りに、Google Home Miniは頭部にすっぽり入ります。
<img width="450" alt="inside_pepper" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/0c1b5f52-4785-1b60-8bfc-a2de29f93111.jpeg">
ぺたんこだった頭が少しふっくらして、ちょっとだけ本物に近づいてきた気がしますね。

# Pepperの挙動を思い出してみる
要件定義の前に、Pepperのよくある挙動をなんとなく思い出してみます。

- 「こんにちは」とか「ペッパー」と話しかけると、簡単な受け答えをしてくれる
- センサーのある部位(頭とか手とか)を触ると、びっくりしたり、くすぐったがる
- 定期的に「ねぇねぇ、何してるのぉ？」とか声かけてくる

これらは、Naoqi OS 2.5.x 版と言われる旧型のモデルの筐体が「オートノマスライフ」という自律モードで動いている時の挙動です。最新のAndroid版と呼ばれるPepperは会話エンジンが異なるのと、センサー値に応じた挙動も異なる可能性があります。
ただ、筆者が開発に利用しているのは前者の旧型ですので、これでよしとしましょう。

# 要件
記憶を辿った結果を受けて、ざっくり以下の要件を定義しました。

1. ユーザーが話しかけたら、言葉を返す
- センサーの値に応じて言葉を発する
- 定期的にユーザーに対して言葉を発する


# 設計
処理フローは以下の通りです。
![mofupepperflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/bae1d71f-124d-f19d-ac6d-6fd34383704f.png)
要件1については、Actions on Googleを使って、Pepperと会話しているような会話フローを作成します。要件2,3についてはgoogle-home-notifierを使い、センサーや時刻をトリガーとしてGoogle Homeに通知を飛ばす仕組みを利用します。

# 実装
## 1. Actions on Googleを使って、Pepperっぽい受け答えをするActionを作成
[Actions Console](https://console.actions.google.com/)から、新規プロジェクトを作成し、Dialogflowで以下のように作成しました。

- Default Welcome Intentの編集
アクション起動時のセリフとして以下を設定しました。
<img width="450" alt="Default Welcome Intent" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/0e318f28-7b77-df5d-585a-f7510d511403.png">

- CallPepper intentを新規作成
Training phrasesに"ペッパー/Pepper"を追加し、
<img width="450" alt="CallPepper1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/f3d0b750-370e-42fd-b774-042826af6591.png">
以下のような返答を返すようにしました。
<img width="450" alt="CallPepper2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/294aff9b-d43b-d19d-ae86-5f74fc58599f.png">


## 2. MESHアプリとMESH SDKでセンサー値に応じた発話を実装
こちらの記事を参考にさせて頂き、google-home-notifierの導入、およびMESHカスタムタグの作成をしました。
https://qiita.com/glory/items/a464872b9655a21e9f2f

複数の返答候補からランダムに選択するようにするため、トリガー時に渡すテキストを以下のような書式にしました。

・MESHのボタンが押された時
`ナニー？, どうしたの？, おなか, くすぐったいよー`

・動きを検出した時
`きゃっハッハー, わあ, びっくりー`

そして、MESHカスタムタグ内のコードについては以下のようにしました。

```javascript
var endPointURL = "https://" + properties.ipAddress + "/google-home-notifier";

var resList = properties.speakText.split(','); //propertiesのspeakTextを配列に変換
var resText = resList[Math.floor( Math.random() * resList.length )]; //発話テキストをランダムに選択

ajax ({
    url : endPointURL,
    type : 'post',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    timeout : 5000,
	data:{text: resText},
    success : function ( contents ) {
		log('trigger success');
        callbackSuccess( {
            resultType : 'continue'
        } );_
    },
    error : function ( request, errorMessage ) {
		log("detail: " +  JSON.stringify(request));
        log('trigger : Network error');
		log(endPointURL);
		log('trigger  : ' + errorMessage);
        callbackSuccess( {
            resultType : 'continue'
        } );
    }
});
 
return {
    resultType : 'pause'
};
```

MESHアプリでは以下のようにフローを設定します。
<img width="400" alt="mesh_flow" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/a3dd3da1-55ab-3dc7-3a83-69bb8970837b.jpeg">
これで、お腹を押されたり、揺らされたら何らかの反応を示すようになりました。


## 3. IFTTTのDate/TimeとWebhookで定期的な発話を設定
[IFTTT](https://ifttt.com/)と、前節で設定したgoogle-home-notifierを使って、決まった時間に「ねぇねぇ、何してるのー？」と発話させます。IFTTTのトリガー(this)をDate&Timeにし、Webhookを使って(that)、毎時45分に稼働中のgoogle-home-notifierにリクエストを飛ばします。設定は以下のようにしました。
<img width="400" alt="IMG_0426 2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137766/0f0c88fd-dc33-0348-fda5-82ba934f2d4f.jpeg">



# 実行結果
それでは、話しかけてみましょう。
[実行結果1] https://youtu.be/pRXoF8uH23c
[![Actionを実行](http://img.youtube.com/vi/pRXoF8uH23c/0.jpg)](https://youtu.be/pRXoF8uH23c)

揺らしたり、お腹を押してみると。。。
[実行結果2] https://youtu.be/ksDXIohJB-w
[![センサー](http://img.youtube.com/vi/ksDXIohJB-w/0.jpg)](https://youtu.be/ksDXIohJB-w)

google-home-notifierを使った方(2つ目の動画)はだいぶタイムラグはありますが、なんとかPepperらしく(？)リアクションしてくれました。


# 結論
・・・やっぱり本物が良いですね。