Tomofiles Note

ドローンとインターネット、そして人との関係を考えるソフトウェアエンジニアのアウトプットブログ

MAVSDKでSITLのドローンからテレメトリーを取得してCesiumJSにアニメーション表示してみた 〜Part 1 紹介編〜

こんにちは。

最近、ドローン関連のOSSや、よく聞く技術について調べています。
特にDronecodeプロジェクトについて、英語のページをGoogle翻訳にぶち込んで読んでいるのですが、ようやく、PX4とQGCとMAVLINKとMAVSDKの大枠がつかめてきました。

そこで今回は、MAVSDKを使用してドローンからテレメトリーを取得してみよう、ということで色々試した内容をまとめたいと思います。

なお、今回は非常に長くなってしまったので、Part1、2に分けます。
Part1は紹介編、Part2は技術トピック編となります。


Dronecodeでドローンを飛行

まずは普通にDronecodeプロジェクトの資材を使用してドローンを飛行させる場合の、全体像です。

f:id:Tomofiles:20191012174850j:plain

通常のドローン、プロポ、およびコンピュータの関係性は上記のとおりです。
(プロポがラジコン操縦機じゃなくてリモコンの形をしているのは無視してくださいww)

DJIの製品等では、コンピュータ(タブレット)とプロポが接続される場合などがありますが、大きく違うことはないと思います。

コンピュータ(タブレット)上にはGCSというソフトウェアが乗っています。
GCSは地上基地局とも言いますが、ドローンの操縦に関するサポートや、機体自体のメンテナンスなどを行う、ソフトウェアです。
DJIでは、DJI GOがそうですね。DronecodeではQGCがそうです。

また、ドローンには、フライトコントローラ(FC)が搭載されています。
自律飛行を司るFCは、基本的なセンサーと、飛行制御を行う演算装置を持っています。
そのFCに、追加のセンサーやプロポとの受信機や、テレメトリー送信機などを接続し、演算装置にはFCソフトウェアをインストールして、ドローンの機能を組み上げていきます。
DronecodeではPX4がそうです。

FCと接続されたテレメトリー装置と、GCSに接続された対のテレメトリー装置で、フライトデータの送受信を行います。
日本では、基本的に2.4GHzを使用しますが、最近は920MHzも使用するようですね。
(ちょっと調べると、920MHzのテレメトリー送受信機は、結構高いです。。。)

テレメトリー接続はMAVLINKというプロトコルを使用しますが、まだ正直正体がつかめていません。
ただ、IPアドレスとポート番号で識別するので、ベースとなるのはTCPUDPなのではないかと思います。
(QGCの手動LINKもIPとポート番号を入力しますしね)

上記のような構成のため、ラジコン用操縦機とFC(Pixhawkなど)とテレメトリー装置と、その他部品を集めれば、
あとはDronecodeのソフトウェアをセットアップするだけで、ドローンを飛行させることができます。
(そういえば、中国からPixhawk4まだ届かないんだけど。。。やっちまったかな)

開発者が介入するには

DronecodeはOSSなので、すべての資材を自由に変更できます。
ただ、まぁQGCの画面をいじったり、PX4のファームウェアを修正したりするのは難しいので、基本的にはMAVLINKでやりとりするテレメトリーデータ等にアクセスして、データを活用するのが現実的な開発者の仕事になると思います。

MAVLINKは、MAVSDKというAPIを通して、プログラマブルにアクセスできます。
MAVSDKは、MAVLINKでアクセスできればいいので、GCSのコンピュータ上で利用できます。
(MAVLINKでアクセスできればいいので、ドローンにコンパニオンコンピュータを搭載して、機体上でMAVSDKを使用することもできるそう)

Introduction · MAVSDK Guide

MAVSDKはiOSPythonがそれなりの実績を持ったバージョンで公開しているそうですが、それ以外の言語は結構乏しいです。
ただ、最近の動向で、SDKをコアと周辺ライブラリに分割して、コアをgRPCサーバ化したそうで、こうすることによりライブラリが対応していなくても、gRPCさえ利用できればSDKが使用できるようになったようです。
なので、今回はMAVSDKのコアライブラリ(C++)のgRPCサーババージョンを使用して、ドローンからテレメトリーを取得してみたいと思います。

CesiumJSとは

MAVSDKで取得したテレメトリーを、せっかくならば地図上に表示したいじゃないですか。
そこで、以前少し利用したことのあるCesiumJSを使って、3Dマップ上に表示することにしました。

CesiumJScesiumjs.org

CesiumJSとは、WebGLを利用した3Dのマップ表示ライブラリです。
デフォルトで3Dの地球儀が表示されるのですが、超拡大すると普通のマップのように使えます。ただ、マウス操作で地図を傾けたりできるので、地図上で三次元の表現ができます。
以下の、サンドキャッスルを使えば、CesiumJSの持つ機能を試すことができます。
三次元表現としては、3Dポリゴンの表示や、モデリングされた3Dオブジェクトの表示ができます。さらに、時間軸も制御できるので、3Dモデルをアニメーションで動作させることもできます。例えば、地図上を滑らかに移動する飛行機を表示したりすることができます。

Cesium Sandcastle

今回試したこと

長くなりましたが、今回の主題です。
MAVSDKから取得したテレメトリーデータをリアルタイムでCesiumJSに三次元表示してみたいと思います。

完成イメージは、以下のドローンの飛行ログ解析サービスみたいな感じを目指してます。
公開された飛行ログの3Dビュー機能みたいな感じで、リアルタイムで飛行するドローンの動きを、CesiumJSのアニメーションを使って表示してみたいと思います。

review.px4.io

全体像は以下のとおりです。

f:id:Tomofiles:20191012190448j:plain

絵のセンスがなくてわかりにくいですが、ちゃんと説明します。

左側のドローンですが、今回はシミュレータを使用します。
DronecodeのシミュレータはHITLとSITLの2種類ありますが、今回はSITLを使用します。
HITLがFC上で直接稼働するシミュレータで、SITLはFCがなくても稼働するシミュレータです。細かい機能が使える、使えないなどがあるようですが、とりあえず飛行データが取得できればいいので、今回はSITLです。

右側のGCSですが、大きく分けて3つのコンポーネントがあります。

1つめは、MAVSDKです。
MAVSDKはコアライブラリをgRPCサーバとして起動します。

2つ目は、独自のアプリケーションです。
今回はGo言語で簡単なgRPCクライアントアプリケーションを作成しました。MAVSDKからgRPCストリーミングで取得したテレメトリーデータを、CesiumJSが稼働するブラウザにSSEでサーバプッシュします。

3つ目は、CesiumJSです。
ブラウザ上でCesiumJSのライブラリを読み込み、2つ目のサーバアプリにSSE接続します。
サーバからは、CZML形式のテレメトリーデータを受信し、マップ上にアニメーションでドローンを表示します。

今回のソースコードは以下のGithubリポジトリにおいてあります。
2つ目と3つ目の独自アプリ部分のソースコードが格納されています。

GitHub - Tomofiles/mavsdk_try

環境構築

それでは、具体的に動作させて、ドローンをCesiumJSまで表示させてみましょう。
SITLのシミュレータと、MAVSDK、QGC、そして、上記独自アプリの環境構築の手順について、順番に説明していきます。

まず、動作環境です。
Dronecodeプロジェクトの推奨環境である、Linux Ubuntuデスクトップ環境を用意します。
今回は、手持ちのデスクトップPCに外付けSSDを差して、Ubuntu18.04LTSをインストールしました。
最近は、個人的にWindows環境よりもLinux環境のほうが慣れてきていて、コマンドの練習にもなって、ちょうどいいタイミングで環境構築できました。

Goのインストール

独自アプリのビルドと実行をするために、Goをインストールします。
バージョンは最新の1.13.1を使用します。
以下のWebサイトから「go1.13.1.linux-amd64.tar.gz」をダウンロードします。

Downloads - The Go Programming Language

ダウンロードしたら、ホームディレクトリ直下に展開します。
tar zxvfコマンドで大丈夫でしょう。

tar zxvf go1.13.1.linux-amd64.tar.gz

展開したら、PATHにホームのgo/binを追加します。
ホームディレクトリに「.bash_profile」を作成して、PATHを記載します。

touch .bash_profile

#viで開いてから
export PATH="$PATH:/home/$ユーザ名/go/bin"
export GOPATH="/home/$ユーザ名/go/vender"

GOPATHも入っていますが、ビルドするだけなら特に必要ないです。
保存したら、適用します。

source .bash_profile

以上でGoの準備は完了です。

SITLのインストール

SITLはPX4のファームウェアのプロジェクトの中に入っています。
そのため、PX4のソースコードをダウンロードします。

その前に、開発ツールチェインという、PX4の開発をするにあたり必要なソフトウェアのインストールが必要です。

Linux · PX4 v1.9.0 Developer Guide

上記Webサイトの以下のコマンドを実行します。

sudo usermod -a -G dialout $USER

それから、以下のシェルを取得し、実行します。
シミュレータだけ使用したい場合に、最低限の資材だけインストールするシェルのようです。
それなりに時間がかかるため、気長に待ってください。

wget https://raw.githubusercontent.com/PX4/Devguide/v1.9.0/build_scripts/ubuntu_sim_common_deps.sh
source ubuntu_sim_common_deps.sh

開発ツールチェインのインストールが終わったら、ファームウェアソースコードをダウンロードします。

git clone git@github.com:PX4/Firmware.git

ダウンロードしたら、実行します。
以下のmakeコマンドでビルドと実行まで行います。
成功すれば、以下の画像のようにドローンが表示された画面が起動するかと思います。

sudo make px4_sitl_default jmavsim

f:id:Tomofiles:20191012202950p:plain

なお、以下のように環境変数を同時に指定すると、ホームポジションを変更できます。

sudo PX4_HOME_LAT=40.729738 PX4_HOME_LON=-73.985235 PX4_HOME_ALT=0.0 make px4_sitl_default jmavsim

PX4のWebサイトだとsudoつけてないのですが、自分の環境だとsudoつけないと以下のエラーになってしまいました。
Linuxの権限周りに疎いのでわからないのが悔しいです。なんとなく、px4のデーモンプロセスが起動できていないような気がしているのですが、追跡は諦めました。

ERROR [px4_daemon] error binding socket
ERROR [px4] Failed to communicate with daemon: Permission denied

これでSITLの準備は完了です。

QGCのインストール

次にQGCをインストールします。

Download and Install · QGroundControl User Guide

上記Webサイトの手順どおり実行していけば、インストール完了します。

sudo usermod -a -G dialout $USER
sudo apt-get remove modemmanager -y
sudo apt install gstreamer1.0-plugins-bad gstreamer1.0-libav -y

QGC本体は以下でダウンロードできます。
公式サイトがダウンロードURLを直接記載しているので、下記もそのまま直リンクとなっています。

https://s3-us-west-2.amazonaws.com/qgroundcontrol/latest/QGroundControl.AppImage

ダウンロードしたら、以下のコマンドでQGCを起動します。

chmod +x ./QGroundControl.AppImage
./QGroundControl.AppImage

SITLが起動したままの場合、以下のようにQGCにドローンの現在位置が表示されるはずです。

f:id:Tomofiles:20191012204119p:plain

QGCの準備は完了です。

MAVSDKのインストール

次は、MAVSDKのインストールです。
以下のWebサイトからダウンロードします。

Releases · mavlink/MAVSDK · GitHub

この記事執筆時点では、v0.20.0が最新だったので、そのバージョンの「mavsdk_server_manylinux1-x64」をダウンロードします。
ちょっと下にAssetというアコーディオンがあるので展開するとあります。

ダウンロードしたら、以下のコマンドを実行すると起動します。

chmod +x ./mavsdk_server_manylinux1-x64
./mavsdk_server_manylinux1-x64

以上でMAVSDKの準備は完了です。

独自アプリをインストール

独自アプリ(mavsdk_try)を環境構築していきます。

まずはソースコードを取得します。

git clone git@github.com:Tomofiles/mavsdk_try.git

ダウンロードできたら、このリポジトリに含まれていない資材を集めます。

CesiumJSのライブラリを取得

CesiumJSのライブラリは公式サイトから取得します。
この記事を執筆している時点での最新バージョンは、「1.62」です。

Downloads | cesium.com

ダウンロードしたら展開して、以下のディレクトリに格納してください。

mavsdk_try/static/Cesium-1.62

ドローンの3Dモデルを取得

最後に、CesiumJSに表示するドローンの3Dモデルを取得します。
本当はDJI系の3Dモデルとか使いたかったのですが、フリーでそういう製品系の3Dモデルデータがなかったので、今回はCesiumJSのサンプルに入っている3Dモデルを使用します。

3Dモデルは、以下のCesiumJSのチュートリアルのワークショップコードの中に含まれています。

Cesium Workshop | cesium.com

ワークショップコードをダウンロード・展開して、以下のディレクトリにアクセスしてください。「CesiumDrone.gltf」というgltfファイルが見つかると思います。

cesium-workshop/Source/SampleData/Models

取得したら、以下のディレクトリに格納してください。

mavsdk_try/static

mavsdk_tryをビルド・実行

準備が整ったら、mavsdk_tryをビルド、実行していきます。
mavsdk_tryプロジェクトはGo Modulesで依存関係を解決しますので、以下のようにコマンドを実行します。

cd mavsdk_try
go build

すると、mavsdk_tryディレクトリにmavsdkという実行ファイルが作成されます。
mavsdkを実行して、アプリを起動してください。

./mavsdk

ブラウザ(Chromeがオススメ)を起動して、「localhost:8080」にアクセスすると、以下の画面が表示されます。
ドローンアイコンは5秒後くらいに表示され始めます。

f:id:Tomofiles:20191012225711p:plain

ドローンを飛行させてみましょう

QGCを使用して、ドローンを飛行させてみましょう。
今回は、QGCからミッションを登録して、飛行開始させます。
(いずれミッションもブラウザからアップロードできるようになれば面白そうですね)

QGCの使い方は細かくは説明しませんが、下記のように入力していけばミッションが登録できます。

  1. 画面左上の「A←B」のアイコン(紙飛行機アイコンの左)をクリックする
  2. 画面左上のPlanからWaypointをクリックして、マップ上をダブルクリックすると地点が追加される
  3. 2を何回か繰り返して、ミッションを作成する
  4. 最後の地点にReturn Homeを入力する

上記の手順でミッションを作成すると、画面上では以下のようになります。

f:id:Tomofiles:20191012231143p:plain

ミッションを作成すると、画面右上に「Upload Required」というボタンが点滅します。
クリックすると、ドローンにミッションがアップロードされます。
今回はSITLに対して、ミッションが送られます。
アップロードが成功すると、「Done」と表示されます。

画面左上の紙飛行機ボタンを押して元の画面に戻ると、以下のように画面中央下部に「Start Mission」というスライドバーが表示されています。
スライドバーを右にスライドすると、ミッションが実行され、ドローンが飛行開始します。

f:id:Tomofiles:20191012231655p:plain

ミッションを実行したら、ブラウザに戻ります。
ドローンのアイコンに近づいて、マップを傾けてみます。
マップ拡大は、マウスホイール操作、マップを傾けるのは、マウスホイールをクリックしたまま、マウスを動かします。
傾けると、以下のような見え方になります。

f:id:Tomofiles:20191012232212p:plain

マップ手前から奥に向けて飛んでいます。奥行きや高さ表現があるので、静止画だとわかりづらいんですよね。

こんな感じでMAVSDKを使用してテレメトリーを取得して、リアルタイムでCesiumJSに表示ができました。
現状5秒のタイムラグがあります。この辺はPart2で詳細をお話します。

まずは、上記のミッションを動画で見てみましょう。
非常に滑らかに見えますよね。それに、アイコンのプロペラが回っています。これだけでも面白い表現してますよね。

https://streamable.com/hvoqqstreamable.com


紹介編は以上になります。疲れましたね。
ここまでをだいたい1週間かけてたどり着いた感じなので、一つの記事にまとめると大変長くなります。
本当は紆余曲折あって、最初はWindows10のWSLでやろうとしたり、SITLをDockerコンテナ版で起動したりしようとしたのですが、色々うまくいかなかったです。
もう記憶も記録も消滅してるので、記事にはできませんが、特にDockerコンテナ版は、起動するたびにコンテナが壊れていくという怪現象に苛まれ、もう放棄しましたww

次回は技術トピック編ということで、mavsdk_tryを作るにあたり、使用した技術や知識、数学的な壁について、お話したいと思います。

◆Next Part
tomofiles.hatenablog.com