2009-08-11 242 views
22

我想从右手系统更改4x4矩阵,其中:
x是左和右,y是正面和背面,z是向上和向下将矩阵从右手改为左手坐标系

到左手系统,其中:
x被左和右,ž是正面和背面和ÿ是向上和向下。

对于一个向量来说很简单,只需交换y和z值,但是如何为矩阵做它?

+0

我可能会在这里感到困惑,为什么你不能只交换y和z值?我假设你的意思是一个4x4x4矩阵,因为4x4不会有z。 – derobert 2009-08-11 21:41:17

+0

只是一个4x4矩阵。 只是翻转y和z翻译值似乎并不工作,矩阵也包含一个旋转操作,所以我认为问题在那里。 – cmann 2009-08-11 21:44:34

+0

我认为你需要在任何人回答你的问题之前确切地说明你想要的东西。对于一个向量'(x,y,z,w)',你已经解释过,“从右手变为左手”意味着你将它改为向量'(x,z,y,w) ',但一点也不清楚这句话对矩阵意味着什么。例如,假设一个矩阵将向量'(1,2,3,4)'带到向量'(5,6,7,8)',那么当你“从右手改为左手”时, (1,2,3,4)'到'(5,7,6,8)',还是应该用'(1,3,2,4)'到'(5,7,6) ,8)',还是你的意思是它做了别的事情? – 2009-08-11 23:52:58

回答

21

让我试着解释它好一点。 我需要从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

您的答案似乎是从左手坐标系变为右手手坐标系,但你的问题描述是改变矢量的方向。 – zionpi 2014-09-22 01:26:31

+1

opengl是一个右手系统。如果您选择y轴向上,只需交换y轴和z轴,就会得到一个不受任何左/右手协调系统影响的坐标系。我不认为这是正确的答案。 – flankechen 2016-08-12 12:05:20

-7

因为这似乎是一个家庭作业的答案;我会给你一个启示:你能做些什么来使矩阵的行列式为负数?进一步(更好的提示):既然你已经知道如何用单独的向量来完成这种转换,你不认为你可以用跨越矩阵表示的转换的基向量来做到吗? (请记住,矩阵可以看作是对单位向量元组执行的线性变换)

+2

谢谢,但实际上它不是功课,我也不知道任何背后的数学,所以我实际上并没有明白这一点。 – cmann 2009-08-11 21:47:02

+0

好吧,为了更务实和更少数学,首先您可以分别处理旋转和平移。 – 2009-08-11 21:53:58

+0

(我假设仿射变换) – 2009-08-11 21:55:49

0

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

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

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

11

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

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

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

试试这个:

有一个给定的世界矩阵

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

这个矩阵改变您正在寻找此的矢量

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

的Y和Z分量:

//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

如果需要镜像轴,可以通过在您的世界矩阵乘法中添加此矩阵来完成此操作: Matrix mMirror_X =新矩阵( {-1,0,0,0} {0,1,0 ,0} {0,0,1,0} {0,0,0,1}) – Gerrit 2012-09-18 15:20:47

+0

感谢Gerrit,它工作的很棒。 – VivekParamasivam 2013-12-24 08:36:03

0

变化sin因子为-sin用于调换左右手之间的坐标空间

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

谢谢,这非常有帮助! – davetcoleman 2015-12-19 20:54:44

+0

我看到Steam_Utils.RigidTransform转换与此处不同。你想在这里填写你的答案吗? – NTj 2016-04-14 07:25:14

2

通常情况下,您希望将矩阵从一组向前/向右/向上约定更改为另一组向前/向右/向上约定。例如,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矩阵,并且她希望在虚幻中使用它。她的原始矩阵采用ROS风格的矢量,做一些东西,并发出ROS风格的矢量。她需要一个采用虚幻风格向量的矩阵,做相同的事情,并发出虚幻风格的向量。看起来像这样:

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

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

Gerrit的回答并不完全一般,因为在一般情况下,rosFromUnreal!= unrealFromRos。如果你只是反转一个单一的轴,这是真的,但如果你正在转换X-> Y,Y-> Z,Z-> X,那么这就是真的。我发现它不太容易出错,总是使用矩阵及其反转来执行这些约定开关,而不是尝试编写只翻转正确成员的特殊函数。

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