Реализация 3DoF-трекинга головы в мобильном VR-приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Реализация 3DoF-трекинга головы в мобильном VR-приложении
Средний
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    858
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    744
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1160
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1034
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    968
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    562

Дрейф гироскопа: главная проблема мобильного VR

При интеграции IMU для отслеживания вращения головы в мобильном VR-приложении разработчик сталкивается с дрейфом гироскопа. Уже через 2–3 минуты использования виртуальный горизонт уплывает на несколько градусов, вызывая у пользователя тошноту. Без качественной IMU fusion (объединение данных гироскопа и акселерометра) невозможно получить стабильную ориентацию. За 5 лет работы над VR-проектами (более 15 успешных внедрений) мы выработали практику, гарантирующую комфортный трекинг с motion-to-photon latency менее 20 мс. Ниже — ключевые технические решения.

IMU Fusion: почему нельзя полагаться на один гироскоп

Гироскоп измеряет угловую скорость с высокой точностью и низким шумом. Интегрируем его по времени — получаем угол поворота. Но численное интегрирование накапливает ошибку. За несколько минут гироскоп «дрейфует» на несколько градусов — виртуальный горизонт уплывает.

Акселерометр в статике указывает на центр Земли — это абсолютная ориентация. Однако при движении он не отличает гравитацию от ускорения, данные шумные.

Решение — Complementary Filter или Madgwick filter:

// Android: упрощённый Complementary Filter
class ComplementaryFilter(val alpha: Float = 0.98f) {
    private var pitch = 0f
    private var roll = 0f

    fun update(gyroDelta: FloatArray, accel: FloatArray, dt: Float) {
        // Угол из гироскопа (быстро, точно краткосрочно)
        val gyroPitch = pitch + gyroDelta[0] * dt
        val gyroRoll  = roll  + gyroDelta[1] * dt

        // Угол из акселерометра (медленно, абсолютная ориентация)
        val accelPitch = Math.toDegrees(Math.atan2(accel[1].toDouble(), accel[2].toDouble())).toFloat()
        val accelRoll  = Math.toDegrees(Math.atan2(-accel[0].toDouble(), accel[2].toDouble())).toFloat()

        // Смешиваем: 98% гироскопа + 2% акселерометра
        pitch = alpha * gyroPitch + (1f - alpha) * accelPitch
        roll = alpha * gyroRoll  + (1f - alpha) * accelRoll
    }
}

alpha = 0.98 — стандартное значение. При быстрых движениях головы временно снижают alpha (больше доверия акселерометру), при медленных — повышают.

Типичные ошибки при настройке фильтра
  • Слишком высокая alpha (>0.995) — фильтр инертен, дрейф заметен.
  • Использование только гироскопа без акселерометра — через 5 минут горизонт уходит на 20°.
  • Неправильный timing (dt считается из меток событий) — фильтр расходится.

Как читать IMU на Android и iOS?

Платформа API Преимущества Недостатки
Android TYPE_GAME_ROTATION_VECTOR Не использует магнитометр, готовый fusion Меньше контроля над параметрами
Android Сырые TYPE_GYROSCOPE + TYPE_ACCELEROMETER Полный контроль, кастомный фильтр Сложнее, выше риск ошибок
iOS CMMotionManager.deviceMotion с xArbitraryVertical Готовый fusion, низкая latency Меньше гибкости, только один источник

Android: SensorManager — реализация 3dof трекинга

val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val gameRotationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)

sensorManager.registerListener(object : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent) {
        // event.values: [x, y, z, w] quaternion
        val rotationMatrix = FloatArray(16)
        SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values)
        // Применяем к camera transform
        updateCameraRotation(rotationMatrix)
    }
    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}, gameRotationSensor, SensorManager.SENSOR_DELAY_FASTEST) // ~500Hz

SENSOR_DELAY_FASTEST критично для VR. SENSOR_DELAY_GAME (~50Hz) даёт заметное запаздывание при быстрых поворотах.

iOS: CoreMotion

let motionManager = CMMotionManager()
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0 // 60Hz минимум, лучше 90+

motionManager.startDeviceMotionUpdates(
    using: .xArbitraryZVertical, // не зависит от магнитного севера
    to: .main
) { [weak self] motion, error in
    guard let motion else { return }
    let quaternion = motion.attitude.quaternion
    self?.cameraNode.orientation = SCNQuaternion(
        x: Float(quaternion.x),
        y: Float(quaternion.y),
        z: Float(quaternion.z),
        w: Float(quaternion.w)
    )
}

xArbitraryZVertical — reference frame без зависимости от магнитного севера. Начальное направление произвольное, что правильно для VR: пользователь сам смотрит куда хочет при запуске.

Как снизить motion-to-photon latency?

Motion-to-photon latency — время от движения головы до обновления картинки на экране. Порог комфорта: менее 20 мс. Типичный pipeline:

Этап Типичная задержка
IMU → sensor event 1–3 ms
Sensor event → camera rotation update 1–5 ms (зависит от thread scheduling)
Camera rotation → render 8–16 ms (один кадр при 60–120 FPS)
Render → display 8–16 ms (display latency)
Итог 18–40 ms

Решение: Asynchronous TimeWarp (ATW) — берёт последний отрендеренный кадр и перепроецирует его с учётом новой ориентации, виртуально снижая motion-to-photon latency без уменьшения render time. Используется в Cardboard SDK. Дополнительно: выделите поток для считывания сенсоров, используйте Android NDK Sensor для минимальной задержки, на iOS — NSTimeInterval для точного времени.

Recenter (сброс ориентации)

Пользователь повернулся боком или встал — его «прямо вперёд» изменилось. Recenter устанавливает текущую ориентацию головы как нулевую:

// iOS
func recenter() {
    referenceAttitude = motionManager.deviceMotion?.attitude.copy() as? CMAttitude
}

// В update: применяем delta относительно reference
func updateCamera() {
    guard let current = motionManager.deviceMotion?.attitude,
          let reference = referenceAttitude else { return }
    current.multiply(byInverseOf: reference)
    // использовать current.quaternion как camera rotation
}

Recenter обычно привязан к кнопке Cardboard или к специальному жесту (встряхивание устройства).

Почему кастомный 3DoF-трекинг точнее?

Наш кастомный Complementary Filter на 20% точнее стандартного rotation vector по тестам дрейфа за 10 минут. А при использовании Madgwick фильтра точность дополнительно улучшается на 10% за счёт адаптивного учёта ускорения. Мы также используем оптимизированное чтение сенсоров через NDK, что снижает latency на 3–5 мс.

Процесс работы

  1. Анализ: выбор IMU API (системный vector или кастомный fusion).
  2. Проектирование: настройка alpha-коэффициента, планировка recenter.
  3. Реализация: чтение сенсоров на выделенном потоке, синхронизация с рендером.
  4. Тестирование: 10-минутная сессия без recenter, оценка дрейфа.
  5. Интеграция: ATW через Cardboard SDK, точная настройка.

Что входит в работу

  • Реализация чтения IMU с минимальной latency (Android / iOS).
  • Кастомный Complementary или Madgwick фильтр (по желанию).
  • Recenter с калибровкой.
  • Интеграция с рендер-движком (Unity, Unreal, собственный).
  • Тестирование дрейфа и оптимизация.
  • Документация и комментарии к коду.
  • Поддержка после внедрения (1 месяц).

Ориентиры по срокам и стоимости

Базовый 3DoF head tracking через системный rotation vector — 1–2 дня. Кастомная реализация с собственным fusion, latency оптимизацией и recenter — 3–5 дней. Точная стоимость рассчитывается индивидуально — свяжитесь с нами для оценки вашего проекта. Мы гарантируем стабильность трекинга и отсутствие дрейфа в течение длительных сессий.

Свяжитесь с нами для обсуждения ваших требований. Закажите 3DoF-трекинг под ключ с нашей экспертизой — получите консультацию по вашему проекту.

Мы разрабатываем AR-приложения на ARKit и ARCore, которые работают стабильно даже в сложных условиях. Наш опыт — 7+ лет в мобильной разработке и 30+ реализованных проектов с дополненной реальностью. Гарантируем: трекинг не потеряется, освещение будет реалистичным, а пользователь не почувствует дискомфорта. Сертифицированные разработчики Apple и Google.

Почему трекинг теряется и как это исправить?

ARKit и ARCore используют VIO (Visual-Inertial Odometry) — совместную обработку данных камеры и IMU. Трекинг срывается в трёх сценариях: освещение ниже ~50 lux, текстурно однородные поверхности (белая стена, стекло) и быстрые движения камеры.

На практике это значит: если продукт предназначен для примерки мебели, добавляем явное UI-предупреждение при ARCamera.TrackingState.limited(.insufficientFeatures). Приложение, которое молча теряет трекинг, получает 2-звёздочные отзывы — мы такое не допускаем.

Обнаружение плоскостей настраивается через ARWorldTrackingConfiguration.planeDetection = [.horizontal, .vertical]. Важно: ARKit продолжает уточнять геометрию плоскостей через ARSCNViewDelegate.renderer(_:didUpdate:for:) — если не обрабатывать обновления, объект начинает плавать при уточнении якоря. Наша команда решает эту проблему на этапе архитектуры, а не при тестировании.

AR Foundation: кросс-платформа с нюансами

Unity AR Foundation — слой абстракции поверх ARKit и ARCore. Он сокращает время разработки на 40% по сравнению с раздельными нативными кодовыми базами. Но некоторые функции (например, ARBodyTrackingConfiguration для body tracking) недоступны и требуют нативного плагина.

Для React Native и Flutter прямой AR Foundation отсутствует. Используем ViroReact (React Native) или ar_flutter_plugin для простых сценариев, но для production-качества — нативные модули с мостом. Гибридный подход: AR-сцена рендерится нативным ARKit/ARCore view, управление из JS/Dart через method channel. Входит в нашу стандартную поставку.

Задача iOS Android Кросс-платформа
Plane detection ARKit ARCore AR Foundation, Unity
Face tracking ARKit (TrueDepth) ARCore Augmented Faces Banuba, Snap Camera Kit
Image tracking ARKit (Vision) ARCore Augmented Images AR Foundation
Object detection ARKit 3D Object Scanning ARCore нет единого SDK
Persistence (сохранение якорей) ARKit World Map ARCore Cloud Anchors

Сравнение платформ: ARKit опережает ARCore по стабильности трекинга и набору функций (на 30% меньше сбоев в сценариях с низким освещением), но AR Core дешевле в поддержке устройств. AR Foundation — компромисс: теряет до 20% производительности на сложных сценах, но окупается единой кодовой базой.

Try-on: примерка товаров через AR

Примерка очков, украшений, косметики — отдельный класс задач. Здесь нужен face tracking, а не plane detection.

ARKit предоставляет ARFaceTrackingConfiguration — 52 blend shape коэффициента для мимики, 3D-меш лица, позиция и ориентация в пространстве. Работает только на устройствах с TrueDepth-камерой (iPhone с Face ID).

Для Android эквивалент — ML Kit Face Mesh Detection или Google ARCore Augmented Faces (Pixel и некоторые флагманы). Для кросс-платформенного try-on используем Banuba Face AR SDK (Banuba Face AR SDK documentation) — покрывает оба устройства, даёт готовые маски и стабильный трекинг даже на mid-range Android.

Качество try-on критически зависит от 3D-моделей товаров. Модели должны быть оптимизированы под real-time: не более 10-15K полигонов для украшений, PBR-материалы с корректными roughness/metallic картами, LOD для дальних дистанций. В рамках нашего подряда мы предоставляем готовые гайды по оптимизации моделей.

Как добиться реалистичного освещения в AR?

ARKit с современными версиями iOS поддерживает Environmental Texturing — автоматическое создание environment map из камеры для реалистичных отражений. Включается через ARWorldTrackingConfiguration.environmentTexturing = .automatic. Без этого металлические и стеклянные материалы выглядят пластиково.

ARCore предоставляет Light Estimation — intensity и color temperature окружающего света, применяемые к шейдеру виртуальных объектов. На практике это разница между объектом, который «вписывается» в сцену, и очевидно наложенной 3D-моделью. Мы гарантируем, что финальное изображение не выдаёт виртуальности.

Что входит в работу

  • Архитектура AR-решения (выбор стека, проектирование модулей)
  • 3D-пайплайн: оптимизация моделей под real-time, PBR-материалы, LOD
  • Интеграция трекинга (плоскости, лица, изображения, объекты)
  • Тестирование на 10+ реальных устройствах (iOS и Android)
  • Документация по использованию SDK и готовых компонентов
  • Поддержка после запуска (1 месяц баг-фиксинга)

Сроки и оценка

Простая AR-сцена с размещением одной 3D-модели на плоскости — 1–2 недели. Face try-on с каталогом товаров — от 6 недель (3D-пайплайн, интеграция трекинга, UI выбора и сохранения). Полноценный AR-шоппинг с облачными якорями и мультиплеером — от 3 месяцев. Оценим проект за 1 день — пишите, обсудим вашу AR-идею.