dronekitのサンプルプログラム

#前の記事
このページの解説が長くなったので，別ページに分離しました．


[ここ](https://qiita.com/hsgucci/items/27fa33d7c7de505839da#%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0) から前のページへ戻れます．

#前提条件

dronekitのソース全体をgitでダウンロードした後に，exampleをホームに移動し，不要フォルダを削除しています．

```bash
$cd ~
$git clone https://github.com/dronekit/dronekit-python.git
$mv dronekit-python/examples ~/
$rm -rf dronekit-python
```

#dronekitのサンプルプログラム

examplesの中には複数のフォルダがあります．

- vehicle_state　　　　　：　Vehicle State 
- simple_goto　　　　　　：　Simple Goto 
- guided_set_speed_yaw　：　Guided Movement and Commands
- mission_basic　　　　　：　Basic Mission 
- mission_import_export　：　Mission Import/Export 
- create_attribute　　　　：　Create Attribute in App 
- follow_me　　　　　　　：　Follow Me (Linux only) 
- drone_delivery　　　　：　Drone Delivery 
- flight_replay　　　　　：　Flight Replay 
- channel_overrides　　　：　Channel Overrides 
- <font color="blue">gcs</font> 
- <font color="blue">reboot</font>
- <font color="blue">play tune</font>
- <font color="blue">performance test</font>

青字で示したものは新しいもので，それ以外は
~~http://python.dronekit.io/examples/index.html~~
　　[2018年7月の保存ページ](https://web.archive.org/web/20180610105749/http://python.dronekit.io/examples/index.html)
で説明されているものです．
フォルダ名の右側に当該ページでの名前を付けておきました．

各フォルダの中には，フォルダ名と<font color="green">ほぼ</font>同じ名前の.pyファイルがあるので，Pythonで実行するだけです．

以下，それぞれの説明です．

#サンプル：simple_goto.py

```bash
$cd ~/examples/simple_goto/
$python simple_goto.py
```

**動作説明**
動作自体はコンソール画面に文字が出るだけなので，<font color="blue">何をやっているかさっぱりわからない</font>のが欠点ですね．
プログラム的には，以下のように動きます．

*dronekit-sitl起動 -> armingチェック -> GUIDEDモード -> arm -> 離陸 -> ウェイポイント移動１ -> ウェイポイント移動２ -> RTLモード*

離陸後のウェイポイント移動は，30秒のtime.sleep関数(ウェイト)で待ち続けるので文字が出力されません．
プログラムが停止しているかと疑ってしまうが，ちゃんと動いています．

**解説**
simple_goto.pyには**フライトモードの変更，ARM，離陸，緯度経度を指定した移動**といった，
**<font color="red">基本的な操作が一通り記述されているので，このファイルをベースにして様々な応用が可能です．</font>**

#サンプル：guided_set_speed_yaw.py

```bash
$cd ~/examples/guided_set_speed_yaw/
$python guided_set_speed_yaw.py
```

**動作説明**
ドローンが離陸した後に移動コマンドを発行し，2秒おきに目的地点までの距離が表示される．
目標地点に到着すると，次の目標地へ向かう．
何回か（結構たくさん）繰り返した後で終了する．
見かけ上は，simple_gotoと同じ移動をしているだけかの様に見えてしまうが，実際は様々な移動方法を試している．

**解説**
プログラムソースの途中に多くの関数が定義されている．
Pythonはどこでも関数を定義できるのがメリットだが，逆にちょっと読みにくい．

通常のウェイポイント移動で事足りる場合には，このサンプルはあまり意味がない．
絶対値での緯度経度を指定するのではなく，
**北へプラス50m/東へマイナス20mなどのように相対距離で目標位置を指定したり，**
**5m/sで40秒間移動などのように速度指令を与えたり**
という使い方をしたい場合に有効なサンプル．

特に，速度指令を与える方法はドローンをロボットのように使いたい研究者には重宝する．
いわゆる「自律移動ロボット」はVx, Vy, Rzの速度指令を与えて使うので．
ROSのcmd_velトピック(Twist型)とか．

#サンプル：mission_basic.py

```bash
$cd ~/examples/mission_basic/
$python basic_basic.py
```

**動作説明**
ミッションを書き込んだ後に，ARMして離陸，ウェイポイント移動，RTLして終了する．

**解説**
Mission Planner等のフライトプランナーで書き込んでから，フライトモードをAUTOにして使うのが従来の自動飛行．
このサンプルでは，それらのソフトを使わず，フライトプランの書き込みをPythonで行う．

プログラム中では，３番目のウェイポイントに到着後，４番目をスキップして５番目に向かうデモをしている．

このサンプルを応用すれば，インターネット上からフライトプランを受信し，
ドローンに書き込み，AUTOで自動飛行できる．
応用性の高いサンプル．

#サンプル：mission_import_export.py

```bash
$cd ~/examples/mission_import_export/
$python basic_import_export.py
```

**動作説明**
以下の作業を行う．

1. フライトプラン(ミッション)の書かれたテキストファイルを読み込む（ファイルのread)
2. フライトコントローラに書き込む（upload）
3. フライトコントローラからミッションを取り出す（download）
4. テキストファイルに書き出す（ファイルのsave）

**解説**
Mission Planner等のプランナーで作成したフライトプランのテキストファイルを，
フライトコントローラに書き込むことができる．
また，フライトコントローラに既に書き込まれているフライトプランを取り出して，
テキストファイルに書き出すこともできる．

このサンプルを応用すれば，
ディスク上に蓄えてある/インターネットからダウンロードしたファイルを
Pythonを使ってフライトコントローラに書き込み，AUTOモードにして自動飛行できる．

つまり，Mission Planner等のプランナーでいちいち書き込まなくても済むソフトウェアを作成できる．


#サンプル：create_attribute.py

```bash
$cd ~/examples/create_attribute/
$python create_attribute.py
```

**動作説明**
MAVLinkメッセージの１つである，RAW_IMUメッセージを５秒間表示する．

**解説**
別のファイル `my_vehicle.py`の中にある， MyVehicleクラスで定義したリスナー関数を，
`vehicle.add_attribute_listener`を使ってコールバック関数を登録するデモ．

これを応用すれば，フライトコントローラから流れてくる任意のMAVLinkメッセージを表示することができる．

しかし，正直な感想としては，
わざわざ事前に別のクラスを作って，attributeで呼び出すよりも，vehicleクラスのある場所で

```py
@vehicle.on_message('RAW_IMU')
def listner( self, name, message ):
    print(message)
```

と書いて直接メッセージを呼び出してしまった方が楽だと思うのだが．．．
私はこの方法で'SYSTEM_TIME'メッセージ（GPS時刻）を取り出しています．

このサンプルの有意義な点があれば是非教えてください．


#サンプル：follow_me.py

```bash
$cd ~/examples/follow_me/
$python follow_me.py
```

プログラムはCtrl+cで終了させます．


**動作説明**
フライトモードをGUIDEDに設定，ドローン離陸後，
ＰＣにつながっているGPSから現在の緯度経度を読み取り，
その場所にドローンを移動させる．

**解説**
Mission Plannerで言えば，Ctrl+fで呼び出せる隠しメニューの中の機能，Follow Meと同じです．
![follow_me.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/d1097333-d635-9b9c-25dc-fa42a13e9486.png)

このデモはLinux専用になっています．
というのは，ＰＣにつながっているGPSの値を取得する方法に**gpsd**を使っているからです．
**gpsd**は

```
$sudo apt install gpsd
```
でインストールするプログラムで，
GPSのNMEAデータをバックグラウンドで受信し，緯度・経度を常に保持しておくサービスです．
GPS時刻を使ってＰＣの時刻合わせをすることもできます．

gpsdを使うと複数のプログラムがGPSのデータを欲しい際には便利です．
しかし，サンプルとして提示するなら，pynmea2などのpythonライブラリを使った方が良いんじゃないかな，という気もしますね．

とはいえ，今まではMission Plannerの入ったノートＰＣを持ち歩く必要がありましたが，
Raspberry Pi等の小型PCでもFollow Meができるようになるのは便利です．


#サンプル：drone_delivery.py
**<font color="blue">pipで複数のライブラリをインストールする必要があります．</font>**

```bash
$pip install simplejson cherrypy jinja2
$cd ~/examples/drone_delivery/
$python drone_delivery.py
```
プログラムはCtrl+cで終了させます．

もし以下のようなエラーが出た場合は，
pythonライブラリがインストールされていない，という意味です．

```python
Traceback (most recent call last):
   File "ファイル名.py", line エラー行, in <module>
   import ライブラリ名
ImportError: No module named ライブラリ名
```
pipで不足ライブラリをインストールしましょう．

```bash
$pip install ライブラリ名
```

**動作説明**
ドローンで輸送を行うサンプルです．
プログラムを起動後，Webブラウザで**http://localhost:8080/**を開くと，
ブラウザの地図上からドローンを操作できるようになるプログラム**でした**．
しかし，作者のmapboxのアクセストークンが有効でないため，今は地図が全く表示されなくなっています．．．

**解説**
自分でmapboxのアカウントを作り，
自分の地図のアクセストークンを組み込んであげれば，
このデモも動くようになるかもしれません．

GoogleMapsを使うとか，leafletかopenlayersでOpenStreetMapを使えば良かったのになあ．

#サンプル：flight_replay.py

```bash
$cd ~/examples/flight_replay/
$python flight_replay.py --tlog flight.tlog
```

**動作説明**
飛行ログ(tlog)を解析し，同じ飛行を行います．なのでreplayです．

**解説**
tlogファイルはフライトコントローラに記録される生のバイナリデータですが，
これを解析して同じ飛行をさせるデモプログラムです．

応用すれば，過去の飛行の再現(事故検証)や，飛行データからフライトプラン作成などもできそうですね．

余談ですが，ログ解析でtlogファイルをテキストにコンバートしたい際には，
[mavlogdump.py](https://github.com/ArduPilot/pymavlink/blob/master/tools/mavlogdump.py)を使います．

```bash
$mavlogdump.py --format csv ログファイル名
```
pymavlinkの機能の一部です．


#サンプル：channel_overrides.py

```bash
$cd ~/examples/channel_overrides/
$python channel_overrides.py
```
**動作説明**
ラジコン送信機から受信した操縦信号を，dronekit側から**上書き(=オーバーライド)**し，操作を乗っ取るサンプルです．

**<font color="red">危険な機能なので，実機ドローンではやらない方が良いでしょう．</font>**
ローバーだとまだ安全ですが．

**解説**
特定のチャンネルだけを上書きできるので，基本操作の4チャンネルやフライトモードch.5はいじらず，それ以外のチャンネルだけ変化させることもできます．

Mission Plannerの[設定]-[Planner]にある[ジョイスティック設定]があります．
![joystick.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/ae56c3e0-837e-83dc-d4d0-9104f70001c2.png)
これはＰＣに繋いだジョイスティックでドローンを操作できるようにする機能です．
チャンネルオーバーライドの応用例です．

本来，ドローンを操作するのはsimple_gotoなどで緯度経度を指定するほうが良いのですが，
特殊なケースについては，ラジコン送信機の信号を上書きすることもあります．

例えば，LIDAR等を使って壁からの距離を測定し，一定距離以内には近づかなくなるように制御する，とか．
送信機のスティックが倒れていても，それを上書きしてしまえば，ドローンは動かない．

#サンプル：microgcs.py
**<font color="blue">aptでTkinterのパッケージをインストールする必要があります．</font>**

```bash
$sudo apt install python-tk
$cd ~/examples/gcs/
$python microgcs.py
```

プログラムの終了は，ウィンドウのＸボタンを押すか，ターミナル上でCtrl+cです．

**動作説明**
プログラムを起動すると，こんなウィンドウが立ち上がります．
![gcs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/6720dfd4-1136-f418-799b-b118f7b6701d.png)
現在の緯度・経度・高度と，姿勢角がリアルタイムに表示されます．
また，2つのボタンでフライトモードを切り替えることができます．


**解説**
Python用のGUIライブラリの１つであるTkinterを使って，ウィンドウを作るサンプルです．
現在位置を表示して，コマンドも送れるので，
「**Ground Control Station**」(GCS)だ！と言っています．
今の機能はショボいですが，拡張していけば色々できるようになります．

しかし，Python用のGUIライブラリは何が良いのでしょうね．
**Tkinter**以外にも，**Kivy**，**PyQt**，**wxPython**もあります.
クロスプラットフォーム対応のライブラリが良い？

#サンプル：reboot

```
$cd ~/examples/reboot/
$python reboot.py
```

**動作説明**
フライトコントローラがリブートします．それだけ．

**解説**
フライトコントローラをリモートでリセットする方法です．

Mission Plannerだと，Ctrl+fで出せる隠しウィンドウで，リセットする方法がありますが，同じ機能です．
![reboot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/f641bdb6-f75d-d981-6c88-e18d7a0a02b6.png)


#サンプル：play_tune.py

```
$cd ~/examples/play_tune/
$python play_tune.py
```

**動作説明**
フライトコントローラ搭載のブザーから，音を出します．
しかし，sitlには音源がないので，意味がありません．エラーで終了します．

**解説**
実機のPixhawkからも音が出ませんでした．
どうやって使うんだろう．

#サンプル：performance test

```
$cd ~/examples/performance_test/
$python performance_test.py
```
**動作説明**
30秒間計算をしたあと，計測した性能を表示しします．

**解説**
フライトコントローラに送ったコマンドの応答がどのくらいすぐに返ってくるか，
のパフォーマンステストです．
USBや有線シリアルで繋がっている場合はほぼ問題ありませんが，
テレメトリでシリアルを無線化している際の通信性能の計測ができます．

#おわりに
Dronekit-Pythonのサンプルを一通り解説しました．
まだ不十分なところもありますが，逐次更新していきたいと思います．

前のページへ戻るには　[ここ](https://qiita.com/hsgucci/items/27fa33d7c7de505839da#%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)