質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

7794閲覧

姿勢センサーでiPad、iPhoneの傾き角度を得たい

Galakuta09

総合スコア18

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/03/15 10:16

###前提・実現したいこと
iOSで、カメラのライブビュー映像にUFO画像を合成するアプリを作っています。
実際に空に浮かんでるかのように、カメラを上に向けるとUFOが下に、下に向けると上に、右を向くと左に、左を向くと右に動くようにしたいです。
UFOを上下左右に動かすためにはカメラの向いている仰角と、方角を知らねばなりませんが、思うようにいかずに困っています。

CoreMotionのattitudeでpitchの値で、デバイスを前後に倒した角度が求められることはわかりました。
しかしデバイスを垂直に立てた状態を90度として、画面が上になるように奥に倒そうが、下になるように手前に倒そうが、同じように90度から角度が減るので、カメラが上を向いているのか下を向いているのか判断できません。
そのため、重力加速度gravityのzの値(画面が上向きならマイナス、下向きならプラス)を見て、判断していますが、このやり方でいいんでしょうか?
ただしpitchの値の増減の境が、必ずしもデバイスを垂直に立てた場合の90とならず、88や86くらいの不定な値になることが多いので、90を想定して処理をしていると値が飛ぶことがあり、困っています。

方角についてはCoreLocationの電子コンパスを使っています。
デバイスを垂直に立てたあたりではちゃんと方位角がわかるのですが、カメラを45度程度以上に向けると値が大きく変わってしまい(たとえば180くらいだったのが300を超えたり)、表示していたUFOが勝手に飛んでいってしまい困っています(苦笑)

###発生している問題・エラーメッセージ
要は、上下左右どこにカメラを向けてもその仰角と方位角がわかればいいのですが、値がはっきりしなかったり、向ける方向によって値が大きく変わってしまうため困っています。
いい方法はないでしょうか。

###該当のソースコード

Swift

1 2/モーションセンサー 3motionMgr = CMMotionManager() 4//更新頻度(秒) 5motionMgr?.deviceMotionUpdateInterval = 0.1 6//姿勢センサースタート(真北基準で) 7motionMgr?.startDeviceMotionUpdates(using: CMAttitudeReferenceFrame.xTrueNorthZVertical, to: OperationQueue.current!, withHandler: { (data, error) in 8 //ラジアンから変換 9 let pitchDeg = 180 * data!.attitude.pitch / M_PI 10 //重力加速度 11 let gravityZ = data!.gravity.z //画面が上なら-1.0、下なら1.0、垂直なら0 12 13 if Double(gravityZ) > 0 { 14 //画面下向き時 15 //デバイス垂直を0度とした角度 16 self.angle = 90 - pitchDeg 17 } else { 18 //画面が上向きならそのままのpitch角を使用 19 //デバイスを垂直時を0度とした角度 20 self.angle = pitchDeg - 90 21 } 22}

###試したこと
姿勢センサーのpitchは、デバイスのZ軸が少しでも傾いていた場合、値の境が88とか86とかになってしまうような感じです。

###補足情報(言語/FW/ツール等のバージョンなど)
Swift3、Xcode8、iOS10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2017/03/16 02:34

画面を横向きにしてデバイスを立てるとpitchは0付近ですか?
Galakuta09

2017/03/17 07:20

ご返事ありがとうございます。おっしゃるとおり0付近の値を返します。
guest

回答2

0

ベストアンサー

回転というのは順番を入れ替えると通常は別の結果になります。
(実際にx軸に90度回してからy軸に90度回したり、y軸に90度回してからx軸に90度回してみてください。)

つまり姿勢を三軸の回転角度で表してある場合は、
どの姿勢を基準に
どういう順番で回してあるか
を確認することが重要になります。


さて、あなたが期待している量はデバイスを鉛直上向きに立てて、カメラ(z軸)を磁北に向けた状態を基準に
yaw(y)->pitch(x)->roll(z)の順番に回した量ですが、

おそらく実際得られるデバイスの姿勢は
画面が水平上向きで、y軸が磁北を向いている状態を基準にして、
yaw(z)->pitch(x)->roll(y)の順番に回した量です。

この表現だと、デバイスを垂直に立ててz軸を少し回すと、
pitchが90度にならないことがわかると思います

IOSやSwiftに全然詳しくないので、もっと直接的な方法があるかはわからないのですが、
愚直にやるなら、
姿勢を回転行列なりクォータニオンで取得して、
あれこれ計算してあなたが期待したオイラー角に変換します。


ところでやりたいことが、
デバイスを中心としたワールド座標上に固定されたUFOを
カメラに射影する感じだとすると、
回転行列を使ってUFOのデバイス座標を計算することになるので、
わざわざ角度を取得する意味は無いと思います。

投稿2017/03/16 02:50

編集2017/03/17 13:59
ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Galakuta09

2017/03/17 10:11

ご返事ありがとうございます。 クォータニオン、回転行列というのはこの件を調べだしてから時々目にしますが、解説サイトを読んでもピンと来ず、まだよくわかっていません。必要とあらば勉強してみようと思います。 なおUFOの方は多少でもふらふらと座標上を動かしたいと思っています。動いてる感じが出ればいいので、位置計算は厳密じゃなくてもいいのですが。
ozwk

2017/03/17 14:07

伝わっているか怪しいので補足すると デバイスを垂直に立てた状態(z軸少し回っている)と言うのは 例えばpitchが86度になっていれば 机の上においた状態から z軸に90度(yaw) x軸に86度(pitch) y軸に90度(roll) という解釈です。
Galakuta09

2017/03/18 11:37

回転に順番があるのですね? たしかに最終的姿勢が同じでも、順番が違うと値に変化があるような気もします。 ただ、よほど固定していないと値が大きく変わることがあるので「いかにも!」と言えないところではあるのですが。 また、寝かせた状態での使用をメインに想定されたセンサーを、立ててつかうことで値が期待通りにならない点もあるのかもしれません。 たとえば方位磁石を立てて使うと正しく北が測れないように。
ozwk

2017/03/18 12:20

90度ピッチアップした状態と、 90度ヨー、90ピッチ、-90度ロールした状態は同じになります。 1つの同じ状態に複数の全然異なる表現がありうるということは、 少しの誤差があるだけで値がかなり変わってしまいます ジンバルロックで調べてみてください
Galakuta09

2017/03/20 03:16

ジンバルロックは、完全理解とはいきませんがなんとなくわかりました。 その他の点についても調べたり、別の方法で実現できないか探ってみます。
guest

0

必ずしもデバイスを垂直に立てた場合の90とならず、88や86くらいの不定な値になることが多い

プログラミングと実際の半導体デバイスの差を考慮する必要があります
理想と現実の差みたいなもので、プログラムは自分の理想を作れますが
現実には周りから様々な要因で影響を受けた結果が現れます

CoreMotionのattitudeでpitchを計測して
どのような動きをするのか検証してみたら良いと思います

そんな暇がないというのであれば
フィルターをかけてみるのが最初の1歩でしょうか

投稿2017/03/16 02:23

aja

総合スコア3733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Galakuta09

2017/03/17 09:49

ご返事ありがとうございます。 フィルターというのはハイパスフィルター/ローパスフィルターというものでしょうか。 ネットで調べ、現在値の9割と前の値の1割を加算する処理をしてみましたが、やはり、多少なりともZ軸中心の傾きがあると90前後の値は飛んでしまいました。 センサーの仕様上、デバイスを垂直に立てた前後はpitchの値は計測しにくいのかもしれません。(そもそも90を境にどちらに倒しても値が減るというのも困った仕様ですし) ポケモンGOや、向けた方向の星図を表示するアプリとかあるので、何かの方法でスムーズな角度が得られるんでしょうね…。
ozwk

2017/03/17 14:00

いや、pitchの値は正しいんです。ただあなたの思っている角度と違うだけで。
Galakuta09

2017/03/18 11:41

ajaさん とりあえず5回値を取ってその中間値を使用するようにしてみました。今回の件では顕著な効果は見られませんが、センサーノイズを減らす上ではこういう地味な作業も必要なんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問