Question

I'm attempting to log accelerometer data to the CoreData sql database in a logging application I've written as an aid to another project. The application is simple: It logs acceleration data to a structure created in Core Data at a frequency of f=100Hz.

Everything is great, except I'm getting a real frequency in the database of closer to 5Hz or at low at 0.1Hz in some test cases.

I've setup the accelerometer per the documentation:

// Accelerometer
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
accelerometer.updateInterval = 1./100; // T = 1/f. f=100Hz.
accelerometer.delegate = self;

Then on the callback I simply log it to a new row in Core Data:

- (void)accelerometer:(UIAccelerometer *)accelerometer
        didAccelerate:(UIAcceleration *)acceleration{
    AccelerometerData *dataPoint = [NSEntityDescription insertNewObjectForEntityForName:@"AccelerometerData" inManagedObjectContext:self.managedObjectContext];
    [self.session addAccelerometerDataObject:dataPoint];
    dataPoint.x = [NSNumber numberWithDouble:acceleration.x];
    dataPoint.y = [NSNumber numberWithDouble:acceleration.y];
    dataPoint.z = [NSNumber numberWithDouble:acceleration.z];
    dataPoint.timestamp = [NSNumber numberWithDouble:acceleration.timestamp];

Any idea why the lack of data?

I'm getting much higher frequencies from Core Location. I know inserting a new row into a managed entity is expensive - but I can't image it being on the scale of 1/100 of a second!

Was it helpful?

Solution 3

Got this working... seems like a bug to me though. I have to set the updateInterval to 1/10 of the desired time. I.e. for 100Hz refresh rate I set it to 1./1000 and I get 100 Hz data. Strange.

OTHER TIPS

One possible cause might be that if you're setting updateInterval as 1/100, it will be 0 since both numbers are integers. Make at least one of them floating point before dividing, e.g. 1.0 / 100.

Another possibility is that the Core Data operations are too slow to keep up with the requested rate. I would suggest that you try to simply store the UIAcceleration objects in an array and see if the update frequency increases. If it does, you need to figure out something to speed things up (e.g., simply write to a file, not Core Data).

The updateInterval documentation says this

This property is measured in seconds. The value of this property is capped to certain minimum and maximum values. The maximum value is determined by the maximum frequency supported by the hardware. To ensure that it can deliver device orientation events in a timely fashion, the system determines the appropriate minimum value based on its needs.

It could also be that the rate is slowed down greatly when the device is static. Although the event handling guide says

You can set the reporting interval to be as small as 10 milliseconds (ms), which corresponds to a 100 Hz update rate, although most applications can operate sufficiently with a larger interval. As soon as you assign your delegate object, the accelerometer starts sending it data. Thereafter, your delegate receives data at the requested update interval.

So it seems unlikely. You might want to write your data to your database in batches and see if that changes something. Rates as low as 0.1 Hz don't seem like its a writing time issue however, have you tried logging the callback? Also, is this when your app is in the foreground?

You could also try:

accelerometer.updateInterval = 0.01;

instead of

accelerometer.updateInterval = 1/100;

as it could be rounding to the closest int (0 or 1...)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top