Платформа Android поддерживает несколько датчиков, которые позволяют отслеживать движение устройства.
Возможные архитектуры датчиков зависят от их типа:
- Датчики силы тяжести, линейного ускорения, вектора вращения, значительного движения, счетчик шагов и детектор шагов могут быть как аппаратными, так и программными.
- Акселерометр и гироскоп всегда являются аппаратными датчиками.
Большинство устройств Android оснащены акселерометром, а многие – ещё и гироскопом. Доступность программных датчиков может быть разной, поскольку они часто используют данные одного или нескольких аппаратных датчиков. В зависимости от устройства эти программные датчики могут получать данные от акселерометра и магнитометра или от гироскопа.
Датчики движения полезны для мониторинга движения устройства, такого как наклон, встряхивание, вращение или качание. Обычно движение отражает действия пользователя (например, управление автомобилем или мячом в игре), но может также отражать физическую среду, в которой находится устройство (например, движение вместе с вами, когда вы едете на автомобиле). В первом случае вы отслеживаете движение относительно системы отсчета устройства или вашего приложения, а во втором – относительно системы отсчета мира. Датчики движения обычно не используются для отслеживания положения устройства, но могут работать вместе с другими датчиками, например датчиком геомагнитного поля, чтобы определять положение устройства относительно мировой системы отсчета (подробнее см. в разделе Датчики положения).
Все датчики движения возвращают многомерные массивы значений для каждого события SensorEvent. Например, во время одного события датчика акселерометр возвращает данные о силе ускорения для трех осей координат, а гироскоп – данные о скорости вращения для трех осей координат. Эти значения возвращаются в массиве float (values) вместе с другими параметрами SensorEvent. В таблице 1 перечислены датчики движения, доступные на платформе Android.
Таблица 1. Датчики движения, которые поддерживаются на платформе Android.
| Датчик | Данные о событиях датчиков | Описание | Единицы измерения |
|---|---|---|---|
TYPE_ACCELEROMETER |
SensorEvent.values[0] |
Сила ускорения по оси X (включая силу тяжести). | м/с2 |
SensorEvent.values[1] |
Сила ускорения по оси Y (включая силу тяжести). | ||
SensorEvent.values[2] |
Сила ускорения по оси Z (включая силу тяжести). | ||
TYPE_ACCELEROMETER_UNCALIBRATED |
SensorEvent.values[0] |
Измеренное ускорение по оси X без компенсации смещения. | м/с2 |
SensorEvent.values[1] |
Измеренное ускорение по оси Y без компенсации смещения. | ||
SensorEvent.values[2] |
Измеренное ускорение по оси Z без компенсации смещения. | ||
SensorEvent.values[3] |
Измеренное ускорение по оси X с расчетной компенсацией смещения. | ||
SensorEvent.values[4] |
Измеренное ускорение по оси Y с расчетной компенсацией смещения. | ||
SensorEvent.values[5] |
Измеренное ускорение по оси Z с расчетной компенсацией смещения. | ||
TYPE_GRAVITY |
SensorEvent.values[0] |
Сила тяжести по оси X. | м/с2 |
SensorEvent.values[1] |
Сила тяжести по оси Y. | ||
SensorEvent.values[2] |
Сила тяжести по оси Z. | ||
TYPE_GYROSCOPE |
SensorEvent.values[0] |
Скорость вращения вокруг оси X. | рад/с |
SensorEvent.values[1] |
Скорость вращения вокруг оси Y. | ||
SensorEvent.values[2] |
Скорость вращения вокруг оси Z. | ||
TYPE_GYROSCOPE_UNCALIBRATED |
SensorEvent.values[0] |
Скорость вращения (без компенсации дрейфа) вокруг оси X. | рад/с |
SensorEvent.values[1] |
Скорость вращения (без компенсации дрейфа) вокруг оси Y. | ||
SensorEvent.values[2] |
Скорость вращения (без компенсации дрейфа) вокруг оси Z. | ||
SensorEvent.values[3] |
Расчетное отклонение по оси X. | ||
SensorEvent.values[4] |
Расчетное смещение вокруг оси Y. | ||
SensorEvent.values[5] |
Расчетное смещение вокруг оси Z. | ||
TYPE_LINEAR_ACCELERATION |
SensorEvent.values[0] |
Сила ускорения по оси X (без учета силы тяжести). | м/с2 |
SensorEvent.values[1] |
Сила ускорения по оси Y (без учета силы тяжести). | ||
SensorEvent.values[2] |
Сила ускорения по оси Z (без учета силы тяжести). | ||
TYPE_ROTATION_VECTOR |
SensorEvent.values[0] |
Компонент вектора вращения вдоль оси X (x * sin(θ/2)). | Без единиц измерения |
SensorEvent.values[1] |
Компонент вектора вращения вдоль оси Y (y * sin(θ/2)). | ||
SensorEvent.values[2] |
Компонент вектора вращения вдоль оси Z (Z * sin(θ/2)). | ||
SensorEvent.values[3] |
Скалярный компонент вектора вращения ((cos(θ/2)).1 | ||
TYPE_SIGNIFICANT_MOTION |
Н/Д | – | Н/Д |
TYPE_STEP_COUNTER |
SensorEvent.values[0] |
Количество шагов, сделанных пользователем с момента последней перезагрузки, когда датчик был активирован. | Шаги |
TYPE_STEP_DETECTOR |
Н/Д | – | Н/Д |
1 Скалярный компонент – необязательное значение.
Датчики вектора вращения и силы тяжести чаще всего используются для обнаружения и отслеживания движения. Датчик вектора вращения особенно универсален и может использоваться для широкого спектра задач, связанных с движением, таких как обнаружение жестов, мониторинг угловых изменений и мониторинг относительных изменений ориентации. Например, датчик вектора вращения идеально подходит для разработки игр, приложений дополненной реальности, двух- или трехмерных компасов, а также приложений для стабилизации камеры. В большинстве случаев использование этих датчиков предпочтительнее, чем использование акселерометра и датчика геомагнитного поля или датчика ориентации.
Датчики Android Open Source Project
В Android Open Source Project (AOSP) есть три программных датчика движения: датчик силы тяжести, датчик линейного ускорения и датчик вектора вращения. В Android 4.0 эти датчики были обновлены и теперь используют гироскоп устройства (в дополнение к другим датчикам) для повышения стабильности и производительности. Чтобы попробовать эти датчики, вы можете идентифицировать их с помощью методов getVendor() и getVersion() (поставщик – Google LLC, номер версии – 3). Идентифицировать эти датчики по поставщику и номеру версии необходимо, поскольку система Android считает их второстепенными. Например, если производитель устройства предоставляет собственный датчик силы тяжести, то датчик силы тяжести AOSP отображается как дополнительный. Все три датчика работают на основе гироскопа. Если на устройстве нет гироскопа, эти датчики не отображаются и недоступны для использования.
Использовать датчик силы тяжести
Датчик силы тяжести предоставляет трехмерный вектор, указывающий направление и величину силы тяжести. Обычно этот датчик используется для определения относительной ориентации устройства в пространстве. В следующем коде показано, как получить экземпляр датчика силы тяжести по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
Единицы измерения и система координат такие же, как у датчика ускорения (м/с2).
Примечание. Когда устройство находится в состоянии покоя, выходные данные датчика силы тяжести должны быть идентичны данным акселерометра.
Использовать линейный акселерометр
Датчик линейного ускорения предоставляет вам трехмерный вектор, представляющий ускорение вдоль каждой оси устройства, исключая силу тяжести. Это значение можно использовать для распознавания жестов. Это значение также может использоваться в качестве входных данных для инерциальной навигационной системы, которая использует счисление пути. В следующем коде показано, как получить экземпляр датчика линейного ускорения по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
Этот датчик предоставляет данные об ускорении в соответствии со следующим соотношением:
linear acceleration = acceleration - acceleration due to gravity
Обычно этот датчик используется, когда нужно получить данные об ускорении без учета силы тяжести. Например, с помощью этого датчика можно узнать, с какой скоростью движется ваш автомобиль. Датчик линейного ускорения всегда имеет смещение, которое необходимо удалить. Проще всего добавить в приложение этап калибровки. Во время калибровки вы можете попросить пользователя положить устройство на стол, а затем считать смещения по всем трем осям. Затем вы можете вычесть это смещение из прямых показаний датчика ускорения, чтобы получить фактическое линейное ускорение.
Система координат и единицы измерения (м/с2) такие же, как у датчика ускорения.
Используйте датчик вектора вращения
Вектор вращения представляет ориентацию устройства как комбинацию угла и оси, в которой устройство повернулось на угол θ вокруг оси (x, y или z). В следующем коде показано, как получить экземпляр датчика вектора вращения по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
Три элемента вектора вращения выражаются следующим образом:
где величина вектора вращения равна sin(θ/2), а направление вектора вращения совпадает с направлением оси вращения.
Рисунок 1. Система координат, используемая датчиком вектора вращения.
Три элемента вектора вращения равны последним трем компонентам единичного кватерниона (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)). Элементы вектора вращения не имеют единиц измерения. Оси X, Y и Z определяются так же, как и для датчика ускорения. Опорная система координат определяется как прямой ортонормированный базис (см. рис. 1). Эта система координат имеет следующие характеристики:
- X определяется как векторное произведение Y x Z. Она касается поверхности земли в текущем местоположении устройства и направлена приблизительно на восток.
- Ось Y касается поверхности земли в текущем местоположении устройства и направлена к геомагнитному Северному полюсу.
- Ось Z направлена вверх и перпендикулярна плоскости земли.
Пример приложения, в котором показано, как использовать датчик вектора вращения, можно найти в файле RotationVectorDemo.java.
Использовать датчик значительного движения
Датчик значительного движения активирует событие каждый раз, когда обнаруживает значительное движение, а затем отключается. Значительное движение – это движение, которое может привести к изменению местоположения пользователя, например ходьба, езда на велосипеде или в движущемся автомобиле. В следующем коде показано, как получить экземпляр датчика значительного движения по умолчанию и как зарегистрировать прослушиватель событий:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION) val triggerEventListener = object : TriggerEventListener() { override fun onTrigger(event: TriggerEvent?) { // Do work } } mSensor?.also { sensor -> sensorManager.requestTriggerSensor(triggerEventListener, sensor) }
Java
private SensorManager sensorManager; private Sensor sensor; private TriggerEventListener triggerEventListener; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); triggerEventListener = new TriggerEventListener() { @Override public void onTrigger(TriggerEvent event) { // Do work } }; sensorManager.requestTriggerSensor(triggerEventListener, mSensor);
Дополнительную информацию можно найти по адресу TriggerEventListener.
Использовать датчик шагомера
Датчик шагомера предоставляет количество шагов, сделанных пользователем с момента последней перезагрузки, когда датчик был активирован. Счетчик шагов работает с большей задержкой (до 10 секунд), но точнее, чем датчик шагов.
Примечание. Чтобы приложение могло использовать этот датчик на устройствах с Android 10 (уровень API 29) или более поздней версии, необходимо объявить разрешение ACTIVITY_RECOGNITION.
В следующем примере кода показано, как получить экземпляр датчика шагов по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
Чтобы экономить заряд батареи на устройствах, где установлено ваше приложение, используйте класс JobScheduler. Он позволяет получать текущее значение от датчика шагов через определенные интервалы времени. Хотя для разных типов приложений требуются разные интервалы считывания данных с датчиков, вы должны сделать этот интервал как можно более длинным, если только вашему приложению не требуются данные с датчика в реальном времени.
Использовать датчик шагов
Датчик шагов активирует событие каждый раз, когда пользователь делает шаг. Задержка не должна превышать двух секунд.
Примечание. Чтобы приложение могло использовать этот датчик на устройствах с Android 10 (уровень API 29) или более поздней версии, необходимо объявить разрешение ACTIVITY_RECOGNITION.
В следующем примере кода показано, как получить экземпляр датчика шагов по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
Как работать с первичными данными
Перечисленные ниже датчики предоставляют приложению первичные данные о линейных и вращательных силах, воздействующих на устройство. Чтобы эффективно использовать значения этих датчиков, необходимо отфильтровать факторы окружающей среды, такие как гравитация. Возможно, вам также потребуется применить алгоритм сглаживания к тренду значений, чтобы уменьшить шум.
Использовать акселерометр
Датчик ускорения измеряет ускорение, приложенное к устройству, включая силу тяжести. В следующем коде показано, как получить экземпляр датчика ускорения по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Примечание. Если ваше приложение предназначено для Android 12 (уровень API 31) или более поздней версии, частота запросов к этому датчику ограничена.
Датчик ускорения определяет ускорение, приложенное к устройству (Ad), измеряя силы, приложенные к самому датчику (Fs), по следующей формуле:
Однако сила тяжести всегда влияет на измеренное ускорение в соответствии со следующим соотношением:
Поэтому, когда устройство лежит на столе (и не ускоряется), акселерометр показывает величину g = 9,81 м/с2. Аналогично, когда устройство находится в свободном падении и, следовательно, быстро ускоряется по направлению к земле со скоростью 9,81 м/с2, его акселерометр считывает величину g = 0 м/с2. Поэтому, чтобы измерить реальное ускорение устройства, вклад силы тяжести должен быть удален из данных акселерометра. Для этого можно применить фильтр высоких частот. И наоборот, фильтр низких частот можно использовать для изоляции силы тяжести. Ниже показано, как это сделать.
Kotlin
override fun onSensorChanged(event: SensorEvent) { // In this example, alpha is calculated as t / (t + dT), // where t is the low-pass filter's time-constant and // dT is the event delivery rate. val alpha: Float = 0.8f // Isolate the force of gravity with the low-pass filter. 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] // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0] linear_acceleration[1] = event.values[1] - gravity[1] linear_acceleration[2] = event.values[2] - gravity[2] }
Java
public void onSensorChanged(SensorEvent event){ // In this example, alpha is calculated as t / (t + dT), // where t is the low-pass filter's time-constant and // dT is the event delivery rate. final float alpha = 0.8; // Isolate the force of gravity with the low-pass filter. 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]; // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0]; linear_acceleration[1] = event.values[1] - gravity[1]; linear_acceleration[2] = event.values[2] - gravity[2]; }
Примечание. Для фильтрации данных датчиков можно использовать разные методы. В приведенном выше примере кода используется простая константа фильтра (альфа) для создания фильтра нижних частот. Эта константа фильтра выводится из постоянной времени (t), которая приблизительно представляет задержку, добавляемую фильтром к событиям датчика, и частоты доставки событий датчика (dt). В примере кода для демонстрации используется значение альфа, равное 0,8. Если вы используете этот метод фильтрации, вам может потребоваться выбрать другое значение альфа.
Акселерометры используют стандартную систему координат датчиков. На практике это означает, что когда устройство лежит на столе в естественной ориентации, выполняются следующие условия:
- Если вы толкнете устройство слева (чтобы оно переместилось вправо), значение ускорения по оси X будет положительным.
- Если вы толкнете устройство от себя, значение ускорения по оси Y будет положительным.
- Если вы подбросите устройство вверх с ускорением A м/с2, значение ускорения по оси Z будет равно A + 9,81, что соответствует ускорению устройства (+A м/с2) минус сила тяжести (-9,81 м/с2).
- Значение ускорения неподвижного устройства будет равно +9,81, что соответствует ускорению устройства (0 м/с2 минус сила тяжести, которая равна −9,81 м/с2).
В целом акселерометр – это хороший датчик, который можно использовать, если вы отслеживаете движение устройства. Акселерометр есть почти в каждом телефоне и планшете Android, и он потребляет примерно в 10 раз меньше энергии, чем другие датчики движения. Одним из недостатков является то, что вам, возможно, придется реализовать фильтры нижних и верхних частот для устранения гравитационных сил и снижения шума.
Использовать гироскоп
Гироскоп измеряет скорость вращения в радианах в секунду вокруг осей X, Y и Z устройства. В следующем коде показано, как получить экземпляр гироскопа по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
Примечание. Если ваше приложение предназначено для Android 12 (уровень API 31) или более поздней версии, частота запросов к этому датчику ограничена.
Система координат датчика совпадает с системой координат, используемой для датчика ускорения. Положительным считается вращение против часовой стрелки. Это значит, что если наблюдатель смотрит на устройство, расположенное в начале координат, из положительной точки на оси X, Y или Z, то он увидит положительное вращение, если устройство вращается против часовой стрелки. Это стандартное математическое определение положительного вращения, которое отличается от определения крена, используемого датчиком ориентации.
Обычно выходные данные гироскопа интегрируются по времени, чтобы рассчитать вращение, описывающее изменение углов за временной шаг. Пример:
Kotlin
// Create a constant to convert nanoseconds to seconds. private val NS2S = 1.0f / 1000000000.0f private val deltaRotationVector = FloatArray(4) { 0f } private var timestamp: Float = 0f override fun onSensorChanged(event: SensorEvent?) { // This timestep's delta rotation to be multiplied by the current rotation // after computing it from the gyro sample data. if (timestamp != 0f && event != null) { val dT = (event.timestamp - timestamp) * NS2S // Axis of the rotation sample, not normalized yet. var axisX: Float = event.values[0] var axisY: Float = event.values[1] var axisZ: Float = event.values[2] // Calculate the angular speed of the sample val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ) // Normalize the rotation vector if it's big enough to get the axis // (that is, EPSILON should represent your maximum allowable margin of error) 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. val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f val sinThetaOverTwo: Float = sin(thetaOverTwo) val cosThetaOverTwo: Float = cos(thetaOverTwo) deltaRotationVector[0] = sinThetaOverTwo * axisX deltaRotationVector[1] = sinThetaOverTwo * axisY deltaRotationVector[2] = sinThetaOverTwo * axisZ deltaRotationVector[3] = cosThetaOverTwo } timestamp = event?.timestamp?.toFloat() ?: 0f val deltaRotationMatrix = FloatArray(9) { 0f } 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; }
Java
// Create a constant to convert nanoseconds to seconds. 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 // (that is, EPSILON should represent your maximum allowable margin of error) 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; }
Стандартные гироскопы предоставляют необработанные данные о вращении без фильтрации или коррекции шума и дрейфа (смещения). На практике шум и дрейф гироскопа приводят к ошибкам, которые необходимо компенсировать. Обычно дрейф (смещение) и шум определяются путем мониторинга других датчиков, таких как датчик силы тяжести или акселерометр.
Использовать некалиброванный гироскоп
Некалиброванный гироскоп похож на гироскоп, но к скорости вращения не применяется компенсация дрейфа гироскопа. К скорости вращения по-прежнему применяется заводская калибровка и температурная компенсация. Некалиброванный гироскоп полезен для постобработки и объединения данных об ориентации. В целом gyroscope_event.values[0] будет близко к uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3].
То есть,
calibrated_x ~= uncalibrated_x - bias_estimate_x
Примечание. Некалиброванные датчики предоставляют более необработанные результаты и могут включать некоторые погрешности, но их измерения содержат меньше скачков из-за корректировок, применяемых при калибровке. Некоторые приложения могут предпочесть эти некалиброванные результаты как более плавные и надежные. Например, если приложение пытается выполнить собственное объединение датчиков, калибровка может исказить результаты.
Помимо скорости вращения, некалиброванный гироскоп также предоставляет расчетный дрейф вокруг каждой оси. В следующем коде показано, как получить экземпляр некалиброванного гироскопа по умолчанию:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
Дополнительные примеры кода
Пример BatchStepSensor демонстрирует использование API, описанных на этой странице.