AirSimでドローンを飛ばして遊ぶ(ドローン持ってなくてもできる！)

## この記事では、以下に関して記載しています
* AirSimについて
* AirSimの入手と起動
* Python APIを使ってドローンを飛ばす

## 前提となる知識
* Pythonの初歩的な知識


# 1. ドローンを飛ばそう

ドローン飛ばしたら面白そうだけど、
いろいろ制約あって、簡単に飛ばせない場合もあると思います。
そんなときは、シミュレータで飛ばしてしまいましょう。

# 2. AirSimについて

AirSimは、Unreal Engineで実装されたドローンや車のシミュレータです。
マイクロソフトが中心となってオープンソースで開発されています。
ソースコードやバイナリは、github上で公開されています。

https://github.com/Microsoft/AirSim

APIも公開されているので、外部アプリからドローンや車をコントロールしたり、
写真撮影したりができます。

たとえば、チャットボットと連携するとか、
まあまあ簡単に実装できます。

動作環境に関しては、
手元のCore i7-7600U + 内臓GPUのノートパソコンでもとりあえずは動作しましたが、
専用のGPUがあった方が快適に動作するはずです。
ちょっと古めのGeForce GTX 760程度でも、デモする分には申し分ない感じだと思います。


# 3. AirSimの入手と起動

https://github.com/Microsoft/AirSim/blob/master/README.md
の**How to Get It**に、WindowsとLinuxでのビルド方法が記載されていますが、
Windowsの場合、自分で改良を加えるのでなければ、
**ビルド済みのバイナリを入手**できます。

とりあえずは、簡単なWindowsでの方法を記載しておきます。

バイナリを入手して実行する場合は、
Unreal EngineのSDKも必要なく、ランタイムだけでOKです。
ランタイムは初回起動時にインストールを促されます。

https://github.com/Microsoft/AirSim/releases
に、Windows用のバイナリがあります。

以下の、好みのものをどれかをダウンロードして解凍します。
CityEnvironは、サイズが大きいので、２つに分割されています。
最初に試す場合は、小さめのサイズのから試すのがおすすめ。

* Africa_001.zip (動物がいる風景)
* AirSimNH.zip (狭い範囲の郊外)
* CityEnviron.zip.001とCityEnviron.zip.002 (広めの都市)
* LandscapeMountains.zip (山の風景)
* ZhangJiaJie.zip (張家界市の自然の風景)

ダウンロードして解凍したら、
`run.bat`を実行します。

Unreal Engineのランタイムがインストールされていない場合は、インストーラが実行されるので、
インストールしましょう。

ランタイムのインストールされた状態で実行すると、
乗り物の選択ダイアログが表示されます。

> Would you like to use car simulation? Choose no to use quadrotor simulation.

ドローンを飛ばす場合は、[いいえ(N)]を選択します。


# 4. Python APIを使ってドローンを飛ばす

AirSimでは、[msgpack](http://msgpack.org/)ベースのRPCを使ったAPIが提供されています。
いろいろなプログラミング言語が利用できますが、
サンプル等もあるPythonが手っ取り早いでしょう。

AirSimと同じマシン上で、Pythonを実行していきます。

## 4.1. 下準備

Python 3.xをインストールしましょう。
(私の環境では、Anacondaをインストールしました。)

pipを使って、必要なモジュールを入手します。

``` shell
> pip install msgpack-rpc-python
> pip install numpy
```

(Anaconda利用時は、numpyは初めから入っているはず。)


https://github.com/Microsoft/AirSim/tree/master/PythonClient
に、Pythonの各種サンプルがありますが、
とりあえずは、
`AirSimClient.py`をローカルの分りやすい場所に保存しておきます。


## 4.2. Python APIを試してみる

ちょっとずつ動かしながら遊ぶと楽しいので、Pythonの対話モードで試してみましょう。
コマンドプロンプト(Anacondaの場合は、Anacondaのプロンプト)を開きます。


さきほど保存しておいた、`AirSimClient.py`で、RPCを使った通信がAPI化されているので、
対話モードで使えるように環境変数を設定しておきます。

``` shell
> set "PYTHONSTARTUP=C:\yourpathto\AirSimClient.py"
```

`C:\yourpathto\AirSimClient.py`は、さきほど保存したフルパスを書いておきます。


環境変数を設定したのと同じコマンドプロンプトから、
pythonコマンドを実行して、対話モードを開始します。

``` shell
> python
```

あとは、対話モードで１つ１つ命令を与えていきます。
この時点でAirSimは起動しておきます。
まずは、おまじない的に、
ドローン用のクライアントのインスタンス作って、API制御を有効にします。

``` python
client = MultirotorClient()
client.confirmConnection()
client.enableApiControl(True)
client.armDisarm(True)
```


そしていよいよ離陸させましょう。

``` python
client.takeoff()
```

これで画面上で離陸するはずです。
![takeoff.png](https://qiita-image-store.s3.amazonaws.com/0/211666/55d4f131-2c2e-0103-4800-cd4425ba4da3.png)



移動させてみましょう。
(x, y, z) = (-5, 10, -15)へ、毎秒2メートルで移動させます。

``` python
client.moveToPosition(-5, 10, -15, 2)
```

障害物に当たると、物理エンジンによって跳ね返ります。
![move.png](https://qiita-image-store.s3.amazonaws.com/0/211666/0d7ca49c-a7dc-c6b8-c213-736948419ca4.png)



## 4.3. 写真を撮ってみる

写真を撮るようなAPIもあります。

単純に、ドローンからのカメラの画像を取得するには以下のような感じです。

``` python
image = client.simGetImage(0, AirSimImageType.Scene)
MultirotorClient.write_file('C:/yourpathto/photo.png', image)
```

`C:/yourpathto/photo.png`は、画像の保存先なので環境に合わせて変更します。

![photo.png](https://qiita-image-store.s3.amazonaws.com/0/211666/8cf497ab-ed93-45ef-7288-53eca339ce1a.png)


# 5. 今回はこの辺で

というわけで、こんな感じで、ドローン飛ばしたり、写真撮ったりできるので、
例えば、チャットボットと連携して、
「離陸」、「〇〇へ行け」、「撮影」など話しかけて、ドローン操作したりのデモも簡単に作れます。

次回は実際に、チャットボットと連携した記事を書こうかと思います。