Реалізація Core Motion (акселерометр, гіроскоп) в iOS-додатку
CoreMotion — єдина точка входу до інерціальних датчиків iPhone та iPad: акселерометр, гіроскоп, магнітометр, барометр, Motion Coprocessor. Прямий доступ до сирих даних зі 100 Гц плюс оброблені дані Device Motion з корекцією гравітації та фільтрацією дрейфу гіроскопа. Більшість завдань розв'язуються на рівні Device Motion — не потрібно реалізовувати фільтри Madgwick або Mahony вручну.
CMMotionManager: один екземпляр на додаток
Це не рекомендація — це вимога. Кілька екземплярів CMMotionManager у різних частинах додатку призводять до конфлікту оновлень та непередбачуваної поведінки. Стандартне рішення — singleton через DI-контейнер або статичну властивість:
final class MotionManager {
static let shared = MotionManager()
let motion = CMMotionManager()
private init() {}
}
Device Motion проти Raw Accelerometer
Raw Accelerometer (startAccelerometerUpdates) — повне прискорення: сума гравітації та лінійного прискорення від руху. На iPhone в спокої на столі: (x: 0, y: 0, z: -1) приблизно — це g ≈ 9.81 м/с² по осі Z. При нахилі — проекція гравітації змінюється по всіх осях.
Device Motion (startDeviceMotionUpdates) — прискорення вже без гравітації (userAcceleration), плюс attitude (орієнтація в просторі: pitch, roll, yaw), плюс rotationRate з корекцією дрейфу.
let manager = MotionManager.shared.motion
manager.deviceMotionUpdateInterval = 1.0 / 60.0 // 60 Гц
manager.startDeviceMotionUpdates(
using: .xMagneticNorthZVertical,
to: .main
) { [weak self] motion, error in
guard let motion = motion else { return }
let pitch = motion.attitude.pitch // нахил вперед/назад (радіани)
let roll = motion.attitude.roll // нахил вліво/вправо
let yaw = motion.attitude.yaw // поворот навколо вертикальної осі
let accel = motion.userAcceleration // лінійне прискорення без гравітації
let rotation = motion.rotationRate // кутова швидкість рад/с
}
CMAttitudeReferenceFrame.xMagneticNorthZVertical — орієнтація відносно магнітного північного полюса, Z вгору. Для ігрових додатків та AR — правильний вибір. Для простої детекції жестів — xArbitraryZVertical (без магнітометра, менша споживання).
Практичні застосування
Детекція жестів
Shake gesture вбудований в UIKit, але обмежений. Для користувацьких жестів — аналіз userAcceleration. Паттерн струсу: піки прискорення > 2.5g з чергуванням знаків на одній осі за < 500 мс.
var accelerationHistory: [Double] = []
// В обробнику device motion:
let magnitude = sqrt(
pow(motion.userAcceleration.x, 2) +
pow(motion.userAcceleration.y, 2) +
pow(motion.userAcceleration.z, 2)
)
accelerationHistory.append(magnitude)
if accelerationHistory.count > 30 { accelerationHistory.removeFirst() }
let peakCount = accelerationHistory.filter { $0 > 2.5 }.count
if peakCount >= 3 {
triggerShakeAction()
accelerationHistory.removeAll()
}
Визначення орієнтації та нахилу
Для додатків-рівнів, AR-розмітки, управління камерою: attitude.pitch та attitude.roll достатньо точні (похибка < 1° у стаціонарних умовах).
Педометрія без CMPedometer
На пристроях без підтримки CMPedometer (iPod Touch без Motion Coprocessor) — детекція кроків з акселерометра. Алгоритм: low-pass фільтр на userAcceleration.y, детекція піків > 0.2g з мінімальним інтервалом 300 мс.
CMAltimeter: барометрична висота
CMAltimeter — окремий клас для барометра:
let altimeter = CMAltimeter()
guard CMAltimeter.isRelativeAltitudeAvailable() else { return }
altimeter.startRelativeAltitudeUpdates(to: .main) { data, error in
guard let data = data else { return }
let relativeAltitude = data.relativeAltitude.doubleValue // метри від старту
let pressure = data.pressure.doubleValue // кПа
}
relativeAltitude — зміна висоти від моменту старту оновлень, не абсолютна висота над рівнем моря. Точність: ±0.1 м у стабільних погодних умовах. Використовується для розрахунку поверхів у CMPedometer.floorsAscended та для фітнес-додатків (набір/втрата висоти на маршруті).
Керування частотою та батарею
| Сценарій | Частота | Споживання |
|---|---|---|
| Детекція жестів | 10–25 Гц | Низька |
| Крокомір | 25–50 Гц | Середня |
| Ігрове управління | 60 Гц | Середня |
| AR/обробка сигналів | 100 Гц | Висока |
Не триматимути датчики активними без необхідності: stopDeviceMotionUpdates() у viewDidDisappear або при переході у фон (якщо дані у фоні не потрібні).
Терміни
Інтеграція базових датчиків (акселерометр, гіроскоп, attitude) з конкретним прикладним сценарієм — 3–7 робочих днів. Складні алгоритми обробки сигналів (детекція активностей, жестів, педометрія) — 2–4 тижні.







