将matrix从右手变为左手坐标系

我想从右手系统中改变一个4x4matrix,其中:
x是左和右,y是前后和z是上和下

到左手系统,其中:
x是左和右, z是前和后, y是上和下。

对于vector来说很简单,只需交换y和z值,但是如何为matrix做这些呢?

让我试着解释一下好一点。 我需要将Blender中的模型(其中z轴朝上)导出到OpenGL中,其中y轴朝上。

对于每个坐标(x,y,z)都很简单; 只需交换y和z值:(x,z,y)。
因为我已经交换了所有的y和z值,所以我使用的任何matrix也需要被翻转以便它具有相同的效果。

经过大量的search,我终于在gamedev上find了一个解决scheme:

如果你的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 } 

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

  • 你从一个世界matrix开始,在Z向上的空间(如世界matrix)中转换一个向量。

  • 现在你有一个Y的空间,你想知道如何处理你的旧matrix。

尝试这个:

有一个给定的世界matrix

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

该matrix改变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; 

结果是在下面发布相同的matrixcmann。 但是,我认为这是可以理解的,因为它结合了以下计算:

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的matrix示例,但我似乎无法得到它的工作。 想知道我是否在某个地方犯了错误。

 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); 

通常情况下,您希望将matrix从一组向前/向右/向上约定更改为另一组向前/向右/向上约定。 例如,ROS使用z-up,而Unreal使用y-up。 无论你是否需要做手势翻转,这个过程都是有效的。

请注意,短语“从右手切换到左手”是不明确的。 有许多左手前进/右/上手的惯例。 例如:forward = z,right = x,up = y; 和forward = x,right = y,up = z。 你应该真的把它看作是“ 如何将ROS的前瞻/正确/转化为虚幻的向前/向右/向上的概念 ”。

所以,创build一个在公约之间转换的matrix是一个简单的工作。 假设我们已经完成了,现在我们已经完成了

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

假设OP有一个来自ROS的matrix,她想在虚幻中使用它。 她的原始matrix需要一个ROS风格的vector,做一些东西,并发出一个ROS风格的vector。 她需要一个采用虚幻风格的vectormatrix,做相同的东西,并发出虚幻风格的vector。 看起来像这样:

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

应该很清楚为什么这个工作。 你把一个虚幻vector,转换成ROS风格,现在你可以使用它的ROS风格的matrix。 这给你一个ROSvector,你可以转换回虚幻风格。

Gerrit的回答并不完全一般,因为在一般情况下,rosFromUnreal!= unrealFromRos。 如果你只是反转一个单一的轴,这是真的,但如果你正在做转换X-> Y,Y-> Z,Z-> X,则不是这样。 我已经发现,总是使用matrix及其相反的方式来执行这些约定开关,而不是尝试编写仅仅翻转正确的成员的特殊函数。

这种matrix运算inverse(M) * X * M出现了很多。 你可以把它看作是“基础改变”的运作; 要了解更多信息,请参阅https://en.wikipedia.org/wiki/Matrix_similarity

这取决于是否通过将matrix从左边或右边相乘来变换点。

如果从左边开始乘(例如:Ax = x',其中A是matrix,x是变换点),则只需交换第二列和第三列即可。 如果从右边乘(例如:xA = x'),则需要交换第二行和第三行。

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

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

因为这似乎是一个作业答案; 我会给你一个提示:你能做些什么来使matrix的行列式为负数?

进一步的(更好的提示):既然你已经知道如何用单独的向量来完成这种转换,你不觉得你可以用跨越matrix表示的转换的基本向量来完成吗? (请记住,matrix可以看作是在单位向量的元组上执行的线性变换)