web-dev-qa-db-ja.com

iPhoneのジャイロスコープ

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が飛行機に横になっているとしましょう。

enter image description here

ピッチ、ロール、ヨーは(ほぼ)0度であり、軸を中心に回転すると、理解できる測定値が返されます。たとえば、デバイスを右に回すと、ヨーが減少し、ピッチアンドロールは0のままになります。

これで、iPhoneは次の位置になります。

enter image description here

そして、測定が再開されます。

読み取り値は次のとおりです。ヨー= 0、ピッチ= 90、ロール= 0

デバイスがこの軸を中心に回転するため、ピッチが増加します。

IPhoneをこの位置に移動する:

enter image description here

読み取り値は次のとおりです。ヨー= 30、ピッチ= 90、ロール= 0

繰り返しになりますが、デバイスはヨー軸を中心に回転するため、この値は変化し、他の値は変化しません。

ロール軸を中心としたデバイスの移動:

enter image description here

読み取り値は、ヨー= 0、ピッチ= 90、ロール= -20です。

今、私が理解できないこと。次の図のように、iPhoneを半径R(R> 0)の円の周りに移動します。

enter image description here

一方、ヨーは変化しますが、ピッチとロールは変化しません。

ヨーは変わらず、ロールも変わっていたと思います。

ユーザーがヨー軸を中心に回転することにのみ関心があるので、これをどのように補正できますか?

私が抱えているもう一つの問題はドリフトです。 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];
                                                           }];
34
Fab

[完全に改訂]

(1)奇妙な角度

一見したところ、私は状況を オイラー角 に関連するいくつかの典型的な問題に遭遇したと誤解しました。彼らはこの問題領域に近く、心に留めておくことが非常に重要なので、私は元の答えのこの部分を残します。オイラー角の問題は次のとおりです。

  • 回転状態とオイラー角表現の関係は二義的ではないため、あいまいさ。つまり、一連の角度は1つの回転を表しますが、回転はオイラー角の1セット。あなたの質問の図3では、1: Yaw=30°, 2: Pitch=90°または1: Pitch=90°, 2: Roll=30°のいずれかによって同じローテーションを達成できます。
  • ジンバルロック 問題:1自由度を失う可能性があり、デバイスは軸の1つを中心に回転できなくなります。解決策は、クォータニオンまたは回転行列を使用することです。

しかし、あなたがコメントで述べたように、本当の犯人は参照フレームであるようです。 iOS5.0以降Appleセンサーフュージョンアルゴリズムが強化され、磁場データも考慮してCMAttitudeが計算されます。古い方法 startDeviceMotionUpdates はまだありますが、デフォルトの参照 CMAttitudeReferenceFrameXArbitraryZVertical を使用するようになったため、すべての測定値は「Z軸は垂直で、X軸は水平面の任意の方向を指します。 」。

開始時(またはその他のローテーション)の参照に関してデータを取得するには、参照として必要なCMAttitudeインスタンスを保存してから、CMAttitudeを使用する必要があります。 multiplyByInverseOfAttitude メソッドを使用して、すべての新しい姿勢を変換します。つまり、handleDeviceMotionメソッドの先頭にあります。

(2)ヨードリフト

これは、以前のバージョンでは正常に機能していた 高速移動後のヨー角のドリフト で説明したようなiOS6のバグに関連していると思います。私はバグを報告しました-彼らがいつそれを修正するのか見てみましょう。


UPDATE 2

コメントとチャットが示したように、目標はデバイスを傾けるだけでロボットを制御することでした。この場合、デバイスの完全な回転状態を知ることは、歩行方向を変更するときに制御を台無しにします。したがって、 CMDeviceMotion.gravity を使用した純粋な加速度計ベースのアプローチの方がはるかに便利です。

6
Kay