Разработка
Как использовать CoreMotion для получения сенсорных данных
В этой статье мы разберемся, как он работает, и создадим простой интерфейс для отображения собранных данных.
Вдохновленный Swift Student Challenge 2023 и моим желанием попробовать что-то новое, я бросил вызов себе и решил изучить фреймворк, который я никогда раньше не использовал — CoreMotion.
В этой статье мы разберемся, как он работает, и создадим простой интерфейс для отображения собранных данных.
Что такое CoreMotion
CoreMotion — это фреймворк Apple, который передает информацию о движении и окружающей среде от бортовых датчиков устройства. Он, в частности, позволяет разработчикам получать доступ к данным о движении устройства, таким как ускорение, скорость и ориентация.
Кроме того, он оптимизирован для получения точных данных о движении даже в сложных условиях, таких как быстрое движение или изменение направления, поскольку использует датчики устройства для измерения и отслеживания движения в режиме реального времени.
Вы можете использовать этот фреймворк для доступа к данным, генерируемым оборудованием, и использовать их для всего, что только можно себе представить. Например, игра может использовать данные акселерометра и гироскопа для управления поведением игры на экране.
Погружение в CoreMotion
Пользователи генерируют события движения, когда двигают, трясут или наклоняют устройство. Эти события движения обнаруживаются аппаратным обеспечением устройства, и фреймворк позволяет вашему приложению получать и обрабатывать данные о движении.
Каждое устройство Apple имеет встроенное оборудование, которое можно использовать для сбора интересных данных. Давайте рассмотрим три основных компонента фреймворка CoreMotion:
- Акселерометр: Измеряет ускорение устройства и используется для обнаружения изменений в скорости и направлении движения
- Гироскоп: Измеряет угловую скорость устройства и используется для обнаружения изменений в ориентации и вращении.
- Магнитометр: Измеряет магнитное поле устройства и используется для определения ориентации устройства относительно магнитного поля Земли.
Существуют и другие типы датчиков, такие как барометры, шагомеры и датчики приближения, которые также хорошо задокументированы и информацию о них вы можете найти здесь.
Прежде чем мы сможем прочитать данные от этих датчиков, нам нужно глубоко погрузиться в то, как они представляются. Во-первых, важно понимать, что все значения, записываемые фреймворком устройства, относятся к референсной системе координат.
Это трехмерная система координат с тремя осями. Ось Z всегда направлена вниз по направлению силы тяжести (центр Земли), а направление оси X может быть определено вами при настройке менеджера движения. Наконец, ось Y перпендикулярна осям X и Z, завершая трехмерную систему координат.
Направление оси Y можно определить по правилу правой руки: если вы направляете большой палец в направлении оси X, а указательный палец — в направлении оси Z, то средний палец указывает в направлении оси Y.
Итак, чтобы лучше понять основные датчики и то, как они помогают отслеживать движение, мы можем взглянуть на то, что они могут измерять в своих трех координатах:
- Ускорение пользователя — ускорение, которое пользователь придает устройству
- Гравитация — ускорение под действием силы тяжести
- Скорость вращения — как пользователь вращает смартфон
Как использовать
В этой статье мы будем использовать SwiftUI и архитектуру MVVM.
Сначала вам нужно создать представление для отображения данных, которые вы будете получать. Вы можете спроектировать его как угодно, или посмотреть исходный код того, который я создал, здесь.
Теперь перейдем к собственно логике. Первое, что вам нужно сделать, это импортировать CoreMotion и создать экземпляр CMMotionManager. Кроме того, вам понадобятся некоторые свойства для хранения полученных значений.
class HomeViewModel: ObservableObject { @Published var accelerationValue: String = "" @Published var gravityValue: String = "" @Published var rotationValue: String = "" // The instance of CMMotionManager responsible for handling sensor updates private let motionManager = CMMotionManager() // Properties to hold the sensor values private var userAcceleration: CMAcceleration = CMAcceleration() private var gravity: CMAcceleration = CMAcceleration() private var rotationRate: CMRotationRate = CMRotationRate() }
Затем нам нужно получить фактические данные, которые мы получаем от датчиков. Поэтому мы создадим private функцию, которая будет проверять, доступны ли они, а затем начнет обновлять их, вызывая соответствующие методы.
private func startFetchingSensorData() { // Check if the motion manager is available and the sensors are available if motionManager.isDeviceMotionAvailable && motionManager.isAccelerometerAvailable && motionManager.isGyroAvailable { // Start updating the sensor data motionManager.startDeviceMotionUpdates(to: .main) { [weak self] (motion, error) in guard let self = self else { return } // Avoid memory leaks // Check if there's any error in the sensor update if let error = error { print("Error: \(error.localizedDescription)") } getMotionAndGravity(motion: motion) } motionManager.startGyroUpdates(to: .main) { [weak self] (gyroData, error) in guard let self = self else { return } getRotation(gyroData: gyroData) } } }
Далее нам останется только создать методы, которые будут извлекать значения ускорения, гравитации и вращения, и сделать так, чтобы они обновляли соответствующие @Published свойства, чтобы они могли публиковать изменения подписчикам нашего представления.
private func getMotionAndGravity(motion: CMDeviceMotion?){ if let motion = motion { // Get user acceleration and gravity data self.userAcceleration = motion.userAcceleration self.gravity = motion.gravity // Update publishers with the new sensor data self.accelerationValue = "X: \(userAcceleration.x), \n Y: \(userAcceleration.y), \n Z: \(userAcceleration.z)" self.gravityValue = "X: \(gravity.x), \n Y: \(gravity.y), \n Z: \(gravity.z)" } } private func getRotation(gyroData: CMGyroData?){ if let gyroData = gyroData { // Get rotation rate data self.rotationRate = gyroData.rotationRate // Update publisher with the new sensor data self.rotationValue = "X: \(rotationRate.x), \n Y: \(rotationRate.y), \n Z: \(rotationRate.z)" } }
После этого вы можете начать перемещаться и вращать свое устройство, чтобы увидеть обновление данных в режиме реального времени! Я призываю вас начать исследовать возможности взаимодействия на основе движения в ваших собственных проектах.
Заключение
CoreMotion — это мощный фреймворк, открывающий бесчисленные возможности для использования движений. Он полезен не только для разработчиков, но и для пользователей, которые могут извлечь пользу из нового и уникального опыта.
Я использовал его для создания своего проекта-победителя WWDC 23, Space Cruiser! 🏆
Логика игры предполагает управление космическим кораблем, а движение устройства используется для управления его перемещением. Космический корабль управляется с помощью наклона устройства, что добавляет игре новый уровень погружения.
Space Cruiser доступен на GitHub, как и исходный код для этой статьи.
-
Интегрированные среды разработки2 недели назад
Лучшая работа с Android Studio: 5 советов
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2024.43
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2024.44
-
Исследования2 недели назад
Поможет ли новая архитектура React Native отобрать лидерство у Flutter в кроссплатформенной разработке?