【AWS・Tello】ドローンをクラウド上で操作するシステムの構築

# はじめに
この記事は
[ドローンを活用した避難勧告システム](https://qiita.com/sk_nimo/items/56ede90072105e14497d)
の第一章です．
製作背景などはそれを参照してください．

# 概要
　TelloドローンをAWS上で操作可能なシステムの構築します．AWS上で操作できれば，いろんなサービスと連携することができるので夢を広げておきましょう．

# 使用するドローンについて
　中国のスタートアップ企業Ryze Techが開発する[Tello edu](https://store.dji.com/jp/product/tello-edu?vid=47091)を使用します．IntelとDJIが技術開発していて公式の[SDK](https://github.com/dji-sdk/Tello-Python)が公開されていて，edu版だとv2が使用可能でドローンを子機とした編隊飛行が可能なのでedu版の購入がお勧めです．
　ドローン制御にはこのSDKを使用するので，事前にgit clone します．環境構築やSDKを用いたPythonでの基本的な飛行や画像ストリーミング方法については適宜SDKの[ユーザーガイド](https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf)やTelloに関する別の記事を参照してください．

## 飛行コマンド
　Telloクラスのsend_commandメソッドの引数に文字列でコマンドを与えるだけで飛行します．参考までに基本飛行コマンドは以下のようになります．これら以外に回転コマンドや速度を指定して円弧を描き飛行させるコマンドもあるので使い方に合わせて適宜確認しましょう．

| Command | 説明 |
|:--|:--|
| command | SDKモードを開始 |
| takeoff | 離陸 |
| land | 着陸 |
| emergency  | 即座にモーター停止 |
| up x  | 20~500cmの間で上昇 |
| down x | 20~500cmの間で下降 |
| left x | 20~500cmの間で左へ飛行 |
| right x | 20~500cmの間で右へ飛行 |
| forward x | 20~500cmの間で前へ飛行 |
| back x | 20~500cmの間で後ろへ飛行 |

# Tello <-> PC <-> AWS 間の通信
　そもそもTelloドローンは4G通信などの移動通信サービスに対応しているわけではなく，実運用において遠隔操作をさせることは考えにくいですが，インターネット上のサービスをトリガにして制御することは今後有用的だと考えられます．本システムではクラウドサービスとしてAWSを使用しクラウドからのtelloの飛行操作を試みることにします．

## 接続方法
　wifi親機としてTelloを使用しPCとwifi接続する場合，AWSとの接続でwifi接続を使用することが不可能です．そのため，今回はPCとスマホを有線接続しスマホのテザリングを介してPCとAWSが通信できるようにしました．この時，インターネット接続に使用するテザリングサービスの優先度をWifiより高くしなければなりません．
<img width="673" alt="wificonnect.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234751/4088f6af-ccb1-c9c0-67c8-9dee0a613c5f.png">


## ドローンとの通信プロトコル
　今回AWSとドローン間の通信にはHTTP通信ではなくMQTT通信を採用しました．HTTP通信より軽量なメッセージプロトコルとされ，文字列コマンドを送る用途であればMQTT通信が適していると考えたからです(MQTTやってみたかったというのもあります笑)．MQTTブローカーにchannelを設定し，そのchannel上にpublishされたデータをsubscribeすることでMQTT通信が行われます．簡単に多対多の通信が行えるのが大きな特徴です．（たぶん）
　AWSIoTCoreはMQTTブローカーを提供していて，本システムではドローンが飛行コマンドのsubscribe側で，IoTCore上で飛行コマンドのpublishを行いひとまず飛行を確認します．
<img width="896" alt="iotcore2tello.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234751/49f8a410-2499-91a5-eeea-6c02a75d5110.png">

## AWS IoT Core
　次にAWSにログインしてIoT Coreを開き，モノとしてDroneを登録します．

![droneiot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234751/c5bbab1c-5375-8b8a-6c7d-29227d16ee9f.png)

　証明書を作り，ポリシーをアタッチし，証明書をアクティブにします．細かい手順は圧倒的にわかりやすいこの記事が参考になります．([参考URL](https://symfoware.blog.fc2.com/blog-entry-2224.html))
　証明書は後で使うので絶対にダウンロードします．

## Tello制御用プログラム
　TelloSDKがpython2系に準拠しているようなのでライブラリ等は2系に合わせるようにすべきだと思います．(python3で動くか未検証) 
`pip install AWSIoTPythonSDK`
をしてPythonからIoT Core用のライブラリを入れておく．
　証明書やTello.pyがあるディレクトリ(例．Single_Tello_Testなど)に以下のようなmainの制御プログラムを書けばOK．

```python:main.py
# -*- coding:utf8 -*-
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from datetime import datetime
from tello import Tello
import ast
import time
import json
import sys

# For certificate based connection
myMQTTClient = AWSIoTMQTTClient('device001') # 適当な値
myMQTTClient.configureEndpoint('xxxxxxxxxxxx.ap-northeast-1.amazonaws.com', 8883) # 管理画面で確認
myMQTTClient.configureCredentials('rootCA.pem', 'xxxxx-private.pem.key', 'xxxxx-certificate.pem.crt') #各種証明書
myMQTTClient.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing
myMQTTClient.configureDrainingFrequency(2) # Draining: 2 Hz
myMQTTClient.configureConnectDisconnectTimeout(10) # 10 sec
myMQTTClient.configureMQTTOperationTimeout(5) # 5 sec
myMQTTClient.connect()

tello = Tello() # Telloインスタンスを作成
tello.send_command('command') # SDKモードを開始

def customCallback(client, userdata, message):
    payload = message.payload
    print('Received a new message: ')
    print(payload)
    print('from topic: ')
    print(message.topic)
    print('--------------\n\n')
    # command = payload[0]
    dic = ast.literal_eval(payload)
    tello.send_command(dic['message'])

myMQTTClient.subscribe("test/pub", 1, customCallback) # test/pub チャネルをサブスクライブ
while True:
    time.sleep(1)
```

## テスト
　はい，テストします．まず上記のPythonコードを実行して，Telloとの接続を確認しておきます．次にIoT Core上のテストタブを開きチャンネルを指定した後，飛行コマンドを"message"の値に文字列で指定しトピックに発行するだけです．
![takeoff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234751/8eaefe1b-974d-33f1-fdc3-8df9ab48d837.png)

　分かり易く，動作を動画でまとめました．
https://youtu.be/MKF2P_rrS9U
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/MKF2P_rrS9U/0.jpg)](https://youtu.be/MKF2P_rrS9U)

# まとめ
　AWS IoT Core上からコマンドを入力してTelloの飛行に成功しました．次は外部サービスと連携してみましょう．
[【AWS・Tello】声でドローンを操作してみたPart1](https://qiita.com/sk_nimo/items/a98d6cd82d3e5d980504)