Как мне рассчитать 3 оси «мировых координат» от движения устройства?

У меня возникают проблемы с преобразованием данных движения устройства в мировые координаты.

Я искал матрицы вращения и проекции и кватернион, но CMAttitude ( roll , pitch , yaw ) – это то, где было больше всего успеха с использованием gravity.y & gravity.z чтобы найти ориентацию устройства вокруг той же оси, что и pitch .

Конечный результат, который я ищу, – это усиленная / виртуальная реальность, когда пользователь ищет объекты 2D-игры вокруг центральной точки.

Я бы не использовал углы Эйлера (рулон, шаг, рыскание). Это довольно сильно придает устойчивость вашему приложению, вот почему: Странное поведение с сенсором ориентации Android .

Я бы использовал матрицы вращения. Они расскажут вам, как перейти от координат устройства к мировым координатам и наоборот. Вы можете найти их полезными:

  • Теоретическое введение
  • Руководство разработчика, см. RotationMatrix

В настоящее время я работаю над приложением на основе наклона и думаю, что поделюсь тем, что нашел. Этот код преобразуется из кватерниона в Euler (выглядит как XYX, ZYZ) и Tait-Bryan углы (выглядит как XYZ или ZYX), хотя я сам использовал только теат-Брайан. После угадывания и проверки по углам Тайта-Брайана я обнаружил, что ZXY отлично работает для моих целей.

Вот ссылка: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/

И вот код:

 /////////////////////////////// // Quaternion to Euler /////////////////////////////// enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx}; void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){ res[0] = atan2( r11, r12 ); res[1] = acos ( r21 ); res[2] = atan2( r31, r32 ); } void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){ res[0] = atan2( r31, r32 ); res[1] = asin ( r21 ); res[2] = atan2( r11, r12 ); } void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq) { switch(rotSeq){ case zyx: threeaxisrot( 2*(qx*qy + qw*qz), qw*qw + qx*qx - qy*qy - qz*qz, -2*(qx*qz - qw*qy), 2*(qy*qz + qw*qx), qw*qw - qx*qx - qy*qy + qz*qz, res); break; case zyz: twoaxisrot( 2*(qy*qz - qw*qx), 2*(qx*qz + qw*qy), qw*qw - qx*qx - qy*qy + qz*qz, 2*(qy*qz + qw*qx), -2*(qx*qz - qw*qy), res); break; case zxy: threeaxisrot( -2*(qx*qy - qw*qz), qw*qw - qx*qx + qy*qy - qz*qz, 2*(qy*qz + qw*qx), -2*(qx*qz - qw*qy), qw*qw - qx*qx - qy*qy + qz*qz, res); break; case zxz: twoaxisrot( 2*(qx*qz + qw*qy), -2*(qy*qz - qw*qx), qw*qw - qx*qx - qy*qy + qz*qz, 2*(qx*qz - qw*qy), 2*(qy*qz + qw*qx), res); break; case yxz: threeaxisrot( 2*(qx*qz + qw*qy), qw*qw - qx*qx - qy*qy + qz*qz, -2*(qy*qz - qw*qx), 2*(qx*qy + qw*qz), qw*qw - qx*qx + qy*qy - qz*qz, res); break; case yxy: twoaxisrot( 2*(qx*qy - qw*qz), 2*(qy*qz + qw*qx), qw*qw - qx*qx + qy*qy - qz*qz, 2*(qx*qy + qw*qz), -2*(qy*qz - qw*qx), res); break; case yzx: threeaxisrot( -2*(qx*qz - qw*qy), qw*qw + qx*qx - qy*qy - qz*qz, 2*(qx*qy + qw*qz), -2*(qy*qz - qw*qx), qw*qw - qx*qx + qy*qy - qz*qz, res); break; case yzy: twoaxisrot( 2*(qy*qz + qw*qx), -2*(qx*qy - qw*qz), qw*qw - qx*qx + qy*qy - qz*qz, 2*(qy*qz - qw*qx), 2*(qx*qy + qw*qz), res); break; case xyz: threeaxisrot( -2*(qy*qz - qw*qx), qw*qw - qx*qx - qy*qy + qz*qz, 2*(qx*qz + qw*qy), -2*(qx*qy - qw*qz), qw*qw + qx*qx - qy*qy - qz*qz, res); break; case xyx: twoaxisrot( 2*(qx*qy + qw*qz), -2*(qx*qz - qw*qy), qw*qw + qx*qx - qy*qy - qz*qz, 2*(qx*qy - qw*qz), 2*(qx*qz + qw*qy), res); break; case xzy: threeaxisrot( 2*(qy*qz + qw*qx), qw*qw - qx*qx + qy*qy - qz*qz, -2*(qx*qy - qw*qz), 2*(qx*qz + qw*qy), qw*qw + qx*qx - qy*qy - qz*qz, res); break; case xzx: twoaxisrot( 2*(qx*qz - qw*qy), 2*(qx*qy + qw*qz), qw*qw + qx*qx - qy*qy - qz*qz, 2*(qx*qz + qw*qy), -2*(qx*qy - qw*qz), res); break; default: std::cout << "Unknown rotation sequence" << std::endl; break; } } 
Давайте будем гением компьютера.