CMMotionManager 从缓存的参考帧更改未按预期工作



当我调用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,我不应该只是在偏航中得到改变吗?

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

所以现在一切都很好。 但仍然希望我明白为什么另一种方法没有按预期工作。

    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);
                }];
        }];

相关内容

  • 没有找到相关文章

最新更新