Ответ 1
Я тестировал это и, похоже, работал в соответствии с тем, что вы ищете в вопросе 1, Андрей.
Я устанавливаю homeangle изначально 0, и сразу после первого прохода я сохраняю угол, возвращаемый из walkaroundAngleFromAttitude: fromHomeAngle: в homeangle, для будущего использования.
Мой тестировании включены начиная обновления устройств с использованием опорного кадра:
[_motionManager
startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical
toQueue:operationQueue
withHandler:handler];
и используя следующие методы, вызываемые в обработчике:
- (CMQuaternion) multiplyQuanternion:(CMQuaternion)left withRight:(CMQuaternion)right {
CMQuaternion newQ;
newQ.w = left.w*right.w - left.x*right.x - left.y*right.y - left.z*right.z;
newQ.x = left.w*right.x + left.x*right.w + left.y*right.z - left.z*right.y;
newQ.y = left.w*right.y + left.y*right.w + left.z*right.x - left.x*right.z;
newQ.z = left.w*right.z + left.z*right.w + left.x*right.y - left.y*right.x;
return newQ;
}
-(float)walkaroundRawAngleFromAttitude:(CMAttitude*)attitude {
CMQuaternion e = (CMQuaternion){0,0,1,1};
CMQuaternion quatConj = attitude.quaternion;
quatConj.x *= -1; quatConj.y *= -1; quatConj.z *= -1;
CMQuaternion quat1 = attitude.quaternion;
CMQuaternion quat2 = [self multiplyQuanternion:quat1 withRight:e];
CMQuaternion quat3 = [self multiplyQuanternion:quat2 withRight:quatConj];
return atan2f(quat3.y, quat3.x);
}
-(float)walkaroundAngleFromAttitude:(CMAttitude*)attitude fromHomeAngle:(float)homeangle {
float rawangle = [self walkaroundRawAngleFromAttitude:attitude];
if (rawangle <0) rawangle += M_PI *2;
if (homeangle < 0) homeangle += M_PI *2;
float finalangle = rawangle - homeangle;
if (finalangle < 0) finalangle += M_PI *2;
return finalangle;
}
Это использует некоторый модифицированный и расширенный код из Поиск нормального вектора для устройства iOS
Изменить для решения вопросов 2 и 2:
Это может быть не разрешимо. Я видел это в других приложениях (например, 360 pano) и читал о ошибочных показаниях в гироскопах и т.д. Если вы попытаетесь компенсировать это, вы, конечно, столкнетесь с неудовлетворительным опытом, когда какое-то подлинное вращательное движение будет зависеть от кода компенсации. Насколько я интерпретировал последние несколько лет, это проблема аппаратного обеспечения.