TOPPERS/箱庭 単体ロボットシミュレータの開発環境を Windows で dockernize したい話

# 動機
昨年(2020年)，TOPPERS/箱庭WGでは，[単体ロボットシミュレータ](https://toppers.github.io/hakoniwa/prototypes/single-robot/)が一般公開されました．

本シミュレータは，様々な環境で利用してもらえるように，Mac/Linux/Windowsで利用でき，とても素敵な環境です．

そんな素敵な環境も月日がたち，色々と思うことがあり，docker化(dockernize)していきたいと思うようになりました．

# dockernize したい理由
理由は以下の通りです．

* 様々な環境に対応している反面，そのための手順書が多岐にわたり，メンテナンスが大変
* 利用者の環境によってはうまくいかないケースがあり，個別サポート対応が大変
* シミュレータの機能拡張スピードが速く，手順書との同期が難しくなってきた
* シミュレータ開発担当者の環境をそのまま利用者に使ってもらいたい
* シミュレータのインストールにより，自分の環境が汚されてしまう

なお，ここでの話は本シミュレータの視点で出てきたものですが，一般的な開発でもありそうな課題ですよね～．

# dockernize する上での課題あれこれ
理由は十分理解いただけたと思いますが，じゃー dockernize ですべて解決できるかというとうまくいかないケースがちらほらあります．特に自分が使っている Windows 10/home で docker 使おうと思った場合，色々と大変です．

以下，課題を列挙してみます．

1. WSL2 では MMAP 通信できない問題
* Unity 連携の課題
* ネットワーク設定の課題
* 性能面の課題

## WSL2 では MMAP 通信できない問題
Windows 上で docker を使えるようにするために，WSL2 を利用することにしました．
一方で，単体ロボットシミュレータは，マイコンシミュレータ(Athrill)と物理シミュレータ(Unity)間で通信を行う必要がありますが，その際の通信方式には以下の２つの方式があります．

* UDP 通信
* MMAP 通信

性能面で有利なのは MMAP であり，シミュレーション精度的にも推奨しています．
ところが，WSL2 では，なぜか MMAP 通信ができない問題があり，Windows で dockernize する場合は，UDP 一択という課題が出てきてしまうのです…

## Unity 連携の課題
単体ロボットシミュレータを docker 化するためには，マイコンシミュレータ(Athrill)と物理シミュレータ(Unity)を docker 内で動作できるようにする必要があります．

Athrill は，dockernize 可能ですが，Unity を docker 上で高速動作させること現時点ではまだ実現できていないと思われます．

ですので，Unity に関しては，Windows 上で動作させないといけないという課題が出てきます．


## ネットワーク設定の課題
前述の通り，Unity は docker 化が困難であるため，Athrill は docker 上で実行し，Unity は Windows 上のプロセスとして動作させる必要があります．

さらに，先述の通り，WSL2 の問題により，AthrillとUnity間の通信は UDP 一択となります．

一方で，WSL2 は WSL1 と異なり，docker の localhost と Windows の localhost が違うため，IP アドレスの設定がそれなりに面倒になります…

さらに，WSL2 の IP アドレスはマシン再起動毎にアドレス変わるので，シミュレーション設定がそれ毎に発生してしまいます…

## 性能面の課題
従来に比べて，性能面の課題としては以下が挙げられます(あくまでも推測です．検証はしていません)．

* Athrill を docker 上で動作させることで，Athrill を素の Linux プロセスとして動作させていた時と比べると多少なりとも遅くなると思われる
* UDP 前提の通信となるため，MMAP 方式に比べて遅くなる
* WSL2のプロセス(Athrill) と Windows プロセス(Unity) は異なるネットワーク体系にいるので，通信オーバーヘッドが加算されると思われる

# やってみる
色々と課題感はありますが，やってみないとなんとも言えないなと思い，とりあえず dockernize　にチャレンジしてみましたのでその結果を共有したいと思います．
※何かよりよい解決案などあれば教えてください！

##全体作業フロー

dockernize することで，導入手順の全体作業フローは以下の通りとなります．
これまでは，Athrill固有のインストールがありましたが，それらはすべて dockernize できましたので，大分環境問題は改善できたと思いますし，自分の環境を汚さない点も見逃せません．

1. Windows に docker をインストールおよび docker サービス起動する
* EV3RT のリポジトリ([ev3rt-athrill-v850e2m](https://github.com/toppers/ev3rt-athrill-v850e2m/))をクローンする
* WSL2 の端末で ev3rt-athrill-v850e2m/docker　に移動する
* docker イメージを作成する
* Unity バイナリをダウンロードする
* UnityとEV3RTのコンフィグ設定を自動生成する

以下，単体ロボットシミュレータ固有の手順のみを説明します．
※他で解説ある内容と従来と同じインストール手順のものは省略します．

## docker イメージを作成する
docker イメージ作成方法は単純です．`ev3rt-athrill-v850e2m/docker`配下で，以下のコマンドを実行するのみです．

```shell

$ bash create-image.bash
```

成功すると，`docker images` コマンドを実行すると以下のように見えます．

```
REPOSITORY                         TAG       IMAGE ID       CREATED        SIZE
single-robot/ev3rt-v850            v1.0.0    ef2b55a98af3   6 hours ago    2.22GB
```

docker コンテナ起動する場合も，以下のコマンドを実行するだけです．

```
$ bash run.bash
root@XXX:~/workspace#
```

## ネットワーク設定
ネットワーク設定は面倒です．ただし，自動化可能ですので，コンフィグ設定は自動化します．

まず，WSL2 ターミナルで，以下の 2 種類の IPアドレスを調べます．

* /etc/resolv.conf で設定されている IP アドレス
* ifconfig で見える IP アドレス

### /etc/resolv.conf で設定されている IP アドレス
以下のコマンドでわかります．

```
$ cat /etc/resolv.conf | grep nameserver
nameserver 172.25.0.1
```

### ifconfig で見える IP アドレス
以下のコマンドで利用している ethernet の IP アドレスです．

```
$ ifconfig | grep -A 1 eth0| grep inet
        inet 172.25.13.128  netmask 255.255.240.0  broadcast 172.25.15.255
```
※eth0 の場合のコマンド実行例です．

これらの IP アドレスの割り当て方は，Athrill の device_config.txt と Unity の config.joson とでそれぞれ変わります．

### Athrill の device_config.txt

|パラメータ|設定対象のIPアドレス|
|---|---|
|DEBUG_FUNC_VDEV_RX_IPADDR|ifconfig で見える IP アドレス|
|DEBUG_FUNC_VDEV_TX_IPADDR|/etc/resolv.conf で設定されている IP アドレス|

### Unity の config.joson
|パラメータ|設定対象のIPアドレス|
|---|---|
|AthrillIpAddr|ifconfig で見える IP アドレス|

## まとめ
今回，単体ロボットシミュレータを dockernize する試みの話をしました．Windows/WSL2の制約により，色々と面倒な課題はありましたが，Athrillのインストール面はかなり改善されたと思います．
※MacやLinux環境であれば，WSL2の制約もないので，もっと楽にインストールできると思われます．

今後，Athrillは，様々な機能拡張が行われる予定ですので，dockernizeのモチベーションはさらに高まると思います．実際，Athrillに 様々なデバイス追加が検討されており(Bluetooth デバイス等)，そのためのインストール手順(gRPC等)がもっと増えることになるはずです．

dockernize されていないと，その環境構築の手間がそのまま利用者の手間になってしまうのですが，dockernize しておけば，手間はdocker イメージの再作成だけで終わります．

現時点では，まだdockernizeの検討段階ですが，来月(2021/3月)に行われる箱庭WG合宿で，今後のリリース方針が固まると思います．こうご期待ください．

## docker と WSL を併用したシミュレーション動画
docker 化してしまえば，シミュレーションはこんな感じです．

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/70a7a391-2727-21fb-9c35-14824a0840b2.gif)