IPhoneでジャイロスコープを使用する際にサポートが必要です。特定の状況でのピッチ、ロール、ヨーに関するCMAttitudeの読みが理解できません。
これは私のコードです
- (void)handleDeviceMotion:(CMDeviceMotion*)motion {
NSLog(@"Yaw %f ",attitude.yaw * 180 / M_PI);
NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
NSLog(@"Roll %f ",attitude.roll * 180 / M_PI);
}
次の図のように、iPhoneが飛行機に横になっているとしましょう。
ピッチ、ロール、ヨーは(ほぼ)0度であり、軸を中心に回転すると、理解できる測定値が返されます。たとえば、デバイスを右に回すと、ヨーが減少し、ピッチアンドロールは0のままになります。
これで、iPhoneは次の位置になります。
そして、測定が再開されます。
読み取り値は次のとおりです。ヨー= 0、ピッチ= 90、ロール= 0
デバイスがこの軸を中心に回転するため、ピッチが増加します。
IPhoneをこの位置に移動する:
読み取り値は次のとおりです。ヨー= 30、ピッチ= 90、ロール= 0
繰り返しになりますが、デバイスはヨー軸を中心に回転するため、この値は変化し、他の値は変化しません。
ロール軸を中心としたデバイスの移動:
読み取り値は、ヨー= 0、ピッチ= 90、ロール= -20です。
今、私が理解できないこと。次の図のように、iPhoneを半径R(R> 0)の円の周りに移動します。
一方、ヨーは変化しますが、ピッチとロールは変化しません。
ヨーは変わらず、ロールも変わっていたと思います。
ユーザーがヨー軸を中心に回転することにのみ関心があるので、これをどのように補正できますか?
私が抱えているもう一つの問題はドリフトです。 iPhoneは、2番目の図に示す位置にあり、長時間(1分以上)静止している私の手に持っています。ヨーは絶えず増加します。漂流を補償する方法はありますか?
前もって感謝します
[〜#〜] update [〜#〜] Kayの提案に従いましたが、何も変わりません。私のコードの詳細。ユーザーがデバイスをYaw軸を中心に回転させた場合にのみ、Yawを使用してUIImageを回転させたいと思います。これは機能しますが、ユーザーが自分の垂直軸を中心に回転すると、ヨーが変化します。ユーザーが垂直軸を中心に移動すると、デバイスは独自のヨー軸を中心に回転しないため、これは正しくないと思います。私が間違っているのかもしれません。これは私の元のコードです:
- (void)handleDeviceMotion:(CMDeviceMotion*)motion {
CMAttitude *attitude = motion.attitude;
NSLog(@"Yaw %f ",attitude.yaw * 180 / M_PI);
NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
NSLog(@"Roll %f ",attitude.roll * 180 / M_PI);
image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}
これは、ケイの提案の後のコードです。
- (void)handleDeviceMotion:(CMDeviceMotion*)motion {
CMAttitude *attitude = motion.attitude;
if (startAttitude == 0) {
startAttitude = attitude;
}
[attitude multiplyByInverseOfAttitude:startAttitude];
NSLog(@"Yaw %f ",attitude.yaw * 180 / M_PI);
NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
NSLog(@"Roll %f ",attitude.roll * 180 / M_PI);
image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}
デバイスのモーションモニタリングを開始します
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMDeviceMotion *motion, NSError *error){
[self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
}];
[完全に改訂]
一見したところ、私は状況を オイラー角 に関連するいくつかの典型的な問題に遭遇したと誤解しました。彼らはこの問題領域に近く、心に留めておくことが非常に重要なので、私は元の答えのこの部分を残します。オイラー角の問題は次のとおりです。
1: Yaw=30°, 2: Pitch=90°
または1: Pitch=90°, 2: Roll=30°
のいずれかによって同じローテーションを達成できます。しかし、あなたがコメントで述べたように、本当の犯人は参照フレームであるようです。 iOS5.0以降Appleセンサーフュージョンアルゴリズムが強化され、磁場データも考慮してCMAttitudeが計算されます。古い方法 startDeviceMotionUpdates はまだありますが、デフォルトの参照 CMAttitudeReferenceFrameXArbitraryZVertical を使用するようになったため、すべての測定値は「Z軸は垂直で、X軸は水平面の任意の方向を指します。 」。
開始時(またはその他のローテーション)の参照に関してデータを取得するには、参照として必要なCMAttitude
インスタンスを保存してから、CMAttitude
の を使用する必要があります。 multiplyByInverseOfAttitude メソッドを使用して、すべての新しい姿勢を変換します。つまり、handleDeviceMotion
メソッドの先頭にあります。
これは、以前のバージョンでは正常に機能していた 高速移動後のヨー角のドリフト で説明したようなiOS6のバグに関連していると思います。私はバグを報告しました-彼らがいつそれを修正するのか見てみましょう。
UPDATE 2
コメントとチャットが示したように、目標はデバイスを傾けるだけでロボットを制御することでした。この場合、デバイスの完全な回転状態を知ることは、歩行方向を変更するときに制御を台無しにします。したがって、 CMDeviceMotion.gravity を使用した純粋な加速度計ベースのアプローチの方がはるかに便利です。