2011-12-29 11 views
17

Y軸に重力ベクトルを持つようにデバイスモーションマネージャリファレンスフレーム(ジャイロ用)を変更したいと考えています。新しいCMAttitudeリファレンスフレームを作成して重力をY軸にする方法

通常、Device Motion Managerのアップデートを開始すると、電話のz軸だけが重力に合わせられます。

これを変更して磁力計を使用して、x軸を磁極または真のN極のいずれかと揃えることができます。これで私のX軸は北を指し、Z軸は下を指します。

私がしたいことは、私のY軸(マイナス)を下に向けて(重力に合わせるように)、また、私のX軸が真の磁極を指しているようにしたいことです。

私の望む結果は、電話機を垂直(縦向き)にしておくと、電話機の右端が北極に位置合わせされ、私のすべての読み(ロール、ピッチ、ヨー)がこれで私の電話機をX軸で回転させるとピッチが変わり、Y軸の周りを回転するとヨーが変わります。

これまでのところ私は自分のリファレンスフレームを設定することができます。これは、以前に保存した姿勢の逆数を乗算した場合です(この姿勢で自分の携帯電話を手動で設定し、この記憶されたものの逆数による態度と私のすべての読みは、私が望むものとまったく同じです)。

しかし、手動で設定することはできません。これをプログラム的にするにはどうすればよいですか?

私自身の姿勢参照フレームを作成する機能はないと思います。少なくとも、回転行列で姿勢を掛ける関数があれば、おそらくこれを解決することができます。 (私はちょうどピッチの90度の変化によってすべての態度を増やすだろうから)。

私はどんな提案を感謝します

、私ははっきりと自分自身を説明願っています。おかげ

PD:これらは、iPhoneの向きは、座標である:

enter image description here

+0

iOS4で真の北に相対的な態度を取る方法をご存じですか? iOS5にはこのための素晴らしい方法があります。 – vale4674

+0

申し訳ありませんが、私は自分の参照姿勢を作成することはできませんthatsなぜなら... – Pochi

+0

この種のもののための良い材料はない..あまりにも悪い。 – vale4674

答えて

-1

I hope this will help you

あなたはCMAttitudeインスタンスが使用する参照フレームを変更することができます。これを行うには、その参照フレームを含む姿勢オブジェクトをキャッシュし、それを引数としてmultiplyByInverseOfAttitude:に渡します。メッセージを受け取った姿勢引数は、その参照フレームからの姿勢の変化を表すように変更されます。

これがどのように役立つかを確認するには、ユーザーがデバイスを回転させてスイングする野球ゲームを考えてみましょう。通常、ピッチの始めでは、バットは何らかの休息の向きになるでしょう。その後、バットは、デバイスの姿勢がピッチの始めの位置からどのように変化したかによって決定される方向でレンダリングされる。リンクの下ではより多くの一見のため

-(void) startPitch { 

// referenceAttitude is an instance variable 

referenceAttitude = [motionManager.deviceMotion.attitude retain]; 

}

- (void)drawView { 

CMAttitude *currentAttitude = motionManager.deviceMotion.attitude; 

[currentAttitude multiplyByInverseOfAttitude: referenceAttitude]; 

// render bat using currentAttitude ..... 

[self updateModelsWithAttitude:currentAttitude]; 

[renderer render]; 

}

あなたが望む同じことという。

http://db-in.com/blog/2011/04/cameras-on-opengl-es-2-x/

+2

これは問題を解決しません。これはリンゴのdevドキュメントからですが、私はそのリファレンス姿勢をキャッシュすることができますが、メソッドをチェックすると、デバイスモーションを使用して現在の姿勢を呼び出してからランタイムが必要になるので、自分の姿勢参照フレームを作成する方法を知りたい私は別の方向でそれを「開始」することができます。 – Pochi

+1

これはAppleのウェブサイトから無断で盗られています。 – aledalgrande

4

擬似コード:

  1. 開始デバイスモーション更新
  2. 背景におけるカメラプレビューを開始;)
  3. 捕捉CMAccelerationようなデバイスからの読み出し電流重力..あなたが重力を持っていればそれをローカル変数に格納します。
  4. 次に、2つのベクトルを取り、それらの間の角度、この場合はデバイスの重力(0,0、-1)と実際の重力ベクトルを得る必要があります。
  5. 次にthetaをthetaPrime ... CoreMotion参照オリエンテーションに一致する変換
  6. アニメーションのタイマーを設定します。
  7. motionManagerのdeviceMotionプロパティのrotationMatrixの逆を取得します。
  8. ここ

(...ヨー、ピッチ、オイラーモードまたはデバイスの四元回転ロール基本的に同じことを言うために3種類の方法を)デバイスの現在の姿勢を反映するには、正しい順序で変換を適用コード:

- (void) initMotionCapture 
{ 
    firstGravityReading = NO; 
    referenceAttitude = nil; 

    if (motionManager == nil) 
    { 
     self.motionManager = [CMMotionManager new]; 
    } 
    motionManager.deviceMotionUpdateInterval = 0.01; 
    self.gravityTimer = [NSTimer scheduledTimerWithTimeInterval:1/60.0 target:self selector:@selector(getFirstGravityReading) userInfo:nil repeats:YES]; 
} 


- (void) getFirstGravityReading 
{ 
    CMAcceleration currentGravity; 

    CMDeviceMotion *dm = motionManager.deviceMotion; 
    referenceAttitude = dm.attitude; 
    currentGravity = dm.gravity; 

    [motionManager startDeviceMotionUpdates]; 

    if (currentGravity.x !=0 && currentGravity.y !=0 && currentGravity.z !=0) 
    { 
     NSLog(@"Gravity = (%f,%f,%f)", currentGravity.x, currentGravity.y, currentGravity.z); 

     firstGravityReading = YES; 
     [gravityTimer invalidate]; 
     self.gravityTimer = nil; 
     [self setupCompass]; 
    } 
} 

- (void) setupCompass 
{ 
    //Draw your cube... I am using a quartz 3D perspective hack! 
    CATransform3D initialTransform = perspectiveTransformedLayer.sublayerTransform; 
    initialTransform.m34 = 1.0/-10000; 


    //HERE IS WHAT YOU GUYS NEED... the vector equations! 
    NSLog(@"Gravity = (%f,%f,%f)", currentGravity.x, currentGravity.y, currentGravity.z); 

    //we have current gravity vector and our device gravity vector of (0, 0, -1) 
    // get the dot product 
    float dotProduct = currentGravity.x*0 + currentGravity.y*0 + currentGravity.z*-1; 
    float innerMagnitudeProduct = currentGravity.x*currentGravity.x + currentGravity.y + currentGravity.y + currentGravity.z*currentGravity.z; 
    float magnitudeCurrentGravity = sqrt(innerMagnitudeProduct); 
    float magnitudeDeviceVector = 1; //since (0,0,-1) computes to: 0*0 + 0*0 + -1*-1 = 1 

    thetaOffset = acos(dotProduct/(magnitudeCurrentGravity*magnitudeDeviceVector)); 
    NSLog(@"theta(degrees) = %f", thetaOffset*180.0/M_PI); 

    //Now we have the device angle to the gravity vector (0,0,-1) 
    //We must transform these coordinates to match our 
    //device's attitude by transforming to theta prime 
    float theta_deg = thetaOffset*180.0/M_PI; 
    float thetaPrime_deg = -theta_deg + 90; // ThetaPrime = -Theta + 90 <==> y=mx+b 

    NSLog(@"thetaPrime(degrees) = %f", thetaOffset*180.0/M_PI); 

    deviceOffsetRotation = CATransform3DMakeRotation((thetaPrime_deg) * M_PI/180.0, 1, 0, 0); 
    initialTransform = CATransform3DConcat(deviceOffsetRotation, initialTransform); 

    perspectiveTransformedLayer.sublayerTransform = initialTransform; 

    self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:1/60.0 target:self selector:@selector(tick) userInfo:nil repeats:YES]; 

} 

- (void) tick 
{ 
    CMRotationMatrix rotation; 

    CMDeviceMotion *deviceMotion = motionManager.deviceMotion; 
    CMAttitude *attitude = deviceMotion.attitude; 

    if (referenceAttitude != nil) 
    { 
     [attitude multiplyByInverseOfAttitude:referenceAttitude]; 
    } 
    rotation = attitude.rotationMatrix; 

    CATransform3D rotationalTransform = perspectiveTransformedLayer.sublayerTransform; 

    //inverse (or called the transpose) of the attitude.rotationalMatrix 
    rotationalTransform.m11 = rotation.m11; 
    rotationalTransform.m12 = rotation.m21; 
    rotationalTransform.m13 = rotation.m31; 

    rotationalTransform.m21 = rotation.m12; 
    rotationalTransform.m22 = rotation.m22; 
    rotationalTransform.m23 = rotation.m32; 

    rotationalTransform.m31 = rotation.m13; 
    rotationalTransform.m32 = rotation.m23; 
    rotationalTransform.m33 = rotation.m33; 

    rotationalTransform = CATransform3DConcat(deviceOffsetRotation, rotationalTransform); 
    rotationalTransform = CATransform3DConcat(rotationalTransform, CATransform3DMakeScale(1.0, -1.0, 1.0)); 


    perspectiveTransformedLayer.sublayerTransform = rotationalTransform; 
} 
+0

これは正しいですか?アプリが起動すると、iPhoneの現在の姿勢に合わせてCM参照フレームが設定されます。すなわち、ロール、ヨー、およびピッチの値は、電話が同じ角度で保持されているときに同じであることが保証されない。しかし、生の加速度計データを読み取ることで、deviceMotion.attitudeプロパティに適用すると、重力に関してデバイスの真の向きを与える変換を取得できます。 –

+0

ベクトルに慣れていない人にとっては、これは最初の重力の読みを3つのオイラー角に変換することと同等でなければなりません - <参照フレームの選択と比較したデバイスの実際の方向、例えば[0,0、-1 ]>これらの角度とmgr.deviceMotionによって同時に供給された角度の差を呼び出します。姿勢は「方位差」である。デバイスの瞬時の実際の姿勢を計算するときは、単にdeviceMotion.attitudeの角度に方位の差を加えることができます。 –

+0

はいこれが正しいです。 – Orbitus007

関連する問題