Home | History | Annotate | Download | only in sensors
      1 page.title=Motion Sensors
      2 page.tags="sensorevent","accelerometer","gyroscope","gravity","rotation"
      3 @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
     27 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html">
     28 API Demos (OS - RotationVectorDemo)</a></li>
     29       <li><a
     30 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html"
     31 >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
     39 Sensors</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
     45 these sensors are always hardware-based (the accelerometer and gyroscope), and three of these
     46 sensors can be either hardware-based or software-based (the gravity, linear acceleration, and
     47 rotation vector sensors). For example, on some devices the software-based sensors derive their data
     48 from the accelerometer and magnetometer, but on other devices they may also use the gyroscope to
     49 derive their data. Most Android-powered devices have an accelerometer, and many now
     50 include a gyroscope. The availability of the softare-based sensors is more variable because they
     51 often 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
     54 swing. The movement is usually a reflection of direct user input (for example, a user steering a
     55 car in a game or a user controlling a ball in a game), but it can also be a reflection of the
     56 physical environment in which the device is sitting (for example, moving with you while you drive
     57 your car). In the first case, you are monitoring motion relative to the device's frame of reference
     58 or your application's frame of reference; in the second case you are monitoring motion relative to
     59 the world's frame of reference. Motion sensors by themselves are not typically used to monitor
     60 device position, but they can be used with other sensors, such as the geomagnetic field sensor, to
     61 determine a device's position relative to the world's frame of reference (see <a
     62 href="{@docRoot}guide/topics/sensors/sensors_position.html">Position Sensors</a> for more
     63 information).</p>
     64 
     65 <p>All of the motion sensors return multi-dimensional arrays of sensor values for each {@link
     66 android.hardware.SensorEvent}. For example, during a single sensor event the accelerometer returns
     67 acceleration force data for the three coordinate axes, and the gyroscope returns rate of rotation
     68 data 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}
     70 parameters. 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
    160 detection and monitoring. The rotational vector sensor is particularly versatile and can be used for
    161 a wide range of motion-related tasks, such as detecting gestures, monitoring angular change, and
    162 monitoring relative orientation changes. For example, the rotational vector sensor is ideal if you
    163 are developing a game, an augmented reality application, a 2-dimensional or 3-dimensional compass,
    164 or a camera stabilization app. In most cases, using these sensors is a better choice than using
    165 the 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
    170 sensor, a linear acceleration sensor, and a rotation vector sensor. These sensors were updated in
    171 Android 4.0 and now use a device's gyroscope (in addition to other sensors) to improve stability and
    172 performance. If you want to try these sensors, you can identify them by using the {@link
    173 android.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
    175 version number is necessary because the Android system considers these three sensors to be secondary
    176 sensors. For example, if a device manufacturer provides their own gravity sensor, then the AOSP
    177 gravity sensor shows up as a secondary gravity sensor. All three of these sensors rely on a
    178 gyroscope: if a device does not have a gyroscope, these sensors do not show up and are not
    179 available 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
    184 gravity. The following code shows you how to get an instance of the default acceleration sensor:</p>
    185 
    186 <pre>
    187 private SensorManager mSensorManager;
    188 private Sensor mSensor;
    189   ...
    190 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    191 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    192 </pre>
    193 
    194 <p>Conceptually, an acceleration sensor determines the acceleration that is applied
    195 to a device (A<sub>d</sub>) by measuring the forces that are applied to the sensor
    196 itself (F<sub>s</sub>) using the following relationship:</p>
    197 
    198 <pre class="no-pretty-print classic">
    199 A<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
    203 the following relationship:</p>
    204 
    205 <pre class="no-pretty-print classic">
    206 A<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
    210 accelerometer reads a magnitude of g = 9.81 m/s<sup>2</sup>. Similarly, when the device is in
    211 free fall and therefore rapidly accelerating toward the ground at 9.81 m/s<sup>2</sup>, its
    212 accelerometer reads a magnitude of g = 0 m/s<sup>2</sup>. Therefore, to measure
    213 the real acceleration of the device, the contribution of the force of gravity must be removed from
    214 the accelerometer data. This can be achieved by applying a high-pass filter. Conversely, a low-pass
    215 filter can be used to isolate the force of gravity. The following example shows how you can do
    216 this:</p>
    217 
    218 <pre>
    219 public 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.
    239 The code sample above uses a simple filter constant (alpha) to create a low-pass filter. This filter
    240 constant is derived from a time constant (t), which is a rough representation of the latency that
    241 the filter adds to the sensor events, and the sensor's event delivery rate (dt). The code sample
    242 uses an alpha value of 0.8 for demonstration purposes. If you use this filtering method you may need
    243 to choose a different alpha value.</p>
    244 
    245 <p>Accelerometers use the standard sensor <a
    246 href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">coordinate
    247 system</a>. In practice, this means that the following conditions apply when a device is laying
    248 flat 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
    252 is positive.</li>
    253   <li>If you push the device on the bottom (so it moves away from you), the y acceleration value is
    254 positive.</li>
    255   <li>If you push the device toward the sky with an acceleration of A m/s<sup>2</sup>, the
    256 z acceleration value is equal to A + 9.81, which corresponds to the acceleration of the device (+A
    257 m/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
    259 acceleration of the device (0 m/s<sup>2</sup> minus the force of gravity, which is -9.81
    260 m/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.
    264 Almost every Android-powered handset and tablet has an accelerometer, and it uses about 10 times
    265 less power than the other motion sensors. One drawback is that you might have to implement
    266 low-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
    269 href="{@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
    274 gravity. The following code shows you how to get an instance of the default gravity sensor:</p>
    275 
    276 <pre>
    277 private SensorManager mSensorManager;
    278 private Sensor mSensor;
    279 ...
    280 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    281 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
    282 </pre>
    283 
    284 <p>The units are the same as those used by the acceleration
    285 sensor (m/s<sup>2</sup>), and the coordinate system is the same as the one used by the
    286 acceleration sensor.</p>
    287 
    288 <p class="note"><strong>Note:</strong> When a device is at rest, the output of the gravity sensor
    289 should 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,
    293 and z axis. The following code shows you how to get an instance of the default gyroscope:</p>
    294 
    295 <pre>
    296 private SensorManager mSensorManager;
    297 private Sensor mSensor;
    298 ...
    299 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    300 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
    301 </pre>
    302 
    303 <p>The sensor's <a
    304 href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">coordinate system</a>
    305 is the same as the one used for the acceleration sensor. Rotation is positive in the
    306 counter-clockwise direction; that is, an observer looking
    307 from some positive location on the x, y or z axis at a device positioned on the origin would report
    308 positive rotation if the device appeared to be rotating counter clockwise. This is the
    309 standard mathematical definition of positive rotation and is not the same as the definition for
    310 roll 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
    313 the change of angles over the timestep. For example:</p>
    314 
    315 <pre>
    316 // Create a constant to convert nanoseconds to seconds.
    317 private static final float NS2S = 1.0f / 1000000000.0f;
    318 private final float[] deltaRotationVector = new float[4]();
    319 private float timestamp;
    320 
    321 public 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
    365 drift (bias). In practice, gyroscope noise and drift will introduce errors that need to be
    366 compensated for. You usually determine the drift (bias) and noise by monitoring other sensors, such
    367 as 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
    372 acceleration along each device axis, excluding gravity. The following code shows you how to get an
    373 instance of the default linear acceleration sensor:</p>
    374 
    375 <pre>
    376 private SensorManager mSensorManager;
    377 private Sensor mSensor;
    378 ...
    379 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    380 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
    381 </pre>
    382 
    383 <p>Conceptually, this sensor provides you with acceleration data according to the following
    384 relationship:</p>
    385 
    386 <pre class="no-pretty-print classic">
    387 linear 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
    391 gravity. For example, you could use this sensor to see how fast your car is going. The linear
    392 acceleration sensor always has an offset, which you need to remove. The simplest way to do this is
    393 to build a calibration step into your application. During calibration you can ask the user to set
    394 the device on a table, and then read the offsets for all three axes. You can then subtract that
    395 offset from the acceleration sensor's direct readings to get the actual linear
    396 acceleration.</p>
    397 
    398 <p>The sensor <a
    399   href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords">coordinate
    400 system</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
    406 axis, in which the device has rotated through an angle  around an axis (x, y, or z). The following
    407 code shows you how to get an instance of the default rotation vector sensor:</p>
    408 
    409 <pre>
    410 private SensorManager mSensorManager;
    411 private Sensor mSensor;
    412 ...
    413 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    414 mSensor = 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">
    420 x*sin(/2)
    421 y*sin(/2)
    422 z*sin(/2)
    423 </pre>
    424 
    425 <p>Where the magnitude of the rotation vector is equal to sin(/2), and the direction of the
    426 rotation 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
    436 quaternion (cos(/2), x*sin(/2), y*sin(/2), z*sin(/2)). Elements of the rotation vector are
    437 unitless. The x, y, and z axes are defined in the same way as the acceleration sensor. The reference
    438 coordinate system is defined as a direct orthonormal basis (see figure 1). This coordinate system
    439 has the following characteristics:</p>
    440 
    441 <ul>
    442   <li>X is defined as the vector product Y x Z. It is tangential to the
    443 ground 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
    445 geomagnetic
    446 North 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.
    451 The sample application is located in the API Demos code (<a
    452 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html">
    453 OS - RotationVectorDemo</a>).</p>