Обнаружение вибраций двигателя с внутренней вибрацией с помощью акселерометраIOS

Программируем под IOS
Ответить
Anonymous
 Обнаружение вибраций двигателя с внутренней вибрацией с помощью акселерометра

Сообщение Anonymous »

Я работаю над приложением для iOS, которое запускает внутренний вибромотор iPhone и, пока телефон вибрирует, собирает показания акселерометра и гироскопа. Я визуализировал данные после сбора и ясно видел вибрации на гироскопе, но ничего не видел на акселерометре. Мне было интересно, делал ли кто-нибудь подобное раньше на iPhone и мог видеть вибрацию акселерометра.
Ниже я поделюсь кодом, который я использовал для сбора данных акселерометра и гироскопа.
Во-первых, этот класс отвечает за процесс сбора:

Код: Выделить всё

class SensorCollector: ObservableObject {
private let motionManager = CMMotionManager()
private let sensorQueue = OperationQueue()

var accBuffer: [VibrateView.SensorReading] = []
var gyrBuffer: [VibrateView.SensorReading] = []

init() {
sensorQueue.name = "SensorCollectionQueue"
sensorQueue.qualityOfService = .userInitiated
}

func startSensors(startTime: TimeInterval) {
// 1. Clear buffers
accBuffer.removeAll(keepingCapacity: true)
gyrBuffer.removeAll(keepingCapacity: true)

// 2. Set Interval (sampling rate)
let interval = 0.0025
motionManager.accelerometerUpdateInterval = interval
motionManager.gyroUpdateInterval = interval

// 3. Start Updates on BACKGROUND QUEUE
if motionManager.isAccelerometerAvailable {
motionManager.startAccelerometerUpdates(to: sensorQueue) { [weak self] data, error in
guard let self = self, let data = data else { return }
let reading = VibrateView.SensorReading(
x: data.acceleration.x,
y: data.acceleration.y,
z: data.acceleration.z,
timestamp: data.timestamp - startTime
)
self.accBuffer.append(reading)
}
}

if motionManager.isGyroAvailable {
motionManager.startGyroUpdates(to: sensorQueue) { [weak self] data, error in
guard let self = self, let data = data else { return }
let reading = VibrateView.SensorReading(
x: data.rotationRate.x,
y: data.rotationRate.y,
z: data.rotationRate.z,
timestamp: data.timestamp - startTime
)
self.gyrBuffer.append(reading)
}
}
}

func stopSensors() {
motionManager.stopAccelerometerUpdates()
motionManager.stopGyroUpdates()
}

// Check availability
var isAccelAvailable: Bool { motionManager.isAccelerometerAvailable }
var isGyroAvailable: Bool { motionManager.isGyroAvailable }
}
Затем я использую эту функцию для запуска внутреннего вибромотора iPhone. Пользователь выбирает тест в пользовательском интерфейсе:

Код: Выделить всё

    struct VibrationEvent {
let time: TimeInterval
let duration: TimeInterval
let intensity: Float
}

func vibrateDevice(forTest test: String) async throws {
var events = [CHHapticEvent]()
let traceDuration: TimeInterval = 2.0
let currentTime: TimeInterval = 0

var someEvents: [VibrationEvent] = []

let test1: [VibrationEvent] = [
VibrationEvent(time: currentTime, duration: 2.0, intensity: 1.0)
]
let test2: [VibrationEvent] = [
VibrationEvent(time: currentTime, duration: 0.5, intensity: 0.8),
VibrationEvent(time: currentTime + 0.5, duration: 0.5, intensity: 0.9),
VibrationEvent(time: currentTime + 1.0, duration: 0.5, intensity: 1.0),
VibrationEvent(time: currentTime + 1.5, duration: 0.5, intensity: 1.0)
]
let test3: [VibrationEvent] = [
VibrationEvent(time: currentTime, duration: 0.4, intensity: 1.0),
VibrationEvent(time: currentTime + 0.8, duration: 0.4, intensity: 1.0),
VibrationEvent(time: currentTime + 1.6, duration: 0.4, intensity: 1.0)
]
let test4: [VibrationEvent] = [
VibrationEvent(time: currentTime, duration: 0.4, intensity: 0.8),
VibrationEvent(time: currentTime + 0.8, duration: 0.4, intensity: 0.9),
VibrationEvent(time: currentTime + 1.6, duration: 0.4, intensity: 1.0)
]
let test5: [VibrationEvent] = [
VibrationEvent(time: currentTime, duration: 0.25, intensity: 1.0),
VibrationEvent(time: currentTime + 0.25, duration: 0.25, intensity: 0.2),
VibrationEvent(time: currentTime + 0.50, duration: 0.25, intensity: 1.0),
VibrationEvent(time: currentTime + 0.75, duration: 0.25, intensity: 0.2),
VibrationEvent(time: currentTime + 1.00, duration: 0.25, intensity: 1.0),
VibrationEvent(time: currentTime + 1.25, duration: 0.25, intensity: 0.2),
VibrationEvent(time: currentTime + 1.50, duration: 0.25, intensity: 1.0),
VibrationEvent(time: currentTime + 1.75, duration: 0.25, intensity: 0.2)
]
let test6: [VibrationEvent] = [
VibrationEvent(time: currentTime, duration: 0.4, intensity: 0.6),
VibrationEvent(time: currentTime + 0.4, duration: 0.4, intensity: 0.7),
VibrationEvent(time: currentTime + 0.8, duration: 0.4, intensity: 0.8),
VibrationEvent(time: currentTime + 1.2, duration: 0.4, intensity: 0.9),
VibrationEvent(time: currentTime + 1.6, duration: 0.4, intensity: 1.0)
]

if selectedTest.contains("Test 1"){
someEvents = test1
} else if selectedTest.contains("Test 2") {
someEvents = test2
} else if selectedTest.contains("Test 3") {
someEvents = test3
} else if selectedTest.contains("Test 4") {
someEvents = test4
} else if selectedTest.contains("Test 5") {
someEvents = test5
} else if selectedTest.contains("Test 6"){
someEvents = test6
}

for event in someEvents {
events.append(addVibration(at: event.time, duration: event.duration, intensity: event.intensity))
}

do {
let pattern = try CHHapticPattern(events: events, parameters: [])
let player = try engine?.makePlayer(with: pattern)
try player?.start(atTime: 0)
} catch {
print("Failed to play pattern: \(error.localizedDescription)")
}

let totalDuration = (someEvents.map { $0.time + $0.duration }.max() ?? 0)
try await Task.sleep(nanoseconds: UInt64(totalDuration * 1_000_000_000))
}
Наконец, я использую эту функцию, чтобы собрать все воедино:

Код: Выделить всё

func startVibrationTest() async {
// 1.  UI Setup
testRunning = true
canClearResults = false
tracesData = []

testStartTime = currentUptimeSeconds()

do {
try await prepareHaptics()

// MARK: - SCENARIO A: Test 0 (Rest Only)
if selectedTest.contains("Test 0") {
let restDuration: TimeInterval = 10.0
let restStart = currentUptimeSeconds()

// A. Start Collecting
collector.startSensors(startTime: currentUptimeSeconds())

// B. Wait
try await Task.sleep(nanoseconds: UInt64(restDuration * 1_000_000_000))

// C. Stop Collecting
collector.stopSensors()

// D. Save Data
let restTrace = TraceReadings(
id: 1,
accelerometer: collector.accBuffer,
gyroscope: collector.gyrBuffer,
startTime: restStart,
endTime: currentUptimeSeconds(),
traceType: .rest
)

// Append to array (UI Update on Main Actor)
await MainActor.run {
tracesData.append(restTrace)
}

sendDataToServer()
}

// MARK: - SCENARIO B: Vibration Tests (1-6)
else {
let numberOfTraces = 10
let breakDuration: TimeInterval = 10.0

for traceIndex in 0..

Подробнее здесь: [url]https://stackoverflow.com/questions/79883592/detecting-vibrations-from-internal-vibration-motor-using-accelerometer[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»