DJI公式アプリ+αなドローン操作アプリ(iOS)を作った話

## はじめに

DJI 製のドローンを触れる機会があったので、ドローンを操作できるiOS アプリを作ってみました。
ドローン操作アプリってハードル高そう🤢 と思っていたのですが、DJI が用意しているSDK を利用することで案外簡単に作ることができたので、敷居を下げるきっかけになればと思います。

### 書くこと

- 今回使用した DJI 製ドローン (Mavic 2 Enterprise) の基本的な概要
- DJI SDK を使った DJI 公式アプリ +α なアプリ作成の要点
- DJI SDK の辛いポイント
- DJI SDK を使用した写真の扱い方

### 書かないこと

- iOS アプリの基本的な作り方
- Onboard SDK / Payload SDK
- 詳細な実装方法、ソースコード

## 使用したドローン

ここでは、今回使用したドローン「Mavic 2 Enterprise」について説明します。
今回使用したドローンは、株式会社メディア・リース様から無償で貸していただきました。🙇

### Mavic 2 Enterprise

以下公式サイトより。

> Mavic 2 Enterpriseは、業務課題や今後の現場要件を見据え、現場従事者を支援するために設計されており、
新時代の業務の在り方を提案します。

上記の通り、業務使用に耐えうる高性能ドローンです。
具体的には以下のような特徴を持っています。

- 4K撮影、光学2倍、デジタル3倍ズームが可能なカメラ搭載
- 全方向障害物検知などによる高い飛行安全性

### コントローラー

Mavic 2 Enterprise のコントローラーは、iOS/Android 端末を接続して利用します。
機体の操縦は上部のコントローラー、カメラ映像やGPSなどの機体情報の確認は下部の iOS/Android 端末といった具合です。

![96F322E3F55AABA575C1A045CE4E3AB8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/5fa029f4-d03b-dada-3fb4-1a738b79f3b4.jpeg)

このコントローラーは、iOS/Android 端末を前提にしているので、もちろんDJI 公式の操縦アプリがあります。
機種によって利用できるアプリが違いますが、 Mavic 2 Enterprise の場合は、 [DJI Pilot](https://www.dji.com/jp/downloads/products/mavic-2-enterprise) です。
ドローンと接続すると、ドローンカメラからの映像や、機体の情報、写真撮影、カメラロールの閲覧などが可能です。
また、 Youtube などへの配信もアプリから行うことができます。

## 作ったもの

今回作成したアプリの機能は、ざっくりと以下です。

1. ドローンの基本的な操縦ができる
2. ドローンカメラでの撮影ができる
3. ドローンカメラで撮影した画像を位置情報と共に、バックエンド API に送信できる

このうち、 1 と 2 の機能は DJI 公式アプリで実現可能ですが、 3 に関しては自分でどうにかする必要があります。
そのため、これらの機能を1つのアプリで満たそうとすると、 DJI 公式アプリ + α のようなアプリを作ってあげる必要があります。

そこで今回作ったのが、以下のようなものです。
一目瞭然なんですが、メインの画面は DJI 公式アプリそのものです。
そこに「 + α 」として、Mediaボタンを押してから画像を送信するまでの部分を付け足した形です。

![0352EE8C8D650E7921819575C58472B5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/e108233d-d58e-5203-2857-39c7323a2f9f.gif)

以降では、DJI 公式アプリ + α アプリの作り方を説明していきます。

## DJI SDK

具体的な説明に入る前に、アプリを作成するために利用するDJI SDK を紹介します。

DJI は、 DJI 製品を扱うための、4つの SDK をオープンソースとして提供しています。
https://enterprise.dji.com/jp/sdk

- Mobile SDK: iOS/Android 向けの、コントローラーに接続して利用するタイプのアプリを開発するために、 API を提供する SDK
- UX SDK: iOS/Android 向けの、コントローラーに接続して利用するタイプのアプリを開発するために、 UI コンポーネントを提供する SDK
- OnBoard SDK: ドローン自体の機能を拡張するための SDK
  - 独自のセンサなどのハードウェア機能
  - ドローンの複雑な制御などのソフトウェア機能
- Payload SDK: 独自のペイロード (カメラ、センサなど) をドローンと統合するための SDK

今回は iOS/Android 向けのアプリなので、Mobile SDK と UX SDK を利用しました。

ただ、この Mobile SDK/UX SDK をちゃんと使おうとすると結構しんどかったです🤢

- 日本語の情報がほぼ存在しない
- iOS向けチュートリアルドキュメントが ObjectiveC で書かれているため、ゆとり Swift 世代お断り
  - GitHub のチュートリアルリポジトリには、 一部Swift のコードが置いてあるので、ドキュメントと GitHub のコードを見比べながらやることは可能

## DJI 公式アプリ + α アプリの作成要点

ここでは、DJI SDK を使用して、DJI 公式アプリ + α アプリを作るための要点を紹介します。

### 0. 前提

- iOS アプリのプロジェクトが作成されていること
  - Xcode 7.0 以上
  - iOS 9.0 以上
- iOS アプリのプロジェクトに、 Mobile SDK, UX SDK がインストールされていること

### 1. DJI Developer Center にアプリを登録

まずは、DJI Developer Center にアプリを登録して App Key を取得する必要があります。
これは、アプリ起動時に DJI Develeper Center の認証を通らないと Mobile SDK が利用できないためです。

フォームを適当に埋めて、CREATE ボタンを押すと、App Key が発行されます。
このとき、Package Name がアプリのID (iOS であれば Bundle Identifier) と一致している必要があります。

![1AB913682F97CD609AA318A206ADE47E.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/00bad5c9-6633-c46f-41ab-02e179628c89.jpeg)

### 2. DJI Developer Center 認証のためのコードを追加

アプリからドローンに接続する前に、 DJI Developer Center への認証を通しておく必要があります。
アプリ起動時、最初のビューが表示されたタイミングで、 `DJISDKManagerDelegate` プロトコルに準拠したクラスで実行します。

```swift
class ViewController: UIViewController, DJISDKManagerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        DJISDKManager.registerApp(with: self)
    }
...
```

このとき、上記の関数は Info.plist の `DJISDKAppKey` に AppKey を読みに行くので、 1 で取得した App Key を Info.plist に登録しておく必要があります。

詳細は、チュートリアルの ViewController.swift を参照してください。
https://github.com/DJI-Mobile-SDK-Tutorials/iOS-ImportAndActivateSDKInXcode-Swift/blob/master/ImportSDKDemo/ViewController.swift

### 3. DJI 公式アプリ画面の利用

次に、 DJI 公式アプリの UI の利用方法です。
DJI 公式アプリの UI は、 UX SDK の中に `DUXDefaultLayoutViewController` という ViewController があるので、これを利用します。
2の認証を行った上で、 `DUXDefaultLayoutViewController` を表示するだけで、ほぼ以下のような画面が描画されます。 (Media ボタン以外)
また、写真撮影などの各種機能もそのまま利用可能です。

![F46432A432D098FC11AC877C5452CD6D.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/499df8a1-0b1b-3dce-2c14-9edcfe17edd1.jpeg)


今回は、 SwiftUI を用いて開発したので `DUXDefaultLayoutViewController` を直接利用できませんでした。
ですが、 SwiftUI の常套手段である `UIViewControllerRepresentable` で包んであげるだけで利用可能だったので、ほとんど問題になりませんでした。

```swift
import SwiftUI
import DJIUXSDK

struct DefaultLayoutView: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> DUXDefaultLayoutViewController {
    return DUXDefaultLayoutViewController()
  }
  
  func updateUIViewController(_ uiViewController: DUXDefaultLayoutViewController, context: Context) {
  }
}
```

SwiftUI 最高😍

### 4. +α の追加

あとは、 ボタンを追加したり、遷移先画面を追加したり、自由自在です。

## まとめ

DJI SDKを使うと基本的なUIコンポーネント、機能が既に用意されているため、簡単にDJI公式アプリ+αなアプリが作れました。
一方でMobile SDK/UX SDKについては、情報がまだまだ足りなかったり、チュートリアルが古の言語で書かれていたりと、まだまだ辛いです🤢
また、SwiftUIネイティブ対応やSwift Package Managerへの対応などモダンなiOSアプリ開発への対応も待ち遠しい🤩