gpt4 book ai didi

iphone - 如何创建新的CMAttitude引用系以使重力位于Y轴上

转载 作者:行者123 更新时间:2023-12-03 18:20:19 28 4
gpt4 key购买 nike

我希望能够更改设备运动管理器引用系(对于陀螺仪),以便我的重力矢量位于 Y 轴上。

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

您可以更改此设置以使用磁力计使 x 轴与磁北极或真北极对齐。这样我的 X 轴就指向北,Z 轴就指向下。

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

我想要的结果是,当我的手机以垂直(纵向)方向静止时,手机的右侧将与北极对齐,并且我的所有读数(滚动、俯仰、偏航)将读取为 0 。然后,如果我在 X 轴上旋转手机,俯仰角就会改变,如果我绕 Y 轴旋转,偏航就会改变。

到目前为止,我知道如果我乘以先前存储的态度的倒数,我可以设置自己的引用系(就像我可以手动将手机设置在这个方向,保存该态度并简单地继续乘以新态度)通过与此存储的相反,我的所有读数将与我想要的完全一样)。

但是手动设置它不是一个选项,那么我如何以编程方式进行此设置?

我不认为有一个函数可以创建我自己的姿态引用系,或者如果至少有一个函数可以将姿态乘以旋转矩阵,那么我可能可以解决这个问题。 (因为我只是将所有姿态乘以 90 度的音高变化)。

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

我将不胜感激任何建议。谢谢

PD:这些是 iPhone 方向坐标:

enter image description here

最佳答案

伪代码:

  1. 开始设备 Action 更新
  2. 在后台启动相机预览;)
  3. 从设备捕获当前重力读数作为 CMAcceleration...一旦获得重力,请将其存储在局部变量中。
  4. 然后您必须获取 2 个向量并获取它们之间的角度,在本例中为 (0,0,-1) 的设备重力和真实重力向量...
  5. 然后我们将 theta 转换为 thetaPrime...与 CoreMotion 引用方向匹配的变换
  6. 设置一个计时器来制作动画......
  7. 在动画过程中获取motionManager的deviceMotion属性的rotationMatrix的倒数。
  8. 以正确的顺序应用变换以反射(reflect)设备当前的姿态(欧拉模式下的偏航、俯仰、滚动或设备四元数旋转......基本上有 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,%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;
}

关于iphone - 如何创建新的CMAttitude引用系以使重力位于Y轴上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8663507/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com