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

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

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

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

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

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

После большого поиска я в конце концов нашел решение у гамедева :

Если ваша matrix выглядит так:

 { 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 } 

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

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

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

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

Существует заданная мировая matrix

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

Эта matrix меняет компоненты 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; 

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

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

2) Старое преобразование

3) Отключить Z и Y

Я работал над преобразованием 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] = mm[0]; m2.m[1] = mm[2]; m2.m[2] = mm[1]; m2.m[3] = mm[3]; m2.m[4] = mm[8]; m2.m[5] = mm[10]; m2.m[6] = mm[9]; m2.m[7] = mm[7]; m2.m[8] = mm[4]; m2.m[9] = mm[6]; m2.m[10] = mm[5]; m2.m[11] = mm[11]; m2.m[12] = mm[12]; m2.m[13] = mm[14]; m2.m[14] = mm[13]; m2.m[15] = mm[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); 

Часто бывает, что вы хотите изменить матрицу из одного набора соглашений о переходе / вправо / вверх в другой набор соглашений о переходе / вправо / вверх. Например, 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 есть matrix, которая поступает из ROS, и она хочет использовать ее в Unreal. Ее оригинальная matrix принимает вектор ROS-стиля, делает некоторые вещи к нему и испускает вектор стиля ROS. Ей нужна matrix, которая принимает вектор стиля 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 .

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

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

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

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

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

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

  • N-ая комбинация
  • Как определить стандартное отклонение (stddev) набора значений?
  • Как вы вычисляете ориентированную по оси ограничительную рамку эллипса?
  • Матричная обратная точность
  • Вычисление матрицы LookAt
  • Плавно соединяющие центры
  • Подписанный угол между двумя 3D-векторами с одинаковым началом в одной плоскости
  • Операции с плавающей запятой в C-ассоциативном?
  • Повышение точности решения трансцендентного уравнения
  • Зачем использовать softmax в отличие от стандартной нормализации?
  • Вычислить вторую точку, зная начальную точку и расстояние
  • Давайте будем гением компьютера.