Изменение матрицы с правосторонней на левостороннюю систему координат - PullRequest
25 голосов
/ 12 августа 2009

Я бы хотел изменить матрицу 4x4 для правой системы, где:
х слева и справа, у спереди и сзади, а г вверх и вниз

в левостороннюю систему, где:
x слева и справа, z спереди и сзади, а y вверх и вниз.

Для вектора это просто, просто поменяйте местами значения y и z, но как это сделать для матрицы?

Ответы [ 7 ]

24 голосов
/ 12 августа 2009

Позвольте мне попытаться объяснить это немного лучше. Мне нужно экспортировать модель из Blender, в которой ось z направлена ​​вверх, в OpenGL, где ось y направлена ​​вверх.

Для каждой координаты (x, y, z) это просто; просто поменяйте местами значения y и z: (x, z, y).
Поскольку я поменял местами все значения y и z, любую матрицу, которую я использую, также необходимо перевернуть, чтобы она имела тот же эффект.

После долгих поисков я в конце концов нашел решение на gamedev :

Если ваша матрица выглядит так:

{ rx, ry, rz, 0 }  
{ ux, uy, uz, 0 }  
{ lx, ly, lz, 0 }  
{ px, py, pz, 1 }

Чтобы изменить его слева направо или справа налево, переверните его так:

{ rx, rz, ry, 0 }  
{ lx, lz, ly, 0 }  
{ ux, uz, uy, 0 }  
{ px, pz, py, 1 }
13 голосов
/ 18 сентября 2012

Мне кажется, я понимаю вашу проблему, потому что в настоящее время сталкиваюсь с подобной.

  • Вы начинаете с матрицы мира, которая преобразует вектор в пространстве, где Z вверх (например, матрица мира).

  • Теперь у вас есть пробел, где Y вверх, и вы хотите знать, что делать со старой матрицей.

Попробуйте это:

Существует данная матрица мира

Matrix world = ...  //space where Z is up

Эта матрица изменяет Y и Z компоненты вектора

Matrix mToggle_YZ = new Matrix(
{1, 0, 0, 0}
{0, 0, 1, 0}
{0, 1, 0, 0}
{0, 0, 0, 1})

Вы ищете это:

//same world transformation in a space where Y is up
Matrix world2 = mToggle_YZ * world * mToggle_YZ;

Результатом является та же матрица cmann, размещенная ниже. Но я думаю, что это более понятно, так как сочетает в себе следующие вычисления:

1) Переключатель Y и Z

2) У старой трансформации

3) Переключите обратно Z и Y

4 голосов
/ 15 сентября 2016

Часто бывает так, что вы хотите изменить матрицу с одного набора соглашений вперед / вправо / вверх на другой набор соглашений вперед / вправо / вверх. Например, ROS использует z-up, а Unreal использует y-up. Процесс работает независимо от того, нужно ли вам сделать бросок на руку.

Обратите внимание, что фраза «переключаться с правой руки на левую» неоднозначна. Есть много левых вперед / вправо / вверх соглашений. Например: вперед = z, вправо = x, вверх = y; и вперед = x, вправо = y, вверх = z. Вы действительно должны думать об этом как ", как я могу преобразовать понятие ROS вперед / вправо / вверх в понятие Unreal вперед / вправо / вверх ".

Итак, простая задача - создать матрицу, которая конвертирует между соглашениями. Давайте предположим, что мы сделали это, и теперь у нас есть

mat4x4 unrealFromRos = /* construct this by hand */;
mat4x4 rosFromUnreal = unrealFromRos.inverse();

Допустим, у ОП есть матрица из ROS, и она хочет использовать ее в Unreal. Ее исходная матрица берет вектор в стиле ROS, делает что-то с ним и испускает вектор в стиле ROS. Ей нужна матрица, которая принимает вектор в стиле Unreal, выполняет те же функции и испускает вектор в стиле Unreal. Это выглядит так:

mat4x4 turnLeft10Degrees_ROS = ...;
mat4x4 turnLeft10Degrees_Unreal = unrealFromRos * turnLeft10Degrees_ROS * rosFromUnreal;

Должно быть достаточно ясно, почему это работает. Вы берете вектор Unreal, конвертируете его в ROS-стиль, и теперь вы можете использовать матрицу в ROS-стиле. Это дает вам вектор ROS, который вы конвертируете обратно в стиль Unreal.

Ответ Геррита не совсем общий, потому что в общем случае rosFromUnreal! = UnrealFromRos. Это правда, если вы просто инвертируете одну ось, но не так, если вы делаете что-то вроде преобразования X-> Y, Y-> Z, Z-> X. Я обнаружил, что менее подвержен ошибкам всегда использовать матрицу и ее инверсию для выполнения этих условных переключений, а не пытаться писать специальные функции, которые переворачивают только нужные члены.

Этот вид матричной операции inverse(M) * X * M часто встречается. Вы можете думать об этом как об операции «изменение базы»; Чтобы узнать больше об этом, см. https://en.wikipedia.org/wiki/Matrix_similarity.

4 голосов
/ 19 декабря 2015

Я работал над преобразованием Unity SteamVR_Utils.RigidTransform в ROS geometry_msgs / Pose, и мне нужно было преобразовать левостороннюю систему координат Unity в правую систему координат ROS.

Это был код, который я написал для преобразования систем координат.

var device = SteamVR_Controller.Input(index);
// Modify the unity controller to be in the same coordinate system as ROS.
Vector3 ros_position = new Vector3(
    device.transform.pos.z,
    -1 * device.transform.pos.x,
    device.transform.pos.y);
Quaternion ros_orientation = new Quaternion(
    -1 * device.transform.rot.z,
    device.transform.rot.x,
    -1 * device.transform.rot.y,
    device.transform.rot.w);

Изначально я пытался использовать пример матрицы из @bleater, но мне не удалось заставить его работать. Хотелось бы знать, если я где-то ошибся.

HmdMatrix44_t m = device.transform.ToHmdMatrix44();
HmdMatrix44_t m2 = new HmdMatrix44_t();
m2.m = new float[16];
// left -> right
m2.m[0] = m.m[0]; m2.m[1] = m.m[2]; m2.m[2] = m.m[1]; m2.m[3] = m.m[3];
m2.m[4] = m.m[8]; m2.m[5] = m.m[10]; m2.m[6] = m.m[9]; m2.m[7] = m.m[7];
m2.m[8] = m.m[4]; m2.m[9] = m.m[6]; m2.m[10] = m.m[5]; m2.m[11] = m.m[11];
m2.m[12] = m.m[12]; m2.m[13] = m.m[14]; m2.m[14] = m.m[13]; m2.m[15] = m.m[15];

SteamVR_Utils.RigidTransform rt = new SteamVR_Utils.RigidTransform(m2);

Vector3 ros_position = new Vector3(
    rt.pos.x,
    rt.pos.y,
    rt.pos.z);
Quaternion ros_orientation = new Quaternion(
    rt.rot.x,
    rt.rot.y,
    rt.rot.z,
    rt.rot.w);
1 голос
/ 12 августа 2009

Это зависит от того, преобразуете ли вы свои очки, умножая матрицу слева или справа.

Если вы умножаете слева (например, Ax = x ', где A - матрица, а x' преобразованная точка), вам просто нужно поменять местами второй и третий столбцы. Если вы умножаете справа (например, xA = x '), вам нужно поменять местами второй и третий ряд.

Если ваши точки являются векторами столбцов, то вы в первом сценарии.

0 голосов
/ 14 ноября 2012

Измените коэффициент sin на -sin для замены координатных пространств между правой и левой рукой

0 голосов
/ 12 августа 2009

Так как это похоже на домашнее задание; я дам вам подсказку: что вы можете сделать, чтобы определитель матрицы был отрицательным?

Далее (лучший совет): поскольку вы уже знаете, как выполнить это преобразование с отдельными векторами, не думаете ли вы, что сможете сделать это с помощью базовых векторов, которые охватывают преобразование, которое представляет матрица? (Помните, что матрица может рассматриваться как линейное преобразование, выполняемое на кортеже единичных векторов)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...