デザイン会社 btrax > Freshtrax > ドローンをハック!Swiftで...
ドローンをハック!SwiftでiPhoneの専用コントローラをプログラミングしてみよう
ドローンと言えば今最も注目を集めるテクノロジーの1つだ。Amazon.comがドローンを宅配システムに使う実験をしているし、空撮や測量用のドローンのサービスを提供するスタートアップも誕生している。今後、様々なところでドローンの利用が進んでいくだろう。
一方で、首相官邸にドローンが落下するなどの事件が起こり、日本では危険という印象も強いと聞く。2015年12月には、アメリカ連邦航空局(FAA)はドローン(約250g以上)を所有者に登録を義務づける制度を発表した。このような法規制は徐々に進んで行くだろう。
ラジコン飛行機とは違う
ラジコンとどう違うの?という疑問を持つ人も多い。ドローンに空撮用の小型カメラを取り付けて、ラジコンと同じような形のコントローラーから操作するだけでは、正直ラジコンとの違いもよくわからない。
しかし、ドローンはセンサ、カメラを駆使して自律飛行ができたり、プログラミングを組んで操作できるという特徴があり、コンピュータが空を飛んでいると言った方が正しい。今回は、この空飛ぶコンピュータを操作するオリジナルのiPhoneアプリを作ってみよう。
高性能手のひらドローン パロット ミニ ドローン エアボーン ナイト
今回使用したのは、パロット ミニ ドローン エアボーン ナイト (Parrot Airborne Night MiniDrone)というドローン。手のひらに乗る小型で、重さはわずか60gほど。 15,000円前後で買える安価なドローンだ。飛行の安定性は高く、iPhoneやAndroidのアプリから簡単に操作することができる。日本でも購入できるようだ。
実は、Parrotのドローンは、SDKが提供されており、簡単にプログラミングすることができる。自分だけのオリジナルのiPhoneコントローラアプリを作ることはもちろん、IoTと連携させたり、ラズベリーパイなどを使って専用のコントローラを作ることや、Webブラウザから操作するなど様々なことが可能になる。しかも、制御プログラムはいたって簡単に書ける。4つの羽を制御するプログラムを書く必要はもちろんなく、離陸、着陸、回転、前進などの簡単な命令を実行するだけでドローンを思うように動かすことができる。今回は、まずiPhoneからドローンを制御して、ジェスチャーで飛ばしてみよう。
作るのはジェスチャーコントロールが可能なシンプルドローンコントローラ
FreeFlight3というアプリを使って操作できるのだが、左の円で左右の回転と上下の移動、右の円で前後左右の移動を行うため、操作が少し難しい。羽を4つ持つクアッドコプターは、前後左右という概念はその原理上はなく、360度、真後ろにも進むことができる。
そこで今回は、
・離陸(take off)
・着陸(land)
・宙返り(flip)
だけを行うことができるコントローラを作る。iPhoneを縦に振り上げると、宙返り(flip)する機能を実装した。
プロジェクトの作成
XCodeを開き、新しいプロジェクトを作成する。テンプレートは、Single View Applicationで構わない。
SDKのダウンロード
Parrotが提供しているチュートリアルに沿って進めていく。まず、SDKをダウンロードする。この記事の執筆段階では、Version 3.7.5だ。
SDK version 3.7.5 frameworks というリンクをクリックして、SDKをダウンロードする。ZIPファイルを解凍して、すべてのFrameworkをプロジェクト内にコピーするのだが、その後にuthashとmavlinkを削除する。この時、ゴミ箱に移動するのではなく、Remove Referenceを選択してほしい。
試しにビルドしようとしても、以下のようなエラーが出てビルドができない場合がある。これは、ParrotのフレームワークがBitcodeに対応していないためだ。Build Settings から Enable Bitcode を Noにすれば良い。これでSDKを使う準備は整った。
ld: '<プロジェクトのパス>/ARSDK3_iOS_3_7_5/libARDiscovery.framework/libARDiscovery(ARDISCOVERY_BonjourDiscovery.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
近くのドローンを見つける
早速近くのドローンを見つけるプログラムを書いてみよう。チュートリアルはObjective-Cで書かれているが、可読性を高めるためになるべくSwiftで書いていく。ライブラリもObjective-Cなので、Bridging-Header.hを作成して、swiftからObjective-Cのソースコードを呼べるようにする。
#import <libARDiscovery/ARDISCOVERY_BonjourDiscovery.h> #import <libARDiscovery/ARDISCOVERY_Device.h>
ドローンを探すコードは、以下のように簡単に書ける。BLEでデバイスを見つけた時に、discoveryDidUpdateServicesが呼ばれる。複数台のドローンが周囲にある時には、複数台の情報を取得できる。
class ViewController: UIViewController { override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) registerReceivers() startDiscovery() } func startDiscovery() { ARDiscovery.sharedInstance().start() } func registerReceivers() { NSNotificationCenter.defaultCenter().addObserver( self, selector: Selector("discoveryDidUpdateServices:"), name: kARDiscoveryNotificationServicesDevicesListUpdated, object: nil ) } func discoveryDidUpdateServices(notification: NSNotification) { if let userInfo = notification.userInfo { let deviceList = userInfo[kARDiscoveryServicesList] // デバイスを発見したら呼ばれる print(deviceList) } } }
お作法として、ViewControllerが非表示になるタイミングでレシーバーを解除する。
class ViewController: UIViewController { .... (中略) .... override func viewDidDisappear(animated: Bool) { super.viewDidDisappear(animated) unregisterReceivers() stopDiscovery() } func unregisterReceivers() { NSNotificationCenter.defaultCenter().removeObserver(self, name: kARDiscoveryNotificationServicesDevicesListUpdated, object: nil) } func stopDiscovery() { ARDiscovery.sharedInstance().stop() } }
この状態で実機にビルドしてドローンに電池を入れると、10秒ほどでドローンを検知し、以下のようなログが出力される。
2015-12-14 16:57:59.531 drone-tutorial[1107:339869] New device Blaze_012778 Optional(( "<ARService: 0x15d8d6e0>" ))
ドローンへ接続
デバイスを発見した後に、ドローンに接続する。
サンプルコードも、チュートリアルも記述がObjective-Cで、メモリのアクセスを多用しているので、swiftに直すのが面倒だ。そこで、Drone用のクラスをDTDroneをObjective-Cで作り、ViewControllerから呼び出すことにする。
Swiftから呼び出せるように、DTDrone.hをBridging-Headerに追加する。
#import <libARDiscovery/ARDISCOVERY_BonjourDiscovery.h> #import <libARDiscovery/ARDISCOVERY_Device.h> #import "DTDrone.h"
簡単のため、見つかったデバイスの1台目に自動的に接続することにする。
class ViewController: UIViewController { var isConnected = false ....(中略).... func discoveryDidUpdateServices(notification: NSNotification) { if let userInfo = notification.userInfo { let deviceList = userInfo[kARDiscoveryServicesList] // 未接続状態なら、1つ目のデバイスに接続する if isConnected == false { let serviceList = deviceList as! [ARService] isConnected = DTDrone.sharedInstance().connectWithService(serviceList[0]) } } } ....(中略).... }
ドローンを見つけるまでは待機画面を表示させておき、ドローンを見つけた段階で、離陸、着陸、一回転のボタンを表示させることにした。
ドローンを飛ばす
デバイスに接続すると、ドローンを操作できるようになる。以下のコードをボタンタップなどのイベントで呼び出せば良い。
DTDrone.sharedInstance().takeoff() // 離陸 DTDrone.sharedInstance().land() // 着陸 DTDrone.sharedInstance().flip() // 一回転
デバイスに接続できた時点で、TakeOffやLandのボタンを表示するようにする。ドローンに接続した状態で、TakeOffのメソッドを呼び出すとDroneが離陸する。その後、Landのメソッドを呼び出すと着陸する。これで、離陸と着陸、宙返りだけできるコントローラが完成した。
ジェスチャーで操作する
ここまでこれば分かるが、iOSのAPIから取得したイベントや、他のシステムと連携してドローンを動かすことも簡単だ。そこで、ジェスチャーでドローンを操作してみよう。
iOSを振り上げるとフリップを決めてみよう。加速度を取得し、z方向の加速度の絶対値が一定以上になった時にFlipのメソッドを呼び出す。
class ViewController: UIViewController { .... (中略) ... override func viewDidAppear(animated: Bool) { .... (中略) ... motionManager.accelerometerUpdateInterval = 0.1 let accelerometerHandler:CMAccelerometerHandler = { (data: CMAccelerometerData?, error: NSError?) -> Void in if self.succeeded && abs(data!.acceleration.z) > 3.5 { DTDrone.sharedInstance().flip() } } motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue()!, withHandler: accelerometerHandler) }
たった1万5千円程度の安価なドローンでも、簡単なコードで制御することができる。今回はiPhoneアプリから制御したが、画像認識と組み合わせたり、インターネット上のシステムと連携させたりと、いろいろなことができる。ぜひドローンを買って遊んでみてほしい。なお、ドローンの一回転のアクションは、墜落してそのままドローンが壊れてしまうことがあるので、あまり多用しないでください。
ソースコードはこちら
CES 2025の革新を振り返りませんか?
1月11日(土)、btrax SFオフィスで「CES 2025 報告会: After CES Party」を開催します!当日は、CEOのBrandonとゲストスピーカーが CES 2025 で見つけた注目トピックスや最新トレンドを共有します。ネットワーキングや意見交換の場としても最適です!