apple watch CMDeviceMotion is not giving me good readings - ios

Currently, I am just recording a bunch of motion data and saving it to a file. However, when I plot the data, I am having a hard time believing I am getting the right readings. Here is my watch code:
- (IBAction)startStopRecording {
if (!recording){
NSLog(#"starting to record");
recording = YES;
data = [[NSMutableArray alloc] init];
[self.startRecording setTitle:#"Stop Recording"];
if (self.motionManager.deviceMotionAvailable) {
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
[data addObject:[NSString stringWithFormat:#"%f, %f, %f, %f, %f, %f, %f, %f, %f", motion.attitude.pitch, motion.attitude.roll, motion.attitude.yaw, motion.userAcceleration.x, motion.userAcceleration.y, motion.userAcceleration.z, motion.rotationRate.x, motion.rotationRate.y, motion.rotationRate.z]];
NSLog(#".");
}];
}
}else{
recording = NO;
NSLog(#"stopping recording");
[self.motionManager stopDeviceMotionUpdates];
[self.startRecording setTitle:#"Start Recording"];
[InterfaceController openParentApplication:#{ #"data": data } reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(#"Data has been saved.");
NSLog(#"replyInfo %#", replyInfo);
}];
}
}
The parent application just writes all the data to a file. I recorded the watch rotating back and forth on all three axes (pitch, then roll, then yaw):
And then when I plotted the data, this is what I got:
The yaw is so noisy that you can't see a signal at all in there. I also have a similar problem when plotting the acceleration after jerking the watch in three different directions. I can see spikes of acceleration, but they don't seem to be direction dependent. Any ideas on how to improve this? Am I missing something? Could I just have a bad sensor in my watch?

The reason is because I wasn't actually pulling data from the watch. It was pulling data from the phone. In order to pull data (currently only acc data is available from the watch) you need to have watchOS2 (currently in beta). Otherwise the watch will just get handed data from the phone.

Related

Sit-Up counter using CMDeviceMotion

I'm trying to replicate a fitness app similar to Runtastic's Fitness Apps.
Sit-Ups
This our first app that uses the phone’s built-in accelerometer to detect movement. You need to hold the phone against your chest then sit up quickly enough and high enough for the accelerometer to register the movement and the app to count 1 sit-up. Be sure to do a proper sit-up by going high enough!
I did a prototype app similar to this question here and tried to implement a way to count sit-ups.
- (void)viewDidLoad {
[super viewDidLoad];
int count = 0;
motionManager = [[CMMotionManager alloc]init];
if (motionManager.deviceMotionAvailable)
{
motionManager.deviceMotionUpdateInterval = 0.1;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
// Get the attitude of the device
CMAttitude *attitude = motion.attitude;
// Get the pitch (in radians) and convert to degrees.
double degree = attitude.pitch * 180.0/M_PI;
NSLog(#"%f", degree);
dispatch_async(dispatch_get_main_queue(), ^{
// Update some UI
if (degree >=75.0)
{
//it keeps counting if the condition is true!
count++;
self.lblCount.text = [NSString stringWithFormat:#"%i", count];
}
});
}];
NSLog(#"Device motion started");
}
else
{
NSLog(#"Device motion unavailable");
}
}
The if condition statement works, as if I place the device on my chest and do a proper sit-up, but the problem about this if statement is that it will just continue counting and I would want it to only count when the device has gone back to it's original position.
Can anyone come up with a logical implementation for this?
A simple boolean flag did the trick:
__block BOOL situp = NO;
if (!situp)
{
if (degree >=75.0)
{
count++;
self.lblCount.text = [NSString stringWithFormat:#"%i", count];
situp = YES;
}
}
else
{
if (degree <=10.0)
{
situp = NO;
}
}
Not the best logical implementation here, but it gets the job done...

Get accelerometer and gyroscope data from apple watch (and not the iphone)?

After seeing this question, I tried to code up a quick program that would save the watches accelerometer and gyroscope data to a file.
#implementation InterfaceController{
NSMutableArray *accData;
bool recording;
}
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
self.motionManager = [[CMMotionManager alloc] init];
[self.motionManager setAccelerometerUpdateInterval:.01];
}
- (IBAction)startStopRecording {
if (!recording){//We are starting to record.
recording = YES;
accData = [[NSMutableArray alloc] init];
[self.startRecording setTitle:#"Stop Recording"];
[self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[accData addObject:[NSString stringWithFormat:#"%f, %f, %f", accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z]];
}];
}else{
recording = NO;//we are stopping the recording
[self.motionManager stopAccelerometerUpdates];
[self.startRecording setTitle:#"Start Recording"];
[InterfaceController openParentApplication:#{ #"accData": accData } reply:^(NSDictionary *replyInfo, NSError *error) { //this method saves the array to a csv file.
NSLog(#"Data has been saved.");
}];
}
}
I had plotted this data and for the life of me, no matter how hard I shook the watch, all my plots looked like this:
Until 8 hours later, I started to suspect that I wasn't grabbing the acceleration data from the watch, but rather from the phone (sitting still on the table next to me). I ran some tests and confirmed that this is exactly what is happening.
Which leads me to the original question. How do I pull acceleration/gyro/data from the watch and not from the iPhone?
The problem was that I wasn't running watchOS2. I assumed I was but it's still in beta and I hadn't installed it. The data I was getting was accelerometer data from the phone. Also, currently, you can only get acc data from the watch using watchOS2 and not gyro data.
you can use CoreMotion framework to get activity data.
while I can only get accel data, the gyro often return false.

Detect user arrived to a location and depart from a location pattern using CMMotionManager

I am working on app which requires to detect user arrived to place and depart from a place and time spent in that location.
I am reading CoreMotion Readings but unable to get any clue how to form patterns.
if (_motionManager == nil) {
_motionManager = [[CMMotionManager alloc]init];
}
_motionManager.deviceMotionUpdateInterval = 1/60;
[_motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
if (error) {
[_motionManager stopDeviceMotionUpdates];
NSLog(#"Error while reading accelerometer data: %#", error.description);
return;
}
[self getacceleration:motion];
}];
In filterMotionData I am trying to read device acceleration with motion.userAcceleration but not find any good solution.
- (void)getacceleration:(CMMotion*)motion {
CMAcceleration acceleration = motion.userAcceleration;
//Calculate Device acceleration
}
Here If I can calculate device acceleration then on slowing down device acceleration I can say user arrived to a Location and when as device acceleration increased for particular time period means user depart from a location.
I was exploring I came to know Moves app does the same for all version of devices.
I gone through CLVisit API provided by CLLocationManager but it won't give short stay of user in a location and also its notify very late.
Please guide if anyone work on same type of requirement.

How to get Acceleration Time & Acceleration Magnitude in iPhone

Currently I'm trying to use CMAcceleration to get accelerometer values for x,y& z axis is it possible to get Acceleration Time & Acceleration Magnitude with this x,y & z values.When i checked the developer forum i can't find any delegates / methods to get this two.Guide me to find the values.
Using the following code:
int updatesensorFrequencyInterval = [sensorFrequencySliderTxt.text intValue];
self.motionManager.accelerometerUpdateInterval = updatesensorFrequencyInterval;
self.motionManager.gyroUpdateInterval = updatesensorFrequencyInterval;
[self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[self outputAccelertionData:accelerometerData.acceleration];
if(error){
NSLog(#"%#", error);
}
}];
The x,y,z values of CMAccelerometerData acceleration struct are magnitudes in m/s^2.
CMAccelerometerData is a subclass of CMLogItem, so it inherits the timestamp property which provides the NSTimeInterval since the phone was booted. This can be used to measure elapsed time between any pair of samples.

iOS gyroscope to make virtual horizon

I'm looking to include a virtual horizon for my app using gyroscope, like this one
I found a lot of documentation on the gyro and i think i use yaw but i don't know how to calibrate with gravity.
Can someone help me please ??
thanks.
I solved my problem with this:
- (void)updateImage: (NSNumber *)rotNum
{
self.image.transform = CGAffineTransformMakeRotation([rotNum floatValue]);
}
// call the above function to rotate the image in reference to the horizon
[motionManager startDeviceMotionUpdatesToQueue: gyroQueue
withHandler: ^(CMDeviceMotion *motion, NSError *error) {
[self performSelectorOnMainThread: #selector(updateImage:)
withObject: [NSNumber numberWithDouble: atan2(motion.gravity.x, motion.gravity.y)-M_PI]
waitUntilDone: NO];
}];

Resources