sugihara-16 / Tello_Control

Apache License 2.0
2 stars 0 forks source link

The usage of Tello API #1

Open tongtybj opened 2 years ago

tongtybj commented 2 years ago

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の差分を確認する必要があるかも。。。

どのコマンドも、動いたり動かなかったりする。1,2回打ち込めば大体反応するが、flipに関しては何回やっても動かないことがある(これは、電池残量が少ないとそうなるのかも)

PC(ground station)とロボット(DJI Tello)とのwifi接続が貧弱だから、socket通信が不安定だと思う。 上記のTELLO SDK2.0とhttps://github.com/anqixu/tello_driverの差分を確認する以外にも、 socket通信が失敗したらretryする仕組みを行うというというのが必要かもしれませんね。

tello_driverには、速度を調整するtopic(tello/cmd_vel)しか用意されていない。そのため位置を制御するには、あらかじめ速度を一定値に決めておき、入力された変位量に応じて移動時間を制御する必要がある。

位置司令 (go-pos司令)がTELLO SDK2.0で対応しているか、まず確認してみましょうか。

sugihara-16 commented 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のコードを読んで実行してみましたが、動きませんでした)。

sugihara-16 commented 2 years ago

通信が不安定という件についてですが、それぞれのtopicについて一回目のmsgは反応せず二回目以降は安定して反応するので、そもそもtello_driverの仕様なのかもしれません。ただやはりflipについては例外的で、充電がほぼmaxのときくらいしか反応しないです。

tongtybj commented 2 years ago

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で書く事自体ナンセンスなんだけどね。。。)。

tongtybj commented 2 years ago

ちなみに、今flipができたのは

のどれなんだっけ?

sugihara-16 commented 2 years ago

試したものは、 ・tello_driver 二回目以降は反応する。 ・tellopy 一回で反応する。 ・tello-pyhton SDK これは一回も試していない。 ・ライブラリなしで、socket通信をつかったもの 一回で反応する。

という感じです。あと完全に見落としで申し訳ないのですが、説明書をよく読んだらバッテリーが50%以下ではflipできないと書いてあったので、そういう仕様でした...。

tongtybj commented 2 years ago

手元の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を用意するだけなので、こっちで実装しておきます。

sugihara-16 commented 2 years ago

僕の場合、位置指令を作るために、自分で追加したpythonのプログラムを通しているのでそのせいかも知れません...(いずれにせよ、明日ご確認いただければと思います)。

tongtybj commented 2 years ago

あと、位置司令だけど、 https://github.com/hanyazou/TelloPy/blob/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa/tellopy/_internal/tello.py#L325-L353 かなとおもったけど、結局はIphoneのタッチ式ジョイスティックに値が変換されるので、ずっと動く。

距離を指定するコードがあれば、教えてくれないかな?上のURLように、コードのどの行なのかハイライトで示してくれるた嬉しい。

tongtybj commented 2 years ago

あ、いまじゃなくて、明日教えてください。。。

tongtybj commented 2 years ago

ちなみに、https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf には明確何センチとかが書いてあるね。

sugihara-16 commented 2 years ago

結局は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()
tongtybj commented 2 years ago

なるほど、いい検証コードを書いたね。

で、思ったのが、 まず、self.left(val)で30cmがself.left_xに代入されると、 そのあと、https://github.com/hanyazou/TelloPy/blob/b52b98c2da57af69bb6fbf1c4389cfe9704a96aa/tellopy/_internal/tello.py#L478-L509self.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左に進んでくださいという司令になるので、見かけ上速度司令になっているのではないかな。

というのが僕の理解だけど、なぜ杉浦くんの上のコードはちゃんと止まるんだろう。。。実機を使って確認してみます。

sugihara-16 commented 2 years ago

すみません、色々ごちゃ混ぜになっていたのですが、こちらのコードでは直接の位置指令は出来ませんでした。 TelloPyで位置指令ができたのは、↑の各コマンドの後でsleep(1)をした後、値を初期化する様な処理を追加した物でした(作ったのが少々前なのと、いくつかバージョンを作ってしまったので推測ですが...)。 直接の位置指令は、結局自分でUDPソケット通信をするしかないのかも知れないです。(あと、×杉浦 ○杉原です)。