0

startDeviceMotionUpdatesUsingReferenceFrame を呼び出してから、最初の参照フレームへの参照をキャッシュし、その後のすべてのモーション更新で MultiplyByInverseOfAttitude を呼び出すと、期待している参照フレームからの変更が得られません。これは、私が理解していないことの本当に簡単なデモンストレーションです。

self.motionQueue = [[NSOperationQueue alloc] init];
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 1.0/20.0;
[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXArbitraryZVertical toQueue:self.motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error){
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        CMAttitude *att = motion.attitude;
        if(self.motionManagerAttitudeRef == nil){
            self.motionManagerAttitudeRef = att;
            return;
        }
        [att multiplyByInverseOfAttitude:self.motionManagerAttitudeRef];
        NSLog(@"yaw:%+0.1f, pitch:%+0.1f, roll:%+0.1f, att.yaw, att.pitch, att.roll);
    }];
}];

まず、私のアプリケーションでは、ピッチとロールだけを気にします。しかし、私の混乱を示すためにヨーもそこにあります。

携帯電話を平らな机の上に置き、アプリを起動してログを見ると、すべてが期待どおりに機能します。すべてのヨー、ピッチ ロールの値は 0.0 です。電話を表面から持ち上げずに 90 度回転させると、ヨーのみが変化します。それで、すべて良いです。

私が問題だと思うことを示すために... 次に、電話を(たとえば)空のコーヒーマグの中に入れて、すべての角度がわずかに傾いて、重力の方向がすべての軸で分数値を持つようにします。ここでアプリを起動します。上記のコードでは、ヨー、ピッチ、ロールの値が 0.0 であるため、すべてが機能していると考えられます。ただし、テーブルの表面から持ち上げずに、マグカップを 90 度回転させます。 ヨー、ピッチ、ロールのすべてで姿勢に大きな変化が見られるのはなぜですか?? 最初の姿勢 (これが現在の新しい基準姿勢) をキャッシュして、muptiplyByInverseOfAttitude を呼び出したので、ヨーだけが変化するのではないでしょうか?

4

1 に答える 1

0

キャッシュされた参照姿勢を乗じた姿勢を使用してもうまくいかない理由がよくわかりません...そして、ジンバルロックの問題ではないと思います。しかし、ここに私が必要とするものを正確に得るものがあります. 上記のコーヒーマグで実験を試みた場合、これはまさに期待どおりの結果を提供します (つまり、平らな面でコーヒーマグを回転させても、ピッチとロールの値には影響しません。コーヒーマグを他のすべての方向に傾けても、今だけです)一度に 1 つの軸にも影響します)。さらに、参照フレームを保存する代わりに、参照ピッチとロールを保存するだけで、アプリが起動すると、動きが発生するまですべてがゼロになります。

だから今は大丈夫です。しかし、他の方法が期待どおりに機能しなかった理由を理解したいと思います。

    self.motionQueue = [[NSOperationQueue alloc] init];
    self.motionManager = [[CMMotionManager alloc] init];
    self.motionManager.deviceMotionUpdateInterval = 1.0/20.0;
    [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXArbitraryZVertical toQueue:self.motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error)
    {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            if(self.motionManagerAttitude == nil){
                                CGFloat x = motion.gravity.x;
                                CGFloat y = motion.gravity.y;
                                CGFloat z = motion.gravity.z;
                                refRollF = atan2(y, x) + M_PI_2;

                                CGFloat r = sqrtf(x*x + y*y + z*z);
                                refPitchF = acosf(z/r);

                                self.motionManagerAttitude = motion.attitude;
                                return;
            }

                            CGFloat x = motion.gravity.x;
                            CGFloat y = motion.gravity.y;
                            CGFloat z = motion.gravity.z;
                            CGFloat rollF = refRollF - (atan2(y, x) + M_PI_2);

                            CGFloat r = sqrtf(x*x + y*y + z*z);
                            CGFloat pitchF = refPitchF - acosf(z/r);

                            //I don't care about yaw, so just printing out whatever the value is in the attitude
                            NSLog(@"yaw: %+0.1f, pitch: %+0.1f, roll: %+0.1f", (180.0f/M_PI)*motion.attitude.yaw, (180.0f/M_PI)*pitchF, (180.0f/M_PI)*rollF);
                }];
        }];
于 2016-02-16T18:32:12.607 に答える