Изменения 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, разве я не должен получать только изменения в рыскании?
1 ответ
Я не очень понимаю, почему использование отношения, умноженного на кэшированное ссылочное отношение, не работает... И я не думаю, что это проблема блокировки карданного подвеса. Но вот что дает мне именно то, что мне нужно. И если вы попробовали эксперимент с кофейной кружкой, которую я описал выше, это дает точно ожидаемые результаты (то есть вращение кофейной кружки на плоской поверхности не влияет на значения высоты тона и крена, и наклон кофейной кружки только во всех других направлениях теперь только влияет на одну ось одновременно). Плюс вместо сохранения опорного кадра, я просто сохранить эталонную высоту и крен, то при запуске приложения, все zero'ed, пока не будет какое-то движение.
Так что все хорошо сейчас. Но все же хотелось бы, чтобы я понял, почему другой метод не сработал, как ожидалось.
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);
}];
}];