エラーの原因:Tello からステータスを得ることができない調査

DJITelloPy を使うとエラーになってしまい Tello の SDK モードにすら入ることができませんでした。
原因を究明したいです
エラーの内容
djitellopy/tello.py", line 547, in connect
raise TelloException('Did not receive a state packet from the Tello')
djitellopy.tello.TelloException: Did not receive a state packet from the Tello
L547 ですね・・・?
エラーの送出箇所
def connect(self, wait_for_state=True):
"""Enter SDK mode. Call this before any of the control functions.
"""
self.send_control_command("command")
if wait_for_state:
REPS = 20
for i in range(REPS):
if self.get_current_state():
t = i / REPS # in seconds
Tello.LOGGER.debug("'.connect()' received first state packet after {} seconds".format(t))
break
time.sleep(1 / REPS)
if not self.get_current_state():
raise TelloException('Did not receive a state packet from the Tello')
not self.get_current_state() で、Exception ということですね・・・。
self.get_current_state() を追っていくと「ポート番号:8890」のステータス取得にたどり着きます。
つまり、Tello からステータスを得られていないことになります。
wait_for_state を False に設定することで無視することも可能ですが、
default が True ということは、動くのが普通なのでしょう・・・。
もう少しシンプルなコードで確認する
Tello-Python/tello_state.py を使って、単純なステータス取得処理を実行してみます。
コードは少し手を入れます。
import socket
from time import sleep
- import curses
INTERVAL = 0.2
- def report(str):
- stdscr.addstr(0, 0, str)
- stdscr.refresh()
if __name__ == "__main__":
- stdscr = curses.initscr()
- curses.noecho()
- curses.cbreak()
local_ip = ''
local_port = 8890
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # socket for sending cmd
socket.bind((local_ip, local_port))
tello_ip = '192.168.10.1'
tello_port = 8889
tello_adderss = (tello_ip, tello_port)
socket.sendto('command'.encode('utf-8'), tello_adderss)
try:
index = 0
while True:
index += 1
+ print('[START] recvfrom')
response, ip = socket.recvfrom(1024)
+ print('[END] recvfrom:', response)
+ response = response.decode('utf-8')
if response == 'ok':
continue
out = response.replace(';', ';\n')
out = 'Tello State:\n' + out
report(out)
sleep(INTERVAL)
except KeyboardInterrupt:
- curses.echo()
- curses.nocbreak()
- curses.endwin()
+ pass
curses がなんか上手く動かなかったので消しました。あとレスポンスは byte 文字列だったので decode しました。
実行してみます
$ python tello_state.py START: recvfrom END: recvfrom: b'ok' START: recvfrom
このまま停止してしまうようです
b'ok' しか返ってこないとなると djitellopy/tello.py#L211-L212 に入ることになるので not {} == True により、エラーということですね・・・。十中八九このステータス取得が上手くいかないことが原因ですね・・・。
別の環境でやってみる
現在、以下の環境で試しています。
- ホストマシン:Windows
- ゲストマシン:Ubuntu 20.04 on VirtualBox
Mac でやってみる
$ python tello_state.py [START] recvfrom [END] recvfrom: b'ok' [START] recvfrom [END] recvfrom: b'pitch:0;roll:0;yaw:0;vgx:0;vgy:0;vgz:0;templ:48;temph:50;tof:10;h:0;bat:55;baro:-14.23;time:0;agx:-2.00;agy:-13.00;agz:-998.00;\r\n' [START] recvfrom [END] recvfrom: b'pitch:0;roll:0;yaw:0;vgx:0;vgy:0;vgz:0;templ:48;temph:50;tof:10;h:0;bat:55;baro:-14.28;time:0;agx:-1.00;agy:-12.00;agz:-999.00;\r\n' [START] recvfrom [END] recvfrom: b'pitch:0;roll:0;yaw:0;vgx:0;vgy:0;vgz:0;templ:48;temph:50;tof:10;h:0;bat:54;baro:-14.06;time:0;agx:0.00;agy:-11.00;agz:-1001.00;\r\n'
完璧やん・・・
Mac で DJITelloPy を使ってみる
import cv2 from djitellopy import Tello tello = Tello() tello.connect() tello.query_battery()
% python app.py [INFO] tello.py - 129 - Tello instance was initialized. Host: '192.168.10.1'. Port: '8889'. [INFO] tello.py - 438 - Send command: 'command' [INFO] tello.py - 462 - Response command: 'ok' [INFO] tello.py - 438 - Send command: 'battery?' [INFO] tello.py - 462 - Response battery?: '50'
完璧やん・・・