tab style guidelines bar apple app ios objective-c core-motion apple-m7

style - tab bar ios



Detectar cuándo alguien comienza a caminar con Core Motion y CMAccelerometer Data (4)

De acuerdo con sus registros, accelerometerUpdateInterval es aproximadamente 0.02 . Las actualizaciones podrían ser menos frecuentes si cambia la propiedad mencionada de CMMotionManager .

Comprobar solo la aceleración x no es muy preciso. Puedo poner un dispositivo en una mesa de tal manera (digamos en el borde izquierdo) que la aceleración x será igual a 1, o inclinarlo un poco. Esto hará que un programa esté en modo de caminar (x> 0.1) en lugar de inactivo .

Aquí hay un enlace a la publicación PEDÓMETRO AVANZADO PARA EL SEGUIMIENTO DE ACTIVIDADES BASADAS EN SMARTPHONE . Realizan un seguimiento de los cambios en la dirección del vector de la aceleración. Este es el coseno del ángulo entre dos lecturas de vector de aceleración consecutivas.

Obviamente, sin ningún movimiento, el ángulo entre dos vectores es cercano a cero y cos(0) = 1 . Durante otras actividades d <1. Para filtrar el ruido, utilizan un promedio móvil ponderado de los últimos 10 valores de d .

Después de implementar esto, sus valores se verán así (rojo - caminando, azul - corriendo):

Ahora puede establecer un umbral para cada actividad para separarlos. Tenga en cuenta que la frecuencia de paso promedio es de 2-4Hz. Debería esperar que el valor actual esté por encima del umbral al menos unas pocas veces en un segundo para identificar la acción.

Otras publicaciones útiles:

ACTUALIZAR

_acceleration.x , _accelaration.y , _acceleration.z son coordenadas del mismo vector de aceleración. Utiliza cada una de estas coordenadas en la fórmula d . Para calcular d también necesita almacenar el vector de aceleración de la actualización anterior (con el índice i-1 en la fórmula).

WMA solo tiene en cuenta 10 valores de la última d con diferentes pesos. Los valores d más recientes tienen más peso, por lo tanto, más impacto en el valor resultante. Es necesario almacenar 9 valores d anteriores para calcular el valor actual. Debe comparar el valor de WMA con el umbral correspondiente.

Estoy tratando de detectar tres acciones: cuando un usuario comienza a caminar, trotar o correr. Entonces quiero saber cuándo parar. He tenido éxito en detectar cuando alguien está caminando, trotando o corriendo con el siguiente código:

- (void)update:(CMAccelerometerData *)accelData { [(id) self setAcceleration:accelData.acceleration]; NSTimeInterval secondsSinceLastUpdate = -([self.lastUpdateTime timeIntervalSinceNow]); if (labs(_acceleration.x) >= 0.10000) { NSLog(@"walking: %f",_acceleration.x); } else if (labs(_acceleration.x) > 2.0) { NSLog(@"jogging: %f",_acceleration.x); } else if (labs(_acceleration.x) > 4.0) { NSLog(@"sprinting: %f",_acceleration.x); }

El problema que encuentro es doble:

1) la actualización se llama varias veces cada vez que hay un movimiento, probablemente porque verifica con tanta frecuencia que cuando el usuario comienza a caminar (es decir, _acceleration.x> = .1000) sigue siendo> = .1000 cuando vuelve a llamar a actualizar.

Ejemplo de registro:

2014-02-22 12:14:20.728 myApp[5039:60b] walking: 1.029846 2014-02-22 12:14:20.748 myApp[5039:60b] walking: 1.071777 2014-02-22 12:14:20.768 myApp[5039:60b] walking: 1.067749

2) Tengo dificultades para descubrir cómo detectar cuándo se detuvo el usuario. ¿Alguien tiene consejos sobre cómo implementar "Detener Detección"?


Estoy siguiendo este documento ( PDF a través de RG ) en mi proyecto de navegación interior para determinar la dinámica del usuario (estática, caminar lento, caminar rápido) a través de los simples datos del acelerómetro para ayudar a determinar la ubicación.

Aquí está el algoritmo propuesto en el proyecto:

Y aquí está mi implementación en Swift 2.0:

import CoreMotion let motionManager = CMMotionManager() motionManager.accelerometerUpdateInterval = 0.1 motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue()) { (accelerometerData: CMAccelerometerData?, error: NSError?) -> Void in if((error) != nil) { print(error) } else { self.estimatePedestrianStatus((accelerometerData?.acceleration)!) } }

Después de todo el código Swifty clásico de iOS para iniciar CoreMotion, aquí está el método para procesar los números y determinar el estado:

func estimatePedestrianStatus(acceleration: CMAcceleration) { // Obtain the Euclidian Norm of the accelerometer data accelerometerDataInEuclidianNorm = sqrt((acceleration.x.roundTo(roundingPrecision) * acceleration.x.roundTo(roundingPrecision)) + (acceleration.y.roundTo(roundingPrecision) * acceleration.y.roundTo(roundingPrecision)) + (acceleration.z.roundTo(roundingPrecision) * acceleration.z.roundTo(roundingPrecision))) // Significant figure setting accelerometerDataInEuclidianNorm = accelerometerDataInEuclidianNorm.roundTo(roundingPrecision) // record 10 values // meaning values in a second // accUpdateInterval(0.1s) * 10 = 1s while accelerometerDataCount < 1 { accelerometerDataCount += 0.1 accelerometerDataInASecond.append(accelerometerDataInEuclidianNorm) totalAcceleration += accelerometerDataInEuclidianNorm break // required since we want to obtain data every acc cycle } // when acc values recorded // interpret them if accelerometerDataCount >= 1 { accelerometerDataCount = 0 // reset for the next round // Calculating the variance of the Euclidian Norm of the accelerometer data let accelerationMean = (totalAcceleration / 10).roundTo(roundingPrecision) var total: Double = 0.0 for data in accelerometerDataInASecond { total += ((data-accelerationMean) * (data-accelerationMean)).roundTo(roundingPrecision) } total = total.roundTo(roundingPrecision) let result = (total / 10).roundTo(roundingPrecision) print("Result: /(result)") if (result < staticThreshold) { pedestrianStatus = "Static" } else if ((staticThreshold < result) && (result <= slowWalkingThreshold)) { pedestrianStatus = "Slow Walking" } else if (slowWalkingThreshold < result) { pedestrianStatus = "Fast Walking" } print("Pedestrian Status: /(pedestrianStatus)/n---/n/n") // reset for the next round accelerometerDataInASecond = [] totalAcceleration = 0.0 } }

También he usado la siguiente extensión para simplificar la configuración de figuras significativas:

extension Double { func roundTo(precision: Int) -> Double { let divisor = pow(10.0, Double(precision)) return round(self * divisor) / divisor } }

Con los valores en bruto de CoreMotion, el algoritmo era unwire.

Espero que esto ayude a alguien.

EDITAR (4/3/16)

Olvidé proporcionar mi valor de roundingPrecision . Lo definí como 3. Es simplemente matemático que ese valor tan significativo es lo suficientemente decente. Si gustas aportas más.

También una cosa más que mencionar es que en este momento, este algoritmo requiere que el iPhone esté en sus manos mientras camina. Vea la imagen de abajo. Lo siento, este fue el único que pude encontrar.

My GitHub Repo con estado de peatón


Puede usar esta biblioteca simple para detectar si el usuario está caminando, corriendo, en el vehículo o no se está moviendo. Funciona en todos los dispositivos iOS y no necesita chip M7.

https://github.com/SocialObjects-Software/SOMotionDetector

En repo puedes encontrar proyecto demo.


Si está utilizando iOS7 y iPhone5S, le sugiero que busque CMMotionActivityManager, que está disponible en iPhone5S debido al chip M7. También está disponible en un par de otros dispositivos:

Chip m7

Aquí hay un fragmento de código que puse juntos para probar cuando estaba aprendiendo sobre él.

#import <CoreMotion/CoreMotion.h> @property (nonatomic,strong) CMMotionActivityManager *motionActivityManager; -(void) inSomeMethod { self.motionActivityManager=[[CMMotionActivityManager alloc]init]; //register for Coremotion notifications [self.motionActivityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMMotionActivity *activity) { NSLog(@"Got a core motion update"); NSLog(@"Current activity date is %f",activity.timestamp); NSLog(@"Current activity confidence from a scale of 0 to 2 - 2 being best- is: %ld",activity.confidence); NSLog(@"Current activity type is unknown: %i",activity.unknown); NSLog(@"Current activity type is stationary: %i",activity.stationary); NSLog(@"Current activity type is walking: %i",activity.walking); NSLog(@"Current activity type is running: %i",activity.running); NSLog(@"Current activity type is automotive: %i",activity.automotive); }]; }

Lo probé y parece ser bastante preciso. El único inconveniente es que no le dará una confirmación tan pronto como comience una acción (por ejemplo, caminar). Algunos algoritmos de caja negra esperan para asegurarse de que realmente está caminando o corriendo. Pero entonces sabes que tienes una acción confirmada.

Esto es mejor que perder el tiempo con el acelerómetro. Apple se encargó de ese detalle!