Bill Gruber | f8c029e | 2011-11-01 09:31:57 -0700 | [diff] [blame] | 1 | page.title=Motion Sensors |
Scott Main | 64461bf | 2013-04-11 19:32:08 -0700 | [diff] [blame] | 2 | page.tags="sensorevent","accelerometer","gyroscope","gravity","rotation" |
Bill Gruber | f8c029e | 2011-11-01 09:31:57 -0700 | [diff] [blame] | 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 |
Scott Main | cd1b08e | 2011-12-27 16:22:27 -0800 | [diff] [blame] | 30 | href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html" |
Bill Gruber | f8c029e | 2011-11-01 09:31:57 -0700 | [diff] [blame] | 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> |