Frage

I need to calculate "facing" (it doesn't matter if it will be based on true north or magnetic one). As it can be seen on the iOS devices the CLHeading objects returned by the CLLocationManager gives us both the true and the magnetic heading by corresponding properties. Also, we can very easily see, that those values are related to the top of the device (the positive Y axis of the devices coordinate system) which is not good for my purposes.

What I actually need is to calculate the facing related to the screen of the device (Z axis) as I don't need the compass, but a king of AG application. The issue is when you rotate the device to landscape you get heading values to the left or to the right from your facing direction, which is what I need in the end. As I know, I can get the magnetometer "raw" data (given to me in microtesla units with values from 128 to -128 for each device axis) along with the gyroscope "raw" data ( which comes in three types: Euler angels, Rotation matrix or Quaternion). What I need is to know, which calculations I need to apply to those to get the "facing" direction instead of "heading".

War es hilfreich?

Lösung

I've made it a while ago and because I see no answers, I've decided to put my solution here for those who'll search answer for the same question...

_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;
    }

And here are some additional snippets that may help to understand this example:

-(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)

Happy coding...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top