/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware; /** * This class represents a {@link android.hardware.Sensor Sensor} event and * holds informations such as the sensor's type, the time-stamp, accuracy and of * course the sensor's {@link SensorEvent#values data}. * *

* Definition of the coordinate system used by the SensorEvent API. *

* *

* The coordinate-system is defined relative to the screen of the phone in its * default orientation. The axes are not swapped when the device's screen * orientation changes. *

* *

* The X axis is horizontal and points to the right, the Y axis is vertical and * points up and the Z axis points towards the outside of the front face of the * screen. In this system, coordinates behind the screen have negative Z values. *

* *

*

Sensors coordinate-system diagram.
*

* *

* Note: This coordinate system is different from the one used in the * Android 2D APIs where the origin is in the top-left corner. *

* * @see SensorManager * @see SensorEvent * @see Sensor * */ public class SensorEvent { /** *

* The length and contents of the {@link #values values} array depends on * which {@link android.hardware.Sensor sensor} type is being monitored (see * also {@link SensorEvent} for a definition of the coordinate system used). *

* *

{@link android.hardware.Sensor#TYPE_ACCELEROMETER * Sensor.TYPE_ACCELEROMETER}:

All values are in SI units (m/s^2) * * * *

* A sensor of this type measures the acceleration applied to the device * (Ad). Conceptually, it does so by measuring forces applied to the * sensor itself (Fs) using the relation: *

* *
Ad = - ∑Fs / mass
* *

* In particular, the force of gravity is always influencing the measured * acceleration: *

* *
Ad = -g - ∑F / mass
* *

* For this reason, when the device is sitting on a table (and obviously not * accelerating), the accelerometer reads a magnitude of g = 9.81 * m/s^2 *

* *

* Similarly, when the device is in free-fall and therefore dangerously * accelerating towards to ground at 9.81 m/s^2, its accelerometer reads a * magnitude of 0 m/s^2. *

* *

* It should be apparent that in order to measure the real acceleration of * the device, the contribution of the force of gravity must be eliminated. * This can be achieved by applying a high-pass filter. Conversely, a * low-pass filter can be used to isolate the force of gravity. *

* *
     *
     *     public void onSensorChanged(SensorEvent event)
     *     {
     *          // alpha is calculated as t / (t + dT)
     *          // with t, the low-pass filter's time-constant
     *          // and dT, the event delivery rate
     *
     *          final float alpha = 0.8;
     *
     *          gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
     *          gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
     *          gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
     *
     *          linear_acceleration[0] = event.values[0] - gravity[0];
     *          linear_acceleration[1] = event.values[1] - gravity[1];
     *          linear_acceleration[2] = event.values[2] - gravity[2];
     *     }
     * 
* *

* Examples: *

* * *

{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD * Sensor.TYPE_MAGNETIC_FIELD}:

* All values are in micro-Tesla (uT) and measure the ambient magnetic field * in the X, Y and Z axis. * *

{@link android.hardware.Sensor#TYPE_GYROSCOPE Sensor.TYPE_GYROSCOPE}: *

All values are in radians/second and measure the rate of rotation * around the device's local X, Y and Z axis. The coordinate system is the * same as is used for the acceleration sensor. Rotation is positive in the * counter-clockwise direction. That is, an observer looking from some * positive location on the x, y or z axis at a device positioned on the * origin would report positive rotation if the device appeared to be * rotating counter clockwise. Note that this is the standard mathematical * definition of positive rotation and does not agree with the definition of * roll given earlier. * *

* Typically the output of the gyroscope is integrated over time to * calculate a rotation describing the change of angles over the timestep, * for example: *

* *
     *     private static final float NS2S = 1.0f / 1000000000.0f;
     *     private final float[] deltaRotationVector = new float[4]();
     *     private float timestamp;
     *
     *     public void onSensorChanged(SensorEvent event) {
     *          // This timestep's delta rotation to be multiplied by the current rotation
     *          // after computing it from the gyro sample data.
     *          if (timestamp != 0) {
     *              final float dT = (event.timestamp - timestamp) * NS2S;
     *              // Axis of the rotation sample, not normalized yet.
     *              float axisX = event.values[0];
     *              float axisY = event.values[1];
     *              float axisZ = event.values[2];
     *
     *              // Calculate the angular speed of the sample
     *              float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
     *
     *              // Normalize the rotation vector if it's big enough to get the axis
     *              if (omegaMagnitude > EPSILON) {
     *                  axisX /= omegaMagnitude;
     *                  axisY /= omegaMagnitude;
     *                  axisZ /= omegaMagnitude;
     *              }
     *
     *              // Integrate around this axis with the angular speed by the timestep
     *              // in order to get a delta rotation from this sample over the timestep
     *              // We will convert this axis-angle representation of the delta rotation
     *              // into a quaternion before turning it into the rotation matrix.
     *              float thetaOverTwo = omegaMagnitude * dT / 2.0f;
     *              float sinThetaOverTwo = sin(thetaOverTwo);
     *              float cosThetaOverTwo = cos(thetaOverTwo);
     *              deltaRotationVector[0] = sinThetaOverTwo * axisX;
     *              deltaRotationVector[1] = sinThetaOverTwo * axisY;
     *              deltaRotationVector[2] = sinThetaOverTwo * axisZ;
     *              deltaRotationVector[3] = cosThetaOverTwo;
     *          }
     *          timestamp = event.timestamp;
     *          float[] deltaRotationMatrix = new float[9];
     *          SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
     *          // User code should concatenate the delta rotation we computed with the current rotation
     *          // in order to get the updated rotation.
     *          // rotationCurrent = rotationCurrent * deltaRotationMatrix;
     *     }
     * 
*

* In practice, the gyroscope noise and offset will introduce some errors * which need to be compensated for. This is usually done using the * information from other sensors, but is beyond the scope of this document. *

*

{@link android.hardware.Sensor#TYPE_LIGHT Sensor.TYPE_LIGHT}:

* * *

{@link android.hardware.Sensor#TYPE_PRESSURE Sensor.TYPE_PRESSURE}:

* * *

{@link android.hardware.Sensor#TYPE_PROXIMITY Sensor.TYPE_PROXIMITY}: *

* * * *

* Note: Some proximity sensors only support a binary near or * far measurement. In this case, the sensor should report its * {@link android.hardware.Sensor#getMaximumRange() maximum range} value in * the far state and a lesser value in the near state. *

* *

{@link android.hardware.Sensor#TYPE_GRAVITY Sensor.TYPE_GRAVITY}:

*

A three dimensional vector indicating the direction and magnitude of gravity. Units * are m/s^2. The coordinate system is the same as is used by the acceleration sensor.

*

Note: When the device is at rest, the output of the gravity sensor should be identical * to that of the accelerometer.

* *

{@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION Sensor.TYPE_LINEAR_ACCELERATION}:

* A three dimensional vector indicating acceleration along each device axis, not including * gravity. All values have units of m/s^2. The coordinate system is the same as is used by the * acceleration sensor. *

The output of the accelerometer, gravity and linear-acceleration sensors must obey the * following relation:

*

* *

{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR Sensor.TYPE_ROTATION_VECTOR}:

*

The rotation vector represents the orientation of the device as a combination of an angle * and an axis, in which the device has rotated through an angle θ around an axis * <x, y, z>.

*

The three elements of the rotation vector are * <x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)>, such that the magnitude of the rotation * vector is equal to sin(θ/2), and the direction of the rotation vector is equal to the * direction of the axis of rotation.

*

The three elements of the rotation vector are equal to * the last three components of a unit quaternion * <cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)>.

*

Elements of the rotation vector are unitless. * The x,y, and z axis are defined in the same way as the acceleration * sensor.

* The reference coordinate system is defined as a direct orthonormal basis, * where: *

* * * *

*

World coordinate-system diagram.
*

* * *

values[3], originally optional, will always be present from SDK Level 18 onwards. * values[4] is a new value that has been added in SDK Level 18. *

* *

{@link android.hardware.Sensor#TYPE_ORIENTATION * Sensor.TYPE_ORIENTATION}:

All values are angles in degrees. * * * *

* Note: This definition is different from yaw, pitch and roll * used in aviation where the X axis is along the long side of the plane * (tail to nose). *

* *

* Note: This sensor type exists for legacy reasons, please use * {@link android.hardware.SensorManager#getRotationMatrix * getRotationMatrix()} in conjunction with * {@link android.hardware.SensorManager#remapCoordinateSystem * remapCoordinateSystem()} and * {@link android.hardware.SensorManager#getOrientation getOrientation()} to * compute these values instead. *

* *

* Important note: For historical reasons the roll angle is positive * in the clockwise direction (mathematically speaking, it should be * positive in the counter-clockwise direction). *

* *

{@link android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY * Sensor.TYPE_RELATIVE_HUMIDITY}:

* *

* When relative ambient air humidity and ambient temperature are * measured, the dew point and absolute humidity can be calculated. *

* Dew Point *

* The dew point is the temperature to which a given parcel of air must be * cooled, at constant barometric pressure, for water vapor to condense * into water. *

*
     *                    ln(RH/100%) + m·t/(Tn+t)
     * td(t,RH) = Tn · ------------------------------
     *                 m - [ln(RH/100%) + m·t/(Tn+t)]
     * 
*
*
td
dew point temperature in °C
*
t
actual temperature in °C
*
RH
actual relative humidity in %
*
m
17.62
*
Tn
243.12 °C
*
*

for example:

*
     * h = Math.log(rh / 100.0) + (17.62 * t) / (243.12 + t);
     * td = 243.12 * h / (17.62 - h);
     * 
* Absolute Humidity *

* The absolute humidity is the mass of water vapor in a particular volume * of dry air. The unit is g/m3. *

*
     *                    RH/100%·A·exp(m·t/(Tn+t))
     * dv(t,RH) = 216.7 · -------------------------
     *                           273.15 + t
     * 
*
*
dv
absolute humidity in g/m3
*
t
actual temperature in °C
*
RH
actual relative humidity in %
*
m
17.62
*
Tn
243.12 °C
*
A
6.112 hPa
*
*

for example:

*
     * dv = 216.7 *
     * (rh / 100.0 * 6.112 * Math.exp(17.62 * t / (243.12 + t)) / (273.15 + t));
     * 
* *

{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE Sensor.TYPE_AMBIENT_TEMPERATURE}: *

* * * * *

{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD_UNCALIBRATED * Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED}:

* Similar to {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD}, * but the hard iron calibration is reported separately instead of being included * in the measurement. Factory calibration and temperature compensation will still * be applied to the "uncalibrated" measurement. Assumptions that the magnetic field * is due to the Earth's poles is avoided. *

* The values array is shown below: *

*

*

* x_uncalib, y_uncalib, z_uncalib are the measured magnetic field in X, Y, Z axes. * Soft iron and temperature calibrations are applied. But the hard iron * calibration is not applied. The values are in micro-Tesla (uT). *

*

* x_bias, y_bias, z_bias give the iron bias estimated in X, Y, Z axes. * Each field is a component of the estimated hard iron calibration. * The values are in micro-Tesla (uT). *

*

Hard iron - These distortions arise due to the magnetized iron, steel or permanenet * magnets on the device. * Soft iron - These distortions arise due to the interaction with the earth's magentic * field. *

*

{@link android.hardware.Sensor#TYPE_GAME_ROTATION_VECTOR}:

* Identical to {@link android.hardware.Sensor#TYPE_ROTATION_VECTOR} except that it * doesn't use the geomagnetic field. Therefore the Y axis doesn't * point north, but instead to some other reference, that reference is * allowed to drift by the same order of magnitude as the gyroscope * drift around the Z axis. *

* In the ideal case, a phone rotated and returning to the same real-world * orientation will report the same game rotation vector * (without using the earth's geomagnetic field). However, the orientation * may drift somewhat over time. See {@link android.hardware.Sensor#TYPE_ROTATION_VECTOR} * for a detailed description of the values. This sensor will not have * the estimated heading accuracy value. *

* *

{@link android.hardware.Sensor#TYPE_GYROSCOPE_UNCALIBRATED * Sensor.TYPE_GYROSCOPE_UNCALIBRATED}:

* All values are in radians/second and measure the rate of rotation * around the X, Y and Z axis. An estimation of the drift on each axis is * reported as well. *

* No gyro-drift compensation is performed. Factory calibration and temperature * compensation is still applied to the rate of rotation (angular speeds). *

*

* The coordinate system is the same as is used for the * {@link android.hardware.Sensor#TYPE_ACCELEROMETER} * Rotation is positive in the counter-clockwise direction (right-hand rule). * That is, an observer looking from some positive location on the x, y or z axis * at a device positioned on the origin would report positive rotation if the device * appeared to be rotating counter clockwise. * The range would at least be 17.45 rad/s (ie: ~1000 deg/s). *

*

*

Pro Tip: Always use the length of the values array while performing operations * on it. In earlier versions, this used to be always 3 which has changed now.

* * @see GeomagneticField */ public final float[] values; /** * The sensor that generated this event. See * {@link android.hardware.SensorManager SensorManager} for details. */ public Sensor sensor; /** * The accuracy of this event. See {@link android.hardware.SensorManager * SensorManager} for details. */ public int accuracy; /** * The time in nanosecond at which the event happened */ public long timestamp; SensorEvent(int valueSize) { values = new float[valueSize]; } }