首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >相对于北极的iOS CoreMotion CMAttitude

问相对于北极的iOS CoreMotion CMAttitude
EN

Stack Overflow用户
提问于 2011-03-04 00:00:20
回答 4查看 3.1K关注 0票数 2

我目前正在使用CoreMotion的DeviceMotion来获取iPhone的方向(滚动、俯仰、偏航)。现在,我希望获得相对于地理北极的这些值;因此,我需要一个包含滚动、俯仰和偏航值的CMAttitude参考对象,如果iPhone的背面朝向北极(3D),则会报告这些值。CLLocationManager仅返回Tesla中的磁航向(x,y,z)。

你知道如何将这些值转换为横摇、俯仰和偏航吗?

提前谢谢你,

亚历山大

EN

回答 4

Stack Overflow用户

发布于 2011-06-23 21:59:39

iOS 5提供了指定的方法。在开发人员文档中查找CMAttitudeReferenceFrameXTrueNorthZVertical。

票数 3
EN

Stack Overflow用户

发布于 2012-05-27 21:51:48

伪代码:

  1. 启动设备运动更新
  2. 在后台启动相机预览;)
  3. 捕获设备的当前重力读数作为CMAcceleration...一旦你有了重力,将它存储在一个局部变量中。
  4. ,然后你必须取这两个矢量,并得到它们之间的角度,在这种情况下,(0,0,-1)的设备重力和真实的重力矢量……然后我们把theta变成thetaPrime..。匹配定时器到animate....
  5. during动画的CoreMotion参考的变换以正确的顺序获得motionManager的rotationMatrix property.
  6. Apply变换的倒数,以反映设备的当前姿态(在欧拉模式下的偏航、俯仰、滚动或设备的四元数旋转...3种不同的方式来表达相同的意思,基本上)

代码如下:

代码语言:javascript
复制
- (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;
}
票数 1
EN

Stack Overflow用户

发布于 2011-08-25 22:39:40

你需要时不时地将你的偏航值校准到磁航向,以确保你在正确的轨道上。看看这个关于如何补偿摇晃罗盘的解释:Compensating compass lag with the gyroscope on iPhone 4

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5183212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档