Реализация AR-сканирования плоскостей в мобильном приложении
Plane detection — фундамент большинства AR-сценариев: расстановка мебели, измерения, навигация по этажам. Без стабильного определения плоскостей AR-объект «плавает» и не воспринимается пользователем как реальный. Реализовать базовое определение плоскости несложно, но довести до ощущения «стоит как настоящее» — уже нет.
Платформенные API и их реальные ограничения
ARKit (iOS). ARWorldTrackingConfiguration с planeDetection: [.horizontal, .vertical]. ARKit возвращает ARPlaneAnchor с ARPlaneGeometry — mesh плоскости, который обновляется по мере сканирования. Проблема: на первых секундах ARKit возвращает маленький прямоугольник, который агрессивно меняет размер и ориентацию. Если разместить объект сразу — он «прыгнет» при следующем обновлении.
Решение — минимальный confidence threshold и debounce на обновления. ARPlaneAnchor не имеет явного поля confidence, но размер плоскости (extent) служит косвенным показателем зрелости: не показывать UI для размещения, пока extent.x < 0.3 и extent.z < 0.3 метра.
ARCore (Android). Plane с TrackingState.TRACKING и PlaneType.HORIZONTAL_UPWARD_FACING / VERTICAL. ARCore дополнительно предоставляет Plane.getSubsumedBy() — когда две плоскости сливаются в одну. Это ломает логику, если якоря были привязаны к исходным плоскостям — нужно переносить Anchor на subsuming plane.
Vertical planes. ARKit стабильно определяет вертикальные плоскости на текстурированных поверхностях (стена с обоями — хорошо, монотонно белая стена — плохо). ARCore с vertical detection работает ещё менее уверенно. Для продуктов, где критична навеска на стену (картины, полки), лучше использовать комбинацию plane detection + LiDAR (iPhone 12 Pro+) для достройки недостающей геометрии.
LiDAR и его влияние на качество сканирования
На устройствах с LiDAR (iPhone 12 Pro, 13 Pro, 14 Pro, 15 Pro, iPad Pro) ARKit строит dense mesh окружения через ARMeshAnchor. Plane detection с LiDAR работает принципиально иначе: плоскости выводятся из mesh, а не из визуального SLAM. Это даёт:
- Детектирование плоскости за 1-2 секунды вместо 5-10
- Стабильные границы даже на монотонных поверхностях
- Корректное определение ступеней, пандусов, наклонных плоскостей
Для приложений, где LiDAR-устройства — основная ЦА (профессиональная съёмка, ремонт, строительство), переключение между ARWorldTrackingConfiguration и конфигурацией с sceneReconstruction: .mesh даёт качественный скачок.
Визуализация прогресса сканирования
Пользователь не знает, что нужно «поводить» камерой — нужна чёткая подсказка. Типовые паттерны:
- Анимированный сканирующий луч из нижней части экрана
- Outline плоскости, который «растёт» по мере обнаружения
- Текстовая инструкция с автоскрытием после первого успешного detection
Для отрисовки границ плоскости в RealityKit — ModelEntity с wireframe материалом, привязанный к PlaneAnchor. В SceneKit — SCNNode с SCNGeometry из ARPlaneGeometry.boundaryVertices. В ARCore Scenekit/Filament — собственный меш из Plane.getPolygon().
Типичные проблемы в production
Плоскость «ломается» при сильном движении камерой — tracking state переходит в LIMITED(.excessiveMotion). Нужно блокировать размещение объектов и показывать предупреждение, а не крашиться.
На тёмных поверхностях (тёмный ламинат, чёрный ковёр) ARKit и ARCore теряют features для визуального SLAM. Предупреждение через ARCamera.TrackingState.Reason.insufficientFeatures — обязательно обрабатывать и сообщать пользователю.
Сроки
Реализация базового plane detection с визуальной подсказкой и размещением объекта — 5-8 дней. Доработка под LiDAR, multi-plane selection, сохранение ARWorldMap — ещё 5-7 дней. Стоимость зависит от целевых устройств и сложности визуальной части.







