ハッカソンでFPS視点ラジコンをデモしたら思った以上に好評だったので作り方を紹介します


## はじめに

[前回紹介したラジコン](https://qiita.com/zgw426/items/ef38db166366a63e7ff0)を改良して、ハッカソンで [RPGのデモ](https://note.com/agw/n/nbfaa159d74d0?creator_urlname=agw) したら、好評だったので作り方を紹介します。前回はFPS視点とコントローラが別々でしたが、今回はそれらをくっつけてFPS視点コントローラにしました。

※とあるイベントで登壇したときに嬉しいお言葉頂きました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">オタク歓喜のFPS仕様<a href="https://twitter.com/hashtag/AzureBaseDKY?src=hash&amp;ref_src=twsrc%5Etfw">#AzureBaseDKY</a> <a href="https://twitter.com/hashtag/%E3%82%86%E3%82%8B%E3%83%A1%E3%82%AB%E3%83%88%E3%83%AD?src=hash&amp;ref_src=twsrc%5Etfw">#ゆるメカトロ</a> <a href="https://twitter.com/hashtag/%E3%83%93%E3%82%B8%E3%83%A5%E3%82%A2%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E4%BA%A4%E6%B5%81%E4%BC%9A?src=hash&amp;ref_src=twsrc%5Etfw">#ビジュアルプログラミング交流会</a> <a href="https://t.co/hKdLLp0Qb5">pic.twitter.com/hKdLLp0Qb5</a></p>&mdash; もりけん (@moriken_tech) <a href="https://twitter.com/moriken_tech/status/1219947815608016896?ref_src=twsrc%5Etfw">2020年1月22日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## デモ

FPS視点コントローラの操作デモです。ライブ配信画面をタップしてラジコンを操作します。画面から指を離すとラジコンが止まります。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ラジコン視点のコントローラーできた。探索できるラジコンできた！ラジコン見ないように操作したので、めちゃ徐行運転(笑) 1人称視点で操作するの難しいな😅<a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a> <a href="https://twitter.com/hashtag/%E3%83%A9%E3%82%B8%E3%82%B3%E3%83%B3?src=hash&amp;ref_src=twsrc%5Etfw">#ラジコン</a> <a href="https://twitter.com/hashtag/%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%83%BC?src=hash&amp;ref_src=twsrc%5Etfw">#コントローラー</a> <a href="https://t.co/flLtuuvNx5">pic.twitter.com/flLtuuvNx5</a></p>&mdash; j4amountain (@zsipparu) <a href="https://twitter.com/zsipparu/status/1214554398598131714?ref_src=twsrc%5Etfw">2020年1月7日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こちらは、コントローラの画面です。スワイプでラジコンを操作します。タップした位置が原点となり、スワイプした方向でラジコンの進む方向が決まります。上にスワイプすると前進し、左にスワイプすると左旋回します。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ラジコン試運転。奥に映っている人(私)が操作しています。<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/%E3%83%92%E3%83%BC%E3%83%AD%E3%83%BC%E3%82%BA%E3%83%AA%E3%83%BC%E3%82%B0?src=hash&amp;ref_src=twsrc%5Etfw">#ヒーローズリーグ</a> <a href="https://t.co/o9Gmout2VD">pic.twitter.com/o9Gmout2VD</a></p>&mdash; j4amountain (@zsipparu) <a href="https://twitter.com/zsipparu/status/1215867554796724224?ref_src=twsrc%5Etfw">2020年1月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## ラジコン本体はこんな感じ

ラジコン本体の構造について概要を紹介します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/fa52fe27-af10-d548-bc0a-318030616342.jpeg" width="400">

このようにIoTデバイス(ラズパイ、obniz)と、給電用のバッテリーを2つ搭載しています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/2ffbf6e0-6e67-8721-cacb-01201012ba35.png" width="400">

※車体はLEGOテクニックで作っています。LEGOパーツと作り方はこちら→ [ラジコン車体編](https://note.com/agw/n/nef10a27ff18a?creator_urlname=agw)


## FPS視点コントローラのソースはこちら

ソースはgithubに置きました

https://github.com/zgw426/obniz-RadioControl/blob/master/controller2.html


`controller2.html`内の `{{ラズパイのIP}}` と `obniz-ID` を環境に合わせて書き換えます。

|||
|---|---|
|obniz-ID|ラジコンにのせるobnizのID|
|{{ラズパイのIP}}|ラジコンにのせるラズパイの（ローカルの）IPアドレス|

ーーー

では、順に作っていきます

## 1.モーターを制御しよう

ラジコンの動力となるモーターをobnizで制御します。obnizは電子回路がわからない私でも気軽に使えるのでありがたいIoTデバイスです。インターネット経由で制御できるようになっており、ラジコンみたいに遠隔操作したいものを作るのにも便利です。

#### モーターとobnizを接続しよう

後輪にはそれぞれモーターがあり、それらモーター制御にobnizを使用します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/8b4ff7df-da6e-53a4-81b9-cd30256a25af.jpeg" width="350">

左車輪のモーターをobnizのメス端子0,1に、右車輪のモーターをobnizのメス端子10,11に接続します。赤と黒の配線を図のように接続します。obnizのメス端子の番号と、モータの配線の色を間違えないように注意します。また、左車輪のモーターは**コードが上**になるように、右車輪のモーターは**コードが下**になるようにします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/e6cf43df-6776-2061-e287-3a4577751374.png" width="350">

※今回使用したモーターはこちらです → [赤い歯車モーター](https://www.amazon.co.jp/gp/product/B07WHPRMM7/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)

## 制御の概要はこんな感じ

Windows上にNodejsでWebサーバーを用意し [controler2.html](https://github.com/zgw426/obniz-RadioControl/blob/master/controller2.html) をサイトからアクセスできるよう(`http://localhost/controler2.html`みたいにアクセスできる)にします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/c9d73c67-45fd-a1e7-b005-52bf2d495561.png" width="400">

この時点で、モーター制御できるコントローラーまでが完成しました。次にFPS視点の機能を作っていきます。

## 2.ライブ配信しよう

ラズパイをライブ配信サーバにします。そして、ラジコンにカメラ付きのラズパイを搭載します。これで、ラズパイは『動くライブ配信サーバ』になります。このライブ配信サーバからの映像をコントローラと合わせることでFPS視点のコントローラーになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/a33004fb-95ca-481e-1a85-6fd54eafa086.png" width="400">


※ラズパイは`Raspberry Pi 4 Model B 4 GB`を使いましたが、次に紹介する MJPEG-Streamerは`Raspberry Pi 4 Model B`, `Raspberry Pi 4 Model B+` でも動作しました。

#### MJPEG-Streamerをインストールしよう

ラズパイをライブ配信サーバにするため、MJPEG-Streamerをインストールします。

```
$ sudo apt-get install build-essential libjpeg8-dev imagemagick libv4l-dev cmake -y
$ git clone https://github.com/jacksonliam/mjpg-streamer.git
$ cd mjpg-streamer/mjpg-streamer-experimental
```

- CMakeLists.txtを編集します。
- ⾏頭に`#`を追加してコメントアウトします。（これすると、make実行時のエラー発生を対策できるみたいです）

```
#add_subdirectory(plugins/input_opencv)
```

```
$ make
$ sudo make install
```

- ※わかってないのですが ↓ をするといいらしいです

```
~/mjpg-streamer/mjpg-streamer-experimental $ cp input_raspicam.so ../
```

インストールが終われば、ストリーミングを起動してライブ配信ができるか確認します。（ここではオプションの説明は省きます）

```
# ストリーミング起動
$ /usr/local/bin/mjpg_streamer -i "input_raspicam.so -x 640 -y 480 -fps 30 -q 80" -o "output_http.so -p 8090 -w /usr/local/share/mjpg-streamer/www" 
```

配信を開始したら、ブラウザで `http://{{ラズパイのIP}}:8090/`にアクセスして、↓のようなサイトが表示されれば成功です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/b4105daa-c739-3250-800f-c9924271bb75.png" width="350">

#### ※参考※ ストリーミングを開始するShellを作ると便利です。

```shell:/usr/local/bin/start_mjpeg.sh
#!/bin/sh
/usr/local/bin/mjpg_streamer -i "input_raspicam.so -x 640 -y 480 -fps 30 -q 80" -o "output_http.so -p 8090 -w /usr/local/share/mjpg-streamer/www"
```

作成したシェル`start_mjpeg.sh`に実行権限を付与します。

```
$ chmod +x start_mjpeg.sh
```

以下のようにシェルを実行するとストリーミングが開始します。

```
$ ./start_mjpeg.sh
```

---

これでFPS視点のコントローラが完成しました。
ライブ配信のオプションを変更したときは、[controler2.html](https://github.com/zgw426/obniz-RadioControl/blob/master/controller2.html)の修正が必要か確認してください。

controler2.htmlにライブ配信のURL`http://{{ラズパイのIP}}:8090/?action=snapshot・・・`が2か所あります。

## コントローラの操作方法を知っとこう

タップした位置を原点に移動した指の位置と原点との距離・角度で左右のモードの回転方向と出力を変更します。指を話すと止まります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/6fe0b6d8-090a-ac57-565b-4077b98f545d.png" width="350">

---

あとは、おまけです。

##【補足情報】

#### ライブ配信のJavaScriptについて

ライブ配信に使用するJavaScriptは、MJPEG-StreamerのWebサイト`http://{ラズパイのIP}:8090/javascript_simple.html`から取得しました。このサイトは↓このように映像配信のみのシンプルなサイトになっています。（カメラの前のカーテンが映っています）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/b32d70f9-90e8-2490-e3ae-48c252a57d79.png" width="350">

`javascript_simple.html`のソースを見ると、videoタグではなくimgタグを使っており、JavaScriptで画像を更新していました。パラパラ漫画なんですね。

```html:javascript_simple.html
<div id="webcam"><noscript><img src="./?action=snapshot" /></noscript></div>
```

## FPS視点のコントローラの構造

ライブ配信のimgタグとコントローラのcanvasタグが重なるようCSSでスタイルを記述しました。重ね合わせのサンプルを紹介します。

```html:sample.html
<!-- img,canvasタグを重ねる -->
<html>
    <head>
        <style>
            #container {
                position: relative;
            }
            #webcam {
                width: 640px;
                height: 480px;
                position: absolute;
                z-index: 1;
            }
            #hoge {
                position: absolute;
                z-index: 2;
            }
        </style>
    </head>
    <body>
        <div id="container">
            <canvas id="hoge" width="600" height="600"></canvas>
            <div id="webcam"><img id="testImage" src="test.jpg" width="600" height="600"></div>
        </div>
    </body>
</html>
```

## 次は・・・

FPS視点をさらに拡張したいと思っていて、"首振り"の機能を追加しようと試行錯誤中です。そのための部品は揃えたので、あとは作るだけ！　のはず

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LEGOテクニック大量購入😃 <a href="https://t.co/voJl1RajlN">pic.twitter.com/voJl1RajlN</a></p>&mdash; j4amountain (@zsipparu) <a href="https://twitter.com/zsipparu/status/1215228984314580992?ref_src=twsrc%5Etfw">January 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>