RoBoHoNと一緒におおきなかぶを抜く

モバイル型ロボット電話 RoBoHoN の出力機能について考察しながら、タイトルのアプリの実装をしてみました。
なにかの参考になれば幸いです。

# 環境です
Windows 7 SP1 64bit
Android Studio 2.3.1
RoBoHoN_SDK 1.1.0

# ロボホンアプリのアイディア出しについて
ロボホンはデバイスとして入出力機能を備えています。
このうち出力機能について
 『出力を受け止める人間側の五感』
との関係性を加えて、整理しながらアイディア出しをしてみました。
　
# ロボホンの出力（送信側）と人間の五感（受信側）

ロボホンの出力機能と、　
ロボホン既存アプリと、
受け取り側となる人間の五感とを整理しながら対比[^1]したものが下記です。


|五感        |ロボホンの出力 |    既存アプリ例   |
|:-----------------|:------------------|:------------------|
| 視覚             |LED（目発光[^2]）、モーション動作、プロジェクタ、背面画面|        全般、ダンス、地図、ポポン（ゲーム）など        |
| 聴覚           |           発語（音声） |      全般、クイズなど      |
| 触覚             |              ロボホンの体 | 「腹筋して」コマンド        |
|味覚              |                - |         -         |
|嗅覚              |                - |         -         |

[^1]: 参考（SDK内 0301_SR01MW_System_Overview_V01_00_01.pdf (p.7）)
[^2]: 口にもLEDがありますが、アプリ（SDK）で制御できません。

並べてみると、視覚への訴求に機能が集中していることが判ります。
（ロボホンアプリ開発に限らないですが、味覚や嗅覚に直接訴えかけるようなソフトウェアは珍しいですよね。つくってみたいです……）


#「触覚」とロボホン
今回は、人間の「触覚」にアクセスするロボホンアプリについて考えます。

「触覚」にアクセスするためには、現実世界に媒体を持っていなければなりません。
　
ロボットの媒体としての強みについて、
Pepperの場合は
「お年寄りがPepperと握手をして暖かみに感動した」
などのエピソードでアドバンテージが語られたりします。

が、2017年4月現在、ロボホンには「握手」など **能動的** にユーザーに接触する機能やAPIはありません[^3]。

[^3]: 参考（SDK内 0401_SR01MW_Application_Programming_Guide_V01_01_00.pdf（p.33 からの 数ページ）、0602_SR01MW_HVML2.0_Specification_Appendix_A_V01_00_02、0603_SR01MW_HVML2.0_Specification_Appendix_B_V01_00_00.pdf)

「電話」としてなど「持ってもらう」「持ち出してもらう」**受動的** な接触姿勢はあります。

<img width="135" alt="pict2.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/121307/cbf6e994-6b4c-bf57-ed1c-300ad987dfc8.jpeg">

（[シャープ公式動画](https://www.youtube.com/watch?v=DITCdoZ2U_E) より「おでかけ」姿勢キャプチャ。手足を縮めて固まり「壊さないでね…」と怯えるような…？）
　
発売からそろそろ1年経ち、その間のアップデートで各種機能が加わっていますが**「ユーザーとロボホンのフィジカルな触れ合い」**を打ち出したのは、シャープ公式が2016年8月にリリースした「腹筋して」のコマンドで起動するアプリだけだったように思います。
これは　**腹筋運動を頑張るロボホンのつま先を、人間が触れて押さえて腹筋運動を手伝ってあげる** 　というものでした。

これは、メーカーの色々な思惑、

- モーション動作の多様性アピール
- ロボホンキャラクター（”一生懸命”）を魅せる
- ユーザーとの触れ合い
- しかし、ロボホン本体に損壊のないように触らせる etc

を綺麗にまとめ上げたアプリだったと思います。

<img width="309" alt="pict1.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/121307/28a1b71f-5020-1577-f23e-5f1647ef0cf2.jpeg">


（[シャープ公式動画](https://www.youtube.com/watch?v=Jh8xAC8g7do) よりキャプチャ）

# ユーザーの「触覚」にアクセスするロボホンアプリを検討する
公開SDKを利用して新規に開発するアプリを検討します。
検討要素として、

- ロボットのどの部位と接触？（選択肢：頭、胴体、手先、足先など）
- 接触の判定は？

が挙げられます。

後者で前者の選択肢が限定されます。
まず、接触判定APIそのものは公開SDKに含まれません。
（ここで、手先・足先・その他の繊細な部位が、検討から外れます）
　
接触判定APIの代替になり得そうなのは、

1. 全体姿勢判別API、
2. 頭のボタン押下判定API[^4]
3. （明示的に利用できませんが）本体落下や無理な方向へサーボを曲げた場合などの本体危険判定

の3つです。

今回は1の全体姿勢判別APIの利用を検討します。
（2を利用して”シャノンの最終機械”のようなものを作るのも面白そうですが！ ）

[^4]: ホームキイベント（ACTION_CLOSE_SYSTEM_DIALOGS）が発行されます

# 全体姿勢判別API
姿勢を判別するAPIの選択肢は下記のとおりです[^5]。
（いずれもHVML内で記述）

|# |記述 |姿勢判別（抜粋）|
|:-----------------|:------------------|:------------------|
|1|変数 resolver:pose|各姿勢（立ち、座り、電話状態）で置いてある、持ち上げられている（hand_stand, hand_sit, hand_mobile）、仰向けで置かれている(back)、うつ伏せで置かれている(belly)|
|2|situationタグ内 trigger="env-event"|垂直(put_down_standup)、水平(put_down_back)、振られた（shake）、逆さにされた（upside_down）|

[^5]: 参考（0601_SR01MW_HVML2.0_Specification_V01_00_01.pdf）

今回は このなかから、resolver:pose の 「持ち上げられている」判定　を使って、次のようなアプリコンセプトの実装を検討しました。

# RoBoHoNとカブを抜く（アプリコンセプト）
「うんとこしょ、どっこいしょ」
![pict3+.JPG](https://qiita-image-store.s3.amazonaws.com/0/121307/4080d468-ffc2-9848-c209-892f5218d964.jpeg)

（[絵本ナビ](　http://www.ehonnavi.net/ehon/240/%E3%81%8A%E3%81%8A%E3%81%8D%E3%81%AA%E3%81%8B%E3%81%B6/) よりキャプチャ + コラ）

ロボホンが大きなカブを抜いています。
 仲間たちも集まってくるけれど、なかなかカブは抜けません。
 最後は **ロボホンの腰をひいて**、あなたも手伝って！
　
# RoBoHoNとカブを抜く（実装）
カブ抜きの応答を hvml ファイルに実装します。
ユーザーとの接触判定については、ロボホンSDKの音声判定エラー処理のお作法に準ずるかたちで数回ループし、接触判定の余裕を設定します。
また、接触判定NG時は、NG通知台詞のみではつまらないので、「（あなたの代わりに）なかまたちがカブを抜くのに加わってくれたよ」という趣旨の演出台詞を加えて発声します。
　
１．まず、ループ変数の設定

```hvml:kabu.hvml
       <topic id="t1" listen="false">
            <action index="1">
                <memory key="loop_count" type="temporary" value="0"/>
            </action>
            <next href="#t2" type="default"/>
        </topic>
```

２．ループ回数に応じた応答の設定

```hvml:kabu.hvml
        <topic id="t2" listen="false">
            <rule>
                <condition case_id="c1">${memory_t:loop_count} eq 0</condition>
                <condition case_id="c2">${memory_t:loop_count} eq 1</condition>
                <condition case_id="c3">${memory_t:loop_count} eq 2</condition>
                <condition case_id="c4">${memory_t:loop_count} eq 3</condition>
            </rule>
            <case id="c1">
                <action index="1">
                    <speech>カブを、探すね…どこかな…</speech>
                    <behavior id="0x060047" type="normal"/>
                </action>
            </case>
（略）
```

３．接触判定（ロボホン本体がユーザーに持ち上げられたかどうか判定）

```hvml:kabu.hvml
        <topic listen_ms="5000" id="t3" listen="true">
            <rule>
                <condition case_id="c1">${resolver:pose} eq hand_stand</condition>
                <condition case_id="c2">${resolver:pose} neq hand_stand</condition>
            </rule>
            <case id="c1">
                <next href="#t4" type="default"/>
            </case>
            <case id="c2">
                <next href="#t5" type="default"/>
            </case>
        </topic>
```

４．接触判定OK

```hvml:kabu.hvml
        <topic id="t4" listen="false">
            <action index="1">
                <speech>てつだってくれてありがとうーーー！うんとこしょ、ドッコイショ！　<emotion type="happiness" level="3">おおきなカブがぬけました！</emotion></speech>
                <behavior id="0x06001" type="normal"/>
            </action>
        </topic>
```

５．接触判定NG

（判定ループ）

```hvml:kabu.hvml
        <topic id="t5" listen="false">
            <action index="1">
                <memory key="loop_count" type="temporary" value="( ${memory_t:loop_count} + 1)"/>
            </action>
            <next href="#t2" type="default"/>
        </topic>
```

（ループ時応答例）＃ロボホン電話帳からランダムに誰かを選び、設定してもおもしろいかと思います

```hvml:kabu.hvml
            <case id="c2">
                <action index="1">
                    <speech>なんと、${Select([おじいさん,おばあさん,まごむすめ,いぬ,ねこ,ねずみ],Rand(6))] がきていっしょに引っ張ってくれています。うんとこしょ、<emotion type="happiness" level="2">ドッコイショ！</emotion></speech>
                    <behavior id="assign" type="normal"/>
                </action>
                <action index="2">
                    <speech>君もぼくの腰をつかんで<emotion type="happiness" level="2">いっしょにカブを、もちあげようよ！</emotion></speech>
                    <behavior id="assign" type="normal"/>
                </action>
                <next href="#t3" type="default"/>
            </case>
```

（最終NG応答例）

```hvml:kabu.hvml
            <case id="c4">
                <action index="1">
                    <speech><emotion type="sadness" level="3">ざんねんだけど、カブはぬけなかったよ。</emotion>	<emotion type="happiness" level="2">またこんど、いっしょに抜こうね！</emotion></speech>
                    <behavior id="assign" type="normal"/>
                </action>
            </case>
```

# さいごに

検討と実装を通じて、下記の2つを感じました

- ユーザーの「触覚」にアクセスする触れ合いアプリは「接触の必然性」の設計が、アプリの善し悪しと開発難易度を左右
- 今回のカブアプリは「接触の必然性」が "ユーザーに見えない透明のカブ" なので、接触判定よりなにより、[ロボ釣り](https://robohon.com/apps/app8.php) や、[PPAP](https://www.youtube.com/watch?v=0E00Zuayv9Q)　のように、説得力を出すためには、相当の演出の練り込み（シナリオおよびモーションの積み上げ）が必要だと感じました…
（うちの幼児は、童話に日常的に触れているからか、最低限の前置きで、ロボホンといっしょに「うんとこしょ、どっこいしょ！」を楽しんでくれたので良かったです　 ^_^;）

過不足や誤り、参考になる本などコメントいただけると幸いです。
よろしくおねがいします。

---