The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.hardware; |
| 18 | |
| 19 | /** |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 20 | * <p> |
| 21 | * This class represents a {@link android.hardware.Sensor Sensor} event and |
| 22 | * holds informations such as the sensor's type, the time-stamp, accuracy and of |
| 23 | * course the sensor's {@link SensorEvent#values data}. |
| 24 | * </p> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 25 | * |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 26 | * <p> |
| 27 | * <u>Definition of the coordinate system used by the SensorEvent API.</u> |
| 28 | * </p> |
| 29 | * |
| 30 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 31 | * The coordinate-system is defined relative to the screen of the phone in its |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 32 | * default orientation. The axes are not swapped when the device's screen |
| 33 | * orientation changes. |
| 34 | * </p> |
| 35 | * |
| 36 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 37 | * The X axis is horizontal and points to the right, the Y axis is vertical and |
| 38 | * points up and the Z axis points towards the outside of the front face of the |
| 39 | * screen. In this system, coordinates behind the screen have negative Z values. |
| 40 | * </p> |
| 41 | * |
| 42 | * <p> |
| 43 | * <center><img src="../../../images/axis_device.png" |
| 44 | * alt="Sensors coordinate-system diagram." border="0" /></center> |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 45 | * </p> |
| 46 | * |
| 47 | * <p> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 48 | * <b>Note:</b> This coordinate system is different from the one used in the |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 49 | * Android 2D APIs where the origin is in the top-left corner. |
| 50 | * </p> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 51 | * |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 52 | * @see SensorManager |
| 53 | * @see SensorEvent |
| 54 | * @see Sensor |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 55 | * |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 56 | */ |
| 57 | |
| 58 | public class SensorEvent { |
| 59 | /** |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 60 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 61 | * The length and contents of the {@link #values values} array depends on |
| 62 | * which {@link android.hardware.Sensor sensor} type is being monitored (see |
| 63 | * also {@link SensorEvent} for a definition of the coordinate system used). |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 64 | * </p> |
Mathias Agopian | 210fc91 | 2010-02-26 13:51:39 -0800 | [diff] [blame] | 65 | * |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 66 | * <h4>{@link android.hardware.Sensor#TYPE_ACCELEROMETER |
| 67 | * Sensor.TYPE_ACCELEROMETER}:</h4> All values are in SI units (m/s^2) |
| 68 | * |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 69 | * <ul> |
| 70 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 71 | * values[0]: Acceleration minus Gx on the x-axis |
| 72 | * </p> |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 73 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 74 | * values[1]: Acceleration minus Gy on the y-axis |
| 75 | * </p> |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 76 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 77 | * values[2]: Acceleration minus Gz on the z-axis |
| 78 | * </p> |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 79 | * </ul> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 80 | * |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 81 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 82 | * A sensor of this type measures the acceleration applied to the device |
| 83 | * (<b>Ad</b>). Conceptually, it does so by measuring forces applied to the |
| 84 | * sensor itself (<b>Fs</b>) using the relation: |
| 85 | * </p> |
| 86 | * |
Brad Fitzpatrick | 612ff27 | 2010-09-06 19:22:09 -0700 | [diff] [blame] | 87 | * <b><center>Ad = - ∑Fs / mass</center></b> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 88 | * |
| 89 | * <p> |
| 90 | * In particular, the force of gravity is always influencing the measured |
| 91 | * acceleration: |
| 92 | * </p> |
| 93 | * |
Brad Fitzpatrick | 612ff27 | 2010-09-06 19:22:09 -0700 | [diff] [blame] | 94 | * <b><center>Ad = -g - ∑F / mass</center></b> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 95 | * |
| 96 | * <p> |
| 97 | * For this reason, when the device is sitting on a table (and obviously not |
| 98 | * accelerating), the accelerometer reads a magnitude of <b>g</b> = 9.81 |
| 99 | * m/s^2 |
| 100 | * </p> |
| 101 | * |
| 102 | * <p> |
| 103 | * Similarly, when the device is in free-fall and therefore dangerously |
| 104 | * accelerating towards to ground at 9.81 m/s^2, its accelerometer reads a |
| 105 | * magnitude of 0 m/s^2. |
| 106 | * </p> |
| 107 | * |
| 108 | * <p> |
| 109 | * It should be apparent that in order to measure the real acceleration of |
| 110 | * the device, the contribution of the force of gravity must be eliminated. |
| 111 | * This can be achieved by applying a <i>high-pass</i> filter. Conversely, a |
| 112 | * <i>low-pass</i> filter can be used to isolate the force of gravity. |
| 113 | * </p> |
Mathias Agopian | fa33565 | 2010-11-09 13:40:41 -0800 | [diff] [blame] | 114 | * |
| 115 | * <pre class="prettyprint"> |
| 116 | * |
| 117 | * public void onSensorChanged(SensorEvent event) |
| 118 | * { |
| 119 | * // alpha is calculated as t / (t + dT) |
| 120 | * // with t, the low-pass filter's time-constant |
| 121 | * // and dT, the event delivery rate |
| 122 | * |
| 123 | * final float alpha = 0.8; |
| 124 | * |
Scott Main | d11ee90 | 2011-02-23 10:55:17 -0800 | [diff] [blame] | 125 | * gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; |
| 126 | * gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; |
| 127 | * gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; |
Mathias Agopian | fa33565 | 2010-11-09 13:40:41 -0800 | [diff] [blame] | 128 | * |
Scott Main | d11ee90 | 2011-02-23 10:55:17 -0800 | [diff] [blame] | 129 | * linear_acceleration[0] = event.values[0] - gravity[0]; |
| 130 | * linear_acceleration[1] = event.values[1] - gravity[1]; |
| 131 | * linear_acceleration[2] = event.values[2] - gravity[2]; |
Mathias Agopian | fa33565 | 2010-11-09 13:40:41 -0800 | [diff] [blame] | 132 | * } |
| 133 | * </pre> |
| 134 | * |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 135 | * <p> |
| 136 | * <u>Examples</u>: |
| 137 | * <ul> |
| 138 | * <li>When the device lies flat on a table and is pushed on its left side |
| 139 | * toward the right, the x acceleration value is positive.</li> |
| 140 | * |
| 141 | * <li>When the device lies flat on a table, the acceleration value is |
| 142 | * +9.81, which correspond to the acceleration of the device (0 m/s^2) minus |
| 143 | * the force of gravity (-9.81 m/s^2).</li> |
| 144 | * |
| 145 | * <li>When the device lies flat on a table and is pushed toward the sky |
| 146 | * with an acceleration of A m/s^2, the acceleration value is equal to |
| 147 | * A+9.81 which correspond to the acceleration of the device (+A m/s^2) |
| 148 | * minus the force of gravity (-9.81 m/s^2).</li> |
| 149 | * </ul> |
| 150 | * |
| 151 | * |
| 152 | * <h4>{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD |
| 153 | * Sensor.TYPE_MAGNETIC_FIELD}:</h4> |
| 154 | * All values are in micro-Tesla (uT) and measure the ambient magnetic field |
| 155 | * in the X, Y and Z axis. |
| 156 | * |
Kevin Powell | 7a0541d | 2010-07-19 19:10:40 -0700 | [diff] [blame] | 157 | * <h4>{@link android.hardware.Sensor#TYPE_GYROSCOPE Sensor.TYPE_GYROSCOPE}:</h4> |
| 158 | * All values are in radians/second and measure the rate of rotation |
| 159 | * around the X, Y and Z axis. The coordinate system is the same as is |
| 160 | * used for the acceleration sensor. Rotation is positive in the counter-clockwise |
| 161 | * direction. That is, an observer looking from some positive location on the x, y. |
| 162 | * or z axis at a device positioned on the origin would report positive rotation |
| 163 | * if the device appeared to be rotating counter clockwise. Note that this is the |
| 164 | * standard mathematical definition of positive rotation and does not agree with the |
| 165 | * definition of roll given earlier. |
| 166 | * |
Mathias Agopian | fa33565 | 2010-11-09 13:40:41 -0800 | [diff] [blame] | 167 | * <ul> |
| 168 | * <p> |
| 169 | * values[0]: Angular speed around the x-axis |
| 170 | * </p> |
| 171 | * <p> |
| 172 | * values[1]: Angular speed around the y-axis |
| 173 | * </p> |
| 174 | * <p> |
| 175 | * values[2]: Angular speed around the z-axis |
| 176 | * </p> |
| 177 | * </ul> |
| 178 | * <p> |
| 179 | * Typically the output of the gyroscope is integrated over time to calculate |
| 180 | * an angle, for example: |
| 181 | * </p> |
| 182 | * <pre class="prettyprint"> |
| 183 | * private static final float NS2S = 1.0f / 1000000000.0f; |
| 184 | * private float timestamp; |
| 185 | * public void onSensorChanged(SensorEvent event) |
| 186 | * { |
| 187 | * if (timestamp != 0) { |
| 188 | * final float dT = (event.timestamp - timestamp) * NS2S; |
Scott Main | d11ee90 | 2011-02-23 10:55:17 -0800 | [diff] [blame] | 189 | * angle[0] += event.values[0] * dT; |
| 190 | * angle[1] += event.values[1] * dT; |
| 191 | * angle[2] += event.values[2] * dT; |
Mathias Agopian | fa33565 | 2010-11-09 13:40:41 -0800 | [diff] [blame] | 192 | * } |
| 193 | * timestamp = event.timestamp; |
| 194 | * } |
| 195 | * </pre> |
| 196 | * |
| 197 | * <p>In practice, the gyroscope noise and offset will introduce some errors which need |
| 198 | * to be compensated for. This is usually done using the information from other |
| 199 | * sensors, but is beyond the scope of this document.</p> |
| 200 | * |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 201 | * <h4>{@link android.hardware.Sensor#TYPE_LIGHT Sensor.TYPE_LIGHT}:</h4> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 202 | * <ul> |
| 203 | * <p> |
| 204 | * values[0]: Ambient light level in SI lux units |
| 205 | * </ul> |
| 206 | * |
| 207 | * <h4>{@link android.hardware.Sensor#TYPE_PROXIMITY Sensor.TYPE_PROXIMITY}: |
| 208 | * </h4> |
| 209 | * |
| 210 | * <ul> |
| 211 | * <p> |
| 212 | * values[0]: Proximity sensor distance measured in centimeters |
| 213 | * </ul> |
| 214 | * |
| 215 | * <p> |
| 216 | * <b>Note:</b> Some proximity sensors only support a binary <i>near</i> or |
| 217 | * <i>far</i> measurement. In this case, the sensor should report its |
| 218 | * {@link android.hardware.Sensor#getMaximumRange() maximum range} value in |
| 219 | * the <i>far</i> state and a lesser value in the <i>near</i> state. |
| 220 | * </p> |
| 221 | * |
Kevin Powell | 7a0541d | 2010-07-19 19:10:40 -0700 | [diff] [blame] | 222 | * <h4>{@link android.hardware.Sensor#TYPE_GRAVITY Sensor.TYPE_GRAVITY}:</h4> |
Mathias Agopian | 7badd2c | 2010-11-22 15:48:10 -0800 | [diff] [blame] | 223 | * <p>A three dimensional vector indicating the direction and magnitude of gravity. Units |
| 224 | * are m/s^2. The coordinate system is the same as is used by the acceleration sensor.</p> |
| 225 | * <p><b>Note:</b> When the device is at rest, the output of the gravity sensor should be identical |
| 226 | * to that of the accelerometer.</p> |
Kevin Powell | 7a0541d | 2010-07-19 19:10:40 -0700 | [diff] [blame] | 227 | * |
| 228 | * <h4>{@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION Sensor.TYPE_LINEAR_ACCELERATION}:</h4> |
| 229 | * A three dimensional vector indicating acceleration along each device axis, not including |
| 230 | * gravity. All values have units of m/s^2. The coordinate system is the same as is used by the |
Mathias Agopian | 7badd2c | 2010-11-22 15:48:10 -0800 | [diff] [blame] | 231 | * acceleration sensor. |
| 232 | * <p>The output of the accelerometer, gravity and linear-acceleration sensors must obey the |
| 233 | * following relation:</p> |
| 234 | * <p><ul>acceleration = gravity + linear-acceleration</ul></p> |
Kevin Powell | 7a0541d | 2010-07-19 19:10:40 -0700 | [diff] [blame] | 235 | * |
| 236 | * <h4>{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR Sensor.TYPE_ROTATION_VECTOR}:</h4> |
Mathias Agopian | 7badd2c | 2010-11-22 15:48:10 -0800 | [diff] [blame] | 237 | * <p>The rotation vector represents the orientation of the device as a combination of an <i>angle</i> |
| 238 | * and an <i>axis</i>, in which the device has rotated through an angle θ around an axis |
| 239 | * <x, y, z>.</p> |
| 240 | * <p>The three elements of the rotation vector are |
| 241 | * <x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)>, such that the magnitude of the rotation |
| 242 | * vector is equal to sin(θ/2), and the direction of the rotation vector is equal to the |
| 243 | * direction of the axis of rotation.</p> |
| 244 | * </p>The three elements of the rotation vector are equal to |
| 245 | * the last three components of a <b>unit</b> quaternion |
| 246 | * <cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)>.</p> |
| 247 | * <p>Elements of the rotation vector are unitless. |
| 248 | * The x,y, and z axis are defined in the same way as the acceleration |
| 249 | * sensor.</p> |
| 250 | * <ul> |
| 251 | * <p> |
| 252 | * values[0]: x*sin(θ/2) |
| 253 | * </p> |
| 254 | * <p> |
| 255 | * values[1]: y*sin(θ/2) |
| 256 | * </p> |
| 257 | * <p> |
| 258 | * values[2]: z*sin(θ/2) |
| 259 | * </p> |
| 260 | * <p> |
| 261 | * values[3]: cos(θ/2) <i>(optional: only if value.length = 4)</i> |
| 262 | * </p> |
| 263 | * </ul> |
Kevin Powell | 7a0541d | 2010-07-19 19:10:40 -0700 | [diff] [blame] | 264 | * |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 265 | * <h4>{@link android.hardware.Sensor#TYPE_ORIENTATION |
| 266 | * Sensor.TYPE_ORIENTATION}:</h4> All values are angles in degrees. |
| 267 | * |
| 268 | * <ul> |
| 269 | * <p> |
| 270 | * values[0]: Azimuth, angle between the magnetic north direction and the |
| 271 | * y-axis, around the z-axis (0 to 359). 0=North, 90=East, 180=South, |
| 272 | * 270=West |
| 273 | * </p> |
| 274 | * |
| 275 | * <p> |
| 276 | * values[1]: Pitch, rotation around x-axis (-180 to 180), with positive |
| 277 | * values when the z-axis moves <b>toward</b> the y-axis. |
| 278 | * </p> |
| 279 | * |
| 280 | * <p> |
| 281 | * values[2]: Roll, rotation around y-axis (-90 to 90), with positive values |
| 282 | * when the x-axis moves <b>toward</b> the z-axis. |
| 283 | * </p> |
| 284 | * </ul> |
| 285 | * |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 286 | * <p> |
| 287 | * <b>Note:</b> This definition is different from <b>yaw, pitch and roll</b> |
| 288 | * used in aviation where the X axis is along the long side of the plane |
| 289 | * (tail to nose). |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 290 | * </p> |
| 291 | * |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 292 | * <p> |
| 293 | * <b>Note:</b> This sensor type exists for legacy reasons, please use |
| 294 | * {@link android.hardware.SensorManager#getRotationMatrix |
| 295 | * getRotationMatrix()} in conjunction with |
| 296 | * {@link android.hardware.SensorManager#remapCoordinateSystem |
| 297 | * remapCoordinateSystem()} and |
| 298 | * {@link android.hardware.SensorManager#getOrientation getOrientation()} to |
| 299 | * compute these values instead. |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 300 | * </p> |
| 301 | * |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 302 | * <p> |
Mathias Agopian | 0f791a7 | 2010-06-22 21:55:01 -0700 | [diff] [blame] | 303 | * <b>Important note:</b> For historical reasons the roll angle is positive |
| 304 | * in the clockwise direction (mathematically speaking, it should be |
| 305 | * positive in the counter-clockwise direction). |
| 306 | * </p> |
| 307 | * |
| 308 | * @see SensorEvent |
| 309 | * @see GeomagneticField |
Mike Lockwood | 4115c51 | 2009-11-03 10:35:43 -0500 | [diff] [blame] | 310 | */ |
Kevin Powell | 7a0541d | 2010-07-19 19:10:40 -0700 | [diff] [blame] | 311 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 312 | public final float[] values; |
| 313 | |
| 314 | /** |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 315 | * The sensor that generated this event. See |
| 316 | * {@link android.hardware.SensorManager SensorManager} for details. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 317 | */ |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 318 | public Sensor sensor; |
| 319 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 320 | /** |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 321 | * The accuracy of this event. See {@link android.hardware.SensorManager |
| 322 | * SensorManager} for details. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 323 | */ |
| 324 | public int accuracy; |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 325 | |
| 326 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 327 | /** |
| 328 | * The time in nanosecond at which the event happened |
| 329 | */ |
| 330 | public long timestamp; |
| 331 | |
Mathias Agopian | 74cde2c | 2010-06-16 18:55:46 -0700 | [diff] [blame] | 332 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 333 | SensorEvent(int size) { |
| 334 | values = new float[size]; |
| 335 | } |
| 336 | } |