スクラッチくらぶ上級編ーTello-Drone

Ryze Tech製のドローン(TELLO)とGameSir製のコントローラを購入しました。

Ryze Tech製のドローン(TELLO) BOOST COMBOセットとGameSir製のコントローラ(T1d)がAmazonから届きました。Raspberry Piと「Python」の組み合わせでプログラミングが出来ます。コントローラはandroid製スマホとWi-Fiとセットで動作します。これから勉強しながらドローンを有効に動かして行こうと思います。

★★★★★ ★★★★★ ★★★★★

Ryze Tech社のHPは、https://www.ryzerobotics.com/jp
GameSir社のコントローラ(T1d)のHPは、https://www.gamesir.hk/pages/tello-tutorial-jp

★★★★★ ★★★★★ ★★★★★

1. Telloの仕様

①. Telloの性能

  1. 最大飛行距離:100m
  2. 最大速度:8m/秒
  3. 最大飛行時間:13分
  4. 最大飛行高度:30m(2020/07/30時点)
  5. 重量:88g(バッテリー、プロペラ、プロペラガード含む)
  6. バッテリー:1.1Ah/3.8V
  7. カメラ:Photo: 5MP (2592×1936) JPG、Video: HD720P30 MP4

★★★★★ ★★★★★ ★★★★★

②. TelloのWi-Fiのアクセスポイント

■Send Command & Receive Response
IPアドレス:192.168.0.10  UDPポート番号:8889

■Receive Tello State
IPアドレス:192.168.10.1  Host Serverアドレス:0.0.0.0  UDPポート番号:8890

■Receive Tello Video Stream
IPアドレス:192.168.10.1  Host Serverアドレス:0.0.0.0  UDPポート番号:1111

③. TelloのAPI(Application Program Interface)

2020年08月時点の最新版: Tello-SDK-2.0-User-Guideダウンロード

★★★★★ ★★★★★ ★★★★★

Tello-SDK-1.0-User-Guide

コマンド意 味応 答
commandコマンドモード開始OKまたはFALSE
takeoff自動離陸OKまたはFALSE
land自動着陸OKまたはFALSE
up xx上昇(xxは20〜500、cmで指定)OKまたはFALSE
down xx下降(xxは20〜500、cmで指定)OKまたはFALSE
left xx左移動(xxは20〜500、cmで指定)OKまたはFALSE
right xx右移動(xxは20〜500、cmで指定)OKまたはFALSE
forward xx前進(xxは20〜500、cmで指定)OKまたはFALSE
back xx後退(xxは20〜500、cmで指定)OKまたはFALSE
ccw xx左回転(xxは1-3600度)OKまたはFALSE
cw xx右回転(xxは1-3600度)OKまたはFALSE
flip xアクロバット(空中で縦方向に一回転します)
l(左)、r(右)、f(前)、b(後)、bl(後左)、br(後右)、fl(前左)、fr(前右)
OKまたはFALSE
speed xx移動速度を設定(xxは1-100、cm/秒)OKまたはFALSE
Speed?現在の速度を取得xx
Battery?現在のバッテリー残量を取得xx(0-100%)
Time?現在までの飛行時間を取得xx

API 1.3以降では15秒以上何も指示を出さない場合には自動で着陸します。このため上空に待機した状態で15秒以上放置しておくと自動着陸しますので注意してください。

★★★★★ ★★★★★ ★★★★★

2. Telloのプログラミング

Tello本体そのものにはプログラムをする機能も,プログラムを書き込むメモリ領域もありません。

Telloはいわば「知能を持たない移動端末」で,知能的な計算をしているのは母艦PCです。

  1. Telloのカメラ映像やセンサーデータをPC(通称:母艦)で受け取る
  2. 母艦PCで画像処理やデータ処理をしてTelloの動き方を計算する
  3. Tello SDKに基づいてTelloへコマンドを送信する
  4. Telloが動く
  5. 1へ戻って繰り返す

★★★★★ ★★★★★ ★★★★★

3. Tello機体状態のLED表示

Telloの機体前部、カメラ横のLEDは、その点灯状態によって、次のような状態を表しています。

パターン 状  態
動作状態 赤.緑.黄 点滅で色の繰り返し 機体が自己診断
2回点滅の繰り返し ビジョンセンサーが動作中
ゆっくり点滅 ビジョンセンサーが無効
充電状態 点 灯 充電完了
ゆっくり点滅 充電中
高速点滅 充電異常
警告状態 高速点滅 スマホとの接続が切れた、または未接続
ゆっくり点滅 バッテリー残量低下
高速点滅 バッテリー残量不足
点 灯 重大なエラー

★★★★★ ★★★★★ ★★★★★

手順については色々な書籍や先人達のHPを参考にしたいと思いますが、過去の古いものから最新?と思われるものまであり、どれを参考にすれば良いのかさっぱり分かりません。行き当たりばったりでTRYして行きますので、無駄な行為や間違った行為があるかと思いますが、お許しください。

①.参考1としては、Ryze(DJI) Tello をScratchやPythonで制御する Scratchでトイドローンをプログラミングして飛ばそう! https://tsq.gapj.net/index.php/tello/
Takao Takahashi 氏のHPを参照

②.参考2としては、書籍「Scratchでトイドローンをプログラミングして飛ばそう」高橋 隆雄 著 秀和システム ISBN978-4-7980-5519-0 C3055

③.参考3としては、書籍「空飛ぶプログラム」株式会社ドローンエモーション 著 C&R研究所 ISBN978-4-86354-300-3 C3055

★★★★★ ★★★★★ ★★★★★

■ Tello スマホ専用アプリでtelloを動かそう!

Android OS の場合、スマホ専用アプリケーションは、下図のQRコードを読み込むことでインストールすることが出来ます。

①. スマホ専用アプリ起動画面

「Telloに接続」をタップするか、あるいはスマホのWi-Fi設定を開きます。Wi-Fiのアクセスポイント一覧に、「TELLO-xxxx」がありますので、これに接続します。

②. コントロール画面

接続が完了すると、画面中央上にバッテリー状態と電波状態を示すアイコンがあり、Telloからの映像がスマホに表示されます。

操作アイコン
その意味
Take off and land離着陸操作
Flight modes飛行モード
Settingsアプリの設定
Playback再生
Switch between photo and video mode静止画と動画の撮影切り替え
Take pictures or start / stop recording静止画撮影あるいは動画撮影の開始/停止

スマホ専用アプリの操作方法は、書籍「Scratchでトイドローンをプログラミングして飛ばそう」高橋 隆雄 著 秀和システム ISBN978-4-7980-5519-0 C3055 を参照してください。

スマホ専用アプリの操作方法は、書籍「空飛ぶプログラム」株式会社ドローンエモーション 著 C&R研究所 ISBN978-4-86354-300-3 C3055 を参照してください。

★★★★★ ★★★★★ ★★★★★

★★★★★ ★★★★★ ★★★★★

★★★★★ ★★★★★ ★★★★★

★★★★★ ★★★★★ ★★★★★

■ GameSir製のコントローラ(T1d)でtelloを動かそう!

GameSir社のコントローラ(T1d)のHPは、https://www.gamesir.hk/pages/tello-tutorial-jpです。

動作説明
意 味
ボタン操作
Take off / Land自動離陸 / 自動着陸R2+Y
Flips Forward前縦方向1回転L2+Up
Flips Back後縦方向1回転L2+Down
Flips Left左縦方向1回転L2+Left
Flips Right右縦方向1回転L2+Right
Take Photo静止画撮影R1
Record video動画撮影L1

GameSir-T1d コントローラー日本語取扱説明書

ファームウェアアップグレード GameSir-T1d Firmware Upgrade tool

★★★★★ ★★★★★ ★★★★★

Japanese Ver. チュートリアル:Tello(ドローン)送信機とペアリングのステップ (GameSir-T1dコントローラー対応)

GameSir社製 T1dはTello専用コントローラで、Wi-Fiによるスマホ専用アプリケーションと連動して飛行制御します。

Tello(ドローン)送信機のペアリング手順

①.Telloアプリをインストールしてください。Telloアプリのファームウェアバージョンを最新版に更新してください。「設定>詳細設定>ファームウェアバージョン>更新」

②.デバイスのBluetoothをオンにしてください 。「設定>接続済みの端末>Bluetooth」

③.powerボタンを2秒押してゲームパッドを起動してください。

④.インジケータライトが点滅になります。

⑤.Telloアプリで「Bluetoothコントローラー設定」では、「Gamesir-T1d-XXXX」が表示されます。

⑥.「Gamesir-T1d-XXXX」をドラックして、ペアリングしてください。

⑦.インジケータライトが点灯になると、ペアリング成功です。

※ご注意:ペアリング失敗の場合は「②~⑦」を繰り返して、やってみてください。

★★★★★ ★★★★★ ★★★★★

■ Raspberry Piから「Python」でtelloを動かそう!

母艦PCは、Raspberry Pi 3 Model Bを使用します。OSは「Raspbian Full」とします。

Raspberry Pi(ラズベリーパイ)は、イギリスのラズベリーパイ財団で開発された教育用のマイコンボードです。※ Raspberry Pi は ラズベリーパイ財団 の登録商標です。

★★★★★ ★★★★★ ★★★★★

Pythonのスクリプトをダウンロード

Ryze(DJI) Tello をScratchやPythonで制御する Scratchでトイドローンをプログラミングして飛ばそう! https://tsq.gapj.net/index.php/tello/
Takao Takahashi 氏のHPからPythonサンプルプログラムをダウンロードします。

場周飛行させるプログラム fly_circle.py をダウンロード

半径と多角形数を指定してTelloを場周飛行させます。fly_circle.zip をダウンロードしておきます。この後、⑧で実行します。よろしくお願いします。

■「Thonny Python IDE」 を使う

「プログラミング」の中の「Thonny Python IDE」を起動します。

①. 離陸のプログラム takeoff.py

離陸してホバリングします。

import socket

tello_ip = "192.168.10.1"
tello_port = 8889

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto("command", (tello_ip, tello_port))
sock.sendto("takeoff", (tello_ip, tello_port))

②. 着陸のプログラム land.py

着陸します。

import socket

tello_ip = "192.168.10.1"
tello_port = 8889

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto("land", (tello_ip, tello_port))

③. 反時計まわり1回転のプログラム ccw.py

反時計まわりに360度回転します。

import socket

tello_ip = "192.168.10.1"
tello_port = 8889

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto("ccw 360", (tello_ip, tello_port))

④. 離陸&時計まわり1回転のプログラム sample.py

離陸して360度回転して着陸します。

import socket
from time import sleep

tello_ip = "192.168.10.1"
tello_port = 8889

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.sendto("command", (tello_ip, tello_port))
sock.sendto("takeoff", (tello_ip, tello_port))

sleep(5)

sock.sendto("ccw 360", (tello_ip, tello_port))

sleep(10)

sock.sendto("land", (tello_ip, tello_port))

⑤. フライト中に応答を確認するプログラム sample2.py

離陸して上昇して右移動して左移動して反時計まわり1回転して着陸します。

import socket
import sys
from time import sleep

tello_ip = "192.168.10.1"
tello_port = 8889

my_ip = ""
my_port = 9000
my_addr = (my_ip, my_port)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(my_addr)

def recv():
    data, server = sock.recvfrom(1518)
    print(data.decode(encoding="utf-8"))

sock.sendto("command", (tello_ip, tello_port))
print('command')
recv()

sock.sendto("takeoff", (tello_ip, tello_port))
print('takeoff')
recv()

sleep(5)

sock.sendto("up 30", (tello_ip, tello_port))
print('up')
recv()

sleep(5)

sock.sendto("right 30", (tello_ip, tello_port))
print('right')
recv()

sleep(5)

sock.sendto("left 30", (tello_ip, tello_port))
print('left')
recv()

sleep(5)

sock.sendto("ccw 360", (tello_ip, tello_port))
print('ccw')
recv()

sleep(10)

sock.sendto("land", (tello_ip, tello_port))
print('land')
recv()

⑥. バッテリーの残量を確認するプログラム battery.py

バッテリーの残量(%)が分かります。

import socket
import sys
from time import sleep

tello_ip = "192.168.10.1"
tello_port = 8889

my_ip = ""
my_port = 9000
my_addr = (my_ip, my_port)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(my_addr)

def recv():
    data, server = sock.recvfrom(1518)
    print(data.decode(encoding="utf-8"))

sock.sendto("command", (tello_ip, tello_port))
print('command')
recv()

sock.sendto("battery?", (tello_ip, tello_port))
print('battery?')
recv()

⑦. フライト動作を設定するプログラム fly_tello.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import sys
from time import sleep

# Telloの飛行プログラムはここに書く
# Telloに送るコマンドを列挙する
# takeoffとlandはダミーで0を付ける

flight_data = [
     ["takeoff", "0"],
     ["right", "30"],
     ["left", "30"],
     ["cw", "360"],
     ["land", "0"]
]

# TelloのIPアドレスとポート
tello_ip = "192.168.10.1"
tello_port = 8889
tello_addr = (tello_ip, tello_port)
# 受信側のアドレスとポート(戻り)
my_ip = ""
my_port = 9000
my_addr = (my_ip, my_port)

# ソケット生成
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(my_addr)

# 受信処理関数
def recv():
    data, server = sock.recvfrom(1518)
    print(data.decode(encoding="utf-8"))

# 離陸処理
def do_takeoff():
    sock.sendto(b"command", tello_addr)
    recv()
    sock.sendto(b"takeoff", tello_addr)
    recv()
    sleep(10)

# 着陸処理
def do_land():
    sock.sendto(b"land", tello_addr)
    recv()

# 離陸以外の処理
def do_cmds(tello_cmd, tello_param):
    t_cmd = tello_cmd + ' ' + tello_param
    t_bytes = t_cmd.encode()
    sock.sendto(t_bytes, tello_addr)
    recv()

# メインループ
# リストから読み出して順次処理
for i in range(len(fright_data)):
    tello_cmd, tello_param = fright_data[i]
    
    #コマンドを表示
    print (tello_cmd, tello_param)
    #コマンド別に処理を実行
    #離陸
    if tello_cmd == 'takeoff' :
        do_takeoff()
    #着陸
    elif tello_cmd == 'land' :
        do_land()
    #それ以外
    elif tello_cmd in {"up", "down", "left", "right", "forward", "back", "cw", "ccw", "speed"}:
        do_cmds(tello_cmd, tello_param)
    #書かれたコマンドが間違い
    else :
        print ("No such command")

⑧. 場周飛行させるプログラム fly_circle.py

半径と多角形数を指定してTelloを場周飛行させます。fly_circle.zip

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import sys
from time import sleep
import math

# 円を多角形で近似してTelloを飛行させる
# 飛行計算用データ
# このデータを変更するだけで飛行します
# 飛行半径(cm)
radius = 50
# 多角形数
n_rect = 6
# 速度
t_speed = 60
# 旋回方向(cwかccw)
# 離陸位置に注意
t_dir = 'ccw'
# 飛行パラメータここまで
#

# 1箇所での旋回角度計算
fly_angle = 360 / n_rect
# 1飛行距離(1辺の長さ)計算
fly_leg = int(2 * radius * math.sin(math.pi/n_rect))

# TelloのIPアドレスとポート
tello_ip = "192.168.10.1"
tello_port = 8889
# 受信側のアドレスとポート(戻り)
my_ip = ""
my_port = 9000
my_addr = (my_ip, my_port)

# ソケット生成
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(my_addr)

# 受信処理関数
def recv():
    data, server = sock.recvfrom(1518)
    print(data.decode(encoding="utf-8"))

# 離陸処理
def do_takeoff():
    sock.sendto(b"command", (tello_ip, tello_port))
    recv()
    sock.sendto(b"takeoff", (tello_ip, tello_port))
    recv()
    sleep(10)

# 着陸処理
def do_land():
    sock.sendto(b"land", (tello_ip, tello_port))
    recv()

# 離陸以外の処理
def do_cmds(tello_cmd, tello_param):
    t_cmd = tello_cmd + ' ' + tello_param
    t_bytes = t_cmd.encode()
    sock.sendto(t_bytes, (tello_ip, tello_port))
    recv()

# メインの処理
print('Takeoff')
do_takeoff()
do_cmds('speed', str(t_speed))

for i in range(n_rect):
    print('Fly ' + str(fly_leg) + ' cm')
    do_cmds('forward', str(fly_leg))
    print('Rotate ' + t_dir + ' ' + str(fly_angle) + ' degree')
    do_cmds(t_dir, str(fly_angle))

sleep(5)
print('Land')
do_land()

★★★★★ ★★★★★ ★★★★★

★★★★★ ★★★★★ ★★★★★