将矩阵从右手坐标系更改为左手坐标系

时间:2009-08-11 21:36:23

标签: math graphics

我想从右手系统更改4x4矩阵,其中:
x是左右,y是前后,z是上下

到左手系统,其中:
x左右, z 是正面和背面, y 是上下。

对于矢量,它很容易,只需交换y和z值,但是你如何为矩阵做?

7 个答案:

答案 0 :(得分:24)

让我试着更好地解释一下。 我需要将模型从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 }

答案 1 :(得分:12)

我想我理解你的问题,因为我目前正面临类似的问题。

  • 您从一个世界矩阵开始,该矩阵在Z向上的空间中转换向量(例如,世界矩阵)。

  • 现在你有一个空间,其中Y已经启动,你想知道如何处理你的旧矩阵。

试试这个:

有一个给定的世界矩阵

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

此矩阵更改Vector

的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

答案 2 :(得分:4)

我一直在努力将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);

答案 3 :(得分:3)

通常情况下,您希望将矩阵从一组前进/右/上传约定更改为另一组前进/右/上惯例。例如,ROS使用z-up,而Unreal使用y-up。无论你是否需要进行左右手翻转,这个过程都会起作用。

请注意,短语"从右手切换到左手"很暧昧。有许多左手前进/右/上惯例。例如:forward = z,right = x,up = y;和forward = x,right = y,up = z。您应该将其视为" 如何转换ROS'向前/向右/向前/向右/向上概念的概念"。

因此,创建一个在约定之间进行转换的矩阵是一项简单的工作。让我们假设我们已经完成了这一点,现在我们已经

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

让我们说OP有一个来自ROS的矩阵,她想在Unreal中使用它。她的原始矩阵采用ROS风格的矢量,为它做一些事情,并发出一个ROS风格的矢量。她需要一个矩阵,它采用虚幻风格的矢量,做同样的事情,并发出虚幻风格的矢量。看起来像这样:

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

应该很清楚为什么这样做。你使用虚幻矢量,将其转换为ROS风格,现在你可以在它上面使用ROS风格的矩阵。这会给你一个ROS矢量,你可以将它转换回Unreal风格。

Gerrit的答案并不完全一般,因为在一般情况下,rosFromUnreal!= unrealFromRos。如果您只是反转单个轴,那么这是正确的,但如果您正在执行诸如转换X-> Y,Y-> Z,Z-> X之类的操作,那么情况并非如此。我发现,总是使用矩阵及其反转来做这些约定开关的错误更少,而不是试图编写只能翻转正确成员的特殊函数。

这种矩阵运算inverse(M) * X * M出现了很多。您可以将其视为"基础的变化"操作;要了解有关它的更多信息,请参阅https://en.wikipedia.org/wiki/Matrix_similarity

答案 4 :(得分:1)

这取决于您是通过将矩阵从左侧还是右侧乘以来变换您的点。

如果你从左边乘(例如:Ax = x',其中A是矩阵而x'是变换点),你只需要交换第二和第三列。 如果从右边乘以(例如:xA = x'),则需要交换第二行和第三行。

如果你的点是列向量,那么你就是第一个场景。

答案 5 :(得分:0)

将sin因子更改为-sin以交换右手和左手之间的坐标空间

答案 6 :(得分:-7)

因为这似乎是一个功课答案;我会给你一个提示:你可以做些什么来使矩阵的行列式为负?

进一步(更好的提示):既然你已经知道如何使用单个向量进行转换,难道你不认为你能用跨越矩阵所代表的变换的基向量来做吗? (请记住,矩阵可以被视为对单位向量元组执行的线性变换)