Казалось бы, это должно быть легко, но мне просто не везет.
То, что я хочу сделать, - это использовать базовое движение, чтобы отслеживать, куда направлена камера телефона (для своего рода приложения дополненной реальности). Пользователь указывает телефон на контрольную точку (как будто фотографирует его) и нажимает кнопку, чтобы «выровнять» положение телефона с объектом. Теперь, когда пользователь направляет камеру телефона на другие объекты, мне нужно определить высоту телефона (от -90º до + 90º) и азимут (от 0º до 360º).
Углы Эйлера, заданные CMAttitude, не являются тем, что мне нужно. Я пытался кэшировать CMAttitude, полученный, когда пользователь нажимает «выровнять». Затем, когда пользователь перемещает телефон, я получаю новое значение CMAttitude и использую multiplyByInverseOfAttitude для определения разницы с эталонным отношением.
- (void)checkForMotion {
CMMotionManager *motionMgr = appDelegate.motionMgr;
CMDeviceMotion *deviceMotion = motionMgr.deviceMotion;
CMAttitude *attitude = deviceMotion.attitude;
if (referenceAttitude != nil)
{
[attitude multiplyByInverseOfAttitude: referenceAttitude];
double deltaAlt = attitude.pitch;
double deltaAzm = attitude.roll;
// Do something with deltaAlt and deltaAz
}
else
{
NSLog(@"Getting new referenceAttitude");
self.referenceAttitude = attitude;
}
}
Но это не дает правильных результатов. Если телефон держать вертикально (длинная ось вверх), то deltaAlt работает нормально. Пока телефон направлен на горизонт (alt = 0), deltaAzm также является правильным. Однако, если телефон указывает (скажем) на 45º в небо, то при перемещении телефона по азимуту компонент высоты также изменяется. Они переплетены так, что я не могу понять.
Есть ли какая-то простая математика, которая мне нужна, чтобы дразнить их отдельно? Опять же, я бы подумал, что это будет необходимым требованием для приложения дополненной реальности, но я не смог найти ни одного примера, который бы это делал.