CMMotionManager vs UIAccelerometer efficiency - ios

I've been working on an AR framework for a while now and am trying to update from UIAccelerometer (deprecated) to CMMotionManager but am running into some efficiency problems?
Basically it seems like CMMotionManager is MUCH larger and slower than UIAccelerometer is. Has anyone experienced performance issues with CMMotionManager before?
As you can see here, I had this:
accelerometer = [UIAccelerometer sharedAccelerometer];
accelerometer.updateInterval = 0.01;
[accelerometer setDelegate:self];
and
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));
rollingX = (acceleration.y * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
if (rollingZ > 0.0) currentInclination = inc_avg(atan(rollingX / rollingZ) + M_PI / 2.0);
else if (rollingZ < 0.0) currentInclination = inc_avg(atan(rollingX / rollingZ) - M_PI / 2.0);
else if (rollingX < 0) currentInclination = inc_avg(M_PI/2.0);
else if (rollingX >= 0) currentInclination = inc_avg(3 * M_PI/2.0);
}
and all works great even on "older" devices like the iPhone 4 (not really old but yea...).
But when trying the exact same code but with CMMotionManager:
motionManager = [[CMMotionManager alloc] init];
with
[motionManager setAccelerometerUpdateInterval:0.01];
[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMAccelerometerData *accelerometerData, NSError *error){
rollingZ = (accelerometerData.acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));
rollingX = (accelerometerData.acceleration.y * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
if (rollingZ > 0.0) currentInclination = inc_avg(atan(rollingX / rollingZ) + M_PI / 2.0);
else if (rollingZ < 0.0) currentInclination = inc_avg(atan(rollingX / rollingZ) - M_PI / 2.0);
else if (rollingX < 0) currentInclination = inc_avg(M_PI/2.0);
else if (rollingX >= 0) currentInclination = inc_avg(3 * M_PI/2.0);
}];
The math seems to slow the crap out of it..! I say this because when I remove all the math part it works great.
An iPhone 5 will work alright but an iPhone 4S will show signs of lag and the iPhone 4 will just freeze...
(I can give you more details if you want but its relatively complicated to explain)

I was just having this same problem, and wouldn't you know it, the solution was in the documentation ;)
The problem is with the block format. All of the tutorials seem to favor that method, but Apple recommends periodic polling of the CMMotionManager as a more performance oriented approach. The block format adds overhead.
From the CMMotionManager Class Reference:
To handle motion data by periodic sampling, the app calls a “start”
method taking no arguments and periodically accesses the motion data
held by a property for a given type of motion data. This approach is
the recommended approach for apps such as games. Handling
accelerometer data in a block introduces additional overhead, and most
game apps are interested only the latest sample of motion data when
they render a frame.
So what you want to do, from the docs again:
Call startAccelerometerUpdates to begin updates and periodically
access CMAccelerometerData objects by reading the accelerometerData
property.
Something along these lines
CMMotionManager *mManager = [(AppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager];
[mManager startAccelerometerUpdates];
Then, in some sort of periodically updating method of your choosing:
CMMotionManager *mManager = [(SEPAppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager];
CMAccelerometerData *aData = mManager.accelerometerData;
This solution appears to work as well as UIAccelerometer on an iPhone 4 from the limited testing I've done.

I use CADisplayLink.
First, setup CMMotionManager instance.
-(void)viewDidLoad
{
[super viewDidLoad];
self.motionManager = [[CMMotionManager alloc]init];
if(self.motionManager.isDeviceMotionAvailable)
{
[self.motionManager startDeviceMotionUpdates];
}
[self setupDisplayLink];
}
Secondly setup displaylink instance like this:
-(void)setupDisplayLink
{
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(update:)];
displayLink.frameInterval = 10;// how many frames to skip before next update
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
Display link is an object that is connected to your device screen, and which can run specified selector with specified frame rate; More on them here
Thirdly you should implement update: method you specified as display link selector.
-(void)update:(CADisplayLink *)displayLink
{
// handle new accelerometer data here
CMDeviceMotion *deviceMotion = self.motionManager.deviceMotion;
NSLog(#"Acceleration: %#", deviceMotion.accelerometerData.acceleration);
}

Related

How to calculate speed and distance from acceleration in iOS

Okay, this is an odd one - and the question has been asked before in various guises and always closed out with the opinion that a) it won't be accurate and b) that it will get less accurate with time.
I understand this - but I'm doing an experiment to see whether that accuracy can be boosted at all by taking into account other evidential sources (for example, if a map has been plotted in advance then the direction of travel from the compass combined with the route could provide another evidence source).
The problem is that my code is clearly rubbish - so I'd welcome your opinion. I suspect that this might be a brown paper bag error!
My ViewController.h looks like this:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIAccelerometerDelegate> {
UIAccelerometer *accelerometer;
long last_speed;
long distance_travelled;
long lastAccel;
long long lastTime;
IBOutlet UITextField* speedView;
IBOutlet UITextField* distanceView;
}
#end
And my ViewController.m looks like this:
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
lastAccel = 0;
last_speed = 0;
distance_travelled = 0;
lastTime = (long)(NSTimeInterval)([NSDate.date timeIntervalSince1970] * 1000.0);
accelerometer = UIAccelerometer.sharedAccelerometer;
accelerometer.updateInterval = 0.1;
accelerometer.delegate = self;
}
- (void)accelerometer:(UIAccelerometer *)meter
didAccelerate:(UIAcceleration *)acceleration
{
long long currentTime = (long)(NSTimeInterval)([NSDate.date timeIntervalSince1970] * 1000.0);
long long deltaTime = currentTime - lastTime;
lastTime = currentTime;
long accel_x = acceleration.x;
long accel_y = acceleration.y;
long accel_z = acceleration.z;
long integrated_acceleration = sqrtl(accel_x*accel_x + accel_y*accel_y + accel_z*accel_z);
long average_acceleration = (lastAccel + integrated_acceleration) / 2;
long speed = last_speed + (average_acceleration * deltaTime);
long average_speed = (speed + last_speed) / 2;
distance_travelled = distance_travelled + (average_speed * deltaTime);
last_speed = speed;
lastAccel = integrated_acceleration;
[speedView setText:[NSString stringWithFormat:#"%ld", speed]];
[distanceView setText:[NSString stringWithFormat:#"%ld", distance_travelled]];
}
#end
When the code is run, the speed and the distance keep going up continually, and deceleration (me slowing down) is never taken into account - so even when I stop, speed and distance keep going up.
Even by the standards of 'this will be a bit inaccurate' that's taking it too far!
All thoughts and opinions gratefully received (well almost - I know that it won't be accurate!)
You can't calculate Speed using UIAccelerometer.
Please find the link for more clarification : How to calculate speed using accelerometer in ios

Particle Filter iOS implementation fails

This problem is driving me crazy and I actually need some help.
I have to implement a particle filter in iOS and I started from a working code in Java.
The algorithm is very close to which is described in the course "Artificial Intelligence for Robotics" of Thrun on Udacity (https://www.udacity.com/course/artificial-intelligence-for-robotics--cs373)
The Java implementation has this behavior: I move the robot, the particles get closer and closer to the robot and then they follow it with a very low error. This is the expected behavior, I think. Changing number of particles, number of landmarks and noise, I get better or worse results.
The iOS implementation behavior is quite different: I move the robot, the particles get closer to the robot but after few iterations they start moving far from the robot. Initially the mean value is still close to the robot but then it jumps far.
Changing number of particles, number of landmarks and noise, I get to almost the same result.
I double checked the iOS code and apparently it's correct.
I suspected that the problem was related to random number generation and/or gaussian random generation.
I have changed my code to use exactly the code that Java library uses (http://docs.oracle.com/javase/7/docs/api/java/util/Random.html#nextGaussian()) getting the same results.
I moved the gaussian random generator to a singleton in order to share the same generator across all the particles, but nothing changed.
I have tried to change drand48() with ((double)arc4random() / (double)UINT32_MAX) getting the same results.
I have no other ideas.
I am not asking you to debug my code but please, give me any advice to sort this problem out.
EDIT 1
Maybe these pictures may help
From this step particles get far from the robot
EDIT 2
This is my Particle class:
#interface Particle ()
#property (nonatomic, strong) MyPoint *point;
#property double orientation;
#property NSInteger worldWidth;
#property NSInteger worldHeight;
#property double probability;
#property double forwardNoise;
#property double turnNoise;
#property double senseNoise;
#property (nonatomic,strong) Utils *utils;
#end
#implementation Particle
-(instancetype)initWithWorldWidth:(float)worldWidth worldHeight:(float)worldHeight {
self = [super init];
if (self) {
_worldWidth = worldWidth;
_worldHeight = worldHeight;
_point = [[MyPoint alloc] initWithX:drand48() * _worldWidth
Y:drand48() * _worldHeight];
_orientation = drand48() * 2. * M_PI;
_forwardNoise = 0;
_turnNoise = 0;
_senseNoise = 0;
_utils = [Utils sharedInstance];
}
return self;
}
-(void)setPosition:(MyPoint *)p orientation:(float)orientation probability:(double)probability {
_point.x = p.x;
_point.y = p.y;
_orientation = orientation;
_probability = probability;
}
-(void)setNoise:(double)forwardNoise turnNoise:(double)turnNoise senseNoise:(double)senseNoise {
_forwardNoise = forwardNoise;
_turnNoise = turnNoise;
_senseNoise = senseNoise;
}
-(MyPoint *)getPosition {
return _point;
}
-(double)getOrientation {
return _orientation;
}
-(double)getProbability {
return _probability;
}
-(double)getForwardNoise {
return _forwardNoise;
}
-(double)getTurnNoise {
return _turnNoise;
}
-(double)getSenseNoise {
return _senseNoise;
}
-(NSArray<NSNumber *>*)sense:(NSArray<Landmark*>*)landmarks {
NSMutableArray<NSNumber*> *measures = [[NSMutableArray alloc] init];
for(int i=0; i<landmarks.count; i++) {
Landmark *landmark = landmarks[i];
double distance = [Utils distanceBetweenP1:_point andP2:landmark];
double measure = distance + [_utils box_muller:0 :1.] * _senseNoise;
[measures addObject:[NSNumber numberWithDouble:measure]];
}
return measures;
}
-(void)moveForward:(double)forward withTurn:(double)turn {
//NSLog(#"---- Move ---- forward: %f ---- %f",forward,turn);
double a1 = [_utils box_muller:0. :1.];
//NSLog(#"\ta1=%.8f",a1);
_orientation = _orientation + turn + a1 * _turnNoise;
_orientation = [Utils circle:_orientation :2*M_PI];
double a2 = [_utils box_muller:0. :1.];
//NSLog(#"\ta2=%.8f",a2);
double dist = forward + a2 * _forwardNoise;
_point.x += cos(_orientation) * dist;
_point.y += sin(_orientation) * dist;
_point.x = [Utils circle:_point.x :_worldWidth];
_point.y = [Utils circle:_point.y :_worldHeight];
}
-(double)measurementProb:(NSArray<NSNumber *> *)measurements landmarks:(NSArray<Landmark *>*)landmarks {
double prob = 1.0;
for(int i=0; i<measurements.count; i++) {
Landmark *landmark = landmarks[i];
double measurement = [measurements[i] doubleValue];
double dist = [Utils distanceBetweenP1:_point andP2:landmark];
prob *= [Utils gaussian:dist :_senseNoise :measurement];
}
_probability = prob;
return prob;
}
This is my Particle filter:
#import "ParticleFilter.h"
#interface ParticleFilter ()
#property (nonatomic,strong) NSMutableArray<Particle *> *particles;
#property (nonatomic,strong) NSArray<Landmark *> *landmarks;
#property NSInteger worldWidth;
#property NSInteger worldHeight;
#end
#implementation ParticleFilter
-(instancetype)initWithLandmarks:(NSArray<Landmark*>*)landmarks numberOfParticles:(NSInteger)numberOfParticles worldWidth:(float)worldWidth worldHeight:(float)worldHeight {
self = [super init];
if (self) {
_worldWidth = worldWidth;
_worldHeight = worldHeight;
_particles = [[NSMutableArray alloc] init];
for (int i = 0; i < numberOfParticles; i++) {
[_particles addObject:[[Particle alloc] initWithWorldWidth:worldWidth worldHeight:worldHeight]];
}
_landmarks = [NSArray arrayWithArray:landmarks];
}
return self;
}
-(void)setNoise:(double)forwardNoise turnNoise:(double)turnNoise senseNoise:(double)senseNoise {
for (Particle *p in _particles) {
[p setNoise:forwardNoise turnNoise:turnNoise senseNoise:senseNoise];
}
}
-(void)moveForward:(double)forward withTurn:(double)turn {
for (Particle *p in _particles) {
[p moveForward:forward withTurn:turn];
}
}
-(void)resample:(NSArray<NSNumber *>*)measurements {
NSMutableArray<Particle *> *newParticles = [[NSMutableArray alloc] init];
for (Particle *p in _particles) {
[p measurementProb:measurements landmarks:_landmarks];
}
double B = 0;
Particle *bestParticle = [self getBestParticle];
NSInteger index = drand48() * _particles.count;
for (int i = 0; i < _particles.count; i++) {
B += drand48() * 2. * [bestParticle getProbability];
while (B > [_particles[index] getProbability]) {
B -= [_particles[index] getProbability];
index = [self circle:index+1 :_particles.count];
}
[newParticles addObject:_particles[index]];
}
[_particles removeAllObjects];
[_particles addObjectsFromArray:newParticles];
}
-(NSInteger)circle:(NSInteger) num :(NSInteger)length {
while(num > length - 1)
num -= length;
while(num < 0)
num += length;
return num;
}
-(Particle *)getAverageParticle {
Particle *p = [[Particle alloc] initWithWorldWidth:_worldWidth worldHeight:_worldHeight];
double x = 0;
double y = 0;
double orient = 0;
double prob = 0;
for(int i=0; i<_particles.count; i++) {
x += [_particles[i] getPosition].x;
y += [_particles[i] getPosition].y;
orient += [_particles[i] getOrientation];
prob += [_particles[i] getProbability];
}
x /= _particles.count;
y /= _particles.count;
orient /= _particles.count;
prob /= _particles.count;
[p setPosition:[[MyPoint alloc] initWithX:x Y:y]
orientation:orient
probability:prob];
[p setNoise:[_particles[0] getForwardNoise]
turnNoise:[_particles[0] getTurnNoise]
senseNoise:[_particles[0] getSenseNoise]];
return p;
}
Each movement is:
[_robot moveForward:2. withTurn:0];
[_particleFilter moveForward:2. withTurn:0];
NSLog(#"%#",_particleFilter);
NSLog(#"Mean %#",[_particleFilter getAverageParticle]);
NSArray<NSNumber*> *measurements = [_robot sense:_landmarks];
[_particleFilter resample:measurements];
NSLog(#"%#",_particleFilter);
NSLog(#"Mean %#",[_particleFilter getAverageParticle]);
NSLog(#"Robot %#",_robot);
NSLog(#"Estimated Robot %#",[_particleFilter getAverageParticle]);
NSLog(#"Best Robot %#",[_particleFilter getBestParticle]);
Here the code involving random numbers
#import "Utils.h"
#interface Utils ()
#property BOOL haveNextNextGaussian;
#property double nextNextGaussian;
#end
#implementation Utils
+ (instancetype) sharedInstance {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[super alloc] initInstance];
});
return sharedInstance;
}
-(instancetype)initInstance {
self = [super init];
if (self) {
srand48(arc4random());
}
return self;
}
+(double)distanceBetweenP1:(MyPoint *)p1 andP2:(MyPoint *)p2 {
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
+(double)gaussian:(double)mu :(double)sigma :(double)x {
return exp(-(pow(mu - x, 2.)) / pow(sigma, 2.) / 2.0) / sqrt(2.0 * M_PI * pow(sigma, 2.));
}
-(double)box_muller:(double)m :(double)s {
if (_haveNextNextGaussian) {
_haveNextNextGaussian = NO;
return _nextNextGaussian;
} else {
double v1, v2, s;
do {
v1 = 2 * drand48() - 1; // between -1.0 and 1.0
v2 = 2 * drand48() - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
}
while (s >= 1 || s == 0);
double multiplier = sqrt(-2 * log(s)/s);
_nextNextGaussian = v2 * multiplier;
_haveNextNextGaussian = YES;
return v1 * multiplier;
}
}
+(double)circle:(double) num :(double)length {
while(num > length - 1)
num -= length;
while(num < 0)
num += length;
return num;
}
#end
This answer was posted as a "how do I find the problem with x" before the OP posted any code.
With code to look at, this may no longer be relevant, particularly since OP asserts that all steps listed below have been followed.
This is a vague answer, but it's a vague question..
It's not possible for us to give any advice or guidance here since the only piece of information really available to the reader is that you suspect that the problem lies in the random number generation.
This yor folt?
To answer this question as a reader, we're basically comparing the chances of a stranger (YOU) on the internet having made a mistake VS the chances of a mistake being made by a team of ios developers, and having that mistake go unnoticed. Unfortunately we have to put our bets on the mistake being your fault.
PROGRAMMER'S RULE OF THUMB: Test your code before blaming someone else's code. If you know the person you are about to blame, test it again. If the person you are about to blame sees you every day, test it a third time. If you are within punching distance of the person you are about to blame, test it once more.
Problem Solving (AKA How to Find and Fix Your Pooch Up)
The first step in solving any coding problem is identifying the problem.
Rather than haphazardly looking at your code for errors again and again (StackOverflow Users Agree(c) you will never find it):
Create some unit tests to verify your code expectations and make sure that you're doing things right. If you are, then..
If the units of code that you've tested are all behaving correctly, check that they behave correctly when combined. Create tests that check chains of operations. The longer the chains, the more of the end to end functionality of your app you will be testing. Still not working? You may consider...
Remote debug your application while it is running to see exactly what is going on. Can't get remote debug to work? You're making this hard, but...
Log a small set of data from your app. Create a test to run your data set through your code. Verify expectations. You still can't get it to work? Then try...
Post your question on StackOverflow, with relevant code and data set.
Basically TEST, TEST, TEST
Every test made will save you time in the long run if your app is in active development (very mature and stable code will benefit less).

How to replace UIAccelerometer with CMMotionManager?

I'm new to iOS development.
I follow the tutorial from Ray Wenderlich to create a little location based AR app. However, the tutorial uses an AR Toolkit which has not been updated for a while. The UIAccelerometer it uses has already been deprecated since iOS 5, so when I try to run it on my iPhone (iOS 7.0.4), the Xcode says that there are 3 warnings, and all of them are caused by UIAccelerometer.
The result it leads to is that all the marks stay at the center of the screen one above another, and the tilt does not work at all.
According to my research, I guess what I need to do is to use CMMotionManager instead of UIAccelerometer, but as I said before, I'm totally new to iOS development and have no idea how to replace it.
Here is the source code. I add some little functions such that you can manually add locations that are not in the Google database, but I don't think it is these functions that result in the problem.
Thanks for you help in advance!
Try this link: https://www.inkling.com/read/learning-ios-programming-alasdair-allan-2nd/chapter-9/the-core-motion-framework
I'm learning a few tidbits that translate some-what with the UIAccelerometer
i.e.
[self setAccelometerManager [UIAccelerometer sharedAccelerometer]];
could become
[self.motionManager = [[CMMotionManager alloc] init];
Setting manual update intervals like
[[self accelerometerManager] setUpdateInterval: 0.25];
you can have
self.motionManager.accelerometerUpdateInterval = 0.25;
and releasing the delegate
self.accelerometerManager.delegate = nil;
would now be
[self.motionManager stopDeviceMotionUpdates];
Also from the link, I ended up doing something like this:
motionManager = [[CMMotionManager alloc] init];
motionManager.accelerometerUpdateInterval = 1.0/10.0; // Update at 10Hz
if (motionManager.accelerometerAvailable) {
queue = [NSOperationQueue currentQueue];
[motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
switch (currentOrientation) {
case UIDeviceOrientationLandscapeLeft:
viewAngle = atan2(accelerometerData.acceleration.x, accelerometerData.acceleration.z);
break;
case UIDeviceOrientationLandscapeRight:
viewAngle = atan2(-accelerometerData.acceleration.x, accelerometerData.acceleration.z);
break;
case UIDeviceOrientationPortrait:
viewAngle = atan2(accelerometerData.acceleration.y, accelerometerData.acceleration.z);
break;
case UIDeviceOrientationPortraitUpsideDown:
viewAngle = atan2(-accelerometerData.acceleration.y, accelerometerData.acceleration.z);
break;
default:
break;
}
[self updateCenterCoordinate];
}];
}

How to detect when the phone has been put down

I would like an action to take place when the phone is stationary for 2 seconds. I've searched for ages around google and stack overflow. I discovered that "Accelerometer DidAccelerate" has been depreciated and that CoreMotion is the replacement. Everything I have seen has been to do with the 'shaking' motion. I've tried reading through apple's documentation but It just confuses me!
Basically, I want the app to detect that the g-forces on the phone have remained within a small limit for a certain amount of time (suggesting that the phone has been laid down on a table or something) and for it to call and instance or make the app do something.
Any help would be greatly appreciated.
It's similar to the problem described in Simple iPhone motion detect. The basic setup for CMMotionManager is described in the Apple docs like Mike Pollard stated in his comment. I recommend especially the Handling Processed Device Motion Data section.
What you then need is CMDeviceMotion.userAcceleration which contains the pure acceleration without gravity.
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
// UPDATE: set interval to 0.02 sec
motionManager.deviceMotionUpdateInterval = 1.0 / 50.0;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *deviceMotion, NSError *error) {
CMAcceleration userAcceleration = deviceMotion.userAcceleration;
double totalAcceleration = sqrt(userAcceleration.x * userAcceleration.x +
userAcceleration.y * userAcceleration.y + userAcceleration.z * userAcceleration.z);
// UPDATE: print debug information
NSLog (#"total=%f x=%f y=%f z=%f", totalAcceleration, userAcceleration.x, userAcceleration.y, userAcceleration.z);
// if(totalAcceleration < SOME_LIMIT) ...
Then proceed like codeplasma has described in his answer above.
Also be aware that the solution might not be precise if used in the underground, bus, etc. because of external accelerations.
You can do something like this:
CMMotionManager *mManager = [[CMMotionManager alloc] init];
if ([mManager isAccelerometerAvailable] == YES) {
__block float lastActivityBefore = 0.0;
[mManager setAccelerometerUpdateInterval:0.1];
[mManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
double totalAcceleration = sqrt(accelerometerData.acceleration.x * accelerometerData.acceleration.x + accelerometerData.acceleration.y * accelerometerData.acceleration.y + accelerometerData.acceleration.z * accelerometerData.acceleration.z);
if(totalAcceleration < SOME_LIMIT)
lastActivityBefore = lastActivityBefore + 0.1;
else
lastActivityBefore = 0.0;
if(lastActivityBefore >= 2.0)
{
//do something
}
}];
}
Accelerometer will show some minimal acceleration even if your device is steady, so you should make a testing in order to determine SOME_LIMIT value.
Also be advised that you should have only one instance CMMotionManager class in your app, so you're better to put it in your AppDelegate and initialize it only once.

CMDeviceMotion does not provide attitude info

For some reason my iPad2 is not providing motion attitude information. I am doing AFAIK precisely what people say to do but still... no data.
float angle = 0;
CMDeviceMotion *deviceMotion;
CMAttitude *attitude;
deviceMotion = motionManager.deviceMotion;
if (deviceMotion) {
attitude = deviceMotion.attitude;
[attitude multiplyByInverseOfAttitude:referenceAttitude];
angle = [attitude roll];
} else {
NSLog (#"Cannot get angles.");
}
Earlier in my code I do this:
motionManager = [[CMMotionManager alloc] init];
if (motionManager.gyroAvailable) {
[motionManager startGyroUpdates];
}
However I never get the angle. Help?
You only get attitude if you use device motion updates, i.e. you have to call for initialisaiton:
if (![motionManager isDeviceMotionActive]) {
[motionManager startDeviceMotionUpdates];
}
And stopDeviceMotionUpdates when going to background.

Resources