Gyroscope on iPhone
Asked Answered
S

1

36

I need some help using gyroscope on iPhone. I can't understand readings from CMAttitude regarding pitch, roll and yaw in a particular situation.

This is my code

- (void)handleDeviceMotion:(CMDeviceMotion*)motion {

   NSLog(@"Yaw   %f ",attitude.yaw * 180 / M_PI);
   NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
   NSLog(@"Roll  %f ",attitude.roll * 180 / M_PI);
}

Let's suppose that iPhone is laying down on a plane as in the following figure:

enter image description here

pitch, roll and yaw are (almost) 0 degrees and any turn around an axis returns understandable readings. For example, turning the device right, the Yaw decreases and Pitch and Roll remains at 0.

Now the iPhone is in the following position:

enter image description here

and measurement is started again.

Readings are: Yaw = 0, Pitch = 90, Roll = 0

Since the devices rotated around this axis, Pitch increases.

Moving the iPhone into this position:

enter image description here

readings are: Yaw = 30, Pitch = 90, Roll = 0

Once again, since the device rotates around the Yaw axis, this value changes and the others not.

Moving the device around the Roll axis:

enter image description here

readings are: Yaw = 0, Pitch = 90, Roll = -20.

Now what I can't understand. Moving the iPhone around a circle of radius R (R > 0), like in this figure:

enter image description here

Yaw changes meanwhile Pitch and Roll don't.

I would have expected Yaw had remained unchanged and Roll had changed.

How can compensate this since I am interested exclusively to rotations around Yaw axis made by the user ?

Another problem I have is drifting. The iPhone is in the position described in the second figure, taken in my hand at rest for a long time (1 minute or more). The Yaw constantly increase. Any idea how to compensate the drifting ?

Thank you in advance

UPDATE I have followed Kay suggestions but nothing changes. Some more detail on my code. I would like to use Yaw to rotated an UIImage only when user rotate the device around the Yaw axis. This works, but when the user rotates around its own vertical axis the Yaw changes. I suppose that is not correct since when the user moves around its vertical axis, the devices doesn't rotate around its own Yaw axis. May be I am wrong. This is my original code:

- (void)handleDeviceMotion:(CMDeviceMotion*)motion { 

   CMAttitude      *attitude = motion.attitude;

   NSLog(@"Yaw   %f ",attitude.yaw * 180 / M_PI);
   NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
   NSLog(@"Roll  %f ",attitude.roll * 180 / M_PI);

   image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}

This is the code after Kay suggestion:

- (void)handleDeviceMotion:(CMDeviceMotion*)motion { 

   CMAttitude      *attitude = motion.attitude;        

   if (startAttitude == 0) {

      startAttitude = attitude;
   }

   [attitude multiplyByInverseOfAttitude:startAttitude];

   NSLog(@"Yaw   %f ",attitude.yaw * 180 / M_PI);
   NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
   NSLog(@"Roll  %f ",attitude.roll * 180 / M_PI);


   image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}

I start device motion monitoring with

 [motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:[NSOperationQueue currentQueue]
                                                           withHandler: ^(CMDeviceMotion *motion, NSError *error){

                                                               [self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
                                                           }];
Siliceous answered 25/1, 2013 at 18:32 Comment(2)
+1 for well presented question!Hypersthene
github.com/raweng/AugmentedRealityView/blob/master/ARView/… wil help you deals with all the sensors gyro magnetometer and accelerometerClosefitting
S
6

[Completely revised]

(1) Strange Angles

At a first glance I mistook the situation as running into some typical problems related to Euler Angles. Because they are close to this problem area and really important to bear in mind, I leave this part of the original answer. Euler Angle problems are:

  • Ambiguity, as the relationship between rotation state and Euler Angles representation is not bijective i.e. a set of angles describes one rotation but a rotation can be represented by more than one set of Euler Angles. In your question's Fig. 3 you can achieve the same rotation by either 1: Yaw=30°, 2: Pitch=90° or by 1: Pitch=90°, 2: Roll=30°
  • Gimbal Lock problem: You may loose one degree of freedom and the device cannot rotate around one of the axes any longer. The solution is to use quaternions or rotation matrices.

But as you stated in your comment the true culprit seems to be the reference frame. Starting with iOS 5.0 Apple enhanced the sensor fusion algorithm and considers magnetic field data as well to calculate CMAttitude. Although there is still the old method startDeviceMotionUpdates, it now uses a default reference CMAttitudeReferenceFrameXArbitraryZVertical so that all measurement is related to "Z axis is vertical and the X axis points in an arbitrary direction in the horizontal plane".

In order to get your data in respect to the reference at start (or any other rotation) you need to store the CMAttitude instance you want as reference and then use CMAttitude's multiplyByInverseOfAttitude method to transform every new attitude i.e. at the beginning of your handleDeviceMotion method.

(2) Yaw Drifting

I think this is related to a bug in iOS 6 like the one I described in Drifting yaw angle after moving fast as it used to work fine in previous version. I filed a bug - let's see when they gonna fix it.


UPDATE 2

As comments and chat showed the goal was to control a robot by just tilting the device. In this case knowing the full rotation state of the device is messing up control when changing the walking direction. Thus a pure accelerometer based approach using CMDeviceMotion.gravity is far more convenient.

Syncopated answered 25/1, 2013 at 20:24 Comment(12)
I don't think that Gimbal Lock is the answer.Siliceous
I don't think that Gimbal Lock is the answer. I put my phone in a position which Yaw, Pitch and Roll are all different from 0. I move the devices around the circle like in my last picture and Yaw changes. Likely, I have misunderstood something about the frame reference respect to which the angles are reported.Siliceous
@Kay, Thank you for your complete explanation. I have updated my code but I get the same result. Please, look at my updated question.Siliceous
@Syncopated Yeah, that happens... When I see 90 degrees and Euler angles I do not read any further. I just conclude that it is gimbal lock.Pneumogastric
@Fabrizio if (startAttitude == 0) { I'm not sure, but I always write if (startAttitude == nil) {Syncopated
@Syncopated You are right. Anyway I checked with debugger and startAttitude is set only the first time handleDeviceMotion is called.Siliceous
@Fabrizio You start with device upright like in Fig. 2? Sorry if so, just to be sure because sometimes when struggling with hard problems one ignores the easy things ;)Syncopated
@Syncopated Yes, I do. I take it on my hand and the image turn right or left if turn the iPhone right or left. If I hold the device still and I turn around with my swivel chair, the image rotates the same, I would expect it to be stopped.Siliceous
@Fabrizio I don't know anything about this CGAffineTransformMakeRotation but what about the logs? Do you see the angles starting at (0; 0; 0) when upright and then a changing roll?Syncopated
@Syncopated No I don't. I see (Yaw, Pitch, Roll) = (0,80,0), because I held my device almost vertical. Obviously 0 is not exatly 0: the first and second decimal digits change continuosly around 0. CGAffineTransformMakeRotation just rotates an image using the Yaw angle. You can ignore it and take in account only the log.Siliceous
let us continue this discussion in chatSyncopated
@Fabrizio The marked answer still doesn't work for me. Is everything updated correctly?Mattiematting

© 2022 - 2024 — McMap. All rights reserved.