加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

iphone – 如何创建一个新的CMAttitude参考框架,使重力在Y轴上

发布时间:2020-12-15 01:57:17 所属栏目:百科 来源:网络整理
导读:我想要更改设备运动管理器参考框架(对于陀螺仪),以便我在Y轴上有我的重力矢量。 通常当您启动“设备运动管理器更新”时,只有手机的z轴与重力对齐。 您可以更改此选项以使用磁力计使x轴与磁极或真正的北极对齐。有了我的X轴指向北,我的Z轴指向下。 我想做
我想要更改设备运动管理器参考框架(对于陀螺仪),以便我在Y轴上有我的重力矢量。

通常当您启动“设备运动管理器更新”时,只有手机的z轴与重力对齐。

您可以更改此选项以使用磁力计使x轴与磁极或真正的北极对齐。有了我的X轴指向北,我的Z轴指向下。

我想做的是让我的Y轴(负)指向下(使其与重力对齐),并且我的X轴指向真正的磁极。

我想要的结果是,当我的手机仍然处于垂直(纵向)方向时,手机的右侧将与北极对齐,我的所有读数(滚动,俯仰,偏航)将读为0.然后与这样,如果我在X轴上旋转手机,则音调将发生变化,如果我绕Y轴旋转,偏航将改变。

到目前为止,我知道我可以设置自己的参考框架,如果我乘以一个以前存储的态度的态度的倒数(像我可以设置我的手机在这个方向MANUALLY,除了这种态度,只是继续将新的态度乘以逆这个存储的一个和所有的读数将完全像我想要的)。

但是手动设置不是一个选择,那么我如何编程呢?

我不认为有一个功能来创建我自己的态度参考框架,或者至少有一个功能可以通过旋转矩阵来增加态度,所以我可以解决这个问题。 (因为我会把所有的态度都乘以90度的变化)。

我希望我能清楚地解释自己,

我会感谢任何建议。谢谢

PD:这些是iPhone方向坐标:

解决方法

伪码:

>启动设备运动更新
>在后台启动相机预览;)
>将重力存储在本地变量中后,将当前重力读数作为CMAcceleration捕获。
>然后你必须拿2个向量并得到它们之间的角度,在这种情况下,设备重力为(0,0,-1)和真实的重力矢量…
>然后我们将theta转换为thetaPrime …与CoreMotion参考方向匹配的变换
>设置一个计时器来动画….
>在动画获取motionManager的deviceMotion属性的rotationMatrix的逆。
>以正确的顺序应用变换,以反映设备的当前态度(偏航,俯仰,滚动欧拉模式或设备四元数旋转…基本上同样的3种不同的方式)

这是代码:

- (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,currentGravity.z);

    //we have current gravity vector and our device gravity vector of (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,-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,-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);
    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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读