Подтвердить что ты не робот

Изменение матрицы от правой до левой системы координат

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

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

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

4b9b3361

Ответ 1

Позвольте мне попытаться объяснить это немного лучше. Мне нужно экспортировать модель из 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 }

Ответ 2

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

  • Вы начинаете с мировой матрицы, которая преобразует вектор в пространстве, где 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

Ответ 3

Я работал над преобразованием 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);

Ответ 4

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

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

Итак, это простая работа по созданию матрицы, которая преобразует между условностями. Предположим, что мы это сделали, и теперь у нас есть

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

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

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

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

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

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