[Python]telloEduで編隊飛行を行った際のカメラ映像の取得方法を教えてください。
質問内容
[Python]telloEduで編隊飛行を行った際のカメラ映像の取得方法を教えてください。
この質問は以下のサイトでマルチポストしています。
分かったこと、補足説明や解決方法はどちらのサイトも更新します。
https://teratail.com/questions/289372
UDPやIPアドレスについてあまり詳しくないため、間違っていましたらご指摘お願いします。
発生している問題
tellopyなどは使わず、TelloSDK2.0のコマンド送信によるプログラムを書いています。
TelloEdu1台での飛行時のカメラ映像は「command」の次に「streamon」とコマンドを送信したのち、OpecCVで
cap = cv2.VideoCapture('udp://0.0.0.0:11111')
ret,frame = cap.read()
cv2.imshow('',frame)
と書きtelloの映像を取得していました。1台の時はこの方法でPC画面に映像を表示させることに成功しました。
しかし、telloEDU3台の編隊飛行の際はこの方法では成功しません。実行画面ではstreamon OK まで進み、その後何も起こりません。3台使うことによりカメラのUDPが変わるなど、何か原因があると思うのですがそれが分かりません。
telloEDUの編隊飛行(前進、後退などの単純な動き)自体はうまくいっています。
補足説明
tello 1台のときは、tello自体がwifiアクセスポイントとなります。
telloのIPアドレス、ポート番号は公式通りに
('192.168.10.1',8889)
を使用しています。
映像受信時のUDPも公式通りに
('udp://0.0.0.0:11111')
を使用しています。
tello3台のときは
wifiルーターにtello3台とパソコンをつなげているため、IPアドレスが変わるため
ドローン1:('192.168.100.112',8889)
ドローン2:('192.168.100.113',8889)
ドローン3:('192.168.100.114',8889)
を使用しています。このIPアドレスはwifiにつなげた状態でパソコンでIPアドレススキャナーのアプリでスキャンして得ました。
映像受信時のUDPは1台の時と変わらず
('udp://0.0.0.0:11111')
を使用していますが、映像を取得できませんでした。「streamon」はきちんと送れているようなので、telloのIPアドレスは正しく、映像受信時のUDPが間違っているのではないかと考えています。
IPアドレスを変更するとUDPも変わるのでしょうか。変わるとしても、変更後の値が分かりません。そもそも編隊飛行ではカメラを使えないのでしょうか。
ご回答宜しくお願い致します。
試したこと
①
3台全てのTelloがPC側の同じUDPのアドレスに同時に映像を(ブロードキャストで)投げ込んでいるため、サーバであるPC側ではそれらが混在して正しく映像として結合できないことが問題かもしれないため、プロキシサーバでPC側で受けた映像をIPアドレスに応じて別のポートに投げ込むといいとアドバイスを頂きました。しかし、プロキシサーバーを起動した状態でもうまくいかず「stereamon OK」で止まりました。
②
wi-fiルーターにパソコンとドローン3台ではなく、1台のみ接続し試しました。
ドローン1:('192.168.100.112',8889)
('udp://0.0.0.0:11111')
で試しましたが、「streamon OK」で止まり、映像の取得はできませんでした。
つまり、混信以前のUDPなどが間違っていることになるのでしょうか。
#試したこと②
import socket
import threading
import time
import cv2
event = threading.Event()
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
sock.bind(('',9000))
tello1_address = ('192.168.100.112',8889)
def send_command1(msg):
print(msg)
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello1_address)
event.wait()
event.clear()
def send_command2(msg):
print(msg)
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello2_address)
event.wait()
event.clear()
def send_command3(msg):
print(msg)
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello3_address)
event.wait()
event.clear()
def send_command(msg):
print(msg,msg,msg, sep='\n', end='\n')
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello1_address)
sock.sendto(msg,tello2_address)
sock.sendto(msg,tello3_address)
event.wait()
event.clear()
def send_command12(msg1,msg2):
print(msg1,msg2, sep='\n', end='\n')
msg1 = msg1.encode(encoding="utf-8")
msg2 = msg2.encode(encoding="utf-8")
sock.sendto(msg1,tello1_address)
sock.sendto(msg2,tello2_address)
event.wait()
event.clear()
def send_command23(msg2,msg3):
print(msg2,msg3, sep='\n', end='\n')
msg2 = msg2.encode(encoding="utf-8")
msg3 = msg3.encode(encoding="utf-8")
sock.sendto(msg2,tello2_address)
sock.sendto(msg3,tello3_address)
event.wait()
event.clear()
def send_command13(msg1,msg3):
print(msg1,msg3, sep='\n', end='\n')
msg1 = msg1.encode(encoding="utf-8")
msg3 = msg3.encode(encoding="utf-8")
sock.sendto(msg1,tello1_address)
sock.sendto(msg3,tello3_address)
event.wait()
event.clear()
def send_command123(msg1,msg2,msg3):
print(msg1,msg2,msg3, sep='\n', end='\n')
msg1 = msg1.encode(encoding="utf-8")
msg2 = msg2.encode(encoding="utf-8")
msg3 = msg3.encode(encoding="utf-8")
sock.sendto(msg1,tello1_address)
sock.sendto(msg2,tello2_address)
sock.sendto(msg3,tello3_address)
event.wait()
event.clear()
def recv():
while True:
try:
data,server = sock.recvfrom(1518)
print(data.decode(encoding="utf-8"))
event.set()
except Exception:
break
recvThread = threading.Thread(target=recv)
recvThread.start()
def main():
try:
send_command1('command')
send_command1('streamon')
cap1 = cv2.VideoCapture('udp://0.0.0.0:11111')
while True:
ret,frame1 = cap1.read()
cv2.imshow('TelloEDU1',frame1)
key = cv2.waitKey(1)
if key == 27:
break
except Exception as ex:
print(ex)
finally:
cap1.release()
cv2.destroyAllWindows()
send_command1('streamoff')
sock.close()
print('--- END ---')
if __name__ == '__main__':
main()
③
('192.168.10.1',8889)と('udp://0.0.0.0:11111')がセットになっている(対になっている)可能性があるか調べました。wi-fiルーターにパソコンとドローンを1台接続し、ドローンは192.168.10.1に割り振られるようにルーター側で設定しました。
この方法もうまくいかず、「streamon OK」で止まりました。
④
ドローン自体をwi-fiアクセスポイントとしたとき(パソコンとドローンを1対1で接続)、
('192.168.10.1',8889)('udp://0.0.0.0:11111')
('192.168.10.1',8889)('udp://127.0.0.1:11111')
('192.168.10.1',8889)('udp://192.168.10.2:11111')
のように映像受信時のIPアドレスを変えても、映像を受信できました。
⑤
wi-fiルーターではなく、ドローンをwi-fiのアクセスポイントとしたとき、このアクセスポイントに他のドローンも接続できるか試しましたができませんでした。
該当のソースコード
import socket
import threading
import time
import cv2
'''
from formationflight.multi_1.tello1 import Tello1
from formationflight.multi_1.tello2 import Tello2
from formationflight.multi_1.tello3 import Tello3
tello1 = Tello1()
tello2 = Tello2()
tello3 = Tello3()
'''
event = threading.Event()
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
sock.bind(('',9000))
tello1_address = ('192.168.100.112',8889)
tello2_address = ('192.168.100.113',8889)
tello3_address = ('192.168.100.114',8889)
def send_command1(msg):
print(msg)
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello1_address)
event.wait()
event.clear()
def send_command2(msg):
print(msg)
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello2_address)
event.wait()
event.clear()
def send_command3(msg):
print(msg)
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello3_address)
event.wait()
event.clear()
def send_command(msg):
print(msg,msg,msg, sep='\n', end='\n')
msg = msg.encode(encoding="utf-8")
sock.sendto(msg,tello1_address)
sock.sendto(msg,tello2_address)
sock.sendto(msg,tello3_address)
event.wait()
event.clear()
def send_command12(msg1,msg2):
print(msg1,msg2, sep='\n', end='\n')
msg1 = msg1.encode(encoding="utf-8")
msg2 = msg2.encode(encoding="utf-8")
sock.sendto(msg1,tello1_address)
sock.sendto(msg2,tello2_address)
event.wait()
event.clear()
def send_command23(msg2,msg3):
print(msg2,msg3, sep='\n', end='\n')
msg2 = msg2.encode(encoding="utf-8")
msg3 = msg3.encode(encoding="utf-8")
sock.sendto(msg2,tello2_address)
sock.sendto(msg3,tello3_address)
event.wait()
event.clear()
def send_command13(msg1,msg3):
print(msg1,msg3, sep='\n', end='\n')
msg1 = msg1.encode(encoding="utf-8")
msg3 = msg3.encode(encoding="utf-8")
sock.sendto(msg1,tello1_address)
sock.sendto(msg3,tello3_address)
event.wait()
event.clear()
def send_command123(msg1,msg2,msg3):
print(msg1,msg2,msg3, sep='\n', end='\n')
msg1 = msg1.encode(encoding="utf-8")
msg2 = msg2.encode(encoding="utf-8")
msg3 = msg3.encode(encoding="utf-8")
sock.sendto(msg1,tello1_address)
sock.sendto(msg2,tello2_address)
sock.sendto(msg3,tello3_address)
event.wait()
event.clear()
def recv():
while True:
try:
data,server = sock.recvfrom(1518)
print(data.decode(encoding="utf-8"))
event.set()
except Exception:
break
recvThread = threading.Thread(target=recv)
recvThread.start()
def main():
try:
send_command('command')
send_command1('streamon')
cap1 = cv2.VideoCapture('udp://0.0.0.0:11111')
#cap2 = cv2.VideoCapture('udp://0.0.0.0:11111')
#cap3 = cv2.VideoCapture('udp://0.0.0.0:11111')
while True:
ret,frame1 = cap1.read()
cv2.imshow('TelloEDU',frame1)
key = cv2.waitKey(1)
if key == 27:
break
except Exception as ex:
print(ex)
finally:
cap.release()
cv2.destroyAllWindows()
send_command('streamoff')
sock.close()
print('--- END ---')
if __name__ == '__main__':
main()
補足情報(FW/ツールのバージョンなど)
python 3.7.6