Pythonによるドローン「Tello」の制御

この記事は1年以上前に書かれました。
内容が古くなっている可能性がありますのでご注意下さい。


Ryze社の小型ドローン「Tello」は手頃な価格でありながら高性能で、一時は品薄状態となった程の人気機種です。

Telloは専用アプリによる操作のほか、ScratchPython等のプログラミング言語を使用して制御することができます。
そこで、簡単なプログラムを作成してAndroid端末上のPython環境からTelloを操作してみることにします。今回作成するプログラムは離陸と着陸の機能しかありませんので、飛行の際には充分な安全を確保して下さい。

Tello SDK
ドキュメントによると、Tello SDK 1.0.0.0では以下のコマンドが提供されています。

コマンド 説明 レスポンス
command commandモードに入る OK / FALSE
takeoff 自動離陸 OK / FALSE
land 自動着陸 OK / FALSE
up xx 上昇 xx=(20-500cm) OK / FALSE
down xx 下降 xx=(20-500cm) OK / FALSE
left xx 左方に飛行 xx=(20-500cm) OK / FALSE
right xx 右方に飛行 xx=(20-500cm) OK / FALSE
forward xx 前方に飛行 xx=(20-500cm) OK / FALSE
back xx 後方に飛行 xx=(20-500cm) OK / FALSE
cw xx 時計回りにxx°回転 xx=(1-3600°) OK / FALSE
ccw xx 反時計回りにxx°回転 xx=(1-3600°) OK / FALSE
flip x フリップ x={l,r,f,b,bl,rb,fl,fr} OK / FALSE
speed xx 速度をxxに設定 xx=(1-100cm/s) OK / FALSE
speed? 現在の設定速度を取得 1-100cm/s
battery? 現在の充電量を取得 0-100%
time? 現在の飛行時間を取得 xx

Telloへのコマンド送信には、UDPのポート8889を使用します。今回使用するコマンドは、command、takeoff、landの3つです。
ドキュメントでレスポンスが OK / FALSE となっていても、実際には ERROR や error が返されることがあります。

サンプルプログラム
今回作成したプログラムは以下の通りです。GitHubでMITライセンスで公開しています。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import threading 
import socket
import time
import sys
from PyQt5.QtWidgets import *

class TelloController1(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self.initConnection()
        self.initUI()

    # 通信の設定
    def initConnection(self):
        host = ''
        port = 9000
        locaddr = (host,port) 
        self.tello = ('192.168.10.1', 8889)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(locaddr)

        # 受信スレッド起動
        recvThread = threading.Thread(target=self.recvSocket)
        recvThread.setDaemon(True)
        recvThread.start()

        # 最初にcommandコマンドを送信
        try:
            sent = self.sock.sendto('command'.encode(encoding="utf-8"), self.tello)
        except:
            pass

    # UIの作成
    def initUI(self):
        self.label = QLabel('')
        self.label.setFrameStyle(QFrame.Box | QFrame.Plain)

        # 終了ボタン
        endBtn = QPushButton("End")
        endBtn.clicked.connect(self.endBtnClicked)

        # 離着陸ボタン
        takeoffBtn = QPushButton("Takeoff")
        takeoffBtn.clicked.connect(self.takeoffBtnClicked)
        landBtn = QPushButton("Land")
        landBtn.clicked.connect(self.landBtnClicked)

        # ボタンのレイアウト
        layout = QGridLayout()
        layout.addWidget(self.label,0,0)
        layout.addWidget(endBtn,0,1)
        layout.addWidget(takeoffBtn,1,0)
        layout.addWidget(landBtn,1,1)
        self.setLayout(layout)

    # 終了処理
    def endBtnClicked(self):
        sys.exit()

    # takeoffコマンド送信
    def takeoffBtnClicked(self):
        try:
            sent = self.sock.sendto('takeoff'.encode(encoding="utf-8"), self.tello)
        except:
            pass

    # landコマンド送信
    def landBtnClicked(self):
        try:
            sent = self.sock.sendto('land'.encode(encoding="utf-8"), self.tello)
        except:
            pass

    # Telloからのレスポンス受信
    def recvSocket(self):
        while True: 
            try:
                data, server = self.sock.recvfrom(1518)
                self.label.setText(data.decode(encoding="utf-8"))
            except:
                pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = TelloController1()
    window.show()
    sys.exit(app.exec_())

Android端末にPython環境を構築
Pythonで開発したプログラムをAndroid端末で動作させるために、Pydroid 3を使用します。

Pydroid 3をインストールして起動すると、以下のような画面が表示されます。

次に、Pythonの拡張ライブラリをインストールします。
左上の「≡」をタップしてメニューを表示させます。

メニューにある「Pip」をタップします。

リストにある「PyQt5」の「INSTALL」ボタンをタップしてインストールします。「PyQt」は、GUIツールキット「Qt」をPython言語で使用するためのものです。

Pythonプログラムの起動と追加インストール
TelloにWiFi接続し、Pydroidの画面上部にあるフォルダのアイコンをタップしてメニューを表示させます。

「Open」をタップし、端末にコピーしておいたPythonプログラムを開きます。

右下の実行ボタン「▶」をタップするとプログラムが起動しますが、初回の起動時には以下のような画面が表示されます。

MinistroはPyQtの実行環境として必要ですので、OKをタップします。

「インストール」をタップしてMinistroをインストールします。
正常に起動すると、以下のような画面が表示されます。

左上に「OK」と表示されているのは、Telloに最初に送信した「command」コマンドの実行結果です。Telloとの通信ができていないと、ここに何も表示されません。

あとは、「Takeoff」ボタンで離陸し、「land」ボタンで着陸します。「End」ボタンはプログラムを終了します。必ず、着陸してからプログラムを終了して下さい。飛行中に「Takeoff」ボタンをタップすると、「ERROR」と表示されます。

Pythonによるドローン「Tello」の制御 123