Per favore, sopportare la mia lunga domanda, sto cercando di renderlo il più chiaro possibile.Utilizzo di quaternion anziché roll, pitch e imbardata per tracciare il movimento del dispositivo
Quello che sto cercando di fare è ottenere l'assetto (roll-and-roll) quando una foto viene scattata usando la fotocamera e quindi salvare i valori di atteggiamento su nsuserdefaults. Dopo il salvataggio, l'orientamento viene modificato e quindi si tenta di portare il telefono nello stesso atteggiamento in cui è stata scattata la foto confrontando costantemente i valori di assetto (salvati e correnti).
Ai fini dell'interfaccia, l'interfaccia utente ha 3 punti (uno per ciascun parametro di atteggiamento) sullo schermo che guidano verso l'orientamento corretto della foto. Al raggiungimento dell'atteggiamento corretto, la bandiera della partita viene mostrata sullo schermo.
Mi è stato trovare i valori di rollio, beccheggio e imbardata come:
CMQuaternion quat = self.motionManager.deviceMotion.attitude.quaternion;
myRoll = radiansToDegrees(atan2(2*(quat.y*quat.w - quat.x*quat.z), 1 - 2*quat.y*quat.y - 2*quat.z*quat.z)) ;
myPitch = radiansToDegrees(atan2(2*(quat.x*quat.w + quat.y*quat.z), 1 - 2*quat.x*quat.x - 2*quat.z*quat.z));
myYaw = radiansToDegrees(2*(quat.x*quat.y + quat.w*quat.z));
Quando ho notato che c'è una certa disparità nei valori di imbardata, ho cercato e poteva trovare da qui: link, che
yaw, pitch and roll from a quaternion you will have the same problem as if you were using just yaw, pitch and roll. You have to use quaternions EVERYWHERE in your code and forget about yaw, pitch and roll
Quindi ora devo indovinare tutto di nuovo ... Per favore, potresti essere così gentile da indicarmi un codice di esempio per l'utilizzo di Quaternion per questo scopo?
Ecco il codice Sto lavorando su:
Nel ViewController.m, all'interno dell'immagine: didFinishSavingWithError:
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
CMQuaternion quat = self.motionManager.deviceMotion.attitude.quaternion;
double tempYaw = radiansToDegrees(asin(2*(quat.x*quat.y + quat.w*quat.z)));
double tempRoll = radiansToDegrees(atan2(2*(quat.y*quat.w - quat.x*quat.z), 1 - 2*quat.y*quat.y - 2*quat.z*quat.z)) ;
double tempPitch = radiansToDegrees(atan2(2*(quat.x*quat.w + quat.y*quat.z), 1 - 2*quat.x*quat.x - 2*quat.z*quat.z));
if (savingGyroOrientation == YES) {
NSLog(@"Roll = %f degrees",tempRoll);
NSLog(@"Pitch = %f degrees",tempPitch);
NSLog(@"Yaw = %f degrees",tempYaw);
[self.deviceStatus setDouble:tempRoll forKey:@"DeviceRoll"];
[self.deviceStatus setDouble:tempPitch forKey:@"DevicePitch"];
[self.deviceStatus setDouble:tempYaw forKey:@"DeviceYaw"];
[self.deviceStatus synchronize];
savingGyroOrientation = NO;
checkingGyroOrientation = YES;
self.savingLabel.hidden = YES;
self.startTimerButton.hidden = NO;
}
savingGyroOrientation = NO;
checkingGyroOrientation = YES;
self.savingLabel.hidden = YES;
self.startTimerButton.hidden = NO;
}
if (timerRunning == YES) {
if (checkingGyroOrientation == YES) {
self.takePicButton.hidden = YES;
int xRoll, yPitch, xYaw, yYaw;
// Roll Checking
if (tempRoll >= [self.deviceStatus doubleForKey:@"DeviceRoll"]-1 && tempRoll <= [self.deviceStatus doubleForKey:@"DeviceRoll"]+1) {
[self.rollDot setFrame:CGRectMake(150, 195, 20, 20)];
self.rollToR.hidden = YES;
self.rollToL.hidden = YES;
self.rollDot.hidden = NO;
rollOk = YES;
}else{
rollOk = NO;
self.rollDot.hidden = YES;
self.rollToR.hidden = NO;
self.rollToL.hidden = NO;
if (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"] < 0) {
xRoll = 150 + (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"]);
self.rollToR.hidden = YES;
if (xRoll <= 0) {
[self.rollToL setFrame:CGRectMake(0, 195, 20, 20)];
}else if (xRoll>= 300){
[self.rollToL setFrame:CGRectMake(300, 195, 20, 20)];
}else{
[self.rollToL setFrame:CGRectMake(xRoll, 195, 20, 20)];
}
}
if (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"] > 0){
xRoll = 150 + (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"]);
self.rollToL.hidden = YES;
if (xRoll <= 0) {
[self.rollToR setFrame:CGRectMake(0, 195, 20, 20)];
}else if (xRoll>=300){
[self.rollToR setFrame:CGRectMake(300, 195, 20, 20)];
}else{
[self.rollToR setFrame:CGRectMake(xRoll, 195, 20, 20)];
}
}
if (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"] > 180){
xRoll = 150 + (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"]-360);
self.rollToR.hidden = YES;
if (xRoll <= 0) {
[self.rollToL setFrame:CGRectMake(0, 195, 20, 20)];
}else if (xRoll>=300){
[self.rollToL setFrame:CGRectMake(300, 195, 20, 20)];
}else{
[self.rollToL setFrame:CGRectMake(xRoll, 195, 20, 20)];
}
}
if (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"] < -180){
xRoll = 150 + (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"]+360);
self.rollToL.hidden = YES;
if (xRoll <= 0) {
[self.rollToR setFrame:CGRectMake(0, 195, 20, 20)];
}else if (xRoll >= 300){
[self.rollToR setFrame:CGRectMake(300, 195, 20, 20)];
}else{
[self.rollToR setFrame:CGRectMake(xRoll, 195, 20, 20)];
}
}
}
//Pitch Checking
if (tempPitch >= [self.deviceStatus doubleForKey:@"DevicePitch"]-1 && tempPitch <= [self.deviceStatus doubleForKey:@"DevicePitch"]+1) {
[self.pitchDot setFrame:CGRectMake(150, 195, 20, 20)];
self.pitchDot.hidden = NO;
self.pitchToDown.hidden = YES;
self.pitchToUp.hidden = YES;
pitchOk = YES;
}else{
pitchOk = NO;
self.pitchDot.hidden = YES;
self.pitchToDown.hidden = NO;
self.pitchToUp.hidden = NO;
if (tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"] < 0) {
yPitch = 195+(tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"]);
// NSLog(@"tempPitch is %0.02f Difference is %0.02f, yPitch is %0.02f",tempPitch, tempPitch-[self.deviceStatus doubleForKey:@"DevicePitch"],195+(tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"]));
self.pitchToDown.hidden = YES;
if (yPitch <= 0) {
[self.pitchToUp setFrame:CGRectMake(150, 0, 20, 20)];
}else if (yPitch >= 390) {
[self.pitchToUp setFrame:CGRectMake(150, 390, 20, 20)];
}else{
[self.pitchToUp setFrame:CGRectMake(150, yPitch, 20, 20)];
}
}
if (tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"] > 0){
yPitch = 195+(tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"]);
// NSLog(@"tempPitch is %0.02f Difference is %0.02f, yPitch is %0.02f",tempPitch, tempPitch-[self.deviceStatus doubleForKey:@"DevicePitch"],195+(tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"]));
self.pitchToUp.hidden = YES;
if (yPitch <= 0) {
[self.pitchToDown setFrame:CGRectMake(150, 0, 20, 20)];
}else if (yPitch >= 390) {
[self.pitchToDown setFrame:CGRectMake(150, 390, 20, 20)];
}else{
[self.pitchToDown setFrame:CGRectMake(150, yPitch, 20, 20)];
}
}
if (tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"] < -180){
yPitch = 195+tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"] + 360;
// NSLog(@"tempPitch is %0.02f Difference is %0.02f, yPitch is %0.02f",tempPitch, tempPitch-[self.deviceStatus doubleForKey:@"DevicePitch"],195+(tempPitch - [self.deviceStatus doubleForKey:@"DevicePitch"]));
// NSLog(@"*yPitch is %d",yPitch);
self.pitchToUp.hidden = YES;
self.pitchToDown.hidden = NO;
if (yPitch <= 0) {
[self.pitchToDown setFrame:CGRectMake(150, 0, 20, 20)];
}else if (yPitch >= 390) {
[self.pitchToDown setFrame:CGRectMake(150, 390, 20, 20)];
}else{
[self.pitchToDown setFrame:CGRectMake(150, yPitch, 20, 20)];
}
}
}
if (tempYaw >= [self.deviceStatus doubleForKey:@"DeviceYaw"]-2 && tempYaw <= [self.deviceStatus doubleForKey:@"DeviceYaw"]+2) {
[self.yawDot setFrame:CGRectMake(150, 195, 20, 20)];
self.yawDot.hidden = NO;
self.rotateRight.hidden = YES;
self.rotateLeft.hidden = YES;
yawOk = YES;
}else{
yawOk = NO;
self.yawDot.hidden = YES;
self.rotateRight.hidden = NO;
self.rotateLeft.hidden = NO;
if (tempYaw - [self.deviceStatus doubleForKey:@"DeviceYaw"] < 0) {
xYaw = 150+(tempYaw - [self.deviceStatus doubleForKey:@"DeviceYaw"]);
yYaw = 195-1.3*(tempYaw - [self.deviceStatus doubleForKey:@"DeviceYaw"]);
NSLog(@"current yaw is %0.02f Difference is %0.02f",tempYaw, tempYaw-[self.deviceStatus doubleForKey:@"DeviceYaw"]);
NSLog(@"saved Yaw is %0.02f",[self.deviceStatus doubleForKey:@"DeviceYaw"]);
NSLog(@"xYaw is %d, yYaw is %d",xYaw,yYaw);
self.rotateRight.hidden = YES;
if (xYaw <=0 && yYaw >=390) {
[self.rotateLeft setFrame:CGRectMake(0, 390, 20, 20)];
}else{
[self.rotateLeft setFrame:CGRectMake(xYaw, yYaw, 20, 20)];
}
}if (tempYaw - [self.deviceStatus doubleForKey:@"DeviceYaw"] > 0){
xYaw = 150+(tempYaw - [self.deviceStatus doubleForKey:@"DeviceYaw"]);
yYaw = 195-1.3*(tempYaw - [self.deviceStatus doubleForKey:@"DeviceYaw"]);
NSLog(@"current yaw is %0.02f Difference is %0.02f",tempYaw, tempYaw-[self.deviceStatus doubleForKey:@"DeviceYaw"]);
NSLog(@"saved Yaw is %0.02f",[self.deviceStatus doubleForKey:@"DeviceYaw"]);
NSLog(@"*xYaw is %d, yYaw is %d",xYaw,yYaw);
self.rotateLeft.hidden = YES;
if (xYaw >=300 && yYaw <=0) {
[self.rotateRight setFrame:CGRectMake(300, 0, 20, 20)];
}else{
[self.rotateRight setFrame:CGRectMake(xYaw, yYaw, 20, 20)];
}
}
}
if (rollOk == YES && pitchOk == YES && yawOk ==YES) {
self.orientationOkay.hidden = NO;
self.centerCircle.hidden = YES;
self.rollDot.hidden = YES;
self.pitchDot .hidden =YES;
self.yawDot.hidden = YES;
[self.clickTimer invalidate];
self.clickTimer = nil;
self.takePicButton.hidden = NO;
timerRunning = NO;
[self.motionManager stopDeviceMotionUpdates];
[self.deviceStatus removeObjectForKey:@"DeviceRoll"];
[self.deviceStatus removeObjectForKey:@"DevicePitch"];
[self.deviceStatus removeObjectForKey:@"DeviceYaw"];
[self.deviceStatus removeObjectForKey:@"DeviceAngle"];
}else{
self.orientationOkay.hidden = YES;
if (flagger == YES) {
self.centerCircle.hidden = NO;
}
else{
self.centerCircle.hidden = YES;
}
}
}
}else{
self.rotateRight.hidden = YES;
self.rotateLeft.hidden = YES;
self.rollToL.hidden = YES;
self.rollToR.hidden = YES;
self.pitchToDown.hidden = YES;
self.pitchToUp.hidden = YES;
self.rollDot.hidden = NO;
self.pitchDot .hidden =NO;
self.yawDot.hidden = NO;
[self.yawDot setFrame:CGRectMake(0, 390, 20, 20)];
[self.rollDot setFrame:CGRectMake(0, 195, 20, 20)];
[self.pitchDot setFrame:CGRectMake(150, 0, 20, 20)];
}
}];
prega fatemi sapere se sono necessari ulteriori dettagli su questo.
Qualsiasi suggerimento o consiglio è sempre il benvenuto, :) Sono un noob alla programmazione e aios.
Grazie !!
Volevo solo farti sapere, nelle definizioni dei quaternioni, che hai attivato Roll and Yaw. La formula per il rotolo è per imbardata e la formula per l'imbardata è per rotolo. – inorganik