6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#でTelloを操作する。TelloLibを使って。

Last updated at Posted at 2019-01-08

#はじめに
Telloを買ったらプログラムで操作したくなることに異論の余地はないと思います。

この記事ではC#でTelloを操作する方法について書きます。

Telloを操作する方法といっても、TelloにUDP通信でコマンドをbyte配列で送るなんてことをゴリゴリ書くのはチョットムズカシイため、あくまでそういったところをマルっとやってくれるライブラリを使って、ということになります。

#TelloLib
強い人がTelloをそうさするためのC#のライブラリをGitHubで公開してくれています。
それがTelloLibです。
これを使うととても簡単にC#でTelloを操作することができます。

#入手方法
こちらにTelloLibとサンプルを含むVisual Studioのソリューションが公開されているので、git cloneするかzipファイルをダウンロードしてください。

簡単なコンソールアプリやAndroidアプリのサンプルプロジェクトがあるので、それを動かしたりしてもよいですが、今回用があるのはこの中のTelloLibプロジェクトです。

#TelloLibをコンパイル
まずはTelloLibをコンパイルして、後で自分のプロジェクトから参照できるようにdllを生成しましょう。
Visual StudioでaTello.slnファイルを開きます。

ソリューションエクスプローラーのTelloLibプロジェクト上で右クリックして、メニューからビルドを実行してください。

image.png

dllファイルの出力先は、以下のようなソリューション構成であれば、以下のフォルダ内にTelloLib.dllという名前であります。

...\TelloLib\bin\Debug

このTelloLib.dllをこれから作る自分のプロジェクトで参照することで、このライブラリを利用できるようになります。

#プロジェクトを作る
これからTelloを操作するアプリケーションを作っていきます。
今回はシンプルなコンソールアプリケーションから離陸と着陸だけを行うプログラムを作成します。

Visual Studioを起動し、コンソールアプリ(.NET Core) Visual C#プロジェクトを作成します。
プロジェクト名はここではMyTelloConsoleとします。
もちろん何でもよいです。

image.png

#参照を追加する
プロジェクトに先ほど生成したTelloLib.dllファイルへの参照を追加します。
ソリューションエクスプローラーの依存関係を右クリックして参照の追加を選択します。
image.png

参照するファイルの選択ダイアログが開くので、先ほど生成したTelloLib.dllファイルを選択して追加ボタンを押します。
image.png

これでライブラリを利用する準備が整いました。

#プログラムを書いていく
Mainメソッドに直接書いていくことにします。
今回のプログラムの流れは以下のとおりです。

  • イベントハンドラを設定
  • Telloとの通信初期化
  • ループ内でコマンド入力→送信

##イベントハンドラを設定
Telloを操作するために使用するクラスはTelloクラスです。
このクラスには以下の3つのイベントがあります。

  • onConnection
  • onUpdate
  • onVideoData

このうち今回必要なのはonConnectionイベントだけですが、これら3つのイベントはTelloLib内ではイベントハンドラが設定されていない場合(つまりnullだった場合)の対処がされていないので、イベントハンドラを設定せずに実行すると、これらのイベントが発火されたときにnull参照で例外が発生することになります。

それらの例外はcatchされてコンソールにエラーメッセージが表示されてアプリケーション自体は動き続けるのですが、エラーメッセージが延々と出力され続けるのは困ります。

これを解決するにはライブラリ利用側で各イベントにイベントハンドラを設定するか、TelloLib側を修正して、それぞれのイベントが発火される箇所でnull条件演算子?.を使ってnull参照を回避する、という方法が考えられます。こんな感じで。

null条件演算子を使ったTelloLibの修正
onUpdate(100) → onUpdate?.Invoke(100)

今回はすべてのイベントにイベントハンドラを設定することにします。
するとこんな感じになります。

using System;
using TelloLib;

namespace MyTelloConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Tello.onConnection += Tello_onConnection;

            Tello.onUpdate += Tello_onUpdate;

            Tello.onVideoData += Tello_onVideoData;
        }


        private static void Tello_onConnection(TelloLib.Tello.ConnectionState newState)
        {
        }

        private static void Tello_onVideoData(byte[] data)
        {
        }

        private static void Tello_onUpdate(int cmdId)
        {
        }
    }
}

この中で今回必要なのはonConnectionイベントのイベントハンドラ(ここではTello_onConnection)だけです。
このイベントハンドラはTelloとの通信のステータスが変化したときに実行されます。
このイベントの重要な役割は、Telloとの通信が開始されたらTelloの初期設定を行うことです。

このイベントハンドラは変化後のステータスが引数(newState)として渡されて実行されるので、このnewStateConnectedになったらTelloの初期設定が行われるようにします。

        private static void Tello_onConnection(TelloLib.Tello.ConnectionState newState)
        {
            if (newState == Tello.ConnectionState.Connected)
            {
                Tello.queryAttAngle();//???
                Tello.setMaxHeight(1);//最大高度?メートル?
            }
        }

このコードについてはサンプルプログラムのTelloConsole内のMainメソッドを参照してください。
setMaxHeightメソッドはわかります。可能最大高度を指定するのでしょう。メートル単位で。
しかしqueryAttAngleメソッドがわかりません。わかりませんがきっと必要と思われるので、ここではおまじないとしておきます。

#Telloとの通信を開始
Telloとの通信は以下の1行で開始されます。
シンプルでよろしいですね。
これをMainメソッド内に追加します。

            Tello.startConnecting();//接続開始

詳しいことはおいといて、この接続処理によって前述の通信ステータスがConnectedになったときにonConnectionイベントが発火されて、設定したイベントハンドラによってTelloの初期設定が行われることになります。

この時点でMainメソッドは以下のとおりです。

        static void Main(string[] args)
        {
            Tello.onConnection += Tello_onConnection;

            Tello.onUpdate += Tello_onUpdate;

            Tello.onVideoData += Tello_onVideoData;

            Tello.startConnecting();//接続開始
        }

#コマンド送信
whileループでユーザーからのコマンド入力を受け付け、それに応じてTelloを操作するようにします。
基本的な形は以下のとおりです。

            var inputStr = "";
            while (inputStr != "exit")
            {
                inputStr = Console.ReadLine().ToLower();

                //inputStrの内容に応じた処理を書く
            }

今回は以下の3つのコマンドを受け付けるようにします

  • takeoff 離陸
  • land 着陸
  • exit アプリケーションの終了(ループから抜ける)

離陸と着陸についてはTelloLibにそれぞれtakeOffメソッドとlandメソッドが用意されていて、これらを呼び出すだけでよくなっています。

ユーザーからの入力に加えて、Telloとの通信ステータス、そして飛行中か否かのステータスを条件としてそれぞれのメソッドを実行するようにします。
加えて、exitと入力されたときにループから抜けてアプリケーションが終了するようにします。

            var inputStr = "";
            while (inputStr != "exit")
            {
                inputStr = Console.ReadLine().ToLower();

                //離陸
                //Telloと接続中、かつ、飛行していない
                if (inputStr == "takeoff" && Tello.connected && !Tello.state.flying)
                {
                    Tello.takeOff();
                }

                //着陸
                //Telloと接続中、かつ、飛行中
                if (inputStr == "land" && Tello.connected && Tello.state.flying)
                {
                    Tello.land();
                }
            }

            //とりあえず着陸命令だしておく
            Tello.land();

以上で、離陸と着陸だけするプログラムが完成しました。
完成したMainメソッドは以下のようになります。

        static void Main(string[] args)
        {
            Tello.onConnection += Tello_onConnection;

            Tello.onUpdate += Tello_onUpdate;

            //Tello.onVideoData += Tello_onVideoData;


            Tello.startConnecting();//接続開始

            var inputStr = "";
            while (inputStr != "exit")
            {
                inputStr = Console.ReadLine().ToLower();

                //離陸
                //Telloと接続中、かつ、飛行していない
                if (inputStr == "takeoff" && Tello.connected && !Tello.state.flying)
                {
                    Tello.takeOff();
                }

                //着陸
                //Telloと接続中、かつ、飛行中
                if (inputStr == "land" && Tello.connected && Tello.state.flying)
                {
                    Tello.land();
                }
            }

            //とりあえず着陸命令だしておく
            Tello.land();
            //これだと、命令が送られる前にアプリケーションが終了してしまうので、
            //ちょっと待つ
            Thread.Sleep(1000);
        }

では実際にTelloを操作してみましょう。

#やってみよう
##TelloとPCを接続
ここでいう接続とはTelloとPCをWifi接続するということです。

まず、Telloの電源を入れます。
しばらく待つと、LEDが黄色く速く点滅を繰り返すようになります。
Telloが起動しましたが、端末との接続がない状態です。

次にPC側です。
PCが拾っているWifiのアクセスポイントのリストに「TELLO-****」という名前のアクセスポイントが現れるので、それを選択して接続します。

「接続済み」となればOKです。

この時点ではTelloは相変わらずLEDが黄色く速く点滅していて何の変化もみられませんが大丈夫です。

##コンソールアプリケーションから操作
いよいよコンソールからTelloを操作してみましょう。
といっても離着陸だけですが。

実行してみてください。

コンソールが表示され、Connected!と表示されたら、takeoffと入力してエンターキーを勢いよく押しましょう。
離陸しましたか?
結構、おおー、って思っちゃいますよね。

続けてlandと入力してこれまた勢いよくエンターキーを押しましょう。スターン!
着陸しましたか。

#おわりに
今回は離着陸のみの簡単なものでしたが、これじゃなんだか物足りませんよね。

次は前進、後退、左回転、右回転について書きたいと思います。

6
3
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?