Преобразование кватерниона IMU Madgwick в положение x, y, z в Unity3D

Я пытаюсь добиться этого и этого, но в Unity3D и с использованием датчика IMU ICM-20948 с 9 степенями свободы:

До сих пор я мог использовать алгоритм Мэджвика и вращать куб, наклоняя датчик в воздухе. Я не знаю, как заставить его двигаться, как указатель мыши. Что я испытываю, так это то, что когда я двигаю датчик вверх и вниз (как бы наклоняя его вверх, как будто это пульт дистанционного управления), кажется, что он работает. Но когда я наклоняю его влево и вправо, это не работает. Также значения быстро меняются от плюса к минусу, в результате чего объект появляется на противоположной стороне экрана - это для x и y. Единственный способ, которым это сработает, - это если я буду двигать его очень легко, но тогда он просто останется в очень небольшом диапазоне. Я хочу иметь возможность перемещать его в любое место на экране.

Вот мой код:

      MadgwickAHRS madgwickAHRS = new MadgwickAHRS(1f / 256f, 0.1f);
madgwickAHRS.Update(gx, gy, gz, ax, ay, az, mx, my, mz); // called in a separate thread loop

float[] angles = ToEuler(madgwickAHRS.Quaternion);

float horzValue = angles[0] - horzZero;
float vertValue = angles[1] - vertZero;

horzZero = angles[0]; // yaw
vertZero = angles[1]; // roll

void FixedUpdate() {
  transform.position = new Vector3(horzValue, vertValue, 0);
}
...

float[] ToEuler(float[] q)
{
  float yaw = (float)Math.Atan2(2.0 * (q[1] * q[2] + q[3] * q[0]), q[3] * q[3] - q[0] * q[0] - q[1] * q[1] + q[2] * q[2]);
  float pitch = (float)Math.Asin(-2.0 * (q[0] * q[2] - q[3] * q[1]));
  float roll = (float)Math.Atan2(2.0 * (q[0] * q[1] + q[3] * q[2]), q[3] * q[3] + q[0] * q[0] - q[1] * q[1] - q[2] * q[2]);

  return new float[2] { yaw, roll };
}

Пытался использовать эту функцию также для каждого значения углов, но это только ухудшает ситуацию.

      private float CalcDist(float angle, float initAngle)
{
 angle = (float)((angle - initAngle) * (180 / Math.PI));
 angle = angle < 0 ? angle + 360 : angle;
 angle = angle > 180 ? angle - 360 : angle;
 float dist = (float)(Math.Round(-offsetDistance * Math.Tan(angle * (Math.PI / 180))));

 return dist;
}

Также попытался использовать исправленный кватернион (кстати, это хорошо работает для вращения):

      Quaternion objectOrientation = new Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
var qEualr = objectOrientation.eulerAngles;
Quaternion correctQuaternion = Quaternion.Euler(qEualr.z, -qEualr.y, qEualr.x);

Может ли кто-нибудь здесь мне помочь?

0 ответов

Другие вопросы по тегам