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.
Related
What is the difference between CMRotationRate and CMAttitude? In the documentation I did not find any useful definition. https://developer.apple.com/reference/coremotion/cmrotationrate and https://developer.apple.com/reference/coremotion/cmattitude.
What do these properties say about the motion of the device?
What are the physical units, the values are represented?
Not code specific, but terms in general (and seem to apply here):
Rotation rate means the rate of turn in reference of an object's axis. Hence the x,y and z properties. So what it means that if the rotation rate is for example y=1 (radians or degrees per second), the attitude of the object changes.
Attitude means the position of the object, described over three axis: x,y and z. Attitude itself does not necessarily imply movement. The object can be still with any attitude.
So, the main difference: Rotation rate describes the change of attitude.
Hope this gives at least a little help.
Without looking at the specific framework you're using, rotation rate describes a change in orientation. It will be expressed in degrees (or radians) per second for each axis.
Attitude, on the other hand, is the orientation of the phone at a moment in time. It will be a fixed value in degrees (or radians). Again, probably with a value for each axis.
If you are facing due east, and are flat and level, that's your attitude at an instant in time.
If your rotation rate is zero, you'll be at the same attitude 5 minutes later.
If on the other hand you're rotating 30°/second in yaw, then 5 minutes later you will have completed 25 revolutions, and have a different attitude. (In fact you'll probably have a pretty bad attitude because you'll be dizzy and nauseous. (grin).)
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.
While porting my Android app to iOS I was confused with one thing, so I want to find out: am I right or mo code works wrong. At Android device accelerometer returns values in physical measure units: m/s2. On ipad i get summary force approximately = 1.0 for still device(and i expect 9.8). My first explanation is that returning value is normalized to 9.8, so I must multiply it with 9.8 to get real force. My second idea - my code is totally wrong, but it's hard to believe.
From the Docs on CMAcceleration:
CMAcceleration
The type of a structure containing 3-axis acceleration values.
typedef struct {
double x;
double y;
double z;
} CMAcceleration;
X-axis acceleration in G's (gravitational force).
Y-axis acceleration in G's (gravitational force).
Z-axis acceleration in G's (gravitational force).
A G is a unit of gravitation force equal to that exerted by the earth’s gravitational field (9.81 m s−2).
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.
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.