【问题标题】:CMMotionManager changes from cached reference frame not working as expectedCMMotionManager 从缓存参考帧更改未按预期工作
【发布时间】:2016-02-05 15:25:48
【问题描述】:

当我调用 startDeviceMotionUpdatesUsingReferenceFrame,然后缓存对我的第一个参考帧的引用并在之后对我的所有运动更新调用 multiplyByInverseOfAttitude 时,我没有从我期望的参考帧中得到变化。这是我不理解的一个非常简单的演示。

self.motionQueue = [[NSOperationQueue alloc] init];
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 1.0/20.0;
[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXArbitraryZVertical toQueue:self.motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error){
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        CMAttitude *att = motion.attitude;
        if(self.motionManagerAttitudeRef == nil){
            self.motionManagerAttitudeRef = att;
            return;
        }
        [att multiplyByInverseOfAttitude:self.motionManagerAttitudeRef];
        NSLog(@"yaw:%+0.1f, pitch:%+0.1f, roll:%+0.1f, att.yaw, att.pitch, att.roll);
    }];
}];

首先,在我的应用程序中,我只关心俯仰和滚动。但是偏航也在那里表明我的困惑。

如果我将手机放在平板上,启动应用程序并查看日志,一切都会按预期进行。所有的偏航、俯仰滚动值都是 0.0,然后如果我将手机旋转 90 度而不将其从表面抬起只有偏航会改变。所以那里一切都很好。

为了证明我认为的问题...现在将手机放在(例如)一个空咖啡杯中,这样所有的角度都略微倾斜,重力方向总共会有一些小数值轴。现在启动应用程序,使用上面的代码,您会认为一切正常,因为偏航、俯仰和滚动的值再次为 0.0。但现在将咖啡杯旋转 90 度,但不要将其从桌面抬起。 为什么我看到所有偏航、俯仰和滚动的姿态发生显着变化?? 因为我缓存了我的初始姿态(现在是我的新参考姿态),并且调用了 muptiplyByInverseOfAttitude,我不应该只是只改变偏航角?

【问题讨论】:

  • 顺便说一句,我已经尝试了 Apple SDK 提供的所有起始参考帧,但由于我不关心偏航,我认为 CMAttitudeReferenceFrameXArbitraryZVertical 是正确的,因为就像我在帖子中提到的那样在我的实际应用程序中,我不关心偏航。尽管做出了这些努力,但我没有得到我觉得文档说我应该得到的结果。具体来说,当我旋转咖啡杯时(在我之前描述的问题模拟中),为什么除了偏航之外什么都发生了变化。
  • 为什么我遇到这么多麻烦?我怀疑我在这里误解了这个文档:[developer.apple.com/library/prerelease/ios/documentation/… 但是,我似乎很清楚,它的目的是解决我想要解决的问题(旋转咖啡杯,同时用 iPhone 放在平坦的表面上)在咖啡杯内倾斜角度,只看到偏航的变化)。

标签: quaternions euler-angles cmmotionmanager


【解决方案1】:

我真的不明白为什么使用缓存的参考姿态乘以姿态不起作用......而且我不认为这是一个万向节锁定问题。但这正是我所需要的。如果您尝试使用我上面描述的咖啡杯进行实验,这将提供完全预期的结果(即在平坦的表面上旋转咖啡杯不会影响俯仰和滚动值,并且现在仅在所有其他方向上倾斜咖啡杯一次也影响一个轴)。另外,我没有保存参考帧,而是保存了参考俯仰和滚动,然后当应用程序启动时,一切都归零,直到有一些运动。

现在一切都好。但仍然希望我能理解为什么其他方法没有按预期工作。

    self.motionQueue = [[NSOperationQueue alloc] init];
    self.motionManager = [[CMMotionManager alloc] init];
    self.motionManager.deviceMotionUpdateInterval = 1.0/20.0;
    [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXArbitraryZVertical toQueue:self.motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error)
    {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            if(self.motionManagerAttitude == nil){
                                CGFloat x = motion.gravity.x;
                                CGFloat y = motion.gravity.y;
                                CGFloat z = motion.gravity.z;
                                refRollF = atan2(y, x) + M_PI_2;

                                CGFloat r = sqrtf(x*x + y*y + z*z);
                                refPitchF = acosf(z/r);

                                self.motionManagerAttitude = motion.attitude;
                                return;
            }

                            CGFloat x = motion.gravity.x;
                            CGFloat y = motion.gravity.y;
                            CGFloat z = motion.gravity.z;
                            CGFloat rollF = refRollF - (atan2(y, x) + M_PI_2);

                            CGFloat r = sqrtf(x*x + y*y + z*z);
                            CGFloat pitchF = refPitchF - acosf(z/r);

                            //I don't care about yaw, so just printing out whatever the value is in the attitude
                            NSLog(@"yaw: %+0.1f, pitch: %+0.1f, roll: %+0.1f", (180.0f/M_PI)*motion.attitude.yaw, (180.0f/M_PI)*pitchF, (180.0f/M_PI)*rollF);
                }];
        }];

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 2016-05-03
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多