Использование кватерниона вместо крена, тангажа и рыскания для отслеживания движения устройства
Пожалуйста, примите мой длинный вопрос, я пытаюсь сделать его как можно более понятным.
То, что я пытаюсь сделать, это получить ориентацию (шаг крена и рыскание), когда снимок сделан с помощью камеры, а затем сохранить значения ориентации в nsuserdefaults. После сохранения ориентация меняется, а затем попробуйте привести телефон в то же положение, в котором был сделан снимок, постоянно сравнивая значения положения (сохраненные и текущие).
Для целей интерфейса пользовательский интерфейс имеет 3 точки (по одной для каждого параметра ориентации) на экране, которые указывают правильную ориентацию, на которой был сделан снимок. При достижении правильного положения на экране отображается флаг матча.
Я нашел значения крена, тангажа и рыскания как:
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));
Когда я заметил, что есть некоторые различия в значениях рыскания, я искал и мог найти здесь:ссылка на сайт, тот
рыскание, тангаж и крен от кватерниона, у вас возникнет та же проблема, что и при использовании только рыскания, тангажа и крена. Вы должны использовать кватернионыВЕЗДЕ в вашем коде и забудьте о рыскании
Так что теперь я думаю, что мне нужно снова все кодировать ... Пожалуйста, не могли бы вы указать мне пример кода для использованиякватернион для этого?
Вот код, над которым я работаю:
В ViewController.m, внутри изображения: 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 180){
xRoll = 150 + (tempRoll - [self.deviceStatus doubleForKey:@"DeviceRoll"]-360);
self.rollToR.hidden = YES;
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 = 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