2017年3月9日木曜日

モーションセンサー、うまくいくようないかないような



モーションセンサーには以下のようなものがある。
値の範囲は決まっているはずだが、センサーの精度の問題なのか、範囲の上限/下限値にならないことも多く、上限/下限値をまたいだ処理をさせると値が飛んでしまうこともあり困る。
プロはどうやってスムーズな処理をしてるんだろう? 誰かおせーて!!
  • 加速度センサー(Accelerometer)
    • X軸、Y軸、Z軸方向に動かした場合、どちらの方向にどれだけ加速度がかかったか
  • ジャイロセンサー(Gyro)
    • X軸、Y軸、Z軸を軸として傾けた場合の、1秒あたりに傾いたラジアン角を得られる(角速度)
  • 姿勢センサー(Attitude)
    • X軸、Y軸、Z軸を軸として傾けた場合の絶対角を得られる。水平な台の上に画面を上にして寝かせて置いた時がそれぞれ0度。
    • X軸中心の前後の傾きがpitch
      • 画面上で寝かせて0度。起こしていくと増えていき、垂直で90度。さらに画面下向きに寝かせていくと減っていき0度に。
      • 増えていった値が90度を境に減るはずだが、時には87度前後で減り出したり、よくわからない。
    • Y軸中心の左右の回転がroll
      • pitchが90度を超えると急に-150度とかになったり、わからない
    • Z軸中心の左右の傾きがyaw
      • これがわずかに傾いてるだけでもpitchの値が90までいかないうちに減り出すことがあるようだ。
  • 重力加速度(Gravity)
    • 地球の重力に対しての向き
    • X軸はLandscapeでホームボタンが右なら-1.0、左なら1.0、Portrateなら0
    • Y軸はPortrateでホームボタンが下なら-1.0、上なら1.0、Landscapeなら0
    • Z軸は画面が真上なら-1.0、垂直に立てると0、画面が真下なら1.0
ライブラリはあらかじめCoreMotionをimportしとく。
import CoreMotion //モーションセンサー

モーションマネージャーはインスタンス変数として作っておかないと、ARCですぐに消されちゃうので注意。
var motionMgr:CMMotionManager?

センサーの設定とスタートまで

//モーションマネージャーは各種センサー共通
motionMgr = CMMotionManager()
//更新頻度(秒)
motionMgr?.deviceMotionUpdateInterval = 0.1 //姿勢センサー
//姿勢センサースタート(クロージャでセンサーが更新された時の処理を書く)
motionMgr?.startDeviceMotionUpdates(to: OperationQueue.current!, withHandler: { (data, error) in
        let pitchDeg = round(180 * data!.attitude.pitch / M_PI)
        let rollDeg = round(180 * data!.attitude.roll / M_PI)
        let yawDeg = round(180 * data!.attitude.yaw / M_PI)

})

//姿勢センサーの停止
motionMgr?.stopDeviceMotionUpdates()

ローパスフィルター

センサーの値がノイズによってばらけることが多いらしく、前回検出した値との加算平均を取る処理(これをローパスフィルターとかハイパスフィルターとか言うらしい)をした方がいいそうである。
最新の値の90%と、前回の値の10%を足すわけですな。

//ローパスフィルター処理(ここでは0.9がレート)
var outputValue:Double
if (self.prevAngle != nil) {
        outputValue = (pitchDeg * 0.9) + (self.prevAngle! * (1.0 - 0.9))
    } else {
        outputValue = pitchDeg
    }
self.prevAngle = outputValue

他のセンサー使用時

センサーの値を取り出す各種プロパティは省略。


//各センサーの更新頻度(秒)設定
motionMgr?.accelerometerUpdateInterval = 0.1 //加速度センサー
motionMgr?.gyroUpdateInterval = 0.1 //ジャイロセンサー

//各センサーのスタート(引数は省略したが姿勢センサーと同様に)

motionMgr?.startAccelerometerUpdates() //加速度センサー

motionMgr?.startGyroUpdates() //ジャイロセンサー



//各センサー停止
motionMgr?.stopAccelerometerUpdates() //加速度センサー
motionMgr?.stopGyroUpdates() //ジャイロセンサー

参考サイト

0 件のコメント:

コメントを投稿