我目前使用CoreMotion的DeviceMotion來獲取iPhone的方向(滾動,俯仰,偏航)。現在我想要把這些值與地理北極相對應;所以我需要一個包含滾動,俯仰和偏航值的CMAttitude參考對象,如果iPhone的背面將面對北極(3D),則會報告這些值。 CLLocationManager只返回Tesla中的磁頭(x,y,z)。iOS CoreMotion CMAttitude相對於北極
你有想法如何將這些值轉換爲滾動,俯仰和偏航?
由於提前,
亞歷山大
我目前使用CoreMotion的DeviceMotion來獲取iPhone的方向(滾動,俯仰,偏航)。現在我想要把這些值與地理北極相對應;所以我需要一個包含滾動,俯仰和偏航值的CMAttitude參考對象,如果iPhone的背面將面對北極(3D),則會報告這些值。 CLLocationManager只返回Tesla中的磁頭(x,y,z)。iOS CoreMotion CMAttitude相對於北極
你有想法如何將這些值轉換爲滾動,俯仰和偏航?
由於提前,
亞歷山大
特斯拉值是磁場強度是多少磁「拉」覺得在三個軸的測量。只有將這些信息與加速度計數據結合起來,並進行一些花哨的數學運算,才能得到實際的航向(設備相對於磁北極「指向」的方式)。然後添加來自GPS的信息並進行更多的數學計算,以獲得真正的標題(相對於地理北極)。長話短說,你可能不想自己做數學。幸運的是,iOS在其CLHeading對象中提供了magneticHeading和trueHeading,可從CLLocationManager標題屬性中獲得。要獲得描述設備如何傾斜的俯仰和滾動,還需要對來自磁力計和加速度計的相同原始數據進行數學運算。對不起,我不知道任何iOS API的音調和滾動。
iOS 5提供了指定的方法。在開發人員文檔中查找CMAttitudeReferenceFrameXTrueNorthZVertical。
你需要現在校準你的偏航值到磁頭,然後確保你在正確的軌道上。退房就如何補償搖搖欲墜指南針這樣的解釋:Compensating compass lag with the gyroscope on iPhone 4
僞代碼:
這裏是代碼:
- (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;
}