quaternions - CMMotionManager changes from cached reference frame not working as expected -
when call startdevicemotionupdatesusingreferenceframe, cache reference first reference frame , call multiplybyinverseofattitude on motion updates after that, don't change reference frame expecting. here simple demonstration of i'm not understanding.
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); }]; }];
first off, in application care pitch , roll. yaw in there demonstrate confusion.
everything works expected if put phone laying on flat desk, launch app , @ logs. of yaw, pitch roll values 0.0, if spin phone 90 degrees without lifting off surface only yaw changes. there.
to demonstrate think problem... put phone inside of (for example) empty coffee mug, of angles tilted , direction of gravity have fractional value in axis. launch app , code above think working because there again 0.0 value yaw, pitch , roll. spin coffee mug 90 degrees without lifting table surface. why see significant change in attitude on of yaw, pitch , roll?? since cached initial attitude (which new reference attitude), , called muptiplybyinverseofattitude shouldn't getting change in yaw only?
i don't understand why using attitude multiplied cached reference attitude doesn't work... , don't think gimbal lock problem. here gets me need. , if tried experiment coffee mug described above, provides expected results (i.e. spinning coffee mug on flat surface doesn't affect pitch , roll values, , tilting coffee mug in other directions affects 1 axis @ time too). plus instead of saving reference frame, save reference pitch , roll, when app starts, zero'ed out until there movement.
so now. still wish understood why other method did not work expected.
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 yaw, printing out whatever value in 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); }]; }];
Comments
Post a Comment