基于磁力计和陀螺仪的北方计算

我需要计算“面对”(如果它将基于真正的北方或磁性而无关紧要)。 正如在iOS设备上可以看到的那样, CLLocationManager返回的CLHeading对象通过相应的属性为我们提供了真实和磁性标题。 此外,我们可以很容易地看到,这些值与设备顶部(设备坐标系的正Y轴)相关,这对我的目的不利。 我真正需要的是计算与设备屏幕相关的面(Z轴),因为我不需要指南针,而是AG应用程序之王。 问题是当您将设备旋转到横向时,您将从面向方向向左或向右获取标题值,这是我最终需要的。 据我所知,我可以得到磁力计“原始”数据(以微特斯拉单位给出,每个设备轴的值为128到-128)以及陀螺仪“原始”数据(有三种类型:Euler天使,旋转矩阵或四元数)。 我需要知道的是,我需要应用哪些计算来获得“面向”方向而不是“标题”

我已经做了一段时间了,因为我没有看到答案,所以我决定把我的解决方案放在那里为那些为同一个问题搜索答案的人……

 _motionManager = [[CMMotionManager alloc]init]; if (_motionManager.gyroAvailable) { _motionManager.deviceMotionUpdateInterval = 1.0/20.0; [_motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) { CMAcceleration gravity = motion.gravity; CGPoint tiltVector = CGPointMake(-gravity.x, -gravity.y); _tiltAngle = [self angleYAxisToVector:tiltVector]; CLLocationDirection heaqding = [[SVSession sharedSession] heading].trueHeading; double newHeading = fmod(heaqding + _tiltAngle, 360.0); self.azimuth = degreesToRadian(newHeading); [self updateLocations]; //this function updates my ui for the new heading }]; } else { NSLog(@"No gyroscope on device."); [_motionManager release],_motionManager = nil; } 

以下是一些可能有助于理解此示例的其他代码段:

 -(double)angleYAxisToVector:(CGPoint)vector{ double dX = vector.x; double dY = vector.y; if(dY == 0){ if(dX > 0){ return 0.0; }else{ if(dX < 0){ return 180.0; }else{ return -1; } } } double beta = radiansToDegrees(atan(dX/dY)); double angle; if(dX > 0){ if (dY < 0){ angle = 180 + beta; }else{ angle = beta; } }else{ if (dY < 0){ angle = 180 + beta; }else{ angle = 360 + beta; } } // NSLog(@"angle = %f, normalized = %f",beta,angle); return angle; } #define degreesToRadian(x) (M_PI * (x) / 180.0) #define radiansToDegrees(x) ((x) * 180.0 / M_PI) #define degreesToRadians(x) degreesToRadian(x) #define radiansToDegree(x) radiansToDegrees(x) 

快乐的编码......