使用 CMDeviceMotion 跟踪 iPhone 随着时间的推移的倾斜度
我正在尝试使用 CMDeviceMotion 来跟踪 iPhone 何时向后倾斜,然后执行某些操作。我已经成功创建了 CMMotionManager,我正在从系统获取运动数据,并且正在过滤高于特定加速度的结果。
不过,我想做的是检测设备何时向后或向前倾斜超过一定速度。我该怎么做?
这是我到目前为止的代码:
更新:我想我解决了它。我正在寻找旋转速率属性,CMRotationRate。我已经将它们配对在一起,我实际上只需要 x 值,所以我会继续努力。如果有人对下面的代码有一些提示,我们将不胜感激。
- (void)startMotionManager{
if (motionManager == nil) {
motionManager = [[CMMotionManager alloc] init];
}
motionManager.deviceMotionUpdateInterval = 1/15.0;
if (motionManager.deviceMotionAvailable) {
NSLog(@"Device Motion Available");
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMDeviceMotion *motion, NSError *error){
//CMAttitude *attitude = motion.attitude;
//NSLog(@"rotation rate = [%f, %f, %f]", attitude.pitch, attitude.roll, attitude.yaw);
[self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
}];
//[motionManager startDeviceMotionUpdates];
} else {
NSLog(@"No device motion on device.");
[self setMotionManager:nil];
}
}
- (void)handleDeviceMotion:(CMDeviceMotion*)motion{
CMAttitude *attitude = motion.attitude;
float accelerationThreshold = 0.2; // or whatever is appropriate - play around with different values
CMAcceleration userAcceleration = motion.userAcceleration;
float rotationRateThreshold = 7.0;
CMRotationRate rotationRate = motion.rotationRate;
if ((rotationRate.x) > rotationRateThreshold) {
if (fabs(userAcceleration.x) > accelerationThreshold || fabs(userAcceleration.y) > accelerationThreshold || fabs(userAcceleration.z) > accelerationThreshold) {
NSLog(@"rotation rate = [Pitch: %f, Roll: %f, Yaw: %f]", attitude.pitch, attitude.roll, attitude.yaw);
NSLog(@"motion.rotationRate = %f", rotationRate.x);
[self showMenuAnimated:YES];
}
}
else if ((-rotationRate.x) > rotationRateThreshold) {
if (fabs(userAcceleration.x) > accelerationThreshold || fabs(userAcceleration.y) > accelerationThreshold || fabs(userAcceleration.z) > accelerationThreshold) {
NSLog(@"rotation rate = [Pitch: %f, Roll: %f, Yaw: %f]", attitude.pitch, attitude.roll, attitude.yaw);
NSLog(@"motion.rotationRate = %f", rotationRate.x);
[self dismissMenuAnimated:YES];
}
}
}
I'm trying to use CMDeviceMotion to track when the iPhone is tilted backwards, and then do something. I've successfully created the CMMotionManager, I'm getting motion data from the system, and I'm filtering for results above a certain acceleration.
What I want to do though, is detect when the device is being tilted backwards or forwards above a certain speed. How do I do that?
Here's the code I have so far:
UPDATE: I think I solved it. I was looking for the rotationRate property, CMRotationRate. I've paired them together, I really only need the x value, so I'll keep working on it. If anyone has some tips at the below code, it's much appreciated.
- (void)startMotionManager{
if (motionManager == nil) {
motionManager = [[CMMotionManager alloc] init];
}
motionManager.deviceMotionUpdateInterval = 1/15.0;
if (motionManager.deviceMotionAvailable) {
NSLog(@"Device Motion Available");
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMDeviceMotion *motion, NSError *error){
//CMAttitude *attitude = motion.attitude;
//NSLog(@"rotation rate = [%f, %f, %f]", attitude.pitch, attitude.roll, attitude.yaw);
[self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
}];
//[motionManager startDeviceMotionUpdates];
} else {
NSLog(@"No device motion on device.");
[self setMotionManager:nil];
}
}
- (void)handleDeviceMotion:(CMDeviceMotion*)motion{
CMAttitude *attitude = motion.attitude;
float accelerationThreshold = 0.2; // or whatever is appropriate - play around with different values
CMAcceleration userAcceleration = motion.userAcceleration;
float rotationRateThreshold = 7.0;
CMRotationRate rotationRate = motion.rotationRate;
if ((rotationRate.x) > rotationRateThreshold) {
if (fabs(userAcceleration.x) > accelerationThreshold || fabs(userAcceleration.y) > accelerationThreshold || fabs(userAcceleration.z) > accelerationThreshold) {
NSLog(@"rotation rate = [Pitch: %f, Roll: %f, Yaw: %f]", attitude.pitch, attitude.roll, attitude.yaw);
NSLog(@"motion.rotationRate = %f", rotationRate.x);
[self showMenuAnimated:YES];
}
}
else if ((-rotationRate.x) > rotationRateThreshold) {
if (fabs(userAcceleration.x) > accelerationThreshold || fabs(userAcceleration.y) > accelerationThreshold || fabs(userAcceleration.z) > accelerationThreshold) {
NSLog(@"rotation rate = [Pitch: %f, Roll: %f, Yaw: %f]", attitude.pitch, attitude.roll, attitude.yaw);
NSLog(@"motion.rotationRate = %f", rotationRate.x);
[self dismissMenuAnimated:YES];
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您是否看过 CMAttitude?听起来像是你需要的,再加上一些数学我猜。
编辑:好的,你做到了。
引用 Apple 文档,第 1 章“获取当前设备方向”:
太好了,他们为我们做了数学。然后我想像上面的文档所解释的那样,像您一样跟踪加速度+跟踪方向应该可以使用
UIDeviceOrientationFaceUp
和UIDeviceOrientationFaceDown
来完成这项工作?如果没有一个
UIDeviceOrientation
满足您的需求,您需要从两个CMAttitude
引用计算一些空间角度,它提供了一个rotationMatrix
和一个四元数
...这些学校数学对我来说很遥远...然后我建议也许用这些搜索/问一个仅数学问题。Have you looked at CMAttitude? Sounds like what you need, plus some mathematics I guess.
EDIT: Ok you did.
Quoting Apple documentation, at chapter "Getting the Current Device Orientation" :
Great, they do the maths for us. Then I guess that tracking acceleration like you do + tracking orientation, as above documentation explains, should do the job, using
UIDeviceOrientationFaceUp
andUIDeviceOrientationFaceDown
?If none of the
UIDeviceOrientation
fit your needs, what you will need is to calculate some spatial angles from twoCMAttitude
references, which provides arotationMatrix
and aquaternion
... these school maths are far away for me... I would then suggest to maybe search/ask a math only question with these.