2014-11-11 26 views
5

Sono un principiante coremotion.Rilevamento movimento iPhone su una superficie piana

Ho bisogno di rilevare il movimento dell'iPhone su una superficie piatta come un tavolo - finora, ho fatto in modo che rilevasse il suo movimento laterale accedendo all'imbardata del giroscopio, ma non riesco a pensare a un modo per rilevare l'up/giù i cambiamenti. Ho provato a utilizzare l'accelerometro, ma rileva più inclinazione del dispositivo rispetto al movimento. Inoltre, c'è una controspinta quando il movimento si ferma.

Avete qualche idea per farlo in modo che sia possibile avere i dati di movimento con la giusta precisione? Ne ho bisogno per qualcosa come la partita di air hockey.

risposta

5

Per determinare la posizione orizzontale dal dispositivo, il movimento non è realmente fattibile. I sensori orizzontali da utilizzare sarebbero gli accelerometri, ma misurano i cambiamenti di velocità. Pertanto, per trovare la posizione da questo, è necessario integrare i dati del sensore due volte. Una volta per ottenere velocità, quindi una seconda volta per ottenere la posizione.

Ciò significa che anche la più piccola inesattezza nei dati di accelerazione causerà un errore nella velocità risultante, il che significa che il tuo programma pensa che il telefono si muova a velocità costante, mentre in realtà è fermo.

Se non è necessario essere precisi (ad esempio, quando non è necessario che ritorni nella stessa posizione quando lo si sposta avanti e indietro), è possibile ottenere risultati accettabili se si forza la velocità a zero se i dati dell'accelerometro sono silenziosi e vicini a zero.

Se si è veramente provati a provare questo, allora uno Kalman filter è probabilmente la soluzione migliore per ricavare velocità e posizione dai dati dell'accelerometro. Ciò significa che il tuo codice alla fine assomiglierà a quanto segue, dove acceleration, speed e position sono tre variabili che mantieni, e acc è un campione di dati dall'accelerometro.

// correction step: 
double delta = (acc - acceleration); 
acceleration += FACTOR1 * delta; 
speed += FACTOR2 * delta; 
position += FACTOR3 * delta; 

// prediction step: 
position = position + speed * DT + 0.5 * acceleration * DT * DT; 
speed = speed + acceleration * DT; 

dove DT è il tempo tra i campioni di dati e valori adatti per FACTOR1..3 hai bisogno di scoprire.

A proposito, Yaw non ti dà movimento orizzontale, ma rotazione.

+0

Ripensamento: potresti ottenere risultati migliori usando la fotocamera frontale e utilizzare l'analisi delle immagini per ricavare il movimento dell'immagine del soffitto ... – fishinear

+0

Ho pensato di usare la fotocamera posteriore, ma questo costringerebbe l'utente a utilizzare custodie per iPhone (altrimenti l'obiettivo è troppo vicino). Grazie per questo post. Ieri ho scoperto la doppia integrazione e me ne occuperò io. Questa mi sembra la risposta più preziosa. Ti farò sapere gli effetti. Grazie! –

1

Questo collegamento può essere in grado di spiegare le cose un po 'più http://blog.denivip.ru/index.php/2013/07/the-art-of-core-motion-in-ios/?lang=en

Sembra che tu abbia bisogno di far salire sul Accelerazione asse Y però. I documenti Apple sembrano coprire abbastanza bene. https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html

Utilizzare i metodi di gestione del movimento per rilevare quando il movimento cambia e quindi accedere alla modifica nella posizione y. Posso provare a fornire del codice se lo desideri.

2

Il dispositivo non è in grado di rilevare il movimento . Un movimento costante rettilineo lungo la superficie del tavolo è assolutamente inosservabile. Questo perché non ci sono forze .

Il dispositivo può rilevare solo atteggiamento (orientamento nello spazio, e cambiamenti in tale orientamento) e forza (aumento o diminuzione della velocità).

Quindi, è necessario formare le vostre aspettative attorno a quelle abilità.

+0

Ok, quindi quello che sto facendo attualmente è 'var ax: Double = data.userAcceleration.x; var ay: Double = data.userAcceleration.y; if ((abs (ax)> 0.05) || (abs (ay)> 0.05)) {// usa i dati} 'e sta sorprendentemente facendo ciò che volevo veramente. Tuttavia, c'è un grosso problema con la reazione inerziale che fondamentalmente mette il giocatore nella posizione in cui si trovava prima che qualsiasi movimento fosse compiuto se il dispositivo smetteva improvvisamente di muoversi. Riesci a pensare a una soluzione che impedirebbe che ciò accada? –

+0

L'unica cosa che posso pensare è di tenere traccia e dedurre quindi, dal fatto che il dispositivo era apparentemente in movimento, che questa decelerazione improvvisa è probabilmente l'arresto del dispositivo, non un'accelerazione che sta riportando il dispositivo a dove si trovava. Anche allora probabilmente starai solo indovinando. – matt

5

Quindi sono abbastanza nuovo per CoreMotion. Darò il mio colpo migliore per spiegare perché quello che chiedi non può essere fatto, almeno non in modo accurato.

Sulla base del Mela Docs ho letto, ci sono 3 gestori di movimento per iOS:

  • accelerometro
  • giroscopio
  • Magnetometro

(credo che i dispositivi più recenti hanno un altimetro ?)

Sulla base della mia comprensione della fisica, ho raccolto quell'accelerometro che Sarebbe molto utile per il tuo scenario, dato che il giroscopio e il magnetometro sono più focalizzati sulla rotazione. Ho fatto qualche ricerca e ho trovato this book. In particolare il capitolo 9.5. Dal libro:

Mentre un accelerometro fornisce misurazione delle forze nelle direzioni x, ye z assi non può misurare rotazioni. D'altra parte, un giroscopio è un dispositivo di velocità di cambiamento; mentre il telefono ruota intorno a un asse, lo consente di misurare la modifica di tali rotazioni.

seguito il proprio codice in figura 9-5 per l'attuazione di una semplice applicazione per guardare l'accelerazione:

#import <UIKit/UIKit.h> 
#import <CoreMotion/CoreMotion.h> 

@interface ViewController : UIViewController { 

    CMMotionManager *motionManager; 
    NSOperationQueue *queue; 
} 


@property (weak, nonatomic) IBOutlet UILabel *xLabel; 
@property (weak, nonatomic) IBOutlet UILabel *yLabel; 
@property (weak, nonatomic) IBOutlet UILabel *zLabel; 

@property (weak, nonatomic) IBOutlet UIProgressView *xBar; 
@property (weak, nonatomic) IBOutlet UIProgressView *yBar; 
@property (weak, nonatomic) IBOutlet UIProgressView *zBar; 

@end 

Poi nel .m viewDidLoad

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    motionManager = [[CMMotionManager alloc] init]; 
    motionManager.accelerometerUpdateInterval = 1.0/10.0; // Update at 10Hz 
    if (motionManager.accelerometerAvailable) { 
     NSLog(@"Accelerometer avaliable"); 
     queue = [NSOperationQueue currentQueue]; 
     [motionManager startAccelerometerUpdatesToQueue:queue 
      withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { 
      CMAcceleration acceleration = accelerometerData.acceleration; 
      xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x]; 
      xBar.progress = ABS(acceleration.x); 

      yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y]; 
      yBar.progress = ABS(acceleration.y); 

      zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z]; 
      zBar.progress = ABS(acceleration.z); 
     }]; 

    } 
} 

Dopo aver collegato tutto installato e funzionante Al telefono, vedo che l'accelerometro misura i cambiamenti del mio telefono accelerando e decelerando mentre lo spostamento su un tavolo piatto. Ora abbiamo l'accelerazione, ma per ottenere il cambio di posizione (che è quello che hai chiesto) da quello richiede una doppia integrazione (es. Calcolo divertente). Mentre fattibile, ho cercato su cosa hanno da dire le persone competenti su arduino su questo here e ragazzo è una notizia triste. (Non stanno discutendo l'accelerometro di iPhone, ma ho estrapolato che questa informazione si applica anche a questa domanda).

Le parti rilevanti che ho postato qui:

Ottenere posizione da accelerazione è una doppia integrazione, in modo da l'errore StackUp è davvero male. Ottenere buoni dati di posizione con un IMU imbullonato verso il basso (cosa si sta tentando di fare) è un problema veramente difficile; il tipo di accelerometro necessario per farlo è molto costoso.

e

cosa si sta parlando è doppia integrazione, che è semplicemente troppo imprecise con un singolo accelerometro su questo hardware. Anche l'integrazione singola avrà un errore crescente per unità di tempo semplicemente a causa di la mancanza di precisione in questa configurazione.

Tutte queste ricerche che conduce fino alla mia conclusione che non è fattibile su un iPhone per fare ciò che si chiede. Anche se come ho detto, anche io sono un principiante! Scusa se questa non è la risposta che volevi sentire.