2011-12-29 53 views
17

我希望能夠改變設備運動管理器參考幀(對於陀螺儀),使我對Y軸我的重力矢量。如何創建一個新的CMAttitude參考框架,使重力是Y軸

通常當你啓動設備運動管理器的更新,你只會有重力對準手機的Z軸。

您可以將其更改爲使用磁力使x軸與任何磁或真北極對齊。有了這個,我的X軸指向北方,Z軸指向下方。

我想要做的是有我的Y軸(負)朝下(以便其與重力對準),也有我的指點真正的磁極X軸。

我想要的結果是,當我的手機靜止在垂直(人像)方位時,手機的右側將與北極對齊,並且我所有的讀數(滾動,俯仰,偏航)都會讀爲0.然後,如果我在X軸上旋轉手機,則音調將會改變,如果我圍繞Y軸旋轉,則偏轉將會改變。

到目前爲止,我知道我可以設置自己的參考框架,如果我乘以以前存儲的態度的態度的倒數(如我可以手動設置我的手機在這個方向MANUALLY,保存這種態度,只是保持乘以新態度由這個存儲的反相和我所有的讀數將完全像我想要的)。

但手動設置不是一個選項,所以我如何編程?

我不認爲這是創造我自己的態度參照系的功能,或者至少有是乘以一個旋轉矩陣的態度功能,那麼我或許可以解決這個問題。 (因爲我只是將所有的態度乘以球場90度的變化)。

我希望我解釋清楚我自己,

我會明白任何建議。感謝

PD:這是iPhone的方位座標:

enter image description here

+0

你知道如何在iOS4上採取相對於真北方的態度嗎? iOS5有很好的方法。 – vale4674 2012-02-17 15:12:01

+0

不抱歉不知道,這就是爲什麼我不能創造我自己的參考態度... – Pochi 2012-02-18 16:54:57

+0

有沒有好的材料在線這種東西..太糟糕了。 – vale4674 2012-02-20 12:52:24

回答

-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

這並不能解決問題。這是來自蘋果開發文檔,當然我可以緩存該參考態度,但如果您檢查該方法需要運行時間,因爲它使用設備動作調用當前態度,所以我想知道如何創建我自己的姿態參考框架,以便我可以以不同的方向「開始」它。 – Pochi 2012-02-04 09:35:03

+1

這是從蘋果的網站剽竊沒有任何歸屬。 – aledalgrande 2014-07-06 02:01:40

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

換句話說,這是正確的:當應用程序啓動時,CM參考框架根據iPhone的當前態度進行設置。即當手機保持在相同的角度時,翻滾,偏航和俯仰的值不能保證相同。但是,通過讀取原始加速度計數據,您可以獲得一個變換,該變換在應用於deviceMotion.attitude屬性時可以提供設備關於重力的真實方向。 – 2012-11-26 13:45:49

+0

對於那些不熟悉矢量的人來說,這應該等同於將初始重力讀數轉換爲一組三個歐拉角 - 設備的實際方向與<您選擇的參考幀相比較,例如[0,0,-1 ]>。調用這些角度與mgr.deviceMotion同時提供的角度之間的差異。態度「取向差異」。在計算設備的瞬時實際姿態時,可以簡單地將方向差值添加到deviceMotion.attitude中的角度。 – 2012-11-26 15:00:52

+0

是的,這是正確的。 – Orbitus007 2013-01-15 20:17:01

相關問題