3D rotation data often moves between libraries as Euler angles, quaternions, matrices, or rotation vectors. SciPy stores the orientation in a Rotation object so Python code can translate one representation into another without changing the spatial rotation.
scipy.spatial.transform.Rotation creates rotations with from_euler(), from_quat(), from_matrix(), and from_rotvec(), then returns the format required by downstream code with matching as_… methods. The object is representation-independent, so one source orientation can be exported several ways.
A lowercase zyx Euler sequence in degrees keeps the axis order explicit before any quaternion or matrix export. Lowercase axes mean extrinsic rotations in SciPy, while uppercase axes mean intrinsic rotations; keep that convention consistent with the system that produced or consumes the data.
import numpy as np from scipy.spatial.transform import Rotation as R np.set_printoptions(precision=4, suppress=True) rotation = R.from_euler("zyx", [45, 20, 10], degrees=True) quat_xyzw = rotation.as_quat() matrix = rotation.as_matrix() rotvec = rotation.as_rotvec() print("Euler zyx degrees:") print(rotation.as_euler("zyx", degrees=True)) print("\nQuaternion xyzw:") print(quat_xyzw) print("\nQuaternion wxyz:") print(rotation.as_quat(scalar_first=True)) print("\nRotation matrix rows:") for row in matrix: print(row) print("\nRotation vector radians:") print(rotvec) print("\nRound-trip checks:") print("from_quat :", R.from_quat(quat_xyzw).approx_equal(rotation, atol=1e-12)) print("from_matrix:", R.from_matrix(matrix).approx_equal(rotation, atol=1e-12)) print("from_rotvec:", R.from_rotvec(rotvec).approx_equal(rotation, atol=1e-12))
$ python3 rotation_convert_demo.py Euler zyx degrees: [45. 20. 10.] Quaternion xyzw: [0.1455 0.127 0.3894 0.9006] Quaternion wxyz: [0.9006 0.1455 0.127 0.3894] Rotation matrix rows: [ 0.6645 -0.6645 0.342 ] [ 0.7384 0.6544 -0.1632] [-0.1154 0.361 0.9254] Rotation vector radians: [0.301 0.2627 0.8057] Round-trip checks: from_quat : True from_matrix: True from_rotvec: True
Lowercase zyx means extrinsic rotations. Uppercase ZYX means intrinsic rotations. Euler outputs are convention-specific and can warn at gimbal lock while still representing the same orientation.
as_quat() defaults to scalar-last order. Use scalar_first=True for w, x, y, z order.
Use assume_valid=True only for matrices already known to be orthogonal with determinant 1. Invalid matrices can otherwise produce incorrect rotations without a repair step.
The vector direction is the rotation axis, and its length is the angle in radians unless a method call explicitly requests degrees.
approx_equal() compares the represented orientation, which is safer than comparing raw quaternion signs because q and -q describe the same spatial rotation.
$ rm rotation_convert_demo.py