android.hardware.SensorEvent Maven / Gradle / Ivy
Show all versions of android-all Show documentation
/*
* 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 information 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.
*
*
*
*
*
*
*
* 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)
*
*
* - values[0]: Acceleration minus Gx on the x-axis
* - values[1]: Acceleration minus Gy on the y-axis
* - values[2]: Acceleration minus Gz on the z-axis
*
*
*
* 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:
*
* - When the device lies flat on a table and is pushed on its left side
* toward the right, the x acceleration value is positive.
*
* - When the device lies flat on a table, the acceleration value is
* +9.81, which correspond to the acceleration of the device (0 m/s^2) minus
* the force of gravity (-9.81 m/s^2).
*
* - When the device lies flat on a table and is pushed toward the sky
* with an acceleration of A m/s^2, the acceleration value is equal to
* A+9.81 which correspond to the acceleration of the device (+A m/s^2)
* minus the force of gravity (-9.81 m/s^2).
*
*
*
* {@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.
*
* - values[0]: Angular speed around the x-axis
* - values[1]: Angular speed around the y-axis
* - values[2]: Angular speed around the z-axis
*
*
* Typically the output of the gyroscope is integrated over time to
* calculate a rotation describing the change of angles over the time step,
* 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 time step'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 time step
* // in order to get a delta rotation from this sample over the time step
* // 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}:
*
* - values[0]: Ambient light level in SI lux units
*
*
* {@link android.hardware.Sensor#TYPE_PRESSURE Sensor.TYPE_PRESSURE}:
*
* - values[0]: Atmospheric pressure in hPa (millibar)
*
*
* {@link android.hardware.Sensor#TYPE_PROXIMITY Sensor.TYPE_PROXIMITY}:
*
*
*
* - values[0]: Proximity sensor distance measured in centimeters
*
*
*
* 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:
* acceleration = gravity + linear-acceleration
*
* {@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:
*
*
*
* - X is defined as the vector product Y.Z (It is tangential to
* the ground at the device's current location and roughly points East).
* - Y is tangential to the ground at the device's current location and
* points towards magnetic north.
* - Z points towards the sky and is perpendicular to the ground.
*
*
*
*
*
*
*
* - values[0]: x*sin(θ/2)
* - values[1]: y*sin(θ/2)
* - values[2]: z*sin(θ/2)
* - values[3]: cos(θ/2)
* - values[4]: estimated heading Accuracy (in radians) (-1 if unavailable)
*
* 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.
*
*
* - values[0]: Azimuth, angle between the magnetic north direction and the
* y-axis, around the z-axis (0 to 359). 0=North, 90=East, 180=South,
* 270=West
*
*
*
* values[1]: Pitch, rotation around x-axis (-180 to 180), with positive
* values when the z-axis moves toward the y-axis.
*
*
*
* values[2]: Roll, rotation around the y-axis (-90 to 90)
* increasing as the device moves clockwise.
*
*
*
*
* 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.Sensor#TYPE_ROTATION_VECTOR
* rotation vector sensor type} and
* {@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}:
*
* - values[0]: Relative ambient air humidity in percent
*
*
* 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}:
*
*
*
* - values[0]: ambient (room) temperature in degree Celsius.
*
*
*
* {@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:
*
* - values[0] = x_uncalib
* - values[1] = y_uncalib
* - values[2] = z_uncalib
* - values[3] = x_bias
* - values[4] = y_bias
* - values[5] = z_bias
*
*
*
* 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 permanent
* magnets on the device.
* Soft iron - These distortions arise due to the interaction with the earth's magnetic
* 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).
*
* - values[0] : angular speed (w/o drift compensation) around the X axis in rad/s
* - values[1] : angular speed (w/o drift compensation) around the Y axis in rad/s
* - values[2] : angular speed (w/o drift compensation) around the Z axis in rad/s
* - values[3] : estimated drift around X axis in rad/s
* - values[4] : estimated drift around Y axis in rad/s
* - values[5] : estimated drift around Z axis in rad/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
*
* {@link android.hardware.Sensor#TYPE_DEVICE_ORIENTATION
* Sensor.TYPE_DEVICE_ORIENTATION}:
* The current device orientation will be available in values[0]. The only
* available values are:
*
* - 0: device is in default orientation (Y axis is vertical and points up)
*
- 1: device is rotated 90 degrees counter-clockwise from default
* orientation (X axis is vertical and points up)
*
- 2: device is rotated 180 degrees from default orientation (Y axis is
* vertical and points down)
*
- 3: device is rotated 90 degrees clockwise from default orientation (X axis
* is vertical and points down)
*
*
* {@link android.hardware.Sensor#TYPE_POSE_6DOF
* Sensor.TYPE_POSE_6DOF}:
*
* A TYPE_POSE_6DOF event consists of a rotation expressed as a quaternion and a translation
* expressed in SI units. The event also contains a delta rotation and translation that show
* how the device?s pose has changed since the previous sequence numbered pose.
* The event uses the cannonical Android Sensor axes.
*
*
*
* - values[0]: x*sin(θ/2)
* - values[1]: y*sin(θ/2)
* - values[2]: z*sin(θ/2)
* - values[3]: cos(θ/2)
*
*
* - values[4]: Translation along x axis from an arbitrary origin.
* - values[5]: Translation along y axis from an arbitrary origin.
* - values[6]: Translation along z axis from an arbitrary origin.
*
* - values[7]: Delta quaternion rotation x*sin(θ/2)
* - values[8]: Delta quaternion rotation y*sin(θ/2)
* - values[9]: Delta quaternion rotation z*sin(θ/2)
* - values[10]: Delta quaternion rotation cos(θ/2)
*
* - values[11]: Delta translation along x axis.
* - values[12]: Delta translation along y axis.
* - values[13]: Delta translation along z axis.
*
* - values[14]: Sequence number
*
*
*
* {@link android.hardware.Sensor#TYPE_STATIONARY_DETECT
* Sensor.TYPE_STATIONARY_DETECT}:
*
* A TYPE_STATIONARY_DETECT event is produced if the device has been
* stationary for at least 5 seconds with a maximal latency of 5
* additional seconds. ie: it may take up anywhere from 5 to 10 seconds
* afte the device has been at rest to trigger this event.
*
* The only allowed value is 1.0.
*
*
* - values[0]: 1.0
*
*
* {@link android.hardware.Sensor#TYPE_MOTION_DETECT
* Sensor.TYPE_MOTION_DETECT}:
*
* A TYPE_MOTION_DETECT event is produced if the device has been in
* motion for at least 5 seconds with a maximal latency of 5
* additional seconds. ie: it may take up anywhere from 5 to 10 seconds
* afte the device has been at rest to trigger this event.
*
* The only allowed value is 1.0.
*
*
* - values[0]: 1.0
*
*
* {@link android.hardware.Sensor#TYPE_HEART_BEAT
* Sensor.TYPE_HEART_BEAT}:
*
* A sensor of this type returns an event everytime a hear beat peak is
* detected.
*
* Peak here ideally corresponds to the positive peak in the QRS complex of
* an ECG signal.
*
*
* - values[0]: confidence
*
*
*
* A confidence value of 0.0 indicates complete uncertainty - that a peak
* is as likely to be at the indicated timestamp as anywhere else.
* A confidence value of 1.0 indicates complete certainly - that a peak is
* completely unlikely to be anywhere else on the QRS complex.
*
*/
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];
}
}