I am testing Core Motion and using the gyroscope. Right now I am getting values that I am not understanding. My assumption was that with each x, y and z I would get a value between 0-360 which would be a full rotation, but this isn't the case.
[self.motionManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMGyroData *gyroData, NSError *error) {
NSString *x = [NSString stringWithFormat:#"%.02f",gyroData.rotationRate.x];
NSLog(#"X: %#", x);
NSString *y = [NSString stringWithFormat:#"%.02f",gyroData.rotationRate.y];
NSLog(#"Y: %#", y);
NSString *z = [NSString stringWithFormat:#"%.02f",gyroData.rotationRate.z];
NSLog(#"Z: %#", z);
frequency = gyroData.rotationRate.y*500;
float rate = gyroData.rotationRate.z;
if (fabs(rate) > .2) {
float direction = rate > 0 ? 1 : -1;
rotation += (direction * M_PI/90.0)*1000;
NSLog(#"Rotation: %f", rotation);
}
}];
It is possible to get more human readable rotation values? Is my assumption that I should be getting values between 0-360 wrong?
The values are in radians, not degrees, so they should be between 0 and 2Pi. Also, they are a rate, not an angle. They are radians per second.
Related
hello i am calculating the device angle by fallowing code and then converting this angle to rise over run formula i am getting the wrong pitch value but when i start rotating device(left to right and right to left in landscape mode) then after some time i started to get correct pitch value here is my code....
operationQueue = [[NSOperationQueue alloc] init];
motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 2.0 / 60.0;
[motionManager startDeviceMotionUpdates];
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:operationQueue
withHandler:^(CMDeviceMotion *motion, NSError *error)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
CGFloat x = motion.gravity.x;
CGFloat y = motion.gravity.y;
CGFloat z = motion.gravity.z;
CGFloat angle = atan2(y, x) + M_PI_2; // in radians
CGFloat angleDegrees = angle * 180.0f / M_PI; // in degrees
CGFloat r = sqrtf(x*x + y*y + z*z);
CMQuaternion quat = motionManager.deviceMotion.attitude.quaternion;
NSNumber *myroll = [NSNumber numberWithInt:radiansToDegrees(atan2(2*(quat.y*quat.w - quat.x*quat.z), 1 - 2*quat.y*quat.y - 2*quat.z*quat.z))];
NSNumber *mypitch = [NSNumber numberWithInt:radiansToDegrees(atan2(2*(quat.x*quat.w + quat.y*quat.z), 1 - 2*quat.x*quat.x - 2*quat.z*quat.z))];
NSNumber *myyaw = [NSNumber numberWithInt:radiansToDegrees(2*(quat.x*quat.y + quat.w*quat.z))];
//double actualYaw = [myyaw doubleValue];
// CGFloat tiltForwardBackward = ceilf(motionManager.deviceMotion.attitude.yaw * 180 / M_PI);
**strong text**float pitchValue = motionManager.deviceMotion.attitude.pitch;
pitchValue = [mypitch doubleValue];
pitchValue = (pitchValue < 0) ? -(pitchValue) : pitchValue;
float pitchAngle = [mypitch doubleValue];
pitchAngle = (pitchAngle < 0) ? -(pitchAngle) : pitchAngle;
//pitchValue = (tan(pitchValue*(M_PI/180))*12);
**strong text**pitchValue = (tan((pitchValue*M_PI)/180))*12; // i am using this formula to calculate roof pitch value.
pitchValue = (pitchValue < 0) ? -(pitchValue) : pitchValue;
if(pitchValue >= 99.9){
pitchValue = 99.9;
}
deviceAngle.text = [NSString stringWithFormat: #"Pitch Value = %0.1f/12, Pitch Angle = %.2f", pitchValue, pitchAngle];
//deviceAngle.text = [NSString stringWithFormat: #" %.1f/12",pitchValue];
}];
}];
please help is there any way to calculate rise over run value by using any of this three value.i am keeping my iPhone in landscape mode and then rotating left to right and right to left.
am using wrong value?.i am interested to calculate roof pitch value.is there any formula?.
please help me thanks in advance.
In my project, want to show the weather in fahrenheit first, then if the user wants clickes on conversion, needs to show the weather in celsius. My code is
NSNumber *metric = [[NSUserDefaults standardUserDefaults] objectForKey:#"metric"];
NSLog(#"Metric is %#", metric);
CGFloat aFloat = [speed floatValue];
CGFloat tFloat = [temperature floatValue];
CGFloat tempFloat = (tFloat-30)/2;
NSNumber * p_Number = [NSNumber numberWithFloat:tempFloat];
//Convert mph to kmph
if ([metric boolValue]) {
[windValueLabel setText:[NSString stringWithFormat:#"%.2f kmph", aFloat * 1.6] ];
temperatureLabel.text = [NSString stringWithFormat:#"%#", p_Number];
}
else{
[windValueLabel setText:[NSString stringWithFormat:#"%.2f mph", aFloat / 1.6]];
temperatureLabel.text = [NSString stringWithFormat:#"%#", temperature];
}
When u start the app, its working and showing temperature in fahrenheit, but crashes at celsius man... is that the current conversion. help me out guys
Your formula is slightly off, you want:
CGFloat tempFloat = (tFloat-32.0) / 1.8;
But that's not what making it crash. In fact, it's not crashing for me. What message do you get when it crashes?
I've taken a look around, and there aren't that many talks or examples on inertial navigation for iOS5. I know that iOS5 introduced some very cool sensor fusion algorithms:
motionQueue = [[NSOperationQueue alloc] init];
[motionQueue setMaxConcurrentOperationCount:1];
motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 1/20.0;
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical toQueue:motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error) {
}];
I've taken a look at both videos from WWDC that deal with the block above.
The resulting CMDeviceMotion contains a device attitude vector, along with the acceleration separated from the user induced acceleration.
Are there any open source inertial navigation projects specifically for iOS 5 that take advantage of this new sensor fusion ? I'm talking about further integrating this data with the GPS and magnetometer output to get a more accurate GPS position.
A bonus question: is this kind of fusion even possible from a hardware standpoint? Will I melt my iPhone4 if I start to do 20hz processing of all available sensor data over extended periods of time?
I'm ready to start tinkering with these, but would love to get something more solid to start with than the empty block above :)
Thank you for any pointers!
I am writing an app for scuba divers and hoped to add inertial navigation since GPS and other radio based navigation is unavailable underwater. I did quite a bit of research and found that there is just too much jitter in the sensor data on the iPhone for accurate inertial navigation. I did a quick experiment and found that even when the device is perfectly still, the "drift" due to noise in the signal showed that the device "moved" many meters after only a few minutes. Here is the code I used in my experiment. If you can see something I am doing wrong, let me know. Otherwise, I want my afternoon back!
- (void)startCoreMotion {
CMMotionManager *manager = [[CMMotionManager alloc] init];
if ([manager isAccelerometerAvailable]) {
manager.deviceMotionUpdateInterval = 1.0/updateHz;
[manager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
xVelocity += (( 9.8 * motion.userAcceleration.x ) / updateHz);
yVelocity += (( 9.8 * motion.userAcceleration.y ) / updateHz);
zVelocity += (( 9.8 * motion.userAcceleration.z ) / updateHz);
xPosition += ( xVelocity * ( 1 / updateHz ));
yPosition += ( yVelocity * ( 1 / updateHz ));
zPosition += ( zVelocity * ( 1 / updateHz ));
self.xPositionLabel.text = [NSString stringWithFormat:#"x = %f m", xPosition];
self.yPositionLabel.text = [NSString stringWithFormat:#"y = %f m", yPosition];
self.zPositionLabel.text = [NSString stringWithFormat:#"z = %f m", zPosition];
self.xVelocityLabel.text = [NSString stringWithFormat:#"vx = %f m/s", xVelocity];
self.yVelocityLabel.text = [NSString stringWithFormat:#"vy = %f m/s", yVelocity];
self.zVelocityLabel.text = [NSString stringWithFormat:#"vz = %f m/s", zVelocity];
self.distanceLabel.text = [NSString stringWithFormat:#"dist = %f m", sqrt( pow(xPosition, 2) + pow(yPosition, 2) + pow(zPosition, 2))];
}];
}
}
Does anybody know that what is the maximum sampling rate of the iphone accelerometer.
I want to have have high update rate. i set it to updateInterval to 1.0/ 300.0
But it seems that i am not getting that much update rate.
So can any body tell me that what is the maximum update rate that we can get or how i can get the high update rate.
The max accelerometer and gyroscope sampling rate on the iPhone 6 is 100Hz. You can empirically test this yourself. Here is the code.
/******************************************************************************/
// First create and initialize two NSMutableArrays. One for accel data and one
// for gyro data. Then create and initialize CMMotionManager. Finally,
// call this function
- (void) TestRawSensors
{
speedTest = 0.0001; // Lets try 10,000Hz
motionManager.accelerometerUpdateInterval = speedTest;
motionManager.gyroUpdateInterval = speedTest;
[motionManager startAccelerometerUpdatesToQueue: [NSOperationQueue currentQueue]
withHandler: ^(CMAccelerometerData *accelerometerData, NSError *error)
{
[rawAccelSpeedTest addObject: [NSNumber numberWithDouble: accelerometerData.timestamp]];
[rawAccelSpeedTest addObject: [NSNumber numberWithDouble: accelerometerData.acceleration.x]];
if (error)
{
NSLog(#"%#", error);
}
if (rawAccelSpeedTest.count > 100)
{
[motionManager stopAccelerometerUpdates];
for (uint16_t i = 0; i < rawAccelSpeedTest.count; i+=2)
{
NSLog(#"Time: %f Accel: %f", [rawAccelSpeedTest[i] doubleValue],
[rawAccelSpeedTest[i+1] doubleValue]);
}
}
}];
[motionManager startGyroUpdatesToQueue: [NSOperationQueue currentQueue]
withHandler: ^(CMGyroData *gyroData, NSError *error)
{
[rawGryoSpeedTest addObject: [NSNumber numberWithDouble: gyroData.timestamp]];
[rawGryoSpeedTest addObject: [NSNumber numberWithDouble: gyroData.rotationRate.x]];
if (error)
{
NSLog(#"%#", error);
}
if (rawGryoSpeedTest.count > 100)
{
[motionManager stopGyroUpdates];
for (uint16_t i = 0; i < rawGryoSpeedTest.count; i+=2)
{
NSLog(#"Time: %f Rate: %f", [rawGryoSpeedTest[i] doubleValue],
[rawGryoSpeedTest[i+1] doubleValue]);
}
}
}];
}
Despite the documentation saying The maximum frequency at which you can request updates is hardware-dependent but is usually at least 100 Hz. it looks to me like the maximum sample rate is still 100Hz.
My approach to figure out was taking the existing sample code for CoreMotion called MotionGraphs and adapting the startUpdates function to look like this:
func startUpdates() {
guard let motionManager = motionManager, motionManager.isGyroAvailable else { return }
sampleCount = 0
let methodStart = Date()
motionManager.gyroUpdateInterval = TimeInterval(1.0/100000.0) // Hardcoded to something verfy fast
motionManager.startGyroUpdates(to: .main) { gyroData, error in
self.sampleCount += 1
//...view update code removed
if (self.sampleCount >= 100) {
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(methodStart)
print("Duration of 100 Gyro samples: \(executionTime)")
self.stopUpdates()
}
}
}
I also set motionManager.deviceMotionUpdateInterval = TimeInterval(1.0/100000.0) for good measure (in case it is a global rate).
With that code in place for both Accelerometer and Gyroscope I confirm that an iPhone 8 on iOS 11.4 still maxes out right around 100Hz for both.
Duration of 100 Accelerometer samples: 0.993090987205505
Duration of 100 Accelerometer samples: 0.995925068855286
Duration of 100 Accelerometer samples: 0.993505954742432
Duration of 100 Accelerometer samples: 0.996459007263184
Duration of 100 Accelerometer samples: 0.996203064918518
Duration of 100 Gyro samples: 0.989820957183838
Duration of 100 Gyro samples: 0.985687971115112
Duration of 100 Gyro samples: 0.989449977874756
Duration of 100 Gyro samples: 0.988754034042358
Maybe duplicate. Look at
update frequency set for deviceMotionUpdateInterval it's the actual frequency?
Actual frequency of device motion updates lower than expected, but scales up with setting
The same should be valid if using old UIAccerometerDelegate interface.
Can any trig or GPS experts help me out here? I'm trying to create a geo-spacial bounding box (rectangle) calculation returning the maximum latitude and longitude using the following method that I've retrieved. I am calling the method once for each of the for bearings: north, south, east and west. With these four values I intend to query my Core Data store for all objects within the box.
-(CLLocation*) offsetLocation:(CLLocation*)startLocation:(double)offsetMeters:(double)bearing {
double EARTH_MEAN_RADIUS_METERS = 6372796.99;
double newLatitude = asin( sin(startLocation.coordinate.latitude) * cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) + cos(startLocation.coordinate.latitude) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(bearing) );
double newLongitude = startLocation.coordinate.longitude + atan2( sin(bearing) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(startLocation.coordinate.latitude), cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) - sin(startLocation.coordinate.latitude) * sin(newLatitude));
CLLocation *tempLocation = [[CLLocation alloc] initWithLatitude:newLatitude longitude:newLongitude];
[tempLocation autorelease];
return tempLocation;
}
The problem is the calculation for the newLatitude offset is definitely incorrect. Given the following:
startLocation: latitude 37.331688999999997, longitude -122.030731
offsetMeters : 1000
bearing : 0 (north)
newLatitude returns -0.36726592610659514 (incorrect).
Any suggestions? I've coded around this particular formula until now and this one has me stumped. I've also tried translating a different formula from PHP to no avail. I figure the above is exactly what I need if it can be tweaked.
Thanks,
b.dot
I haven't looked at your code, but you could also use the MapKit function MKCoordinateRegionMakeWithDistance() to have the framework calculate a bounding box for you.
CLLocationCoordinate2D center = { 37.3, -122.0 };
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center, 2000.0, 2000.0);
CLLocationCoordinate2D northWestCorner, southEastCorner;
northWestCorner.latitude = center.latitude - (region.span.latitudeDelta / 2.0);
northWestCorner.longitude = center.longitude + (region.span.longitudeDelta / 2.0);
southEastCorner.latitude = center.latitude + (region.span.latitudeDelta / 2.0);
southEastCorner.longitude = center.longitude - (region.span.longitudeDelta / 2.0);
CLLocationCoordinate2D stores coordinates in degrees, but the trig functions you're using require radian units. If you convert to radians (multiply by M_PI/180, or 0.017453293f), it will probably work.
How are you guys setting up the NSPredicates?
I seem to run into performance issues with mine.
NSPredicate *northWestLat = [NSPredicate predicateWithFormat:#"ANY locations.lat > %lf", northWestCorner.latitude];
NSPredicate *southhWestLat = [NSPredicate predicateWithFormat:#"ANY locations.lat < %lf", southEastCorner.latitude];
NSPredicate *latitudePredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:northWestLat, southhWestLat, nil]];
NSPredicate *northWestLng = [NSPredicate predicateWithFormat:#"ANY locations.lng < %lf", northWestCorner.longitude];
NSPredicate *southEastLng = [NSPredicate predicateWithFormat:#"ANY locations.lng > %lf", southEastCorner.longitude];
NSPredicate *longitudePredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:northWestLng, southEastLng, nil]];
NSPredicate *coordPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:latitudePredicate, longitudePredicate, nil]];