[watchOS 3] Apple Watch でデバイスモーションを取得する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Device Motion on Apple Watch

watchOS 3 から CoreMotion フレームワークを利用して、Apple Watch の様々なデバイス情報が取得できるようになりました。
今回は取得することのできる、いくつかの情報について説明したいと思います。

前提

Apple Watch の方向を以下のように定義します。

  • 文字盤 :
  • 底面 :
  • 12 時方向 :
  • 6 時方向 :
  • 3 時方向 :
  • 9 時方向 :

CMDeviceMotion

CMDeviceMotion オブジェクトには以下のようなデバイスモーションの基本情報が含まれます。

  • Attitude
  • Gravity
  • Rotation rate
  • User acceleration

Attitude

姿勢角 を表します。
CMAttitude クラスで表されるこのプロパティは Double 型の以下の値を保持します。

  • roll
  • pitch
  • yaw

roll

roll(ロール) は Apple Watch の前後 Y 軸 に関する回転角を表します。
値の範囲は から π までの弧度法(ラジアン)で表現されます。
飛行機が左右に旋回するようにデバイスを傾けると、この値が増減します。

pitch

pitch(ピッチ) は Apple Watch の左右 X 軸 に関する回転角を表します。
値の範囲は -π/2 から π/2 までです。
これらを超えた場合、値は減少し roll が π 分回転した値になるようです。
Apple Watch の前方を上下に傾けることで値が増減します。

yaw

yaw(ヨー) は Apple Watch の上下 Z 軸 に関する回転角を表します。
値の範囲は から π までです。
Apple Watch の底面を床に接地した状態で、コマのように回転させることで値が増減します。

Gravity

重力加速度 を表します。
CMAcceleration クラスで表されるこのプロパティは Double 型の以下の値を保持します。

  • x
  • y
  • z

Apple Watch の底面を床に接地した状態では (x, y, z) は (0, 0, -1) となります。
Apple Watch を縦に置くと (0, -1, 0) というように変化します。
x, y, z はそれぞれ

  • 右、前、上が正の値
  • 左、後、下が負の値

となっています。
値の範囲は -1 から 1 までで、合計の加速度はこの値に User acceleration を加えたものになります。

Rotation rate

回転率 を表します。
CMRotationRate クラスで表されるこのプロパティは Double 型の以下の値を保持します。

  • x
  • y
  • z

これらはそれぞれ X 軸、Y 軸、Z 軸に関する回転率(ラジアン / sec)となりますので、速く回転させるほど値は大きくなっていきます。

User acceleration

ユーザーがデバイスに与えている加速度 を表します。
Gravity と同様に CMAcceleration クラスで表されます。
この値に Gravity を加えたものが合計の加速度となります。

サンプルコード

CoreMotion を利用するプログラムは複雑ではありません。
値の取得だけであれば以下のような短いコードで実現可能です。

import CoreMotion

class InterfaceController: WKInterfaceController {

    let motionManager = CMMotionManager()
    let queue = OperationQueue()

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        if !motionManager.isDeviceMotionAvailable {
            print("Device Motion is not available.")
            return
        }

        motionManager.startDeviceMotionUpdates(to: queue) { (deviceMotion: CMDeviceMotion?, error: Error?) in
            if error != nil {
                print("Encountered error: \(error!)")
            }

            if deviceMotion != nil {
                print("attitude = \(deviceMotion!.attitude)")
                print("gravity = \(deviceMotion!.gravity)")
                print("rotationRate = \(deviceMotion!.rotationRate)")
                print("userAcceleration = \(deviceMotion!.userAcceleration)")
            }
        }
    }
}

CMMotionManager のインスタンスを生成し startDeviceMotionUpdates() メソッドを実行することで、一定間隔でハンドラが呼び出され、デバイス情報を参照することができます。
Apple も サンプルコード を公開しているので、興味のある方は確認してみてください。

さいごに

デバイスモーションということで結構カラダを動かしました。
サンプルコードを作りながら Apple Watch をブンブン振り回すのは、楽しくもあり恥ずかしくもありました。
今回から 会社が支給してくれた Apple Watch Series 2 を利用してみたのですが、Xcode からのプログラム転送速度も Series 1 に比べて格段に速く、ストレスフリーで開発することができました。
個人的にはとてもデバッグしやすくなったと感じました。
いいこと!

リンク

ミレニアム・ファルコン製作日記 #41

41 号 表紙

mfd_41_1

パーツ

mfd_41_2

mfd_41_3

mfd_41_4

成果

mfd_41_5

今回の作業は以下の 2 つでした。

  • 砲操作プラットホームを組み立てる
  • 上部砲塔ベイを組み立てる

これまでで一番細かいパーツを扱った作業かもしれません。
上部砲塔ベイには LED を取り付けたので、ここもライトアップされることでしょう。

砲塔ベイは フォースの覚醒 にも登場してきました。
ですが、フォースの覚醒でフィンが操作したのはおそらく下部砲塔ベイです。
よって、今後もう一対の砲塔ベイの組み立て作業も発生すると思います。

ロール・ピッチ・ヨー

今回ブログ本編で紹介した、これら回転運動の考えは 週間 スター・ウォーズ ミレニアム・ファルコン でも紹介されています。
以下、引用。

すべてのパイロットは、ロール(傾点)・ピッチ(仰角変化)・ヨー(振向)という3つの基本的な飛行制御技術をマスターしなければならない。 高速飛行する宇宙船で上昇・下降・急旋回を同時に行うには、冷静な頭脳と素早い反射神経、そして船の位置を三次元で把握する直観力が要求される。

映画では簡単に宇宙船を飛ばしていますが、それはとても難しいことなのですね。
改めてハン・ソロは非常に有能なパイロットであることがわかりました!

それではまた次回。

May the Force be with you!