在平板上检测iPhone移动

时间:2022-09-11 07:25:57

I'm a coremotion beginner.

我是一个coremotion初学者。

I need to detect iPhone movement on a flat surface like table - so far, I made it to detect its sideways movement by accessing the yaw of the gyro, but I can't think of a way to detect the up/down changes. I tried using the accelerometer, but it detects more of a device tilt than movement. Also, there is a counterforce when the movement stops.

我需要在一个像桌子一样的平面上检测iPhone的运动——到目前为止,我通过获取陀螺仪的偏航来检测它的侧向运动,但我想不出一种方法来检测上下变化。我试过使用加速计,但它探测到的设备倾斜程度要比运动的多。此外,当运动停止时,还会有一股反作用力。

Do you have any idea to do it so that it would be possible to have the movement data with fair precision? I need it for something like air-hockey game.

你有什么办法让运动数据精确到一定程度吗?我需要它来打曲棍球。

4 个解决方案

#1


6  

In order to determine horizontal position from the deviceMotion is not really doable. The horizontal sensors to use would be the accelerometers, but they measure changes in speed. Therefore, to find position from that, you would need to integrate the sensor data twice. Once to get speed, then a second time to get position.

为了确定从设备的水平位置,情感并不是真的可行。使用的水平传感器将是加速度计,但它们测量的是速度的变化。因此,要从中找到位置,需要对传感器数据进行两次集成。一次得到速度,再一次得到位置。

That means that even the smallest inaccuracy in the acceleration data will make an error in the resulting speed, meaning that your program thinks the phone is moving at constant speed, while in reality it is standing still.

这意味着,即使是加速度数据中最小的不准确性也会导致速度错误,这意味着你的程序认为手机在匀速移动,而实际上它是静止的。

If you don't need to be accurate (for example, when you do not need it to come back to the same position when you move it back and forth), then you might get acceptable results if you force the speed to zero if the accelerometer data is quiet and close to zero.

如果你不需要准确的(例如,当你不需要它回到相同的位置来回移动时),那么你可能会得到可以接受的结果,如果你的力量速度为零,如果加速度计数据是安静的和接近于零。

If you are really set on trying this, then a Kalman filter is probably your best bet to derive speed and position from the accelerometer data. That means that your code will in the end look something like the following, where acceleration, speed, and position are three variables you keep, and acc is a data sample from the accelerometer.

如果你真的想尝试这个,那么卡尔曼滤波器可能是你从加速度计数据中得出速度和位置的最佳选择。这意味着您的代码最终将看起来类似如下所示,其中加速度、速度和位置是您保留的三个变量,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;

where DT is the time between data samples, and suitable values for FACTOR1..3 you will need to find out.

其中DT为数据样本之间的时间,为FACTOR1的合适值。你需要弄清楚。

By the way, Yaw does not give you horizontal motion, but rotation.

顺便说一下,偏航不是水平运动,而是旋转。

#2


5  

So I'm pretty new to CoreMotion as well. I'll give my best shot at explaining why what you ask can't be done, at least not accurately.

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

Based on the Apple Docs I read, there are 3 motion handlers for iOS:

根据我读到的苹果文档,iOS有3个运动处理器:

  • Accelerometer
  • 加速度计
  • Gyroscope
  • 陀螺仪
  • Magnetometer
  • 磁强计

(I believe the newest devices have an altimeter?)

(我相信最新的设备有测高仪吗?)

Based on my understanding of physics, I gathered that accelerometer would be most useful for your scenario, as the gyroscope and magnetometer are more focused on rotation. I did some research and found this book. Chapter 9.5 in particular. From the book:

基于我对物理学的理解,我认为加速度计对你的场景最有用,因为陀螺仪和磁强计更关注旋转。我做了一些调查,发现了这本书。尤其是9.5章。从这本书中说:

While an accelerometer provides measurement of forces in the x-, y-, and z-axes it cannot measure rotations. On the other hand, a gyroscope is a rate-of-change device; as the phone rotates around an axis, it allows you to measure the change in such rotations.

虽然加速度计可以测量x轴、y轴和z轴的力,但它不能测量旋转。另一方面,陀螺仪是一种变化速率装置;当手机围绕一个轴旋转时,它允许你测量这种旋转的变化。

Following their code under figure 9-5 for implementing a simple app to watch the acceleration:

按照图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

Then in the .m viewDidLoad

然后在。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);
        }];

    }
}

After linking everything up and running it on the phone, I see that the accelerometer is measuring the changes of my phone accelerating and decelerating as I move it on a flat table. Now we have the acceleration, but to get the change in position (which is what you asked) from that requires double integration (ie fun calculus). While doable, I looked up what the knowledgeable folks over at arduino have to say about that here and boy is it grim news. (They aren't discussing the iPhone accelerometer but I extrapolated that this info applies to this question as well).

连接好所有东西并在手机上运行后,我看到加速度计正在测量我的手机在平板上移动时的加速和减速变化。现在我们有了加速度,但是要得到位置的变化(这是你问的),需要双积分(即有趣的微积分)。在可行的同时,我查了阿都诺的知识分子们对此的看法,天哪,这真是个坏消息。(他们不是在讨论iPhone的加速度计,但我推断这个信息也适用于这个问题)。

The relevant parts I've posted here:

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

Getting position from acceleration is a double integration, so the error stackup is really evil. Getting good position data with a bolted down IMU (what you are trying to do) is a genuinely hard problem; the kind of accelerometers needed to do it are very expensive.

从加速度获取位置是一个双重积分,所以错误堆叠是非常邪恶的。用一个固定的IMU(你正在尝试做的)获取良好的位置数据是一个真正困难的问题;需要的加速度计非常昂贵。

and

What you are talking about is double integration, which is just too inaccurate with a single accelerometer on this hardware. Even single integration will have a growing error per unit time simply because of the lack of accuracy in this setup.

你说的是双积分,这对这个硬件上的一个加速度计来说太不准确了。即使是单次集成,单次集成在单位时间内的误差也会越来越大,这仅仅是因为这种设置缺乏准确性。

All of this research leading up to my conclusion that it's not feasible on an iPhone to do what you ask. Though like I said, I'm a beginner at this as well! Sorry that this isn't the answer you wanted to hear.

所有这些研究导致了我的结论:在iPhone上做你要求的事情是不可行的。虽然就像我说的,我也是个初学者!对不起,这不是你想要的答案。

#3


3  

The device cannot detect movement. A straight-line constant motion along the surface of the table is absolutely undetectable. That is because there no forces acting.

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

The device can detect only attitude (orientation in space, and change in that orientation) and force (increase or decrease in velocity).

该设备只能检测姿态(空间方向,方向变化)和力(速度增加或减少)。

So, you need to form your expectations around those abilities.

所以,你需要围绕这些能力形成你的期望。

#4


1  

This link may be able to explain things a little more http://blog.denivip.ru/index.php/2013/07/the-art-of-core-motion-in-ios/?lang=en

这个链接可以解释更多的东西:http://blog.denivip.ru/index.php/2013/07/core - motionin -ios/?lang=en

It seems like you need to pick up on the Y-Axis Acceleration though. The Apple Docs seem to cover this pretty well. https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

看起来你需要考虑y轴的加速度。苹果文档似乎很好地涵盖了这一点。https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

Use the motion-handling methods to detect when motion changes and then access the change in y position. I can attempt to provide some code if you'd like as well.

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

#1


6  

In order to determine horizontal position from the deviceMotion is not really doable. The horizontal sensors to use would be the accelerometers, but they measure changes in speed. Therefore, to find position from that, you would need to integrate the sensor data twice. Once to get speed, then a second time to get position.

为了确定从设备的水平位置,情感并不是真的可行。使用的水平传感器将是加速度计,但它们测量的是速度的变化。因此,要从中找到位置,需要对传感器数据进行两次集成。一次得到速度,再一次得到位置。

That means that even the smallest inaccuracy in the acceleration data will make an error in the resulting speed, meaning that your program thinks the phone is moving at constant speed, while in reality it is standing still.

这意味着,即使是加速度数据中最小的不准确性也会导致速度错误,这意味着你的程序认为手机在匀速移动,而实际上它是静止的。

If you don't need to be accurate (for example, when you do not need it to come back to the same position when you move it back and forth), then you might get acceptable results if you force the speed to zero if the accelerometer data is quiet and close to zero.

如果你不需要准确的(例如,当你不需要它回到相同的位置来回移动时),那么你可能会得到可以接受的结果,如果你的力量速度为零,如果加速度计数据是安静的和接近于零。

If you are really set on trying this, then a Kalman filter is probably your best bet to derive speed and position from the accelerometer data. That means that your code will in the end look something like the following, where acceleration, speed, and position are three variables you keep, and acc is a data sample from the accelerometer.

如果你真的想尝试这个,那么卡尔曼滤波器可能是你从加速度计数据中得出速度和位置的最佳选择。这意味着您的代码最终将看起来类似如下所示,其中加速度、速度和位置是您保留的三个变量,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;

where DT is the time between data samples, and suitable values for FACTOR1..3 you will need to find out.

其中DT为数据样本之间的时间,为FACTOR1的合适值。你需要弄清楚。

By the way, Yaw does not give you horizontal motion, but rotation.

顺便说一下,偏航不是水平运动,而是旋转。

#2


5  

So I'm pretty new to CoreMotion as well. I'll give my best shot at explaining why what you ask can't be done, at least not accurately.

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

Based on the Apple Docs I read, there are 3 motion handlers for iOS:

根据我读到的苹果文档,iOS有3个运动处理器:

  • Accelerometer
  • 加速度计
  • Gyroscope
  • 陀螺仪
  • Magnetometer
  • 磁强计

(I believe the newest devices have an altimeter?)

(我相信最新的设备有测高仪吗?)

Based on my understanding of physics, I gathered that accelerometer would be most useful for your scenario, as the gyroscope and magnetometer are more focused on rotation. I did some research and found this book. Chapter 9.5 in particular. From the book:

基于我对物理学的理解,我认为加速度计对你的场景最有用,因为陀螺仪和磁强计更关注旋转。我做了一些调查,发现了这本书。尤其是9.5章。从这本书中说:

While an accelerometer provides measurement of forces in the x-, y-, and z-axes it cannot measure rotations. On the other hand, a gyroscope is a rate-of-change device; as the phone rotates around an axis, it allows you to measure the change in such rotations.

虽然加速度计可以测量x轴、y轴和z轴的力,但它不能测量旋转。另一方面,陀螺仪是一种变化速率装置;当手机围绕一个轴旋转时,它允许你测量这种旋转的变化。

Following their code under figure 9-5 for implementing a simple app to watch the acceleration:

按照图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

Then in the .m viewDidLoad

然后在。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);
        }];

    }
}

After linking everything up and running it on the phone, I see that the accelerometer is measuring the changes of my phone accelerating and decelerating as I move it on a flat table. Now we have the acceleration, but to get the change in position (which is what you asked) from that requires double integration (ie fun calculus). While doable, I looked up what the knowledgeable folks over at arduino have to say about that here and boy is it grim news. (They aren't discussing the iPhone accelerometer but I extrapolated that this info applies to this question as well).

连接好所有东西并在手机上运行后,我看到加速度计正在测量我的手机在平板上移动时的加速和减速变化。现在我们有了加速度,但是要得到位置的变化(这是你问的),需要双积分(即有趣的微积分)。在可行的同时,我查了阿都诺的知识分子们对此的看法,天哪,这真是个坏消息。(他们不是在讨论iPhone的加速度计,但我推断这个信息也适用于这个问题)。

The relevant parts I've posted here:

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

Getting position from acceleration is a double integration, so the error stackup is really evil. Getting good position data with a bolted down IMU (what you are trying to do) is a genuinely hard problem; the kind of accelerometers needed to do it are very expensive.

从加速度获取位置是一个双重积分,所以错误堆叠是非常邪恶的。用一个固定的IMU(你正在尝试做的)获取良好的位置数据是一个真正困难的问题;需要的加速度计非常昂贵。

and

What you are talking about is double integration, which is just too inaccurate with a single accelerometer on this hardware. Even single integration will have a growing error per unit time simply because of the lack of accuracy in this setup.

你说的是双积分,这对这个硬件上的一个加速度计来说太不准确了。即使是单次集成,单次集成在单位时间内的误差也会越来越大,这仅仅是因为这种设置缺乏准确性。

All of this research leading up to my conclusion that it's not feasible on an iPhone to do what you ask. Though like I said, I'm a beginner at this as well! Sorry that this isn't the answer you wanted to hear.

所有这些研究导致了我的结论:在iPhone上做你要求的事情是不可行的。虽然就像我说的,我也是个初学者!对不起,这不是你想要的答案。

#3


3  

The device cannot detect movement. A straight-line constant motion along the surface of the table is absolutely undetectable. That is because there no forces acting.

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

The device can detect only attitude (orientation in space, and change in that orientation) and force (increase or decrease in velocity).

该设备只能检测姿态(空间方向,方向变化)和力(速度增加或减少)。

So, you need to form your expectations around those abilities.

所以,你需要围绕这些能力形成你的期望。

#4


1  

This link may be able to explain things a little more http://blog.denivip.ru/index.php/2013/07/the-art-of-core-motion-in-ios/?lang=en

这个链接可以解释更多的东西:http://blog.denivip.ru/index.php/2013/07/core - motionin -ios/?lang=en

It seems like you need to pick up on the Y-Axis Acceleration though. The Apple Docs seem to cover this pretty well. https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

看起来你需要考虑y轴的加速度。苹果文档似乎很好地涵盖了这一点。https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

Use the motion-handling methods to detect when motion changes and then access the change in y position. I can attempt to provide some code if you'd like as well.

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