кватернион ‹-› Эйлер

Я использую C #, и в своей программе я получаю кватернион тела в Quaternions, но ось не соответствует ориентации оси, которую я использую, поэтому я хочу повернуть кватернион. Для этого я конвертирую кватернион в углы Эйлера, переключаю тангаж, рыскание и крен так, чтобы он соответствовал моей системе координат, конвертирую его обратно в кватернионы, а затем генерирую матрицу вращения для преобразования позиций.

Однако что-то идет не так, когда я просто конвертирую один и тот же ввод из кватерниона в эйлер и обратно, я получаю другой кватернион ... поэтому одна из функций делает что-то не так, и я не знаю, где ...

Quaternion q = new Quaternion(-0.4, -0.7, -0.8, 0.5);

double yaw = 0, pitch = 0, roll = 0;
toEuler(q, ref yaw, ref pitch, ref roll);

Quaternion quat = ToQ((float)(yaw), (float)(pitch), (float)(roll));





private void toEuler(Quaternion q, ref double x, ref double y, ref double z)
        {
            double test = q.X * q.Y + q.Z * q.W;
            if (test > 0.499)                            // singularity at north pole
            {
                y = 2.0F * System.Math.Atan2(q.X, q.W);
                z = Math.PI / 2.0F;
                x = 0.0F;
                return;
            }

            if (test < -0.499)                           // singularity at south pole
            {
                y = -2.0F * System.Math.Atan2(q.X, q.W);
                z = -Math.PI / 2.0F;
                x = 0.0F;
                return;
            }

            double sqx = q.X * q.X;
            double sqy = q.Y * q.Y;
            double sqz = q.Z * q.Z;
            y = System.Math.Atan2(2.0F * q.Y * q.W - 2.0 * q.X * q.Z, 1.0F - 2.0 * sqy - 2.0 * sqz);
            z = System.Math.Asin(2.0F * test);
            x = System.Math.Atan2(2.0 * q.X * q.W - 2.0 * q.Y * q.Z, 1.0F - 2.0 * sqx - 2.0 * sqz);
        }

 public Quaternion ToQ(float yaw, float pitch, float roll)
        {
            float rollOver2 = roll * 0.5f;
            float sinRollOver2 = (float)Math.Sin((double)rollOver2);
            float cosRollOver2 = (float)Math.Cos((double)rollOver2);
            float pitchOver2 = pitch * 0.5f;
            float sinPitchOver2 = (float)Math.Sin((double)pitchOver2);
            float cosPitchOver2 = (float)Math.Cos((double)pitchOver2);
            float yawOver2 = yaw * 0.5f;
            float sinYawOver2 = (float)Math.Sin((double)yawOver2);
            float cosYawOver2 = (float)Math.Cos((double)yawOver2);
            Quaternion result = new Quaternion();
            result.W = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
            result.X = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2;
            result.Y = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2;
            result.Z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;

            return result;
        }

person sven    schedule 03.03.2013    source источник


Ответы (3)


Ваш кватернион не кажется нормализованным. Кватернионы, представляющие вращение, должны иметь норму 1.

person Ben    schedule 09.10.2015

Чтобы расширить ответ Бена, нормализуйте кватернион, разделив на квадратный корень из суммы квадратов.

Если вам нужно повернуть кватернион и сохранить его длину, я рекомендую использовать кватернионы для вращения. В Википедии есть отличная страница по этому поводу: https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

person pscheidler    schedule 20.11.2017

Убедитесь, что вы используете те же Ангелы Эйлера для преобразования «в» и «из».

Вы можете найти хороший справочный код на сайте Ken Shoemake http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/

И статья "Преобразование угла Эйлера" Кена Шумейка из серии "Graphics Gems"

person minorlogic    schedule 07.03.2014
comment
По этой ссылке сейчас 404с. Вместо этого, по возможности, предоставьте соответствующую информацию. - person Rebs; 12.02.2016