【问题标题】:Detecting iPhone movement on a flat surface检测 iPhone 在平面上的移动
【发布时间】:2014-11-11 23:06:11
【问题描述】:

我是 coremotion 初学者。

我需要在桌子等平面上检测 iPhone 的运动 - 到目前为止,我通过访问陀螺仪的偏航来检测它的侧向运动,但我想不出一种方法来检测上/下变化。我尝试使用加速度计,但它检测到的设备倾斜多于运动。此外,当运动停止时会有反作用力。

您是否有任何想法这样做,以便可以获得具有相当精确度的运动数据?我需要它来进行空气曲棍球比赛。

【问题讨论】:

    标签: ios cocoa-touch accelerometer gyroscope core-motion


    【解决方案1】:

    为了从 deviceMotion 确定水平位置是不可行的。使用的水平传感器将是加速度计,但它们测量速度的变化。因此,要从中找到位置,您需要将传感器数据集成两次。一次获得速度,第二次获得位置。

    这意味着即使加速度数据中的最小误差也会导致结果速度出现错误,这意味着您的程序认为手机正在以恒定速度移动,而实际上它是静止不动的。

    如果您不需要精确(例如,当您来回移动它时不需要它回到同一位置时),那么如果您将速度强制为如果加速度计数据安静且接近零,则为零。

    如果您真的打算尝试这个,那么Kalman filter 可能是您从加速度计数据中获取速度和位置的最佳选择。 这意味着您的代码最终将如下所示,其中accelerationspeedposition 是您保留的三个变量,acc 是来自加速度计的数据样本。

    // correction step:
    double delta = (acc - acceleration);
    acceleration += FACTOR1 * delta;
    speed += FACTOR2 * delta;
    position += FACTOR3 * delta;
    
    // prediction step:
    position = position + speed * DT + 0.5 * acceleration * DT * DT;
    speed = speed + acceleration * DT;
    

    其中DT 是数据样本之间的时间,您需要找出适合FACTOR1..3 的值。

    顺便说一下,Yaw 不会给你水平运动,而是旋转。


    编辑:如今,您可以使用ARKit's Motion Tracking 获得良好的结果,它将加速度计输入与来自相机的图像分析相结合。它为您完成所有艰苦的工作。

    【讨论】:

    • 事后思考:使用前置摄像头可能会得到更好的结果,并使用一些图像分析来推导天花板图片的运动......
    • 我考虑过使用后置摄像头,但这会迫使用户使用 iPhone 手机壳(否则镜头太近)。感谢您对这篇文章。我昨天发现了双重积分,我会试一试。在我看来,这似乎是最有价值的答案。我会让你知道效果。谢谢!
    【解决方案2】:

    所以我对 CoreMotion 也很陌生。我会尽力解释为什么你的要求不能完成,至少不能准确。

    根据我阅读的 Apple Docs,iOS 有 3 个运动处理程序:

    • 加速度计
    • 陀螺仪
    • 磁力计

    (我相信最新的设备有高度计?)

    根据我对物理学的理解,我认为加速度计对您的场景最有用,因为陀螺仪和磁力计更侧重于旋转。我做了一些研究,发现this book。特别是第 9.5 章。从书中:

    虽然加速度计可以测量 x、y 和 z 轴无法测量旋转。另一方面,陀螺仪是 变化率装置;当手机绕轴旋转时,它 允许您测量此类旋转的变化。

    按照他们在图 9-5 下的代码来实现一个简单的应用程序来观察加速:

    #import <UIKit/UIKit.h>
    #import <CoreMotion/CoreMotion.h>
    
    @interface ViewController : UIViewController {
    
        CMMotionManager *motionManager;
        NSOperationQueue *queue;
    }
    
    
    @property (weak, nonatomic) IBOutlet UILabel *xLabel;
    @property (weak, nonatomic) IBOutlet UILabel *yLabel;
    @property (weak, nonatomic) IBOutlet UILabel *zLabel;
    
    @property (weak, nonatomic) IBOutlet UIProgressView *xBar;
    @property (weak, nonatomic) IBOutlet UIProgressView *yBar;
    @property (weak, nonatomic) IBOutlet UIProgressView *zBar;
    
    @end
    

    然后在.m viewDidLoad中

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        motionManager = [[CMMotionManager alloc] init];
        motionManager.accelerometerUpdateInterval  = 1.0/10.0; // Update at 10Hz
        if (motionManager.accelerometerAvailable) {
            NSLog(@"Accelerometer avaliable");
            queue = [NSOperationQueue currentQueue];
            [motionManager startAccelerometerUpdatesToQueue:queue
              withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
                CMAcceleration acceleration = accelerometerData.acceleration;
                xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x];
                xBar.progress = ABS(acceleration.x);
    
                yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y];
                yBar.progress = ABS(acceleration.y);
    
                zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z];
                zBar.progress = ABS(acceleration.z);
            }];
    
        }
    }
    

    将所有内容连接起来并在手机上运行后,我看到加速度计正在测量我的手机在平板上移动时加速和减速的变化。现在我们有了加速度,但是要从中获得位置变化(这是您所要求的),需要双重积分(即有趣的微积分)。虽然可行,但我查看了 arduino 的知识渊博的人对 here 的看法,这是一个可怕的消息。 (他们没有讨论 iPhone 加速度计,但我推断此信息也适用于这个问题)。

    我在这里发布的相关部分:

    从加速度获得位置是一个双重积分,所以 错误叠加真的很邪恶。使用螺栓获得良好的位置数据 down IMU(你正在尝试做的事情)是一个真正的难题;这 所需的加速度计非常昂贵。

    你说的是双重整合,这也是 此硬件上的单个加速度计不准确。甚至单身 仅仅因为 此设置缺乏准确性。

    所有这些研究得出的结论是,在 iPhone 上执行您要求的操作是不可行的。 虽然就像我说的,但我也是这方面的初学者!抱歉,这不是您想听到的答案。

    【讨论】:

      【解决方案3】:

      设备无法检测到移动。沿着桌子表面的直线恒定运动是绝对无法检测到的。那是因为没有力量在起作用。

      该设备只能检测 attitude(空间中的方向,以及该方向的变化)和 force(速度的增加或减少)。

      因此,您需要围绕这些能力形成期望。

      【讨论】:

      • 好的,所以我现在正在做的是var ax: Double = data.userAcceleration.x; var ay: Double = data.userAcceleration.y; if((abs(ax) &gt; 0.05) || (abs(ay) &gt; 0.05)) { //use the data },它令人惊讶地做了我真正想要的。然而,惯性反应存在一个大问题,如果设备突然停止移动,它基本上会将玩家置于任何移动之前的位置。您能想出任何解决方案来防止这种情况发生吗?
      • 我唯一能想到的就是继续跟踪,从而从设备正在明显移动的事实中推断出这种突然减速可能是设备停止了,不是将设备移回原来位置的加速度。即使那样,您也可能只是猜测。
      • 我们可以通过核心运动检测表面的水平测量吗?或者您能否建议任何替代方式
      【解决方案4】:

      这个链接也许能解释更多 http://blog.denivip.ru/index.php/2013/07/the-art-of-core-motion-in-ios/?lang=en

      不过,您似乎需要了解 Y 轴加速度。 Apple Docs 似乎很好地涵盖了这一点。 https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

      使用运动处理方法检测运动何时发生变化,然后访问 y 位置的变化。如果您也愿意,我可以尝试提供一些代码。

      【讨论】:

        猜你喜欢
        • 2018-03-20
        • 1970-01-01
        • 2020-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-04
        • 1970-01-01
        • 2012-09-05
        相关资源
        最近更新 更多