2012-02-02 8 views
5

Ho provato questo progetto su Android e iOS con scarso successo. C'è una buona possibilità che questa roba sia proprio sopra la mia testa. Comunque ho pensato che avrei posto la mia domanda qui come ultimo sforzo.
Sto cercando di capire quando un dispositivo viene ruotato o capovolto. La mia app dovrebbe sapere quando ha fatto un 180, 360 o se il dispositivo è stato ruotato verticalmente.
Nel tentativo di capire come funziona, ho provato a scaricare due progetti di esempio: AccelerometerGraph e CoreMotionTeapot. Con questi e un mix di altre cose che ho capito che stavo cercando in questo modo:sensore di movimento, rotazione di lettura

motionManager = [[CMMotionManager alloc] init]; 
motionManager.accelerometerUpdateInterval = 0.01; 
motionManager.deviceMotionUpdateInterval = 0.01; 
[motionManager startDeviceMotionUpdates]; 

if (motionManager.gyroAvailable) { 
    motionManager.gyroUpdateInterval = 1.0/60.0; 
     motionManager.deviceMotionUpdateInterval = 0.01; 
    [motionManager startGyroUpdatesToQueue:[NSOperationQueue currentQueue] 
           withHandler: ^(CMGyroData *gyroData, NSError *error) 
    { 
     CMRotationRate rotate = gyroData.rotationRate; 
     NSLog(@"rotation rate = [%f, %f, %f]", rotate.x, rotate.y, rotate.z); 
    }]; 
} else { 
    NSLog(@"No gyroscope on device."); 
} 

Ma io non so come raccogliere le informazioni richieste (orizzontale e rotazioni verticali) da questi tre valori (x, y, z).

+0

Esattamente quale tipo di rotazione stai cercando? Ad esempio, la situazione più semplice sarebbe che il telefono si trovi con lo schermo verso l'alto sul tavolo e quando lo si mette con lo schermo verso il basso, esso ha ruotato di 180 gradi (attorno a qualsiasi asse). Ma cosa costituisce una rotazione di 90 gradi? È dalla sua parte? Sta in piedi? O stai cercando una soluzione in cui stai tenendo il tuo dispositivo in un orientamento casuale e vuoi sapere quando ha ruotato di 180 gradi in qualsiasi direzione entro, diciamo, 2 secondi? Cioè una soluzione molto generale, ma molto interessante :) – Desmond

+3

In nessun modo stavo cercando di farti venire la tua idea. :) Mi dispiace per quello. Ma capisco il tuo problema ora. Può essere fatto, ma questo è difficile da fare ed è improbabile che una risposta "semplice" su stackoverflow.com possa fare. Mi hai incuriosito, sembra molto divertente da costruire! – Desmond

+0

andando a provare e convertire questi numeri in gradi e vedere se aiuta: http://stackoverflow.com/questions/4576493/how-can-i-use-sensormanager-getorientation-for-tit-controls-like-my- paper-plan –

risposta

0

dalla documentazione di Apple: CMMotionManager Classe di riferimento (molto spiacente di lettura, ho grassetto alcune frasi per un rapido over-lettura)

Dopo aver creato un'istanza di CMMotionManager, un'applicazione può essere utilizzato per ricevere quattro tipi di movimento: dati di accelerometro grezzi, dati di giroscopio grezzo, dati grezzi del magnetometro e dati di movimento del dispositivo elaborati (che include accelerometro, velocità di rotazione e misurazioni di assetto). I dati di movimento del dispositivo elaborati forniti dagli algoritmi di fusione del sensore di Core Motion forniscono l'assetto del dispositivo, la velocità di rotazione, i campi magnetici calibrati, la direzione di gravità e l'accelerazione che l'utente sta impartendo al dispositivo.

Importante Un'applicazione deve creare solo una singola istanza della classe CMMotionManager. Istanze multiple di questa classe possono influenzare la velocità con cui i dati vengono ricevuti dall'accelerometro e dal giroscopio. Un'applicazione può adottare uno dei due approcci quando riceve i dati di movimento, gestendola a intervalli di aggiornamento specificati o campionando periodicamente i dati di movimento. Con entrambi questi approcci, l'applicazione deve chiamare il metodo di arresto appropriato (stopAccelerometerUpdates, stopGyroUpdates, stopMagnetometerUpdates e stopDeviceMotionUpdates) quando ha terminato l'elaborazione di dati di accelerometro, velocità di rotazione, magnetometro o movimento del dispositivo.

Distribuendo Proposta aggiornamenti a intervalli specificati Per ricevere i dati di movimento a intervalli specifici, l'applicazione chiama un metodo “start” che prende una coda funzionamento (esempio di NSOperationQueue) ed un gestore blocchi di un tipo specifico di trattamento di questi aggiornamenti. I dati di movimento vengono passati al gestore di blocchi. La frequenza degli aggiornamenti è determinata dal valore di una proprietà "intervallo".

Accelerometro. Impostare la proprietà accelerometerUpdateInterval per specificare un intervallo di aggiornamento. Chiama il metodo startAccelerometerUpdatesToQueue: withHandler: passando un blocco di tipo CMAccelerometerHandler. I dati dell'accelerometro vengono passati nel blocco come oggetti CMAccelerometerData. Giroscopio. Impostare la proprietà gyroUpdateInterval per specificare un intervallo di aggiornamento. Chiama il metodo startGyroUpdatesToQueue: withHandler: passando un blocco di typeCMGyroHandler. I dati di velocità di rotazione vengono passati nel blocco come oggetti CMGyroData. Magnetometro.Impostare la proprietà magnetometerUpdateInterval per specificare un intervallo di aggiornamento. Chiama il metodo startMagnetometerUpdatesToQueue: withHandler: passando un blocco di tipo CMMagnetometerHandler. I dati del campo magnetico vengono passati nel blocco come oggetti CMMagnetometerData. Movimento del dispositivo. Impostare la proprietà deviceMotionUpdateInterval per specificare un intervallo di aggiornamento. Chiama o startDeviceMotionUpdatesUsingReferenceFrame: toQueue: withHandler: o startDeviceMotionUpdatesToQueue: withHandler: metodo, passando un blocco di tipo CMDeviceMotionHandler. Con il metodo precedente (nuovo in iOS 5.0), è possibile specificare un frame di riferimento da utilizzare per le stime di atteggiamento. I dati di velocità di rotazione vengono passati nel blocco come oggetti CMDeviceMotion. Campionamento periodico dei dati di movimento Per gestire i dati di movimento mediante campionamento periodico, l'applicazione chiama un metodo di "avvio" senza argomenti e accede periodicamente ai dati di movimento di una proprietà per un dato tipo di dati di movimento. Questo approccio è l'approccio consigliato per applicazioni come i giochi. La gestione dei dati dell'accelerometro in un blocco introduce un sovraccarico aggiuntivo e la maggior parte delle applicazioni di gioco è interessata solo all'ultimo campione di dati di movimento durante il rendering di un frame.

Accelerometro. Chiama startAccelerometerAggiorna per avviare gli aggiornamenti e accedere periodicamente agli oggetti CMAccelerometerData leggendo la proprietà accelerometerData. Giroscopio. Chiama startGyroUpdates per iniziare gli aggiornamenti e accedere periodicamente agli oggetti CMGyroData leggendo la proprietà gyroData. Magnetometro. Call startMagnetometerUpdates per iniziare gli aggiornamenti e accedere periodicamente agli oggetti CMMagnetometerData leggendo la proprietà magnetometerData. Movimento del dispositivo. Chiama il metodo startDeviceMotionUpdatesUsingReferenceFrame: o startDeviceMotionUpdates per avviare gli aggiornamenti e accedere periodicamente agli oggetti CMDeviceMotion leggendo la proprietà deviceMotion. Il metodo startDeviceMotionUpdatesUsingReferenceFrame: (nuovo in iOS 5.0) consente di specificare un fotogramma di riferimento da utilizzare per le stime di atteggiamento.

A proposito di raccolta dei dati:

@property(readonly) CMGyroData *gyroData 

Discussione Se non ci sono dati giroscopio è disponibile, il valore di questa proprietà è pari a zero. Un'applicazione che riceve i dati del giroscopio dopo aver chiamato startGyroUpdates verifica periodicamente il valore di questa proprietà ed elabora i dati del giroscopio.

Così si dovrebbe avere qualcosa di simile

gyroData.rotationRate.x 
gyroData.rotationRate.y 
gyroData.rotationRate.z 

memorizzando loro e confrontando periodicamente si dovrebbe essere in grado di vedere se il dispositivo capovolto attorno ad un asse, ecc

+0

ya Ho letto la documentazione, e il campione che hai dato è lo stesso che ho postato. la mia domanda è la stessa, come ottenere informazioni sulla rotazione da questi valori x y z. –

+0

nella documentazione che ho citato, si dice che è necessario memorizzare i valori x, y, z quindi confrontarlo frequentemente per vedere se cambiano. in base a questo cambiamento si vede se c'è stata una rotazione o meno. – moxy

+0

ad esempio: quando l'applicazione è stata lanciata, avevi x = 20, y = 3, z = 40. Li memorizzi in variabili referenceX, referenceY e referenceZ, quindi controlli gyroData.rotationRate.x, yez con aggiornamenti frequenti, probabilmente scoprirai piccole variazioni e quindi qualcosa come x = 30, y = 170, z = 10 quindi deduci che iPhone è stato capovolto sull'asse y (meglio mettere un margine di errore, non solo di 180 gradi.x, y e z sono l'asse tridimensionale ed è guardando come cambiano (monitorandoli e aggiornandoli periodicamente) – moxy

1

Quello che stai tentando non è banale, ma è certamente possibile. Questo video dovrebbe essere molto utile per comprendere le capacità del dispositivo e come avvicinarsi al tuo obiettivo: http://www.youtube.com/watch?v=C7JQ7Rpwn2k

Mentre parla di Android, gli stessi concetti si applicano a iPhone.

+0

sicuramente alcune buone informazioni in quel video ma ancora lontane da una risposta. ma penso che la mia risposta potrebbe essere per molto questa citazione riassume cosa intendo "Gli sviluppatori di applicazioni che desiderano dare un senso al movimento rotazionale devono padroneggiare gli angoli di Eulero, le matrici di rotazione ei quaternioni. per creare descrizioni reattive, accurate e silenziose del movimento. " –

+0

Devi capire le capacità del dispositivo e come usarlo. Alcuni aspetti di CoreMotion utilizzano già la fusione di sensori per fornire dati ad alta fedeltà, non è questo il problema. Come utilizzare i dati forniti dal dispositivo per descrivere il movimento in 3 dimensioni, questo è ciò che devi risolvere. Quello che stai cercando di implementare è l'equivalente di un'unità di misura inerziale, che non è banale sul dispositivo. Devi decidere quanto vicino a un IMU/INS è "abbastanza buono" per i tuoi scopi. Nel video parla di questo. Il filtro di Kalman può aiutare, ma potrebbe non soddisfare le tue esigenze. – quellish

0

Tutto dipende su iPhone posizione. Supponiamo che, se il telefono viene ruotato di 360 attorno all'asse y, la bussola non cambierà perché continuerà a puntare nello stesso modo durante il flip. E non è solo questo. Il mio suggerimento è di registrare l'accelerometro e confrontare i dati raccolti con il movimento effettuato, quindi identificare le fasi del trucco e creare un elenco di fasi per ogni trucco.

+0

ya è piuttosto raro tutti questi valori che si aggiornano così frequentemente. in più io non capisco perché come il mio esempio mostra sto interrogando il giroscopio ma sembra che ci sia una forza di gravità applicata che non capisco. il che significa che lanciare il telefono velocemente o lentamente ha una lettura diversa, il che non dovrebbe essere il caso se è solo un giroscopio –

0

Allora forse quello che stai cercando è solo l'orientamento del dispositivo. Dovresti guardare lo UIDevice Class Reference. In particolare il

– beginGeneratingDeviceOrientationNotifications 
– endGeneratingDeviceOrientationNotifications 

metodi.

e usarlo in questo modo:

[UIDevice currentDevice].orientation 

Otterrete in cambio questi valori possibili:

typedef enum { 
    UIDeviceOrientationUnknown, 
    UIDeviceOrientationPortrait, 
    UIDeviceOrientationPortraitUpsideDown, 
    UIDeviceOrientationLandscapeLeft, 
    UIDeviceOrientationLandscapeRight, 
    UIDeviceOrientationFaceUp, 
    UIDeviceOrientationFaceDown 
} UIDeviceOrientation; 

così sarete in grado di verificare se è in modalità ritratto (su o giù) o orizzontale (sinistra o destra) e se è stato capovolto.

Sarete in grado di implementare i seguenti metodi:

- willRotateToInterfaceOrientation 
- didRotateToInterfaceOrientation 

Si può guardare in this link per verificare come è possibile implementare i metodi.

Problemi correlati