Реверсивный RotateAxisAngle обратно на углы

Я пытаюсь выяснить, как повернуть RotateAxisAngle, чтобы вернуть вращение вокруг этих произвольных осей (или эквивалентные вращения, которые дают одинаковое чистое вращение, не должны быть идентичными). кто нибудь знает как это сделать? Я использую MathGeoLib, но я не вижу обратного пути, чтобы вернуть углы вокруг осей, когда у вас есть только матрица.

Вот код прямого направления (RotateAxisAngle от MathGeoLib):

float4x4 matrixRotation = float4x4::RotateAxisAngle(axisX, ToRadian(rotation.x));
matrixRotation = matrixRotation * float4x4::RotateAxisAngle(axisY, ToRadian(rotation.y));
matrixRotation = matrixRotation * float4x4::RotateAxisAngle(axisZ, ToRadian(rotation.z));

Теперь я хочу вернуться к градусам, относительно этих произвольных осей, в том же порядке (ну, оттяните Z, затем Y, затем X), так что, если бы я сделал это снова, направление вперед получило бы те же чистые вращения.

Вот пример / матрица, соответствующая тому набору вращений, который я выложил выше, если это поможет, при возврате к нему:

axisX:
x   0.80878228  float
y   -0.58810818 float
z   0.00000000  float
Rot about that axis:
30.000000   float

axisY:
x   0.58811820  float
y   0.80877501  float
z   0.00000000  float
Rot about that axis:
60.000000   float

axisZ:
x   0.00000000  float
y   0.00000000  float
z   1.0000000   float
Rot about that axis:
40.000000   float

Это формирует эту матрицу, которая хранится в файле и должна извлекать вращения вокруг вышеуказанных осей (без какой-либо информации о первоначально использованных вращениях)

[4][4]
[0x0]   0.65342271  float
[0x1]   -0.51652151 float
[0x2]   0.55339342  float
[0x3]   0.00000000  float
[0x0]   0.69324547  float
[0x1]   0.11467478  float
[0x2]   -0.71151978 float
[0x3]   0.00000000  float
[0x0]   0.30405501  float
[0x1]   0.84856069  float
[0x2]   0.43300733  float
[0x3]   0.00000000  float
[0x0]   0.00000000  float
[0x1]   0.00000000  float
[0x2]   0.00000000  float
[0x3]   1.0000000   float

1

Решение

Хорошо, я собираюсь сделать еще один удар в этом. Мой первый ответ был для XYZ порядка вращения. Этот ответ для заказа ZYX, теперь, когда я знаю больше о том, как работает MathGeoLib.

MathGeoLib представляет векторы положения как векторы столбцов v = [x y z 1]^T где ^T это оператор транспонирования, который переворачивает строки в столбцы (и наоборот). Матрицы вращения предварительно умножают векторы столбцов. Так что, если у нас есть матрица Rx(s) представляет вращение вокруг оси х на s градусов, затем вращение Ry(t) представляет вращение вокруг оси Y на t градусов, затем вращение Rz(u) представляющий вращение вокруг оси z на u градусов, и мы объединяем их и умножаем на v как Rx(s) Ry(t) Rz(u) vмы на самом деле применяем вращение z первым. Но мы все еще можем определить углы из объединенной матрицы, просто формулы будут отличаться от более распространенного порядка XYZ.

У нас есть верхние левые блоки матриц вращения следующим образом. (Четвертая строка и столбец — все 0, за исключением диагонального элемента, который равен 1; он никогда не меняется в последующих вычислениях, поэтому мы можем спокойно его игнорировать.) MathGeoLib, похоже, использует левосторонние координаты, поэтому матрицы вращения:

        [1      0      0]          [ cos t  0  sin t]          [ cos u -sin u  0]
Rx(s) = [0  cos s -sin s], Ry(t) = [     0  1      0], Rz(u) = [ sin u  cos u  0]
[0  sin s  cos s]          [-sin t  0  cos t]          [     0      0  1]

(Обратите внимание на положение — войти в Ry(t); это там, потому что мы думаем о координатах в циклическом порядке. Rx(s) вращается y и z; Ry(t) вращается z и x; Rz(u) вращается х и у. поскольку Ry(t) вращает z и x не в алфавитном порядке, а в циклическом порядке, вращение противоположно направлению, которое вы ожидаете для алфавитного порядка.

Теперь мы умножим матрицы в правильном порядке. Rx(s) Ry(t) является

[1      0      0][ cos t  0  sin t]   [       cos t      0        sin t]
[0  cos s -sin s][     0  1      0] = [ sin s*sin t  cos s -sin s*cos t]
[0  sin s  cos s][-sin t  0  cos t]   [-cos s*sin t  sin s  cos s*cos t]

Продукт этого с Rz(u) является

[       cos t      0        sin t][ cos u -sin u  0]
[ sin s*sin t  cos s -sin s*cos t][ sin u  cos u  0] =
[-cos s*sin t  sin s  cos s*cos t][     0      0  1]

[                   cos t*cos u                   -cos t*sin u        sin t]
[ sin s*sin t*cos u+cos s*sin u -sin s*sin t*sin u+cos s*cos u -sin s*cos t]
[-cos s*sin t*cos u+sin s*sin u  cos s*sin t*sin u+sin s*cos u  cos s*cos t]

Таким образом, мы можем выяснить углы следующим образом:

tan s = -(-sin s * cos t)/(cos s * cos t) = M23/M33 => s = -arctan2(M23,M33)
sin t = M13 => t = arcsin(M13)
tan u = -(-cos t * sin u)/(cos t * cos u) = M12/M11 => u = -arctan2(M12,M11)

Если мы хотим реализовать эти вычисления, нам нужно понять, как матрица индексируется в MathGeoLib. Индексация является основной строкой, точно так же как математическая запись, но индексация начинается с 0 (компьютерный стиль), а не с 1 (математический стиль), поэтому формулы C ++, которые вам нужны,

s = -atan2(M[1][2],M[2][2]);
t = asin(M[0][2]);
u = -atan2(M[0][1],M[0][0]);

Углы возвращаются в радианах, поэтому при желании их необходимо преобразовать в градусы. Вы должны проверить этот результат в случае, когда оси для поворотов Z, Y и X находятся в стандартном положении (001), (010) и (100).

Если мы хотим повернуть вращение вокруг нестандартных осей, как в вашем примере, проблема становится более сложной. Тем не менее, я думаю, что это может быть сделано путем «изменения координат». Так что, если наша матрица тайны вращения matrixRotationЯ полагаю, вы можете просто сформировать «сопряженную» матрицу

M = coordinateChangeMatrix*matrixRotation*coordinateChangeMatrix^{-1}

а затем используйте приведенные выше формулы. Вот coordinateChangeMatrix будет матрица

[Xaxis0 Xaxis1 Xaxis2 0]
[Yaxis0 Yaxis1 Yaxis2 0]
[Zaxis0 Zaxis1 Zaxis2 0]
[     0      0      0 1]

где ось X вращения (Xaxis0,Xaxis1,Xaxis2), В вашем примере эти цифры будут (0.808...,-0.588...,0), Вы должны убедиться, что матрица вращения является ортонормированной, то есть, произведение точки Xaxis с самим собой равно 1, произведение точки Xaxis с другой осью равно 0, и то же самое для любой другой оси. Если матрица изменения координат не является ортонормированной, вычисление все еще может работать, но я точно не знаю.

Обратная матрица изменения координат может быть рассчитана с помощью float4x4::inverseOrthonormal или если это не ортонормированный вы можете использовать float4x4::inverse но, как я уже говорил, я не знаю, насколько хорошо это будет работать.

0

Другие решения

Если вы просто хотите вращение, обращающее вращение, которое вы получили за один шаг, вы можете инвертировать матрицу вращения. float4x4::InverseOrthonormal должно работать, и это быстро и точно. float4x4::Inverse также будет работать, но это медленнее и менее точно.

Если вы действительно хотите восстановить углы, это происходит примерно так. (Существует множество различных соглашений, даже для X-Y-Z; я думаю, что это соответствует, но вам, возможно, придется взять транспонирование матрицы или сделать какую-то другую модификацию. Если это не сработает, я могу предложить альтернативы.) Сначала мы следуем Статья в википедии для описания преобразования углов Эйлера в матрицу. В полученной матрице имеем

A11 = cos theta cos psi
A21 = -cos theta sin psi
A31 = sin theta
A32 = -sin phi cos theta
A33 = cos phi cos theta

где phi — вращение вокруг оси x, theta — вращение вокруг оси y, а psi — вращение вокруг оси z. Чтобы восстановить углы, мы делаем

phi = -arctan2(A32,A33)
theta = arcsin(A31)
psi = -arctan2(A21,A11)

Углы могут не точно соответствовать исходным углам, но повороты должны совпадать. arctan2 — это форма с двумя аргументами функции arctan, которая учитывает квадрант точки, представленной аргументом, и правильно обрабатывает углы в 90 градусов.

Учитывая способ представления ваших вращений, я думаю, что вам, возможно, придется использовать вместо этого транспонирование. Это просто: вы просто меняете индексы в приведенных выше формулах:

phi = -arctan2(A23,A33)
theta = arcsin(A13)
psi = -arctan2(A12,A11)

Если ни одна из этих работ не работает, я мог бы ближе взглянуть на библиотеку MathGeoLib и выяснить, что они делают.

Обновить

Я не учел информацию об осях вращения в моем предыдущем ответе. Теперь я думаю, что у меня есть план борьбы с ними.

Идея состоит в том, чтобы «изменить координаты», а затем выполнить операции, как указано выше, в новых координатах. Я немного запутан в деталях, поэтому процесс немного «алхимический» в данный момент. ОП должен попробовать различные комбинации моих предложений и посмотреть, работает ли какое-либо из них … их не слишком много (всего 4 … на данный момент).

Идея состоит в том, чтобы сформировать матрица изменения координат используя координаты осей вращения. Мы делаем это так:

axisX: 0.80878228 -0.58810818 0.00000000 0.00000000
axisY: 0.58811820  0.80877501 0.00000000 0.00000000
axisZ: 0.00000000  0.00000000 1.0000000  0.00000000
and..: 0.00000000  0.00000000 0.00000000 1.0000000

Я только что взял три 3-вектора axisX, axisY, axisZ, дополнил их 0 в конце и добавил строку [0 0 0 1] внизу.

Мне также нужна обратная сторона этой матрицы. Поскольку система координат является ортонормированной системой отсчета, обратная — это транспонирование. Вы можете использовать InverseOrthonormal функция в библиотеке; все, что он делает, это формирует транспонирование.

Теперь возьмите свою загадочную матрицу и предварительно умножьте ее на матрицу изменения координат, а затем умножьте ее на обратную матрицу изменения координат. Затем примените одно из двух приведенных выше вычислений с использованием обратных функций триггера. Скрестив пальцы, я думаю это все …

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

Это работает?

0

По вопросам рекламы [email protected]