1
1

More than 3 years have passed since last update.

Telloプログラミング:data, server = sock.recvfrom(1518)のdataの中身を覗いてみた

Last updated at Posted at 2021-07-28

Telloプログラミングの中で、TelloとMacbookとの通信経路を確立する部分の定番コードは、次のようなものです。

data, server = sock.recvfrom(1518)

ここで、返り値を受け止めるdata変数に、どのような値が入るのか、興味を持ちました。
この変数の中身を、Terminalに出力して確認してみました。

前回の記事を改良してみました。ソースコードの全体は、この記事の最後に掲載してあります。

コード改編部分

以下を追加(2021/7/28)
dataはバイト列(例:b'\x 16指数表記データ')だから、str型に変換するにはdecodeが必要
received_data = data.decode('utf-8')
print("Telloからの返り値: " + received_data)

コード該当箇所1
def recv():
    count = 0
    while True: 
        try:
            data, server = sock.recvfrom(1518)
            #以下を追加(2021/7/28)
            #dataはバイト列(例:b'\x 16指数表記データ')だから、str型に変換するにはdecodeが必要
            received_data = data.decode('utf-8')
            print("Telloからの返り値: " + received_data)
        except Exception:
            print ('\nExit . . .\n')
            break

#recvThread create
recvThread = threading.Thread(target=recv)
recvThread.start()

以下の2つが入り乱れてTerminalに表示されないように、time.sleep(1)を間にはさむ。

  • 操作コマンドの入力待ち受けプロンプト(の表示)
  • 前の指令コマンドの返り値(の表示)

前に入力したコマンドに対するTelloからの返り値をprint出力するrecv()メソッドの処理が終わるまで、2秒待機する
time.sleep(2)

コード該当箇所2
while True: 
    # 最初に入力が必要な"command"命令は、ユーザが打ち込まなくて良いようにスクリプト側でTelloに送出する
    msg = str("command").encode(encoding="utf-8") 
    sent = sock.sendto(msg, tello_address)
    # "takeoff"以降の命令をユーザ入力から受け取る
    try:
    # 前に入力したコマンドに対するTelloからの返り値をprint出力するrecv()メソッドの処理が終わるまで、2秒待機する
        time.sleep(2)
        msg = input("Telloに送る指示コマンドを入力してください。:  ")
        if not msg:
            break  

検証画面と、その結果分かったこと

送出した操作コマンドと対応する返り値

  • Tello SDKで定義されている正しい操作コマンド:「OK」という返り値が戻される
  • 未定義の操作コマンド (引数のみが未定義の場合を含む): 「unknown command」という返り値が戻される
  • (同上) :「out of range」という返り値が戻される

その他

  • 「error No valid imu」という返り値が戻される
Terminal
electron@diynoMacBook-Pro Tello % python3 tello_python_rev2.py
Telloからの返り値: ok
Telloに送る指示コマンドを入力してください。:  takeoff
Telloからの返り値: ok
kefTelloに送る指示コマンドを入力してください。:  t 50
Telloからの返り値: unknown command: keft
Telloからの返り値: ok
Telloに送る指示コマンドを入力してください。:  Telloからの返り値: ok
right 50
Telloからの返り値: ok
Telloからの返り値: ok
Telloに送る指示コマンドを入力してください。:  up 100
Telloからの返り値: ok
Telloからの返り値: error No valid imu
Telloに送る指示コマンドを入力してください。:  up x
Telloからの返り値: out of range
Telloからの返り値: ok
Telloに送る指示コマンドを入力してください。:  upp
Telloからの返り値: unknown command: upp
Telloからの返り値: ok
Telloに送る指示コマンドを入力してください。:  upppppp
Telloからの返り値: unknown command: upppppp
Telloからの返り値: ok
Telloに送る指示コマンドを入力してください。:  ^C  
Exit . . .

electron@diynoMacBook-Pro Tello % 

ソースコード全文

tello_python_rev2.py
import threading 
import socket
import sys
import time

host = ''
port = 9000
locaddr = (host, port) 

# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tello_address = ('192.168.10.1', 8889)

sock.bind(locaddr)

def recv():
    count = 0
    while True: 
        try:
            data, server = sock.recvfrom(1518)
            #以下を追加(2021/7/28)
            #dataはバイト列(例:b'\x 16指数表記データ')だから、str型に変換するにはdecodeが必要
            received_data = data.decode('utf-8')
            print("Telloからの返り値: " + received_data)
        except Exception:
            print ('\nExit . . .\n')
            break

#recvThread create
recvThread = threading.Thread(target=recv)
recvThread.start()

while True: 
    # 最初に入力が必要な"command"命令は、ユーザが打ち込まなくて良いようにスクリプト側でTelloに送出する
    msg = str("command").encode(encoding="utf-8") 
    sent = sock.sendto(msg, tello_address)
    # "takeoff"以降の命令をユーザ入力から受け取る
    try:
    # 前に入力したコマンドに対するTelloからの返り値をprint出力するrecv()メソッドの処理が終わるまで、2秒待機する
        time.sleep(2)
        msg = input("Telloに送る指示コマンドを入力してください。:  ")
        if not msg:
            break  

        # Send data
        # Tello SDK v2.0 https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf
        if msg == "land":
            order_command = "battery?"
            battery_volume = sock.sendto(order_command.encode(encoding="utf-8") , tello_address)
            order_command = "time?"
            flight_time = sock.sendto(order_command.encode(encoding="utf-8") , tello_address)            
            print("着陸します。")
            message = "累積飛行時間: {0} \nバッテリ残量(%): {1}".format(str(flight_time), str(battery_volume))
            print(message)
            sock.close()  
            break
        elif msg == "battery?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("バッテリ残量(%): " + str(sent))
        elif msg == "speed?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("現在の速度: " + str(sent))
        elif msg == "time?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("累積飛行時間: " + str(sent))
        elif msg == "sdk?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("この機体のSDK Ver.: " + str(sent))
        elif msg == "sn?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("この機体のシリアル番号: " + str(sent))
        else:
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)

    except KeyboardInterrupt:
        sock.close()  
        break

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1