Donkey Carを組み立てる前にシミュレーターで楽しんでみる Donkey Car 3.1.0編

# はじめに

[Donkey Car](https://www.donkeycar.com/)は市販のラジコンカーを改造して自律走行させることができるプラットフォームです。RCカーの改造の仕方や機械学習アルゴリズムがオープンソースで公開されいるので誰でも組み立てることができ、各地で走行会やレースが開催されています。

[AIカーが来てる！ 自動運転でラジコンカーを走らせよう！](https://weekly.ascii.jp/elem/000/000/422/422742/)

先日のMaker Faire Tokyo 2019でも[AIでRCカーを走らせよう！コミュニティの主宰で走行会&レース](https://makezine.jp/event/mft2019/program/feature/)が開催されました。

Donkey CarはRCカーにRaspberry Piなどの小型コンピュータとカメラを搭載してカメラで撮影した画像を機械学習アルゴリズムで認識し、RCカーのステアリングやスロットルをコンピュータ制御する仕組みになっています。搭載するコンピュータは[Raspberry Pi 3b+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/)の他、バージョン3.0.2から[NVIDIA Jetson Nano](https://www.nvidia.com/ja-jp/autonomous-machines/embedded-systems/jetson-nano/)に対応しました。

この記事では、Donkey Carに関心を持たれた方々向けに、[Donkey Simulator](https://docs.donkeycar.com/guide/simulator/)を使ってPC上でDonkey Carのテスト走行、教師あり学習、自律走行をシミュレーションで楽しむ方法をご紹介します。

RCカーを購入する前にDonkey Carで必要な作業がどんなものなのか、どういったところが楽しいのかを体感していただければ幸いです。

以下、Macによる手順をご紹介しますがWindowsでもほぼ同じ手順で実現可能です。Windowsでセットアップする場合は、[Anaconda Navigator](https://docs.anaconda.com/anaconda/navigator/)をインストールしてPythonの仮想環境を作成してから下記を実行すると便利だと思います。

# Donkey Simulatorをインストールする

![donkey_sim_icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/f8463480-49b4-1a35-640e-741963d61851.png)

シミュレーターをインストールします。各プラットフォーム毎に用意されています
https://github.com/tawnkramer/gym-donkeycar/releases

Macの場合、最新版をダウンロードしてzipで展開すると`DonkeySimMac`が作成されます。その中にある`donkey_sim`を`/Application`にドラッグ&ドロップします。このようにセットアップしたDonkey Simulatorのロードモジュールのパスは以下のようになります

```shell
/Applications/donkey_sim.app/Contents/MacOS/donkey_sim
```

これのパスはあとで大事になるので覚えておいてください

# DonkeyCarをセットアップする

[Install Donkeycar on Mac](https://docs.donkeycar.com/guide/host_pc/setup_mac/)に従ってPCにdonkeycarをセットアップします。Donkey Carは現時点の最新バージョン`3.1.0`です。Donkey Carの開発は活発なのでバージョンアップされてセットアップ方法が変更される可能性があります

以下の環境を想定しています

Mac 10.14.5
Python 3.7.3

まず適当なディレクトリを作成します。ディレクトリ名はなんでもいいですが、ここでは`donkeypjtest`としました

```shell
mkdir ./donkeypjtest
cd donkeypjtest
```

tensorflowをインストールします。tensorflowでGPUが利用可能な環境であれば`tensorflow-gpu`をインストールすると高速に学習できます

```
pip install tensorflow
```

[donkeycar](https://github.com/autorope/donkeycar)のレポジトリをcloneしてセットアップします

```shell
git clone -b master https://github.com/autorope/donkeycar
pip install -e donkeycar
```

上記が正常にセットアップできると、`donkey`コマンドが使えるようになります

[gym-donkeycar](https://github.com/tawnkramer/gym-donkeycar)をセットアップします

```shell
git clone https://github.com/tawnkramer/gym-donkeycar
pip install -e gym-donkeycar
```

# プロジェクトを作成する

`donkey createcar`コマンドでプロジェクトを作成します

```shell
donkey createcar --path ./mycar
cd ./mycar
```

プロジェクトが作成されると以下のようなディレクトリ構成になります

```shell
tree .
.
├── config.py
├── data
├── logs
├── manage.py
├── models
├── myconfig.py
└── train.py

3 directories, 4 files
```

キモは`manage.py`です。基本的に`python manage.py train`と`python manage.py drive`という2つのコマンドを使います

```shell
python manage.py 
using donkey v3.1.0 ...
Usage:
    manage.py (drive) [--model=<model>] [--js] [--type=(linear|categorical|rnn|imu|behavior|3d|localizer|latent)] [--camera=(single|stereo)] [--meta=<key:value> ...]
    manage.py (train) [--tub=<tub1,tub2,..tubn>] [--file=<file> ...] (--model=<model>) [--transfer=<model>] [--type=(linear|categorical|rnn|imu|behavior|3d|localizer)] [--continuous] [--aug]
```

`myconfig.py`を編集します。このプロジェクトをDonkey Simulatorに対応させるための設定を行います。200行目あたりの以下の3行のコメントを外し、`DONKEY_GYM`を`True`に`DONKEY_SIM_PATH`にDonkey Simulatorのパスを設定します

```myconfig.py
DONKEY_GYM = True
DONKEY_SIM_PATH = "/Applications/donkey_sim.app/Contents/MacOS/donkey_sim"
DONKEY_GYM_ENV_NAME = "donkey-generated-track-v0"
```

以上でDonkey Carシミュレーターで遊ぶ準備ができました

# シミュレーターを起動してテスト走行する

`donkey_sim`を起動します。コンフィギュレーションダイアログが表示されるので`Screen resolution`を`800 x 600`、`Windowed`にチェックを入れて`Play!`ボタンをクリックします。

`Screen resolution`はなんでもよいです。ディスプレイの解像度に合わせて指定してください。`Windowed`のチェックを外すとフルスクリーンモードで起動します

![スクリーンショット 2019-08-19 11.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/8dab84e3-f9eb-6435-0c2b-2336c1edcc0c.png)

シミュレーターには複数のコースが用意されています。今回は左下の`Generated Track`をクリックします

![スクリーンショット 2019-08-19 11.46.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/92a84896-9471-f7f8-d8ef-d8191b889941.png)

`Joystick/Keyboard No Rec`をクリックするとコースを走ることができます。キーボードのカーソルキー`↑`で前進`←`で左折`→`で右折`↓`でバックです。`Stop`ボタンをクリックするとコースを終了します

![スクリーンショット 2019-08-19 11.52.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/c51fcaab-1ddf-448a-940b-5bb887d33bac.png)

しばらく走行してみて感覚をつかんでください。このあと教師用データを集めるために走行しますが、その前にキーボードでの走行に慣れておくほうがよいです

# 教師用データを取得する

Donkey Car実機では教師データを取得するために手動で記録用走行を行います。このとき前方に搭載したカメラで走行中の景色を画像データとして記録し、同時に手動操作されたスロットルやハンドルの操作履歴を記録してそれを教師用データとします。シミュレーターでは記録モードで走行することで実機と同様のデータを取得することができます。

まず、テスト走行のときと同様に`donkey_sim`を起動します。コースを選択する前に画面右下の`Log dir`ボタンをクリックします

![スクリーンショット 2019-08-19 16.13.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/d79611c8-5eb7-24cd-a8a7-62951195eb69.png)

ダイアログで先ほど作成した`mycar`プロジェクトの`logs`フォルダを指定して`Select`ボタンをクリックします

![スクリーンショット 2019-08-19 16.18.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/4e1959c5-70aa-6535-8d7c-c0948e00686a.png)

`Generated Track`を選択します

![スクリーンショット 2019-08-19 11.46.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/eb607287-d4da-76c5-1984-5209ede30736.png)

`Joystick/Keyboard w Rec`ボタンをクリックして記録用走行を開始します

![スクリーンショット 2019-08-19 16.22.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/6bf07853-4449-3ea8-3b01-5ff68c1e3074.png)

カーソルキーでDonkey Carを操作してコースを周回します。左下の`Log:`の表示で記録されている画像の枚数を確認できます。だいたい5000〜10000くらいを目安にしてください。十分に記録ができたら右上の`Stop`ボタンでシミュレーターを終了します

![スクリーンショット 2019-08-19 16.24.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/6c31d59e-86f3-2591-dc50-a894ec0f10bb.png)

記録走行が終了すると、`./mycar/logs`に教師用データが保存されます

![スクリーンショット 2019-08-19 16.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/1b25df6b-5354-a3ee-2ac5-0aed3646e967.png)

カメラ画像は160x120ピクセルのJPEG画像で保存されています

![550_cam-image_array_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/b0c618be-5855-f0eb-eaef-0ee6f870cf8b.jpeg)

スロットルやハンドル確度などの情報がJSONで保存されています。保存されているJSONデータは改行されていませんが、下記は読みやすさのため改行して記載しています

```record_550.json
{
  "cam/image_array":"550_cam-image_array_.jpg",
  "user/throttle":10.0,
  "user/angle":0.0,
  "user/mode":"user",
  "track/lap":0,
  "track/loc":10
}
```

# 学習する

`mycar`プロジェクト下で以下のコマンドを実行して学習を開始します。ここで`--type=categorical`の指定は大事なので覚えておいてください

```shell
python manage.py train --tub=logs --model=models/mypilot.h5 --type=categorical
```

以下のように`./mycar/logs`のデータでモデルを訓練していきます。訓練が終わるまで待ちます

```shell
using donkey v3.1.0 ...
loading config file: /src/work/donkeypjtest/mycar/config.py
loading personal config over-rides

config loaded

...中略...

found 0 pickles writing json records and images in tub logs
logs
collating 7538 records ...
train: 6030, val: 1508
total records: 7538
steps_per_epoch 47
Epoch 1/100
46/47 [============================>.] - ETA: 1s - loss: 2.0719 - angle_out_loss: 1.9795 - throttle_out_loss: 1.0821 - angle_out_acc: 0.4536 - throttle_out_acc: 0.5652      
Epoch 00001: val_loss improved from inf to 1.35425, saving model to models/mypilot.h5
47/47 [==============================] - 83s 2s/step - loss: 2.0617 - angle_out_loss: 1.9745 - throttle_out_loss: 1.0744 - angle_out_acc: 0.4543 - throttle_out_acc: 0.5662 - val_loss: 1.3542 - val_angle_out_loss: 1.4905 - val_throttle_out_loss: 0.6090 - val_angle_out_acc: 0.5817 - val_throttle_out_acc: 0.6513
Epoch 2/100
17/47 [=========>....................] - ETA: 47s - loss: 1.3048 - angle_out_loss: 1.5335 - throttle_out_loss: 0.5380 - angle_out_acc: 0.6140 - throttle_out_acc: 0.7403 
```

学習が終わると`./mycar/models`下に`mypilot.h5`という学習済モデルが出来上がります

![スクリーンショット 2019-08-19 17.12.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/5dbd5706-fde5-d8ac-0a88-9c51cbaa6ad2.png)

# 自律走行してみる

以下のコマンドを実行します。`--type=categorical`に注意してください。`--type`で指定するモデルタイプは上記の`python manage.py train`のときに指定したものと必ず一致させる必要があります

```shell
python manage.py drive --type=categorical --model=models/mypilot.h5 
```

上記を実行するとDonkey Simulatorのコンフィギュレーションダイアログが起動するのでテスト走行のときのように設定して`Play!`をクリックします

![スクリーンショット 2019-08-19 11.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/8dab84e3-f9eb-6435-0c2b-2336c1edcc0c.png)

シミュレーターが起動してしばらくするとターミナルに以下のようなログが表示されます

```shell
finished loading in 3.236067771911621 sec.
Adding part FileWatcher.
Adding part FileWatcher.
Adding part DelayedTrigger.
Adding part TriggeredCallback.
Adding part KerasCategorical.
Adding part DriveMode.
Adding part AiLaunch.
Adding part AiRunCondition.
Tub does NOT exist. Creating new tub...
New tub created at: /src/work/donkeypjtest/mycar/data/tub_1_19-08-19
Adding part TubWriter.
You can now go to <your pi ip address>:8887 to drive your car.
Starting vehicle...
8887
```

`Starting vehicle...`と表示されたら、Webブラウザで [http://localhost:8887](http://localhost:8887) にアクセスします。すると以下のような`Donkey Monitor`が表示されます

![スクリーンショット 2019-08-19 22.40.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/bfffa1df-4a01-8c0d-06dc-7b657b504cfa.png)

画面右下の**Mode & Pilot**のセレクトボックスから`Local Pilot(d)`を選択すると、シミュレーター上のDonkey Carが動き出します

![スクリーンショット 2019-08-19 22.46.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/44be47cf-c2ca-ce22-6532-8372023a3595.png)

これが先ほど訓練した学習済みモデル`mypilot.h5`を使った自律運転です。学習が不十分だった場合はコースをうまく認識せずにコースアウトしたり、スタート地点から動かないことすらあります。そういったときには右下の`Exit`ボタンをクリックするとコースが再起動して運転を再開します

同じ学習済みモデルを使っていても一回ごとにDonkey Carの運転は微妙に違いますし、新たに訓練したモデルを使うとまた違う動きをします。記録する画像の量も多ければよい運転をするとも限りません。記録走行での運転方法や画像の枚数などをいろいろ変えてみてうまくコースが周回できるモデルを作成してみてください

記録、訓練、自律走行までの一連の流れはDonkey Car実機でもほぼ同じです。シミュレーターでこの流れに慣れておけば実機を組み立てた際にスムーズに走らせることができるでしょう

シミュレーターの遊び方は以上です

# 遊ぶ上でのポイントとかコツとか

上記に慣れた後に楽しめるポイントやぼくが経験上得たコツなんかを記載しておきます。参考になれば幸いです

## Colabで高速に訓練する

[FaBo DonkeyCar Docs Colabでの学習(GPU)](https://faboplatform.github.io/DonkeyDocs/2.DonkeyCar%E5%80%8B%E5%88%A5%E8%A8%AD%E5%AE%9A/13.train_colab/)で[Google Colab](https://colab.research.google.com/notebooks/welcome.ipynb)のGPUを利用できるnotebookが公開されています。このnotebookを使うとGPUを使って高速に訓練することができるので大変便利です。教師用画像データが5000枚程度であればだいたい5分くらいで訓練が完了します。使い方はNotebookに丁寧に記載されているので、記載どおりにすすめていけばよいです

## いろんなモデルを訓練してみる

`python manage.py train --type=[MODEL TYPE]`で指定できるモデルタイプは複数あり、様々なアルゴリズムを使って訓練させることができます。現時点でサポートされているタイプは`linear|categorical|rnn|imu|behavior|3d|localizer`となっています。各モデルの解説は公式ドキュメントの[Keras](https://docs.donkeycar.com/parts/keras/)に記載されています

同じ教師データでも異なるモデルを訓練させることで全く違う運転をするのでいろいろ試してみてください。経験上`categorical`が安定している気がしています

上述のとおり、訓練時と運転時の`--type`指定は同一にする必要があります。異なるモデルを指定した場合は`python manage.py drive`でのモデル読み込み時にエラーが発生します

## 何度訓練してもスタート地点から発進しない場合

何度記録と訓練を繰り返してもDonkey Carがスタート地点から発進しないことがありました。いろいろ試したところ記録運転で周回しているときにスタート地点周辺でスロットルをオン（`↑`キー）していると発進しやすくなりました

検証したわけではないですが、おそらくスタート地点周辺でスロットルを開けてるデータを学習させないと発進時にスロットルを開ける確率が低下してしまうためではないかと思います。スタート地点前後では`↑`キーを押し続けるとか小刻みに連打するなどして周辺でスロットルを開けることを教えてやるといいでしょう

![スクリーンショット 2019-08-19 16.25.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/1786d100-6646-c9d1-c6dd-762ea99cecb4.png)

# おわりに

Donkey Carでシミュレーターを使った遊び方を紹介しました。Donkey Carは実機を組み立てて現実世界のコースで走らせるのがなんといっても楽しいですが、組み立てる前の練習や訓練方法を試行するときなどにシミュレーターが役に立ちますし、シミュレーターであれこれ試行錯誤するだけでもなかなか楽しいものです。

Donkey Carに興味を持たれた方はぜひシミュレーターを使ってDonkey Carに対する知識を深めてください！