IPhone motion detection on a flat surface

I am a beginner novice.

I need to detect the movement of the iPhone on a flat surface such as a table - while I did this, to detect its lateral movement, turning to the yaw of the gyroscope, but I can not come up with a way to detect up / down changes. I tried using an accelerometer, but it detects more tilt of the device than movement. In addition, there is opposition when the movement stops.

Do you have any idea to do this so that you can get motion data with reliable accuracy? I need this for a bit of an air hockey game.

+6
source share
4 answers

In order to determine the horizontal position from the device, the movement is not actually feasible. The horizontal sensors used will be accelerometers, but they measure changes in speed. Therefore, to find the position from this, you will need to integrate the sensor data twice. One time to get speed, then a second time to get position.

This means that even the smallest inaccuracy in the acceleration data will lead to an error in the resulting speed, which means that your program believes that the phone is moving at a constant speed, while in reality it stands still.

If you do not need to be precise (for example, when you do not need to return to the same position when you move it back and forth), you can get acceptable results if you force the speed to zero if the accelerometer data is quiet and close to to zero.

If you are really trying to do this, then the Kalman filter will probably be the best choice for determining speed and position according to the accelerometer. This means that your code will eventually look something like this: where acceleration , speed and position are the three variables that you save, and acc is the selection of data from the accelerometer.

 // 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 the appropriate values ​​for FACTOR1..3 you need to find out.

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


EDIT : Currently, you can get good results with ARKit Motion Tracking , which combines accelerometer input with camera image analysis. It does all the hard work for you.

+7
source

So, I'm pretty new to CoreMotion. I will do my best to explain why what you ask cannot be done, at least inaccurate.

Based on the Apple docs I read, there are 3 move handlers for iOS:

  • Accelerometer
  • Gyroscope
  • magnetometer

(I believe that the latest devices have an altimeter?)

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

While the accelerometer provides a measurement of forces in the x-, y- and z-axis can not measure rotation. On the other hand, a gyroscope is a speed changing device; when the phone rotates around an axis, it allows you to measure changes in such turns.

Following their code in accordance with Figure 9-5 to implement a simple application for viewing acceleration:

 #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 .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 everything is connected and working on the phone, I see that the accelerometer measures the changes in my phone, which accelerate and decelerate when I move it to a flat table. Now we have acceleration, but in order to get a change in position (this is what you requested), it requires double integration (for example, fun calculus). While doable, I looked at what knowledgeable people in arduino have to say about it here , and boy is dark news. (They don’t discuss the iPhone’s accelerometer, but I extrapolated that this information applies to this issue as well).

Relevant parts that I posted here:

Getting a position from acceleration is a double integration, so the stack error is really evil. Obtaining good position data using IMU bolting down (what you're trying to do) is a truly difficult problem; The kind of accelerometers needed for this is very expensive.

and

What you are talking about is double integration, which is also too inaccurate with one accelerometer on this equipment. Even single integration will have a growing error per unit of time simply due to a lack of accuracy in this setting.

All this research leads to my conclusion that on the iPhone it is impossible to fulfill what you ask. Although, as I said, I am also a beginner! Sorry, this is not the answer you wanted to hear.

+5
source

The device cannot detect movement. Direct continuous movement along the table surface is absolutely impossible to detect. This is because there are no forces acting.

The device can only detect the ratio (orientation in space and a change in this orientation) and force (increase or decrease in speed).

So, you need to shape your expectations around these abilities.

+3
source

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

Sounds like you need to pick up the Y-Axis acceleration. Apple Docs seems to do very well with this. https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

Use motion processing methods to determine when the movement changes, and then access the change in position y. I can try to provide some code if you want.

+1
source

Source: https://habr.com/ru/post/1206676/


All Articles