可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I would like to change a 4x4 matrix from a right handed system where:
x is left and right, y is front and back and z is up and down
to a left-handed system where:
x is left and right, z is front and back and y is up and down.
For a vector it's easy, just swap the y and z values, but how do you do it for a matrix?
回答1:
Let me try to explain it a little better.
I need to export a model from Blender, in which the z axis faces up, into OpenGL, where the y axis faces up.
For every coordinate (x, y, z) it's simple; just swap the y and z values: (x, z, y).
Because I have swapped the all the y and z values, any matrix that I use also needs to be flipped so that it has the same effect.
After a lot of searching I've eventually found a solution at gamedev:
If your matrix looks like this:
{ rx, ry, rz, 0 }
{ ux, uy, uz, 0 }
{ lx, ly, lz, 0 }
{ px, py, pz, 1 }
To change it from left to right or right to left, flip it like this:
{ rx, rz, ry, 0 }
{ lx, lz, ly, 0 }
{ ux, uz, uy, 0 }
{ px, pz, py, 1 }
回答2:
I think I understand your problem because I am currently facing a similar one.
Try this:
There is a given world matrix
Matrix world = ... //space where Z is up
This Matrix changes the Y and Z components of a Vector
Matrix mToggle_YZ = new Matrix(
{1, 0, 0, 0}
{0, 0, 1, 0}
{0, 1, 0, 0}
{0, 0, 0, 1})
You are searching for this:
//same world transformation in a space where Y is up
Matrix world2 = mToggle_YZ * world * mToggle_YZ;
The result is the same matrix cmann posted below. But I think this is more understandable as it combines the following calculation:
1) Switch Y and Z
2) Do the old transformation
3) Switch back Z and Y
回答3:
I have been working on converting the Unity SteamVR_Utils.RigidTransform to ROS geometry_msgs/Pose and needed to convert Unity left handed coordinate system to the ROS right handed coordinate system.
This was the code I ended up writing to convert coordinate systems.
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);
Originally I tried using the matrix example from @bleater, but I couldn't seem to get it to work. Would love to know if I made a mistake somewhere.
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:
It is often the case that you want to change a matrix from one set of forward/right/up conventions to another set of forward/right/up conventions. For example, ROS uses z-up, and Unreal uses y-up. The process works whether or not you need to do a handedness-flip.
Note that the phrase "switch from right-handed to left-handed" is ambiguous. There are many left-handed forward/right/up conventions. For example: forward=z, right=x, up=y; and forward=x, right=y, up=z. You should really think of it as "how do I convert ROS' notion of forward/right/up to Unreal's notion of forward/right/up".
So, it's a straightforward job to create a matrix that converts between conventions. Let's assume we've done that and we now have
mat4x4 unrealFromRos = /* construct this by hand */;
mat4x4 rosFromUnreal = unrealFromRos.inverse();
Let's say the OP has a matrix that comes from ROS, and she wants to use it in Unreal. Her original matrix takes a ROS-style vector, does some stuff to it, and emits a ROS-style vector. She needs a matrix that takes an Unreal-style vector, does the same stuff, and emits an Unreal-style vector. That looks like this:
mat4x4 turnLeft10Degrees_ROS = ...;
mat4x4 turnLeft10Degrees_Unreal = unrealFromRos * turnLeft10Degrees_ROS * rosFromUnreal;
It should be pretty clear why this works. You take a Unreal vector, convert it to ROS-style, and now you can use the ROS-style matrix on it. That gives you a ROS vector, which you convert back to Unreal style.
Gerrit's answer is not quite fully general, because in the general case, rosFromUnreal != unrealFromRos. It's true if you're just inverting a single axis, but not true if you're doing something like converting X->Y, Y->Z, Z->X. I've found that it's less error-prone to always use a matrix and its inverse to do these convention switches, rather than to try to write special functions that flip just the right members.
This kind of matrix operation inverse(M) * X * M
comes up a lot. You can think of it as a "change of basis" operation; to learn more about it, see https://en.wikipedia.org/wiki/Matrix_similarity.
回答5:
It depends if you transform your points by multiplying the matrix from the left or from the right.
If you multiply from the left (e.g: Ax = x', where A is a matrix and x' the transformed point), you just need to swap the second and third column.
If you multiply from the right (e.g: xA = x'), you need to swap the second and third row.
If your points are column vectors then you're in the first scenario.
回答6:
Change sin factor to -sin for swaping coordinate spaces between right and left handed
回答7:
Since this seems like a homework answer; i'll give you a start at a hint: What can you do to make the determinant of the matrix negative?
Further (better hint): Since you already know how to do that transformation with individual vectors, don't you think you'd be able to do it with the basis vectors that span the transformation the matrix represents? (Remember that a matrix can be viewed as a linear transormation performed on a tuple of unit vectors)