Reputation: 67
I am using the iOS core motion framework to detect if the device is tilted forward or backwards. See image for details: https://i.sstatic.net/2Ojw5.jpg
Using the pitch value a can detect this movement but I can not distinguish between forward AND backward.
More details:
I try to detect if there is a movement (tilting forward and backward) in either the forward area OR backward area (see updated sketch).
The problem with the pitch is that it starts with a value of about 1.6 if the device is in an upright position. And the value decreases the same when I am tilting it towards a horizontal potion either forward or backward. The same behavior applies to the accelerometer y value.
It looks like I miss something in the whole core motion thing. ANy Ideas
thanks christian
Upvotes: 4
Views: 3568
Reputation: 1
Use BOTH pitch and roll. If roll (which varies from -180 degrees to 180 degrees) is less than -90 degrees or greater than 90 degrees, it is face down. When the pitch of the device comes over the top (reaches 90 degrees, and proceeds to decrease) roll switches to represent the equivalent of a 180 degree flip. Between the two, you can determine which way the device is facing, even if orientation lock is engaged.
Upvotes: -1
Reputation: 25525
Using attitude pitch, leaning forward and backward are indistinguishable. However with quaternions you can calculate pitch, and if you convert radians to degrees,
The opposite hemisphere of rotation is 0 to -180. Here's the code:
func radiansToDegrees(_ radians: Double) -> Double {
return radians * (180.0 / Double.pi)
}
let quat = motionData.attitude.quaternion
let qPitch = CGFloat(radiansToDegrees(atan2(2 * (quat.x * quat.w + quat.y * quat.z), 1 - 2 * quat.x * quat.x - 2 * quat.z * quat.z)))
Upvotes: 11
Reputation: 153
You don't want to read the accelerometer for tilt. Accelerometer is for detecting differences in movements. You want the gyroscope so you can determine the absolute attitude (i.e. yaw, pitch and roll). In your case it sounds like you just want roll.
Use startDeviceMotionUpdatesToQueue and then attitude.roll for front and back and attitude.pitch for side to side. Here is what I did in Swift:
func motion(data: CMDeviceMotion){
let pitch = data.attitude.pitch
let roll = data.attitude.roll
let dampener:Float = -0.25 // the ball was rolling too fast
var forward_force = Float(1.6 - roll) * dampener //1.6 is vertical
var side_force = Float(pitch) * dampener // 0 is untilted when rotating cw/ccw
ballNode.physicsBody?.applyForce(SCNVector3Make(side_force, 0, forward_force), atPosition: SCNVector3Make(0, 0, 0), impulse: true)
}
With this you can see if it tilted frontward or backward based on whether the roll is greater than or equal to 1.6 which is approximately straight up.
Upvotes: 0
Reputation: 2980
You are right, pitch works that way, considering the 4 typical quadrants (http://en.wikipedia.org/wiki/Quadrant_(plane_geometry)) and the counterclockwise direction:
Considering this looks pretty obvious that you cannot difference between the phone leaning forwards or backwards.
I have recently faced the same problem for an iOS app that counts the number of flips that the phone does. Apple has rejected it so I have published it on GitHub, may be useful for you:
Flip Your Phone! - https://github.com/apascual/flip-your-phone
Upvotes: 0
Reputation: 23
Try this:
// Create a CMMotionManager
CMMotionManager *mManager = [(AppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager];
// Check whether the accelerometer is available
if ([mManager isAccelerometerAvailable] == YES) {
[mManager setAccelerometerUpdateInterval: .02];
[mManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[self updateGravityWithAccelerometerX:accelerometerData.acceleration.x y:accelerometerData.acceleration.y z:accelerometerData.acceleration.z];
}];
}
This will call updateGravityWithAccelerometerData every .02 seconds. You should be able to create that method and use NSLog to watch the values change to decipher what you are looking for. I believe you are looking for the acceleration.y value.
Upvotes: 0