blob: 289c63972c1628af64718296c2fad856add4580f [file] [log] [blame]
Bill Gruberf8c029e2011-11-01 09:31:57 -07001page.title=Motion Sensors
Scott Main64461bf2013-04-11 19:32:08 -07002page.tags="sensorevent","accelerometer","gyroscope","gravity","rotation"
Bill Gruberf8c029e2011-11-01 09:31:57 -07003@jd:body
4
5<div id="qv-wrapper">
6 <div id="qv">
7 <h2>In this document</h2>
8 <ol>
9 <li><a href="#sensors-motion-accel">Using the Accelerometer</a></li>
10 <li><a href="#sensors-motion-grav">Using the Gravity Sensor</a></li>
11 <li><a href="#sensors-motion-gyro">Using the Gyroscope</a></li>
12 <li><a href="#sensors-motion-linear">Using the Linear Accelerometer</a></li>
13 <li><a href="#sensors-motion-rotate">Using the Rotation Vector Sensor</a></li>
14 </ol>
15 <h2>Key classes and interfaces</h2>
16 <ol>
17 <li>{@link android.hardware.Sensor}</li>
18 <li>{@link android.hardware.SensorEvent}</li>
19 <li>{@link android.hardware.SensorManager}</li>
20 <li>{@link android.hardware.SensorEventListener}</li>
21 </ol>
22 <h2>Related samples</h2>
23 <ol>
24 <li><a href="{@docRoot}resources/samples/AccelerometerPlay/index.html">Accelerometer
25 Play</a></li>
26 <li><a
27href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html">
28API Demos (OS - RotationVectorDemo)</a></li>
29 <li><a
Scott Maincd1b08e2011-12-27 16:22:27 -080030href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html"
Bill Gruberf8c029e2011-11-01 09:31:57 -070031>API Demos (OS - Sensors)</a></li>
32 </ol>
33 <h2>See also</h2>
34 <ol>
35 <li><a href="{@docRoot}guide/topics/sensors/index.html">Sensors</a></li>
36 <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
37 <li><a href="{@docRoot}guide/topics/sensors/sensors_position.html">Position Sensors</a></li>
38 <li><a href="{@docRoot}guide/topics/sensors/sensors_environment.html">Environment
39Sensors</a></li>
40 </ol>
41 </div>
42</div>
43
44<p>The Android platform provides several sensors that let you monitor the motion of a device. Two of
45these sensors are always hardware-based (the accelerometer and gyroscope), and three of these
46sensors can be either hardware-based or software-based (the gravity, linear acceleration, and
47rotation vector sensors). For example, on some devices the software-based sensors derive their data
48from the accelerometer and magnetometer, but on other devices they may also use the gyroscope to
49derive their data. Most Android-powered devices have an accelerometer, and many now
50include a gyroscope. The availability of the softare-based sensors is more variable because they
51often rely on one or more hardware sensors to derive their data.</p>
52
53<p>Motion sensors are useful for monitoring device movement, such as tilt, shake, rotation, or
54swing. The movement is usually a reflection of direct user input (for example, a user steering a
55car in a game or a user controlling a ball in a game), but it can also be a reflection of the
56physical environment in which the device is sitting (for example, moving with you while you drive
57your car). In the first case, you are monitoring motion relative to the device's frame of reference
58or your application's frame of reference; in the second case you are monitoring motion relative to
59the world's frame of reference. Motion sensors by themselves are not typically used to monitor
60device position, but they can be used with other sensors, such as the geomagnetic field sensor, to
61determine a device's position relative to the world's frame of reference (see <a
62href="{@docRoot}guide/topics/sensors/sensors_position.html">Position Sensors</a> for more
63information).</p>
64
65<p>All of the motion sensors return multi-dimensional arrays of sensor values for each {@link
66android.hardware.SensorEvent}. For example, during a single sensor event the accelerometer returns
67acceleration force data for the three coordinate axes, and the gyroscope returns rate of rotation
68data for the three coordinate axes. These data values are returned in a <code>float</code> array
69({@link android.hardware.SensorEvent#values}) along with other {@link android.hardware.SensorEvent}
70parameters. Table 1 summarizes the motion sensors that are available on the Android platform.</p>
71
72<p class="table-caption" id="table1">
73 <strong>Table 1.</strong> Motion sensors that are supported on the Android platform.</p>
74<table>
75 <tr>
76 <th scope="col" style="white-space:nowrap">Sensor</th>
77 <th scope="col" style="white-space:nowrap">Sensor event data</th>
78 <th scope="col" style="white-space:nowrap">Description</th>
79 <th scope="col" style="white-space:nowrap">Units of measure</th>
80 </tr>
81 <tr>
82 <td rowspan="3">{@link android.hardware.Sensor#TYPE_ACCELEROMETER}</td>
83 <td><code>SensorEvent.values[0]</code></td>
84 <td>Acceleration force along the x axis (including gravity).</td>
85 <td rowspan="3">m/s<sup>2</sup></td>
86 </tr>
87 <tr>
88 <td><code>SensorEvent.values[1]</code></td>
89 <td>Acceleration force along the y axis (including gravity).</td>
90 </tr>
91 <tr>
92 <td><code>SensorEvent.values[2]</code></td>
93 <td>Acceleration force along the z axis (including gravity).</td>
94 </tr>
95 <tr>
96 <td rowspan="3">{@link android.hardware.Sensor#TYPE_GRAVITY}</td>
97 <td><code>SensorEvent.values[0]</code></td>
98 <td>Force of gravity along the x axis.</td>
99 <td rowspan="3">m/s<sup>2</sup></td>
100 </tr>
101 <tr>
102 <td><code>SensorEvent.values[1]</code></td>
103 <td>Force of gravity along the y axis.</td>
104 </tr>
105 <tr>
106 <td><code>SensorEvent.values[2]</code></td>
107 <td>Force of gravity along the z axis.</td>
108 </tr>
109 <tr>
110 <td rowspan="3">{@link android.hardware.Sensor#TYPE_GYROSCOPE}</td>
111 <td><code>SensorEvent.values[0]</code></td>
112 <td>Rate of rotation around the x axis.</td>
113 <td rowspan="3">rad/s</td>
114 </tr>
115 <tr>
116 <td><code>SensorEvent.values[1]</code></td>
117 <td>Rate of rotation around the y axis.</td>
118 </tr>
119 <tr>
120 <td><code>SensorEvent.values[2]</code></td>
121 <td>Rate of rotation around the z axis.</td>
122 </tr>
123 <tr>
124 <td rowspan="3">{@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION}</td>
125 <td><code>SensorEvent.values[0]</code></td>
126 <td>Acceleration force along the x axis (excluding gravity).</td>
127 <td rowspan="3">m/s<sup>2</sup></td>
128 </tr>
129 <tr>
130 <td><code>SensorEvent.values[1]</code></td>
131 <td>Acceleration force along the y axis (excluding gravity).</td>
132 </tr>
133 <tr>
134 <td><code>SensorEvent.values[2]</code></td>
135 <td>Acceleration force along the z axis (excluding gravity).</td>
136 </tr>
137 <tr>
138 <td rowspan="4">{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR}</td>
139 <td><code>SensorEvent.values[0]</code></td>
140 <td>Rotation vector component along the x axis (x * sin(θ/2)).</td>
141 <td rowspan="4">Unitless</td>
142 </tr>
143 <tr>
144 <td><code>SensorEvent.values[1]</code></td>
145 <td>Rotation vector component along the y axis (y * sin(θ/2)).</td>
146 </tr>
147 <tr>
148 <td><code>SensorEvent.values[2]</code></td>
149 <td>Rotation vector component along the z axis (z * sin(θ/2)).</td>
150 </tr>
151 <tr>
152 <td><code>SensorEvent.values[3]</code></td>
153 <td>Scalar component of the rotation vector ((cos(θ/2)).<sup>1</sup></td>
154 </tr>
155</table>
156
157<p class="note"><strong><sup>1</sup></strong> The scalar component is an optional value.</p>
158
159<p>The rotation vector sensor and the gravity sensor are the most frequently used sensors for motion
160detection and monitoring. The rotational vector sensor is particularly versatile and can be used for
161a wide range of motion-related tasks, such as detecting gestures, monitoring angular change, and
162monitoring relative orientation changes. For example, the rotational vector sensor is ideal if you
163are developing a game, an augmented reality application, a 2-dimensional or 3-dimensional compass,
164or a camera stabilization app. In most cases, using these sensors is a better choice than using
165the accelerometer and geomagnetic field sensor or the orientation sensor.</p>
166
167<h3>Android Open Source Project Sensors</h3>
168
169<p>The Android Open Source Project (AOSP) provides three software-based motion sensors: a gravity
170sensor, a linear acceleration sensor, and a rotation vector sensor. These sensors were updated in
171Android 4.0 and now use a device's gyroscope (in addition to other sensors) to improve stability and
172performance. If you want to try these sensors, you can identify them by using the {@link
173android.hardware.Sensor#getVendor} method and the {@link android.hardware.Sensor#getVersion} method
174(the vendor is Google Inc.; the version number is 3). Identifying these sensors by vendor and
175version number is necessary because the Android system considers these three sensors to be secondary
176sensors. For example, if a device manufacturer provides their own gravity sensor, then the AOSP
177gravity sensor shows up as a secondary gravity sensor. All three of these sensors rely on a
178gyroscope: if a device does not have a gyroscope, these sensors do not show up and are not
179available for use.</p>
180
181<h2 id="sensors-motion-accel">Using the Accelerometer</h2>
182
183<p>An acceleration sensor measures the acceleration applied to the device, including the force of
184gravity. The following code shows you how to get an instance of the default acceleration sensor:</p>
185
186<pre>
187private SensorManager mSensorManager;
188private Sensor mSensor;
189 ...
190mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
191mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
192</pre>
193
194<p>Conceptually, an acceleration sensor determines the acceleration that is applied
195to a device (A<sub>d</sub>) by measuring the forces that are applied to the sensor
196itself (F<sub>s</sub>) using the following relationship:</p>
197
198<pre class="no-pretty-print classic">
199A<sub>d</sub> = - ∑F<sub>s</sub> / mass
200</pre>
201
202<p>However, the force of gravity is always influencing the measured acceleration according to
203the following relationship:</p>
204
205<pre class="no-pretty-print classic">
206A<sub>d</sub> = -g - ∑F / mass
207</pre>
208
209<p>For this reason, when the device is sitting on a table (and not accelerating), the
210accelerometer reads a magnitude of g = 9.81 m/s<sup>2</sup>. Similarly, when the device is in
211free fall and therefore rapidly accelerating toward the ground at 9.81 m/s<sup>2</sup>, its
212accelerometer reads a magnitude of g = 0 m/s<sup>2</sup>. Therefore, to measure
213the real acceleration of the device, the contribution of the force of gravity must be removed from
214the accelerometer data. This can be achieved by applying a high-pass filter. Conversely, a low-pass
215filter can be used to isolate the force of gravity. The following example shows how you can do
216this:</p>
217
218<pre>
219public void onSensorChanged(SensorEvent event){
220 // In this example, alpha is calculated as t / (t + dT),
221 // where t is the low-pass filter's time-constant and
222 // dT is the event delivery rate.
223
224 final float alpha = 0.8;
225
226 // Isolate the force of gravity with the low-pass filter.
227 gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
228 gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
229 gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
230
231 // Remove the gravity contribution with the high-pass filter.
232 linear_acceleration[0] = event.values[0] - gravity[0];
233 linear_acceleration[1] = event.values[1] - gravity[1];
234 linear_acceleration[2] = event.values[2] - gravity[2];
235}
236</pre>
237
238<p class="note"><strong>Note:</strong> You can use many different techniques to filter sensor data.
239The code sample above uses a simple filter constant (alpha) to create a low-pass filter. This filter
240constant is derived from a time constant (t), which is a rough representation of the latency that
241the filter adds to the sensor events, and the sensor's event delivery rate (dt). The code sample
242uses an alpha value of 0.8 for demonstration purposes. If you use this filtering method you may need
243to choose a different alpha value.</p>
244
245<p>Accelerometers use the standard sensor <a
246href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">coordinate
247system</a>. In practice, this means that the following conditions apply when a device is laying
248flat on a table in its natural orientation:</p>
249
250<ul>
251 <li>If you push the device on the left side (so it moves to the right), the x acceleration value
252is positive.</li>
253 <li>If you push the device on the bottom (so it moves away from you), the y acceleration value is
254positive.</li>
255 <li>If you push the device toward the sky with an acceleration of A m/s<sup>2</sup>, the
256z acceleration value is equal to A + 9.81, which corresponds to the acceleration of the device (+A
257m/s<sup>2</sup>) minus the force of gravity (-9.81 m/s<sup>2</sup>).</li>
258 <li>The stationary device will have an acceleration value of +9.81, which corresponds to the
259acceleration of the device (0 m/s<sup>2</sup> minus the force of gravity, which is -9.81
260m/s<sup>2</sup>).</li>
261</ul>
262
263<p>In general, the accelerometer is a good sensor to use if you are monitoring device motion.
264Almost every Android-powered handset and tablet has an accelerometer, and it uses about 10 times
265less power than the other motion sensors. One drawback is that you might have to implement
266low-pass and high-pass filters to eliminate gravitational forces and reduce noise.</p>
267
268<p>The Android SDK provides a sample application that shows how to use the acceleration sensor (<a
269href="{@docRoot}resources/samples/AccelerometerPlay/index.html">Accelerometer Play</a>).</p>
270
271<h2 id="sensors-motion-grav">Using the Gravity Sensor</h2>
272
273<p>The gravity sensor provides a three dimensional vector indicating the direction and magnitude of
274gravity. The following code shows you how to get an instance of the default gravity sensor:</p>
275
276<pre>
277private SensorManager mSensorManager;
278private Sensor mSensor;
279...
280mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
281mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
282</pre>
283
284<p>The units are the same as those used by the acceleration
285sensor (m/s<sup>2</sup>), and the coordinate system is the same as the one used by the
286acceleration sensor.</p>
287
288<p class="note"><strong>Note:</strong> When a device is at rest, the output of the gravity sensor
289should be identical to that of the accelerometer.</p>
290
291<h2 id="sensors-motion-gyro">Using the Gyroscope</h2>
292<p>The gyroscope measures the rate or rotation in rad/s around a device's x, y,
293and z axis. The following code shows you how to get an instance of the default gyroscope:</p>
294
295<pre>
296private SensorManager mSensorManager;
297private Sensor mSensor;
298...
299mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
300mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
301</pre>
302
303<p>The sensor's <a
304href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">coordinate system</a>
305is the same as the one used for the acceleration sensor. Rotation is positive in the
306counter-clockwise direction; that is, an observer looking
307from some positive location on the x, y or z axis at a device positioned on the origin would report
308positive rotation if the device appeared to be rotating counter clockwise. This is the
309standard mathematical definition of positive rotation and is not the same as the definition for
310roll that is used by the orientation sensor.</p>
311
312<p>Usually, the output of the gyroscope is integrated over time to calculate a rotation describing
313the change of angles over the timestep. For example:</p>
314
315<pre>
316// Create a constant to convert nanoseconds to seconds.
317private static final float NS2S = 1.0f / 1000000000.0f;
318private final float[] deltaRotationVector = new float[4]();
319private float timestamp;
320
321public void onSensorChanged(SensorEvent event) {
322 // This timestep's delta rotation to be multiplied by the current rotation
323 // after computing it from the gyro sample data.
324 if (timestamp != 0) {
325 final float dT = (event.timestamp - timestamp) * NS2S;
326 // Axis of the rotation sample, not normalized yet.
327 float axisX = event.values[0];
328 float axisY = event.values[1];
329 float axisZ = event.values[2];
330
331 // Calculate the angular speed of the sample
332 float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
333
334 // Normalize the rotation vector if it's big enough to get the axis
335 // (that is, EPSILON should represent your maximum allowable margin of error)
336 if (omegaMagnitude > EPSILON) {
337 axisX /= omegaMagnitude;
338 axisY /= omegaMagnitude;
339 axisZ /= omegaMagnitude;
340 }
341
342 // Integrate around this axis with the angular speed by the timestep
343 // in order to get a delta rotation from this sample over the timestep
344 // We will convert this axis-angle representation of the delta rotation
345 // into a quaternion before turning it into the rotation matrix.
346 float thetaOverTwo = omegaMagnitude * dT / 2.0f;
347 float sinThetaOverTwo = sin(thetaOverTwo);
348 float cosThetaOverTwo = cos(thetaOverTwo);
349 deltaRotationVector[0] = sinThetaOverTwo * axisX;
350 deltaRotationVector[1] = sinThetaOverTwo * axisY;
351 deltaRotationVector[2] = sinThetaOverTwo * axisZ;
352 deltaRotationVector[3] = cosThetaOverTwo;
353 }
354 timestamp = event.timestamp;
355 float[] deltaRotationMatrix = new float[9];
356 SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
357 // User code should concatenate the delta rotation we computed with the current rotation
358 // in order to get the updated rotation.
359 // rotationCurrent = rotationCurrent * deltaRotationMatrix;
360 }
361}
362 </pre>
363
364<p>Standard gyroscopes provide raw rotational data without any filtering or correction for noise and
365drift (bias). In practice, gyroscope noise and drift will introduce errors that need to be
366compensated for. You usually determine the drift (bias) and noise by monitoring other sensors, such
367as the gravity sensor or accelerometer.</p>
368
369<h2 id="sensors-motion-linear">Using the Linear Accelerometer</h2>
370
371<p>The linear acceleration sensor provides you with a three-dimensional vector representing
372acceleration along each device axis, excluding gravity. The following code shows you how to get an
373instance of the default linear acceleration sensor:</p>
374
375<pre>
376private SensorManager mSensorManager;
377private Sensor mSensor;
378...
379mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
380mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
381</pre>
382
383<p>Conceptually, this sensor provides you with acceleration data according to the following
384relationship:</p>
385
386<pre class="no-pretty-print classic">
387linear acceleration = acceleration - acceleration due to gravity
388</pre>
389
390<p>You typically use this sensor when you want to obtain acceleration data without the influence of
391gravity. For example, you could use this sensor to see how fast your car is going. The linear
392acceleration sensor always has an offset, which you need to remove. The simplest way to do this is
393to build a calibration step into your application. During calibration you can ask the user to set
394the device on a table, and then read the offsets for all three axes. You can then subtract that
395offset from the acceleration sensor's direct readings to get the actual linear
396acceleration.</p>
397
398<p>The sensor <a
399 href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">coordinate
400system</a> is the same as the one used by the acceleration sensor, as are the units of measure
401(m/s<sup>2</sup>).
402
403<h2 id="sensors-motion-rotate">Using the Rotation Vector Sensor</h2>
404
405<p>The rotation vector represents the orientation of the device as a combination of an angle and an
406axis, in which the device has rotated through an angle θ around an axis (x, y, or z). The following
407code shows you how to get an instance of the default rotation vector sensor:</p>
408
409<pre>
410private SensorManager mSensorManager;
411private Sensor mSensor;
412...
413mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
414mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
415</pre>
416
417<p>The three elements of the rotation vector are expressed as follows:</p>
418
419<pre class="no-pretty-print classic">
420x*sin(θ/2)
421y*sin(θ/2)
422z*sin(θ/2)
423</pre>
424
425<p>Where the magnitude of the rotation vector is equal to sin(θ/2), and the direction of the
426rotation vector is equal to the direction of the axis of rotation.</p>
427
428<div class="figure" style="width:246px">
429 <img src="{@docRoot}images/axis_globe.png" alt="" height="235" />
430 <p class="img-caption">
431 <strong>Figure 1.</strong> Coordinate system used by the rotation vector sensor.
432 </p>
433</div>
434
435<p>The three elements of the rotation vector are equal to the last three components of a unit
436quaternion (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)). Elements of the rotation vector are
437unitless. The x, y, and z axes are defined in the same way as the acceleration sensor. The reference
438coordinate system is defined as a direct orthonormal basis (see figure 1). This coordinate system
439has the following characteristics:</p>
440
441<ul>
442 <li>X is defined as the vector product Y x Z. It is tangential to the
443ground at the device's current location and points approximately East.</li>
444 <li>Y is tangential to the ground at the device's current location and points toward the
445geomagnetic
446North Pole.</li>
447 <li>Z points toward the sky and is perpendicular to the ground plane.</li>
448</ul>
449
450<p>The Android SDK provides a sample application that shows how to use the rotation vector sensor.
451The sample application is located in the API Demos code (<a
452href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html">
453OS - RotationVectorDemo</a>).</p>