我需要计算"面向";(它是基于正北还是基于磁北并不重要)。在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)
编码快乐。。。