Position + Euler Angles to Transformation Matrix
Question:
I have a position and three Euler angles from a Unity scene:
# position
cam_pos = [-0.1219461, -0.04402884, -1.995793]
# rotation (in degrees)
cam_rot = [-1.261, 176.506, 0.038]
In Unity the coordinate system is LHS and the Euler angle convention is Z,X,Y. I’d like to know how to turn this rotation+translation information into a 4×4 transformation matrix. Right now what I’ve got is:
import numpy as np
import pyquaternion as pyq
cam_pos = [-0.1219461, -0.04402884, -1.995793]
cam_rot = [-1.261, 176.506, 0.038]
qx = pyq.Quaternion(axis=[1, 0, 0], angle=np.radians(cam_rot[0]))
qy = pyq.Quaternion(axis=[0, 1, 0], angle=np.radians(cam_rot[1]))
qz = pyq.Quaternion(axis=[0, 0, 1], angle=np.radians(cam_rot[2]))
qr = qz * qx * qy
trans = np.zeros((4,4))
trans[0:3, 0:3] = rotmat
trans[0:3, 3] = cam_pos
trans[3, 3] = 1
which gives me
[[-9.98140077e-01 -6.63064448e-04 6.09585697e-02 -1.21946100e-01]
[-2.00317624e-03 9.99757601e-01 -2.19254941e-02 -4.40288400e-02]
[-6.09292554e-02 -2.20068252e-02 -9.97899457e-01 -1.99579300e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
But after plotting the result in with some other data, I’m pretty sure I’ve fundamentally misunderstood something about the math here. Any help is greatly appreciated!
Answers:
In Unity, eulerAngles represent rotations in the following sequence: around Z-axis, around X-axis, and around Y-axis.
We can represent this in a 4×4 transformation matrix by applying each of these rotations in matrix form:
(taken from: https://en.wikibooks.org/wiki/Cg_Programming/Unity/Rotations)
This will give you the upper-left 3×3 values of the 4×4 matrix.
Here are some snippets in python:
import math
# ...
cam_rot_rad = [math.radian(rot) for rot_deg in cam_rot]
x_rad = cam_rot_rad[0]
y_rad = cam_rot_rad[1]
z_rad = cam_rot_rad[2]
rot_z = np.identity(4)
rot_z[0,0] = math.cos(z_rad)
rot_z[0,1] = -math.sin(z_rad)
rot_z[1,0] = math.sin(z_rad)
rot_z[1,1] = math.cos(z_rad)
rot_x = np.identity(4)
rot_x[1,1] = math.cos(x_rad)
rot_x[1,2] = -math.sin(x_rad)
rot_x[2,1] = math.sin(x_rad)
rot_x[2,2] = math.cos(x_rad)
rot_y = np.identity(4)
rot_y[0,0] = math.cos(y_rad)
rot_y[0,2] = math.sin(y_rad)
rot_y[2,0] = -math.sin(y_rad)
rot_y[2,2] = math.cos(y_rad)
# xform = rot_y*rot_x*rot_z
xform = np.dot(rot_y, np.dot(rot_x, rot_z))
# this could also be achieved by multiplying a 4x4 translation matrix
xform[0:3, 3] = cam_pos
I have a position and three Euler angles from a Unity scene:
# position
cam_pos = [-0.1219461, -0.04402884, -1.995793]
# rotation (in degrees)
cam_rot = [-1.261, 176.506, 0.038]
In Unity the coordinate system is LHS and the Euler angle convention is Z,X,Y. I’d like to know how to turn this rotation+translation information into a 4×4 transformation matrix. Right now what I’ve got is:
import numpy as np
import pyquaternion as pyq
cam_pos = [-0.1219461, -0.04402884, -1.995793]
cam_rot = [-1.261, 176.506, 0.038]
qx = pyq.Quaternion(axis=[1, 0, 0], angle=np.radians(cam_rot[0]))
qy = pyq.Quaternion(axis=[0, 1, 0], angle=np.radians(cam_rot[1]))
qz = pyq.Quaternion(axis=[0, 0, 1], angle=np.radians(cam_rot[2]))
qr = qz * qx * qy
trans = np.zeros((4,4))
trans[0:3, 0:3] = rotmat
trans[0:3, 3] = cam_pos
trans[3, 3] = 1
which gives me
[[-9.98140077e-01 -6.63064448e-04 6.09585697e-02 -1.21946100e-01]
[-2.00317624e-03 9.99757601e-01 -2.19254941e-02 -4.40288400e-02]
[-6.09292554e-02 -2.20068252e-02 -9.97899457e-01 -1.99579300e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
But after plotting the result in with some other data, I’m pretty sure I’ve fundamentally misunderstood something about the math here. Any help is greatly appreciated!
In Unity, eulerAngles represent rotations in the following sequence: around Z-axis, around X-axis, and around Y-axis.
We can represent this in a 4×4 transformation matrix by applying each of these rotations in matrix form:
(taken from: https://en.wikibooks.org/wiki/Cg_Programming/Unity/Rotations)
This will give you the upper-left 3×3 values of the 4×4 matrix.
Here are some snippets in python:
import math
# ...
cam_rot_rad = [math.radian(rot) for rot_deg in cam_rot]
x_rad = cam_rot_rad[0]
y_rad = cam_rot_rad[1]
z_rad = cam_rot_rad[2]
rot_z = np.identity(4)
rot_z[0,0] = math.cos(z_rad)
rot_z[0,1] = -math.sin(z_rad)
rot_z[1,0] = math.sin(z_rad)
rot_z[1,1] = math.cos(z_rad)
rot_x = np.identity(4)
rot_x[1,1] = math.cos(x_rad)
rot_x[1,2] = -math.sin(x_rad)
rot_x[2,1] = math.sin(x_rad)
rot_x[2,2] = math.cos(x_rad)
rot_y = np.identity(4)
rot_y[0,0] = math.cos(y_rad)
rot_y[0,2] = math.sin(y_rad)
rot_y[2,0] = -math.sin(y_rad)
rot_y[2,2] = math.cos(y_rad)
# xform = rot_y*rot_x*rot_z
xform = np.dot(rot_y, np.dot(rot_x, rot_z))
# this could also be achieved by multiplying a 4x4 translation matrix
xform[0:3, 3] = cam_pos