前回の記事では、Pythonのインストールを行いました。今回は、そのPythonでドローンをプログラミングを行っていきます。
Pythonのインストールがまだの方は前回の記事を参考にしてください。
合わせて読みたい

この記事の目次

結論

結論としては、このコードで無事飛ばすことができました。

 

#UDPの確立
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#コマンド実行
socket.sendto(“takeoff”.encode(encoding=’utf-8′),(“192.168.10.1”, 8889))
socket.sendto(“land”.encode(encoding=’utf-8′),(“192.168.10.1”, 8889))

Pythonを使ってみる

いきなりドローンを始める前にPythonの基本的な使い方から学んでいきましょう。私もPythonを初めて間もないので、初心者にとってはプログラミングというのは、しきいが高いですよね。

バージョン確認

前回の記事でPythonをインストールしたため、Pythonがインストールされているか確認しましょう。コマンドプロンプトを立ち上げてPythonのバージョンを確認します。以下のコマンドを実行して下さい。Pythonのバージョンが表示されているのがわかると思います。

python –version
python -V

python -v
とコマンドを打つとどうでしょうか?このように、よくわからない文字の羅列が表示されると思います。
私が一番最初に困惑したのが、コレでした。小文字の-vだとこういう表示になり、これはこれで正しい表示です。バージョンを確認する際は、大文字で-Vとしましょう。

ファイル作成

次にPythonを実行するためのハコを作ってあげる必要があります。エクスプローラーを立ち上げて、任意の場所に空のファイルを作成します。

test.py

拡張子は「.py」で作成します。

プログラムを書く

先ほど作成したtest.pyをメモ帳で開き、プログラムを入力します。
なんでもいいですが、print(“任意の文字”)で記載して、上書き保存をします。今回はI like DRONEと記載しました。

プログラム実行

先ほど作成したプログラムファイルの場所まで移動します。私はDドライブにPythonというフォルダを作成し、その中に入れました。

コマンドプロンプトを立ち上げたら、

cd d:
cd Python
python test.py

実行結果に先ほど入力した”I like DRONE”が表示されました。これでクリアです。

  • 拡張子を.pyとしてファイル作成
  • .pyファイルにプログラムを記載
  • コマンドプロンプトでプログラム実行

プログラム

少しだけ知識を得る

少し初心者には難しくなってきます。ドローンと接続するための準備を行います。具体的なプログラムの前に、”ソケット通信”というものを理解する必要がありそうです。
タイトルに”少しだけ知識を得る”と書きましたが、今回の最終目標はドローンを飛ばすことです。Pythonでプログラムを組みますが、Pythonを理解してからやるのでは、時間がかかってしまうと思いました。
ドローンに関する部分をまずは習得し、そこからPythonに興味を持てば、そこから広げていこうと思います。
まずは、動かしてみましょう。

ソケット通信とは

ソケット通信とは、サーバー(ドローン)とクライアント(PC)間でネットワーク経由でデータの送受信を行う通信のこととの事。このソケット通信では、IPアドレスとポート番号を指定して、データの送受信を行います。

  • ドローンとPCでソケット通信を確立
  • ドローンのIPアドレスは「192.168.0.5」でポートは「8890」で通信しよう。
  • 通信が確立されたら、クライアントからサーバーに命令を出す。
  • コマンドでテイクオフを送る→サーバーが命令を受け取り実行する

ざっくりと、このようなやりとりをしていきます。



どうやってプログラム書くのか

一体どうやってプログラムを作っていけばよいのでしょうか?Pythonはドローンだけのためのプログラムではないため、どうやってドローンに命令したらよいのか分かりませんよね。私も最初全くわからずでした。

まずはTelloの公式ホームページを確認していきましょう。また英語ばかりのドキュメントで恐怖です。

ドキュメント確認

Telloのサイトへ行きましょう。みんな大好きな英語の時間です。私は英語が大の苦手なので、全力でGoogle翻訳してなんとか理解していきます。
上段のTello EDUからダウンロードをクリックし、左側メニュー内にSDK2.0 User Guideというドキュメントがありますので、クリックして下さい。ここから英語の世界に入ります。

Telloサイトより引用

ドキュメントを開いて、とりあえずコピーしてGoogle翻訳にかけていこうと思います。

まじか。。。。

コピーが許可されていないドキュメントでした。。最悪です。悪夢です。重要そうな単語だけをとりあえずメモしていきます。間違っているかもしれませんので、ご自身で確認してみてください。

Telloサイトより引用

私が読めたのは・・・・

  • WiFiでTelloとPCやMac、モバイル端末と接続しろ。
  • TelloのIPアドレスは192.168.10.1 UDP Port8889でPCと接続しろ
  • Step1. PCでUDPクライアントをセットまたはモバイル端末でなんちゃら(わからん)
  • Step2.コマンドを”command”でUDPポート8889から流せ?
  • Step3.何言ってるのかわけわからん
  • Step4. UDPサーバーをPCでセットして、IPは0.0.0.0でUDP Portは11111?
  • Step5.telloに”streamon”をUDP8889ポートで流して、なんちゃら

まじで何言ってるのかわからないけど・・・・後半はコマンド一覧が載ってました。

  • takeoff 離陸
  • land 着陸
  • streamon ビデオストリームをON
  • emergency モーターストップ
  • up/down/left/right/back x xセンチ上昇
  • cw x x度時計回りに回転
  • ccw x度反時計回りに回転
  • もっとたくさんある

初学者には難しいです。

とりあえずTelloとPCはWiFiでUDP通信をして、コマンドを実行すれば動くことがわかりました。

ファイル作成

まずは先ほどと同じように、今回のプログラムのハコを作っていきましょう。すでにTelloをPythonで動かすプログラムがサイトによっては載っていますが、極力確認せずあまり答えを見ないでにやってみるとします。
※私のやり方でもTelloを最終的に動かす事はできましたが、きれいなコードではないと思います。

フォルダに「tello.py」を作成しました。



UDP通信の設定

早速分からないので、ググることに。もちのき研究所さんの記事を参考にさせて頂きました。

UDPの確立はこう書くようです。IPアドレスとポート番号はTellのドキュメント通りにしました。これでStep1は完了なのか!?

コマンド

Telloに流すコマンドを書いていきます。最初は簡単に、離陸して着陸するというプログラムにしていきます。離陸→50cm上昇→着陸

離陸:takeoff

50cm:up 50

着陸:land

・・・・え?これって、このまま書けばいいわけじゃないよね?と思ったので、ドキュメントを再度確認してみることに。英語なので相当ストレスです。

これは、Telloというより、Pythonのコマンドの書き方のようなので、またググって探すことに。

ソケット通信の設定

UDP通信の設定でさらっと流してしまったが、もう少し理解を深める必要がありそうなので、DelftStackさんの記事を参考にさせて頂いた。

import socket
Pythonはソケットプログラミングを実装するためのsocketモジュールがあり、ソケットを使用する場合は、import socketと書いてやる。

HOST NAME
説明するまでもないが、ホストのアドレス

PORT
使用するUDPポート

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ソケットの作成には上記コードが必要なようです。

前半のsocket.xxxx
xxxxには、以下のようなものを指定するみたい。今回はIPV4なのでAF_INETでよさそう。

  • AF_INET:IPV4プロトコル
  • AF_INET6:IPV6プロトコル
  • AF_UNIX:ローカル通信用プロトコル

後半のsocket.xxxx
xxxxには、以下のようなものを指定するみたい。今回はUDPなのでSOCK_DGRAMでよさそう。

  • SOCK_STREAM:TCP
  • SOCK_DGRAM:UDP

ということで、

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

がなんとなく理解できました。

ここまでのプログラムとしては、

#UDPの確立
import socket
HOST_NAME = ‘192.168.10.1’
PORT = 8889#Scoketの設定
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

までできました。

次に実際にSocketにコマンドを流す方法を調べてみました。

コマンドの流す方法

ここからは、TelloのSDKに指示に従う感じだと思います。やっぱりドキュメントを読まないと分からないため、手打ちで翻訳しました。

Step1.

Set up a UDP client on the PC,Mac, or mobile device to send and reveive messages from the Tello via the same port.

PC、Mac、またはモバイルデバイスでUDPクライアントを設定して、同じポートを介してTelloからメッセージを送受信します。

Step2.

Before sending any other commands,send”command” to the Tello via UDP PORT 8889 to initiate SDK mode.

他のコマンドを送信する前に、UDPポート8889を介してTelloに「command」を送信してSDKモードを開始します。

Step3.

Set up a UDP server on the PC,Mac, or mobile device and check the message from IP 0.0.0.0 via UDP PORT 8890.Steps 1 and 2 must be completed before attempting step 3.For more details,refer to the Tello State section.

PC、Mac、またはモバイルデバイスにUDPサーバーをセットアップし、UDPポート8890を介してIP 0.0.0.0からのメッセージを確認します。手順3を実行する前に、手順1と2を完了する必要があります。詳細については、「TelloState」セクションを参照してください。

Step4.

Set up a UDP server on the PC,Mac, or mobile device and check the message from IP 0.0.0.0 via UDP PORT 11111.

PC、Mac、またはモバイルデバイスにUDPサーバーをセットアップし、UDPポート11111を介してIP0.0.0.0からのメッセージを確認します。

Step5.

Send “steamon” to the Tello via UDP PORT 88889 to start streaming.Steps 1 and 2 must be completed before attempting step 5.

「steamon」をUDPポート88889経由でTelloに送信して、ストリーミングを開始します。ステップ5を実行する前に、ステップ1と2を完了する必要があります。

なんとなくは理解できますが、初心者の私にとってはかなりハードルが高いです。まずここまでで、Step1は完了しています。

#UDPの確立
import socket
HOST_NAME = ‘192.168.10.1’
PORT = 8889#Scoketの設定
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

次にStep2の部分をやっつける必要がありそうです。

UDPポート8889を介してTelloに「command」を送信してSDKモードを開始します。

これはいったいどうしろと??単純に文字列の「command」をTelloに投げればいいのか?とりあえずその認識でプログラムに追記。

#UDPの確立
import socket
HOST_NAME = ‘192.168.10.1’
PORT = 8889
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#commandの送信
“command”

仮ではあるが、Step2までは完了した。次にStep3へ移る。

PC、Mac、またはモバイルデバイスにUDPサーバーをセットアップし、UDPポート8890を介してIP 0.0.0.0からのメッセージを確認します。手順3を実行する前に、手順1と2を完了する必要があります。詳細については、「TelloState」セクションを参照してください。

色々書いてあるぞ。まずは、PCにUDPサーバーをセットアップとはどういう方法でできるのか調べてみた。

OFFICE54さんのサイトを参考にさせて頂いた。

冒頭に、「Pythonでサーバーにデータを送信する方法」と書いてあり、「きたー」って感じでした。このサイトにたどり着くまでだいぶ時間がかかりました。

クライアントとサーバについて、今回のTelloの場合は、

Tello:サーバ
PC:クライアント

になり、クライアントから命令は出すけど、Telloからデータを受け取る必要はないはず。(サイトにレシーブの解説も書いてありましたので、頭の中で整理しました)

sendtoメソッド

OFFICE54さんのサイトからの引用です。

sendto()メソッドはソケットにデータを送信するために使用します。

socket.sendto(bytes, address)

bytesにはバイト型のデータを指定します。
データがstring型の場合はencode()メソッドでバイトに変換する必要がある。

addressにはタプルでIPアドレスとポート番号を指定します。

サーバー側は常にコネクト状態(待機状態)である必要がなく、UDPソケットへの通信時にsendtoメソッドは使用されます。

そう、ソケットにデータを送信したかったのです。

今回はtakeoffやlandなど文字列を送るので、string型になるという事ですね。

string型の場合はencode()メソッドでバイトに変換する必要がある。
↑encodeメソッドとは何だろう・・・

encodeメソッド

このメソッドについては、こちらのサイトを参考にさせて頂きました。

encoding=’utf-8′

こういう事のようです。つまり、

socket.sendto(“takeoff”.encoding=’utf-8′,192,168.10.1)
socket.sendto(“land”.encoding=’utf-8′,192,168.10.1)

でいいのかな。仮で追加してみよう。

#UDPの確立
import socket
HOST_NAME = ‘192.168.10.1’
PORT = 8889
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#commandの送信
“command”#コマンド実行
socket.sendto(“takeoff”.encoding=’utf-8′,192,168.10.1)
socket.sendto(“land”.encoding=’utf-8′,192,168.10.1)

テストフライト

Step3以降のことは考慮できていないですが、この段階で動作するか確認してみます。

  1. PCをWiFiに切り替えます
  2. Telloの電源を入れ、PCからTelloへWiFi接続します
  3. PCからtello.pyを実行します

残念ながらエラーとなって動作はしませんでした。

書き方が正しくないようです。他のサイトでもサンプルをみたりしましたが、少し変更してみました。

#UDPの確立
import socket
HOST_NAME = ‘192.168.10.1’
PORT = 8889
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#commandの送信
“command”#コマンド実行
socket.sendto(“takeoff”.encode(encoding=’utf-8′),192.168.10.1)
socket.sendto(“land”.encode(encoding=’utf-8′),192.168.10.1)

結果は・・・・

ダメでした。アドレスの指定が間違っているようです。

#UDPの確立
import socket
HOST_NAME = ‘192.168.10.1’
PORT = 8889
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#commandの送信
“command”#コマンド実行
socket.sendto(“takeoff”.encode(encoding=’utf-8′),”192.168.10.1″)
socket.sendto(“land”.encode(encoding=’utf-8′),”192.168.10.1″)

これもダメ・・・・色々な行をコメントアウトしたりしながら、最終的にはこれで起動できました。

このコードで動いた

#UDPの確立
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#コマンド実行
socket.sendto(“takeoff”.encode(encoding=’utf-8′),(“192.168.10.1”, 8889))
socket.sendto(“land”.encode(encoding=’utf-8′),(“192.168.10.1”, 8889))

色々となぜ???と思う部分はありますので、まだまだ勉強ですね。

ScratchでのTelloは以下を参考にして下さい。

合わせて読みたい