ドローン業界では、QGroundControl(QGC)を採用してカスタマイズし、そのカスタマイズを製品のライフサイクル全体にわたって維持するのが一般的です。そのため、慣れないコードベースを理解するための高い学習コスト、変更のたびに必要となる再ビルド、アップストリームのリリースごとに発生するマージ作業が伴います。Qt Groupのエンジニアが実際に検証した結果、ブランディング、プロトコルで使用するメッセージ、オペレーターパネル、マップといった製品を特徴づける要素は、起動時に読み込む設定ファイルとして管理できることが分かりました。
ドローン業界におけるQGroundControlのカスタマイズ
多くのドローン開発では、地上管制ステーションをゼロから構築することはありません。QGroundControlをベースに、自社製品に合わせてカスタマイズします。
QGroundControl は汎用性を重視して設計されているため、カスタマイズすることが想定されており、プロジェクトではコンパイル時の拡張メカニズムが提供されています。このメカニズムは柔軟性に優れていますが、それを利用するためのコストは過小評価されがちです。
- より分かりやすく可視化するパネル、MAVLinkメッセージの追加、メニューオプションの追加といった比較的小さな要件であっても、大規模で慣れないコードベースを理解するための学習コストが発生します。
- 変更のたびに再ビルドが必要となり、イテレーションにかかる時間が長くなります。
- アップストリームのリリースごとにマージ作業が必要となり、この作業は製品のライフサイクルを通じて繰り返し発生します。また、編集するファイルが増えるほど、そのコストも増大します。
Qt Groupのエンジニアは、この作業をより効率化できないか検証を始めました。ソースコードに一切手を加えずに変更できるものは何か、そしてそれを実現するにはどのようなワークフローやツールが必要なのかを探りました。
デモ動画:設定、起動、パネルの配置、フリートへの展開。
これまでなかったランタイム設定レイヤー
QGCのコンパイル時の拡張メカニズムは柔軟性に優れていますが、コードベースに不慣れな開発者にとっては、習得のハードルが高いという課題があります。製品のカスタマイズ要件そのものは、より分かりやすく可視化する新しいパネル、MAVLinkメッセージの追加、新しいマップレイヤーなど、通常は比較的小規模です。しかし、変更のたびに大規模なソースツリーから適切な場所を見つけ、再ビルドし、さらにアップストリームのリリースに合わせて変更を維持していく必要があるため、大きな作業負担が生じます。
インターフェース開発には、もう一つの障壁があります。新しいパネルはQMLで記述する必要があるため、純粋にビジュアル上の変更であってもコーディング作業となり、デザイナーではなくアプリケーション開発者が対応することになります。従来のワークフローには、それ以外の方法で作業するためのツールがありません。
以下で紹介する代替アプローチは、社内で概念実証(PoC)として開発したもので、ランタイム設定レイヤーを活用することで、このようなカスタマイズを再コンパイルなしで実現します。
ランタイム設定で広がる可能性
このPoCでは、4つのカスタマイズ領域をQGCのメインラインソースから切り離し、アプリケーションが起動時に読み込むフォルダへ移します。それぞれをファイルとして編集、置換、生成でき、コンパイラを使用する必要はありません。
これらのファイルを手作業で編集することもできますが、このPoCでは、Qt for PythonとQMLで構築したConfiguration Appを地上管制ステーションと組み合わせています。Configuration Appには設定ごとにタブが用意され、変更内容の検証、各ファイルのアトミックな書き込み、配置用フォルダの作成、検証用の最小構成シミュレーターの追加、さらに同じウィンドウから地上管制ステーションのビルドと起動まで行えます。
このワークフローでは、「設定、実行、確認、調整」というサイクルになり、その過程で再コンパイルは一切必要ありません。
お問い合わせ
4つのカスタマイズ領域
このPoCでは、新しいQtモジュールの追加やQtの動作変更は必要ありません。QGCがサポートする拡張アーキテクチャであるカスタムビルドディレクトリとプラグインのサブクラス化(QGCCorePlugin、FirmwarePlugin)の範囲内で実装し、それ以外はQtがすでに提供している仕組みを利用しています。
MAVLinkの設定
MAVLinkではメッセージをXMLで定義します。従来は、このファイルをコードジェネレーターに入力し、生成されたコードをコンパイルして組み込んでいました。
今回のPoCでは起動時にこのファイルを読み込むため、メッセージの追加や、インターフェース上に表示するメッセージの変更に、コードジェネレーターの実行や再ビルドは必要ありません。ランタイムで定義したメッセージにも、コンパイル時に組み込まれたメッセージと同じプロトコル検証が適用されます。

地上管制ステーションでサポートするMAVLinkメッセージを選択。

地上管制ステーションでサポートするカスタムMAVLinkメッセージを追加。
実装
QXmlStreamReader(Qt Core)が起動時にダイアレクトを解析します。フィールドのワイヤーオフセットはMAVLinkのシリアライズ規則に従い、各メッセージのCRCシードを算出してプロトコルレイヤーに登録します。これにより、ランタイムで定義されたメッセージにも、コンパイル時に組み込まれたメッセージと同じ検証を適用できます。デコードされた値はQGCのFactシステムに格納され、QMLから宣言的にバインドできます。そのため、パネルを追加する際に中間的な連携処理を実装する必要はありません。
<message id="200" name="DRONE_HEALTH">
<field type="float" name="battery_temp">Battery C</field>
</message>
Qt Design Studioで作成するカスタムパネル
今回のPoCでは、テレメトリパネル、メッセージログ、ビデオウォールなどをQMLファイルとして配置用フォルダに格納します。それぞれをフローティングウィンドウとして生成し、任意のディスプレイ上に配置したり、メインウィンドウ内にドッキングしたりできます。ファイルを削除すればパネルも削除され、各パネルは機体のライブデータにバインドされます。
Qtでは、UIの作成に必ずしもアプリケーション開発者は必要ありません。Qt Design Studioをスタンドアロンのデザインツールとして使用することで、デザイナー自身が機体データのインターフェース定義を再現したモックを使ってパネルをレイアウトし、アプリケーションが直接読み込めるファイルとして保存できます。

Qt Design Studioで、機体データのインターフェース定義を再現したモックを使ってパネルを編集。
実装
QMLエンジンは任意のURLからコンポーネントをインスタンス化できるため、固定されたリソースパスから解決するのではなく、配置用フォルダからパネルを検出できます。1つのURLインターセプターを使用することで、組み込みインターフェースをファイル名に基づいて上書きできます。
QUrl OverrideInterceptor::intercept(const QUrl &url, DataType) {
if (url.scheme() != QStringLiteral("qrc"))
return url;
const QString candidate = m_dropDir.filePath(url.fileName());
return QFile::exists(candidate) ? QUrl::fromLocalFile(candidate) : url;
}
Qt Design Studio向けには、スクリプトがダイアレクト定義を読み込み、機体データのインターフェース定義を再現するモックQMLモジュールを生成して、プロジェクトのmockImports配下に配置します。同じインポートが、デザインツール内ではモックに、ランタイムでは実際のアプリケーションオブジェクトに解決されるため、完成したパネルを変更せずにそのまま製品に組み込めます。
2D・3Dマップ
多くの地上管制ステーションでは、プロバイダーから取得した地図画像を表示するため、外観が固定され、ネットワーク接続も必要になります。この地上管制ステーションでは、地図データからマップそのものを描画し、色、レイヤー、ラベルを指定する1つのJSONスタイルファイルに従って表示します。このファイルは無料のMaputnik エディターで視覚的に編集でき、ネットワーク接続なしでも動作します。
3Dビューは、運用エリアに対応する2つのデータファイルから構成されます。建物のフットプリントと高さを示すOpenStreetMapのデータと、地形の標高グリッドです。この2つのファイルを置き換えるだけで、世界の別の地域へシーンを切り替えられます。また、どちらのデータも地域ごとにダウンロードできるため、オフィスで設定した地上管制ステーションを、ネットワーク接続のない現場でもすべての機能を維持したまま使用できます。
-webp.webp?width=1919&height=1074&name=2D%20Map%20(1)-webp.webp)
MapLibre 2Dマップのスタイルをカスタマイズ

3D運用ビュー:地形、構造物、航空機を実際の高度で表示。
実装
2DスタイルにはMapLibreのスタイルドキュメントを使用します。3Dシーンでは、OpenStreetMapから抽出したデータを使って建物を立体化し、DEM(GeoTIFF)から地形の標高を取得します。地形のテクスチャには現在の2Dスタイルを再利用するため、2Dと3Dの両方で統一した外観を実現できます。
テーマ、ブランディング、アイコン
カラーパレット、アプリケーション名、ウィンドウアイコンも起動時にファイルから読み込まれます。そのため、地上管制ステーションは起動時から指定したブランドとテーマが適用された状態になります。
製品ごとに個別のコードベースを維持する代わりに、いくつかの設定ファイルを変更するだけで、同じビルドを複数の異なる製品として展開できます。

アプリ名とロゴを設定

テーマを選択。
実装
テーマとブランディングについては、起動時にプラグインがJSONファイルと画像ファイルを読み込むだけで、ほかに特別な処理は必要ありません。
設定から実行へ
設定が完了したら、アプリを実行できます。地上管制ステーションは、選択したマップスタイル、カラーパレット、テレメトリ、カスタムパネル/ウィンドウが適用され、ブランディングとテーマが反映された状態で起動します。
-webp.webp?width=1909&height=953&name=Multi-panel%20(1)-webp.webp)
Qt Design Studioのワークフローで実現するカスタムの埋め込み/フローティングパネル

カスタムスタイルを適用したMapLibre 2Dマップ
-webp.webp?width=1917&height=886&name=Mission%20Plan%20(1)-webp.webp)
3D運用ビュー:地形、構造物、航空機を実際の高度で表示。
メンテナンスとメインラインとの差分
QGCの開発者ガイドでは、フォークしてcustom-exampleをコピーするよう案内されており、フォークすること自体は想定されています。ただし、メンテナンスコストは、フォーク内でどれだけ変更を加えるかに比例します。同ガイドでも、次のように明記されています。
「QGCのメインラインソースへの変更は、最小限に抑えることが最善です。」
設定レイヤーを設けることで、メインラインとの差分をほぼゼロに抑えられます。また、最新のアップストリームに対して定期的に再ビルドすることで、残っている差分も継続的に把握できます。汎用的に役立つ変更については、今回の取り組みで候補となった3Dビューアーの地形標高サポートのように、アップストリームへコントリビュートすることで差分を完全になくすことができます。これはQGCプロジェクト自体が推奨している方法でもあります。
同様の取り組みをご検討ですか?ぜひご相談ください
今回の取り組みは概念実証(PoC)であり、議論の題材にするためのものです。QGroundControlをベースに製品を開発している、あるいは採用を検討している場合は、今回構築した内容やその仕組み、そして皆さまの製品に設定レイヤーを導入するとどのような形になるのかをご紹介します。
お問い合わせ
ライセンスと規制上の考慮事項
QGroundControlはApache 2.0とGPL v3のデュアルライセンスで提供されており、どちらを選択するかによって、出荷する製品に適用される義務が異なります。
GPL v3では変更内容を公開する必要があります。一方、Apache 2.0では変更内容をプロプライエタリとして維持できますが、その場合は商用Qtライセンスが必要になります。
この選択は、企業がどの部分をプロプライエタリとして維持できるかに関係するため、コードを書いた後で見直すよりも、開発を始める前に方針を決めておくほうが、はるかに少ないコストで済みます。
詳しく見る