Open tongtybj opened 2 years ago
TELLO SDKには位置司令があります。 また、tello_driver ( https://github.com/appie-17/tello_driver ) がラッピングしている Tellopy ( https://github.com/hanyazou/TelloPy/tree/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa )も位置司令を提供しています(そもそも、このTellopyと公式のTELLO-Python sdk ( https://github.com/dji-sdk/Tello-Python ) の違いはよくわからず、自分で接続をしなくてよいとか、画像認識のサンプルコードが付いてるとかくらいしか相違はみつけられなかったです)。 Tellopyでもコマンドライン入力で動かすプログラムを作ってみましたが、こちらのほうは基本的に反応に問題はありませんでした(ただし、flipについてはサンプルコードがなかったため、gitのコードを読んで実行してみましたが、動きませんでした)。
通信が不安定という件についてですが、それぞれのtopicについて一回目のmsgは反応せず二回目以降は安定して反応するので、そもそもtello_driverの仕様なのかもしれません。ただやはりflipについては例外的で、充電がほぼmaxのときくらいしか反応しないです。
Tellopy ( https://github.com/hanyazou/TelloPy/tree/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa )も位置司令を提供しています
なるほど、APIが提供されているのなら、まずはこっち(Tellopy)を使って行きましょう。
このTellopyと公式のTELLO-Python sdk ( https://github.com/dji-sdk/Tello-Python ) の違いはよくわからず
socket通信の部分の実装が違うのかもしれませんが、僕もまだその部分のコードを読めていませんので、憶測です。
通信が不安定という件についてですが、それぞれのtopicについて一回目のmsgは反応せず二回目以降は安定して反応するので、そもそもtello_driverの仕様なのかもしれません。ただやはりflipについては例外的で、充電がほぼmaxのときくらいしか反応しないです。
tello_driverもといtellopyのsocket通信の実装がちょっと貧弱だからというのがありますね。憶測ですが。。。(そもそも画像ストリームを含むsocket通信をpythonで書く事自体ナンセンスなんだけどね。。。)。
ちなみに、今flipができたのは
のどれなんだっけ?
試したものは、 ・tello_driver 二回目以降は反応する。 ・tellopy 一回で反応する。 ・tello-pyhton SDK これは一回も試していない。 ・ライブラリなしで、socket通信をつかったもの 一回で反応する。
という感じです。あと完全に見落としで申し訳ないのですが、説明書をよく読んだらバッテリーが50%以下ではflipできないと書いてあったので、そういう仕様でした...。
手元のDJI Telloでhttps://github.com/appie-17/tello_driver を試していますが、
二回目以降は反応する。
という現象はなく、スムーズにコマンドも送れますね。 考えられるのは、PCの問題 or Telloの個体差. 明日両方確認してみましょう。 (ただ、僕の機体は1,2分放置すると自動でシャットダウンするみたいです。。。)
あと、知っているかもしれませんが、速度は
$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py cmd_vel:=/tello/cmd_vel
で操作できます。
キーの使い方: http://wiki.ros.org/teleop_twist_keyboard
ちなみに、前進のつもりで"i"を押したら、横移動を始めます。。。少し焦ります。"k"を押すと停止します。
キーのマッピングがおかしいようなので、調査しておきます。
位置司令はtellopyでAPIが用意されているのであれば、ros subscriberを用意するだけなので、こっちで実装しておきます。
僕の場合、位置指令を作るために、自分で追加したpythonのプログラムを通しているのでそのせいかも知れません...(いずれにせよ、明日ご確認いただければと思います)。
あと、位置司令だけど、 https://github.com/hanyazou/TelloPy/blob/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa/tellopy/_internal/tello.py#L325-L353 かなとおもったけど、結局はIphoneのタッチ式ジョイスティックに値が変換されるので、ずっと動く。
距離を指定するコードがあれば、教えてくれないかな?上のURLように、コードのどの行なのかハイライトで示してくれるた嬉しい。
あ、いまじゃなくて、明日教えてください。。。
ちなみに、https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf には明確何センチとかが書いてあるね。
結局はIphoneのタッチ式ジョイスティックに値が変換されるので、ずっと動く。
なるほど、、、 すみません、コードの詳しい処理内容は知識不足でよくわからなかったのですが、実際にTelloPyをimportして使うときは、 https://github.com/hanyazou/TelloPy/blob/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa/tellopy/_internal/tello.py#L328-L353 (先生がハイライトされた箇所とほぼ同じ箇所) にある関数を、位置を引数として呼び出せば位置司令ができました。 例えば、telllopyを使って、標準入力でTelloをコントロールするプログラムは以下の様に書いて動きました。 ここで指定したコマンドで言うと、n,u,h,j,b,pあたりが位置司令です。
from time import sleep
import tellopy
import cv2
import av
import numpy
def handler(event, sender, data, **args):
drone = sender
def test():
drone = tellopy.Tello()
drone.connect()
drone.wait_for_connection(60.0)
while True:
msg = input("command:")
if msg == "s":
print("your command is {0}".format(msg))
print("takeoff")
drone.takeoff()
sleep(10)
elif msg == "n":
print("your command is {0}".format(msg))
print("down 30")
drone.down(30)
sleep(3)
elif msg == "u":
print("your command is {0}".format(msg))
print("up 30")
drone.up(30)
sleep(3)
elif msg == "h":
print("your command is {0}".format(msg))
print("left 30")
drone.left(15)
sleep(3)
elif msg == "j":
print("your command is {0}".format(msg))
print("right 15")
drone.right(15)
sleep(3)
elif msg == "b":
print("your command is {0}".format(msg))
print("back 15")
drone.backward(15)
sleep(3)
elif msg == "p":
print("your command is {0}".format(msg))
print("forward 15")
drone.forward(15)
sleep(3)
elif msg == "c":
print("your command is {0}".format(msg))
print("flip left")
drone.flip_left()
sleep(3)
elif msg == "q":
print("your command is {0}".format(msg))
print("land")
drone.land()
sleep(3)
print("drone.subscrive()します。")
drone.subscribe(drone.EVENT_FLIGHT_DATA, handler)
print("quit")
drone.quit()
break
else:
print("invalid")
continue
if __name__ == '__main__':
test()
なるほど、いい検証コードを書いたね。
で、思ったのが、
まず、self.left(val)
で30cmがself.left_x
に代入されると、
そのあと、https://github.com/hanyazou/TelloPy/blob/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa/tellopy/_internal/tello.py#L478-L509
でself.left_x
, self.right_y
などがstick commandに変換される。
最後に、このself.__send_stick_command()
という関数は
https://github.com/hanyazou/TelloPy/blob/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa/tellopy/_internal/tello.py#L727-L733
で独立したスレッドがずっと回っているので、self.left_x
とかを0にしない限り、ずっと一定の値でその方向に動くようになる。
つまり、30cmをself.left_xに代入したら、毎周期、新たに30cm左に進んでくださいという司令になるので、見かけ上速度司令になっているのではないかな。
というのが僕の理解だけど、なぜ杉浦くんの上のコードはちゃんと止まるんだろう。。。実機を使って確認してみます。
すみません、色々ごちゃ混ぜになっていたのですが、こちらのコードでは直接の位置指令は出来ませんでした。 TelloPyで位置指令ができたのは、↑の各コマンドの後でsleep(1)をした後、値を初期化する様な処理を追加した物でした(作ったのが少々前なのと、いくつかバージョンを作ってしまったので推測ですが...)。 直接の位置指令は、結局自分でUDPソケット通信をするしかないのかも知れないです。(あと、×杉浦 ○杉原です)。
https://github.com/sugihara-16/Tello_Control の問題点を確認しました。 全体的に、通信が不安定だったり、サポートしている機能が少ないという問題が目立つので、 もしかして、https://github.com/anqixu/tello_driverが[TELLO SDK2.0](https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf)に対応がなされていないのが根本的な原因かもしれませんね。
TELLO SDK2.0とhttps://github.com/anqixu/tello_driverの差分を確認する必要があるかも。。。
PC(ground station)とロボット(DJI Tello)とのwifi接続が貧弱だから、socket通信が不安定だと思う。 上記のTELLO SDK2.0とhttps://github.com/anqixu/tello_driverの差分を確認する以外にも、 socket通信が失敗したらretryする仕組みを行うというというのが必要かもしれませんね。
位置司令 (go-pos司令)がTELLO SDK2.0で対応しているか、まず確認してみましょうか。