Detect programmatically if iPhone is dropped using CoreMotion/Accelerometer - ios

So I am writing a piece of code where I have to detect different movement gestures using Accelerometer and gyroscope in iOS 4.3 above.
Q1: Is there any existing opensource code which has achieved any movement/gesture detection?
If not
Q2: For now I want to detect if the iPhone is dropped.
What I have achieved so far:
CoreMotion API gives userAcceleration, which (afaik) is the acceleration that the user is giving to the device or the acceleration of device in some direction (x, y or z) with out considering the gravity so what I can do is: store, let's say, previous 5-6 values of acceleration parameters and can check where any of them hits large negative value, which basically represents the sudden deceleration.
But this solution is not very optimal, I think I need to somehow detect the freefall/downwards motion of the device too first. Any idea how to approach this problem?
UPDATE:
Thanks Misch for sharing your approach. I was not at all thinking about total acceleration. I did exactly what you said:
"You would however have to test yourself, what means "total acceleration corresponds
approximately to earth acceleration" and "for some time" in your case."
The acceleration value is actually in G's so I tested the "total acceleration" values with in range of 0.9 - 1.1. And I checked them over some time, initially I checked four consecutive values when updateInterval is set to 1/20.0. For now I have relaxed the condition of consecutiveness a little.
Here's a sample output:
Acceleration = 0.090868
Acceleration = 0.074473
Acceleration = 0.159797
Acceleration = 1.157513
Acceleration = 1.224588
Acceleration = 1.036272
Acceleration = 0.914698
Acceleration = 0.904093
Acceleration = 0.941516
Acceleration = 0.046362
Acceleration = 0.045109
Acceleration = 0.060045
I think, I still have to keep on testing and adjusting values. If you have any optimization in mind kindly do share, I know in order to help you'd need to see the many samples of freefall acceleration values. For now I am thinking to:
round off the values of acceleration to 3 decimal places and play with the acceleration range I am using.
May be check if, after the freefall condition is met, total acceleration value suddenly goes down.
Do you think the acceleration values I have quoted are a bit noisy?

To Q2:
Checking for large negative values does not tell you whether the phone is being dropped.
First, the user could just move the phone with a rapid gesture, this would also result in a large (maybe negative) value.
Secondly, the phone could fall in another direction than you imagine, and therefore, the acceleration could be positive, although the phone is moving towards the ground.
You could just calculate the total acceleration (a = sqrt(ax^2 + ay^2 + az^2)) and check whether this total acceleration corresponds approximately to earth acceleration (9.81). The phone is falling if the acceleration corresponds to earth acceleration for some time.
You would however have to test yourself, what means "total acceleration corresponds approximately to earth acceleration" and "for some time" in your case.
The physics behind this:
Let's assume you drop your phone in a way, that the y axis of the phone shows upwards. Then the x and z accelerations will be 0 and the y acceleration will be like this:
The acceleration will be 0 in the beginning, will then reach -9.81 the moment, you release your phone. Then it will hit the ground, which you see in the small acceleration peak, and then the acceleration is zero again.
However you can't use only the acceleration in y direction, because your phone may fall in a different angle.
So you have to watch the total acceleration of your phone:
Here you don't see a negative acceleration anymore. However, here it doesn't matter anymore in which direction your phone is facing, as a free fall will always be characterized by an acceleration of 9.81.
To your edits:
1. Why would you want to round off the values of acceleration to 3 decimal places? If you test 0.9 < x < 1.1, it doesn't matter if x is 0.914698 or 0.915.
2. What if someone drops the phone but then catches it again, so the total acceleration does not necessarily have to go down again. Additionally, there should be a large acceleration value (a sudden deceleration) the moment the phone hits the floor. Maybe the reason one does not see this in your values is that it is so short, that it falls between two consecutive measurements. However this could be measured, so don't suppose that immediately after the free fall, the acceleration should decrease again.

Related

UIAccelleration value range

The AppleDeveloper guide seem to imply that UIAccelerationValue can range between a double value of -1.0 and +1.0.
I have logged the values from a real device whilst "shaking" with crazy gestures my iPod touch and got x values above 2.0 (e.g. +2.1, -2.1) and NO y value above 2.0f.
Could anyone explain this?
Has anyone identified the MAX and MIN values for UIAccelerationValue?
My take on this is that Apple has implemented some algorithm that approximates the force of gravity and takes as 1.0 values that are above a standard speed approximation (e.g. have values 9.8 m/s of speed).
Any other guesses?
You may be misunderstanding a part of the documentation. Nowhere does it say that the value ranges between -1.0. and 1.0, as far as I can see. It says that:
The device accelerometer reports values for each axis in units of
g-force, where a value of 1.0 represents acceleration of about +1 g
along a given axis. When a device is laying still with its back on a
horizontal surface, each acceleration event has approximately the
following values:
"g" is used in a particular technical sense here; 1 g is one standard gravity; a phone accelerating faster than this will register readings higher than 1. Violent shaking in the hand is easily enough to cause acceleration and deceleration values higher than 9.8m/s2.

how can i get velocity with UIAcceleration?

Do you know the app "motion ruler"? It can be used to get the length of an object by moving an iPhone.
How can I get the velocity from UIAcceleration when moving an iPhone?
Velocity is just acceleration * time. I.e. you can use the formula
v = u + acceleration * time.
As a starter you could look at assuming the initial speed is 0, 'u' can be ignored to get accelration * time.
if you want distance just use
distance = initial velocity * time + 0.5 * acceleration * time * time.
or better still use dead reckoning and keep adding your velocity vectors as frequently as you get updates from the accelerometers.
To get acceleration as a scalar you can do a = sqrt(x*x+y*y+z*z). You will want to remove gravity from this before though! Also this will only give you distance in straight line, you may prefer to measure velocity in x,y,z independently and use vector analysis to measure the path for a more accurate reading. Be warned though, you may also need to take into account any rotations to be super accurate and this feature is only on iPhone4s. This can get tricky and you'll probably want to use some matrix maths to orientate the 'space' the phone is in.
You will also need to do a low pass filter on the accelerometer to get rid of the 'shakes' and this is where a significant error margin will creep in and why I'd expect all rulers in appstore have spent a long time refining this.
to do a filter, a very simple one is filteredValue = ((lastValue * n) + accelerationValue )/(n+1) where a larger n value gives a smoother result but less responsive.

Blackberry Device Movement Angle Difference

I am working on a Blackberry application in which I need to retrieve the Angle difference when the device moves. It means the difference of angle between when the movement starts and ends. It must be 25 degrees to call some function.
In simple words, call a function when the device moves by 25 degrees.
Please read AccelerometerSensor docs, it is available in API 4.7.0 and higher. All data that you can retrieve is described in class AccelerometerData, it is orientation and acceleration (gravity data).
It is described more in details how to get angle from gravity sensor data in JavaME docs, "Mobile Sensor API" section:
If the phone was placed flat, the accelerometer would tell us that the acceleration along the z-axis (up and down) is about 1000 (this value represents 1G). The accelerations along the X and Y axises (sideways) would be about 0 since the phone is sitting still and gravity only works downwards. Flipping the phone over with the screen facing down, the accelerometer would give us the value of -1000 on the Z-axis. Standing on its side, would give us a value of 1000 or -1000 along either the X- or the Y-axis, depending on which side you put it. Putting the phone in a 45 degree angle along the X-axis would give us a value of ±707 on the Z-axis and ±707 on the Y-axis, since gravity cannot affect either axis with its full force (You can easily calculate what the value should be for a certain angle for each axis using the sine and cosine functions). Using the values from the X and Y-axis from the accelerometer, we can determine the position of the phone at any time, and then use that value to move our ship to avoid the incoming asteroids.
So, having accelerometer data for all 3 axes we may figure it out what is horizontal angle of a device.

Mapping device tilt to player character (etc) movement behaviour

The context is an iPad game in which I want an on-screen object to be controlled by X/Y tilt of the device.
I was wondering if anybody can point me in the direction of resources for deciding on an appropriate mapping of tilt to the movement behaviour (e.g. whether people tend to use the "raw" rotation values to control the acceleration, velocity or direct position, and how comfortable players have been found to be with these different types of 'mapping' of device rotation to object movement).
I appreciate that the appropriate choice can depend on the particular type of game/object being controlled, and that some trial and error will be needed, but I wondered as a starting point at least what existing knowledge there was to draw on.
First you're going to want to apply a low-pass filter to isolate tilt from noise and your user's shaky hands, Apple shows this in their accelerometer examples
x = accel.x * alpha + x * (1.0 - alpha);
y = accel.y * alpha + y * (1.0 - alpha);
more alpha causes more responsiveness at the cost of more noisy input.
Unless your game is intentionally simulating a ball balancing on the face of the screen, you probably don't want to apply your tilt values to acceleration, but rather to target velocity or target position, applying "fake" smooth acceleration to get it there.
Also, this answer has a neat idea if Unity3d is acceptable for your project, and this paper has some handy numbers on the practical limits of using tilt control as input, including making the important point that users have a much easier time controlling absolute angle position than velocity of tilt.
So, we desire to move our character - we'll call him 'loco' - based on the accelerometer's x and y data.
Now, if we do want the magnitude of the tilt to affect the rate of loco's travel, we can simply factor the accelerometer x or y value directly into our algorithm for his movement.
For example: (psuedocode)
// we'll call our accelerometer value for x 'tiltX'
// tiltX is .5; // assume that accelerometer updated the latest x value to .5
// unitOfMovement = 1; // some arbitraty increment you choose for a unit of movement
loco.x += unitOfMovement * tiltValueX;
This will cause loco to move that number of pixels for each game cycle (or whatever cycle you are driving the updates for movement by) and that here is 1 pixel multiplied by the accelerometer value. So if the character normally moves 1 pixel right at full tiltX (1.0), then if tiltX comes in from the accelerometer at .5, loco will move half that. When the value of tiltX increases, so too will the movement of Loco.
Another consideration is whether you want the movement tied directly to the rate of accelerometer events? Probably not, so you can use an array to just hold the last ten x values (same concept for y values too) sent by the accelerometer and use the latest average of the array (sum of x values / number of elements in array) at each game loop. That way, the sensitivity will feel more appropriate than driving the movement by whatever the update rate of the accelerometer may be.
Have a look at Point in Tilt Direction - iPhone which is first answer is very helpful I think.

Easy code sample for formula for simulating deceleration of a rotating sphere due to friction and gravity?

I have a rotating sphere that the user rotates by applying a virtual force, like a virtual accelerator. I want to be able to simulate a nice momentum effect so that when they lift off the accelerator the ball winds down in speed in a natural and realistic way, as if due to friction and/or gravity. I don't want to get into any deep physics equations. I'd like to do this quick so if I could find a code sample that shows how to do this, or even a page of formulas clear enough that I could encode, that would be great.
I'd like a formula that has one or two adjustable coefficients that I could tune to make the ball decelerate faster or slower depending on my needs. I don't want to get into anything heavy like an open source physics library or the like. Just something simple.
I'm using Delphi 6 Pro but I also know C/C++, Basic, Java, and Javascript.
Velocity is change in displacement. Acceleration is change in velocity.
Gravity or friction just causes an acceleration (possibly negative).
So all you need to do is apply a negative acceleration when they do not activate the accelerator.
So lets assume you have an angle that is changing. Applying the accelerator increases the amount the angle changes by each iteration or time step. If your angle is t and your change in angle is called dt (angular velocity) then when the accelerator is applied you'll have:
t = t + dt
dt = dt + a
where a depends on how much force you're applying, or how much they've 'pressed' the accelerator (i.e. this is the acceleration).
You'll probably want to limit dt (i.e. speed of rotation) - if you only want to spin in one direction you'll have an upper positive limit and a lower limit of 0. If you want both directions, you can have a lower negative limit and an upper positive limit.
All you need to do is make a some negative number when the accelerator is not applied (if dt is positive - make a positive if dt is negative), and ensure you don't 'wrap' (i.e. make dt 0 when it gets near 0).
It has been some time ago, but according to my dynamics study books the Mass Moment of Inertia for a sphere is defined as I=(2/5)m*r^2. m is the mass, r is the radius of the sphere (all in SI untis). On this page you'll find some examples to use the mass moment of inertia to calculate deceleration of the sphere as a result of the applied negative torque. This toqrue is a result of the friction. Since you are not defining the material of the surface of the sphere and the surroudings you cannot calculate the friction and will have to choose a good force yourself.
As long as you are not solving stellar problems, I don't see how gravity has much to do with decelerating the rotation.
Friction is almost proportional to the current rotation speed (actually the speed on the surface of the sphere).
So a formula for the current rotation speed over time w(t) may be something like this:
w(t) = w0*exp(-c*(t - t0))
with t0 being the time the friction starts, wt being the rotation speed at that time.
The coefficient c > 0 determines how fast the speed will decrease - the higher c, the faster the speed will go down. This formula is valid for all t >= t0.
Note that for t = t0 the exp function returns 1 and you get the initial speed, while for t -> ∞ the exp function (and so the resulting speed) returns -> 0 (the minus in front of the c guarantees this).
You've already accepted an answer, but I'll put in my piece.
I'll assume you already know how to make the sphere spin at a constant rate, and how to make it accelerate under the applied torque. Making it decellerate is just a matter of applying another torque, one that must be calculated.
When an object slides on a solid surface, the rate of deceleration is constant. The force is in the direction opposite to motion, and its magnitude depends on a couple of things but not speed. When the object comes to a full stop, the force vanishes. The same applies to a globe turning on a solid pivot.
When an object passes through a fluid, the force of decelleration increases with speed, so the faster the object the greater the drag. As the object slows down, decelleration grows weaker, and the object keeps slowing down but never stops. This describes a globe spinning in air or water. At reasonably high speeds, drag is proporional to v2, and at very low speeds it is proportional to v (I don't know about the transition between these domains).
So I suggest t = -a wb, where w is angular velocity. The parameter a is the strength of the friction, and b describes the kind of decelleration; b=0 is like friction on a solid pivot, b=2 is like spinning in air, and b=1 is like rotating in syrup. Other values of b may or may not look realistic or be realistic.

Resources