Swift

スノーボードと学ぶCoreMotion

今回は


前回に引き続き、冬っぽいテーマを探しました。
そこで、傾きによって光るスノーボードを作ってみたいなと漠然と思っておりましたので

iPhoneを使用して、簡単に傾きの角度が取得できないか調べてみました。

その中で、CoreMotion1を使うことで、簡単に傾きが取れることがわかりましたので、概要をまとめることとしました。

CoreMotionについて


iPhoneには加速度センサ、ジャイロセンサ…などといった様々なセンサーが搭載されています。
CoreMotion2は、これらのセンサーからの情報にアクセスして、アプリでの使用を可能とするフレームワークです。

CMAttitude


今回はその中でもiPhone端末の傾きから、左右の傾き情報が取得可能な、CMAttiudeクラスを使って見みました。
ここでは、pitch、roll、yawの3つの端末の傾きの角度を取得することができます。

取得できる角度を、図でまとめてみました。

①pitch

図のx軸方向を中心軸とした時の、端末の傾きの角度

②roll

図のy軸方向を中心軸とした時の、端末の傾きの角度

③yaw

図のz軸方向を中心軸とした時の、端末の傾きの角度

今回は、この3つのうち①のpitchを使って、傾きの取得にのぞみました。

実際の計測方法を考える


iPhoneを使って、端末から傾きの情報を取得できることがわかりましたので、実際に計測する方法を考えました。

試みその1


最初はスノーボードの板に対して、垂直にiPhoneを立てて計測する方法を考えました。
この方法は、バインディングの背の部分に端末を貼り付けて、計測を行うことで角度を取得できないかと試みたものです。

しかしこの試みは、次の問題点によって見送ることにしました。

基準角度の考慮漏れ


この試みでは端末が地面に対して、垂直に立った状態を0度として、そこからpitchの値を参照して、何度傾いたかを取得しようと考えていました。

しかし、実際に使ってみましたところ、地面に対して水平になっている状態を0度として扱われるため、当初考えていた方法ですと値を調整して扱う必要があることがわかりました。

計測開始時にCMAttitudeReferenceFrame3にて、基準角度を指定できるようですが、z軸が垂直な状態が前提のものが多い為、見送ることとしました。

試みその2


端末が地面に対して、水平になっている状態を0度として扱う必要性があることがわかったので、板に付けて計測することとしました。

この方法ですと、端末が下に傾く状態(トゥエッジ)ですと、マイナスの角度が取得できます。
また、端末が上に傾いた状態(ヒールエッジ)は、プラスの角度が取得できます。

これによって、滑っている斜面に対して

  • 板をどれぐらいの角度傾けているか
  • 前と後ろのどちらに重心がかかっているか

がそれぞれ、判定できるようになります。

実際に実装してみる


以上を踏まえて、傾きの値を取得、判定をこちらで試してみました。

import CoreMotion

class ViewController: UIViewController {
    let motionManager = CMMotionManager()
    let deg = 180/Double.pi

    override func viewDidLoad() {
        super.viewDidLoad()

        motionManager.deviceMotionUpdateInterval = 0.1

        motionManager.startDeviceMotionUpdates(to: OperationQueue.current!) { (deviceMotion, error) in
            let pitch = deviceMotion!.attitude.pitch * deg

            if pitch == 0 {
                print("フラット")
            } else if pitch < 0 {
                print("トゥエッジ:\(-pitch)度")
            } else {
                print("ヒールエッジ:\(pitch)度")
            }
        }
    }
}

備考


deviceMotionUpdateInterval

ここでは、端末の傾き情報を取得する間隔を指定しています。
単位は秒となるので、ここでは0.1秒毎に傾き情報が更新されることになります。

startDeviceMotionUpdates(to:withHandler:)

startDeviceMotionUpdatesを呼び出して、端末の傾き情報の取得を開始します。
情報はhandler内で、deviceMotionUpdateIntervalに設定した間隔で更新されます。

pitch

CMAttitude.pitchから取得される傾き情報の単位は、ラジアン(rad)になります。
(このままですと、取得した値もパッと見でイメージするのが難しいです)
そのため、以下の公式に当てはめて、度数法(deg)で表現しています。deg=rad×180π

https://qiita.com/koiwai2020/items/7d511698d08ad0364686

補足:

X傾斜角度

Y傾斜角度

Z傾斜角度①

Z傾斜角度②