Rotation Matrices and Rigid-Body Orientation
Learning Objectives
- Read a rotation matrix as the axes of one frame written in another, and check the two conditions that define it, and .
- Use the same matrix actively (rotate a vector) and passively (re-express a fixed vector in a rotated frame), and predict the sign difference.
- Compose rotations about fixed axes by pre-multiplication and about the moving body's axes by post-multiplication.
- State the ZYX Euler convention used in this track, recognize that it equals roll-pitch-yaw about fixed axes taken in the reverse order, and see a library convention give a different matrix for the same three numbers.
- Show gimbal lock as a rank loss of the map from Euler-angle rates to angular velocity, and measure what it does to the angles near the lock.
Context & Motivation
what-a-robot-is-classification-components-and-degrees-of-freedom counted 6 degrees of freedom for a rigid body in space: 3 for position and 3 for orientation. Position is a vector. Orientation needs a representation, and every later computation in this track (poses, Jacobians, controllers) inherits the one chosen here.
orthogonality-and-orthogonal-matrices showed that a square matrix with orthonormal columns satisfies and that such matrices are rotations, reflections, or combinations of the two. Robotics needs the rotations only, and needs to be explicit about four conventions that textbooks and libraries choose differently: which way a matrix acts, which frame an axis belongs to, the order of Euler angles, and the sign of an angle. Mixing two of them gives a valid-looking rotation matrix with the wrong orientation, and nothing in the matrix itself signals the mistake.
Core Theory
Conventions used in this track
Vectors are columns. Frames are right-handed, and a positive angle turns counterclockwise when the axis points at the viewer. Following Modern Robotics (Lynch and Park), is the orientation of frame relative to frame : its columns are the unit axes written in coordinates. The elementary rotations are
with , . The minus sign in sits in the lower-left corner, unlike the other two, because the cyclic order is for a rotation about .
The group SO(3)
Unit columns give 3 equations and pairwise orthogonal columns give 3 more, together . Nine entries minus six constraints leave 3 free parameters, matching the count of the previous lesson. Those six constraints allow ; requiring keeps the right-handed frames and excludes reflections. The set of such matrices is the special orthogonal group . A product of rotations is a rotation, the inverse is the transpose, a rotation preserves lengths, and in three dimensions in general (plane rotations do commute).
Three uses, and active versus passive
Modern Robotics lists three uses of a rotation matrix: to represent an orientation, to change the frame in which a vector is written, and to rotate a vector or frame. The last two are the readings known as passive (alias) and active (alibi).
- Active: the vector moves, the frame stays. gives the coordinates of the rotated vector in the same frame.
- Passive: the vector stays, the frame changes. If are the coordinates of a vector in , then , so the coordinates in the rotated frame are .
The same therefore acts with opposite sign in the two readings: rotating a vector by produces the same numbers as describing the unmoved vector in a frame turned by . Frame changes chain by cancelling the inner subscripts, and .
Fixed axes and moving axes
Rotating a frame by is ambiguous until one says in which frame is written:
So successive rotations about fixed axes pile up on the left, and successive rotations about the body's own, moving axes pile up on the right.
Euler angles: the ZYX convention
This track uses the ZYX Euler angles of Modern Robotics (Appendix B): starting from aligned with , rotate by about the body , then by about the new , then by about the newest . Body-axis rotations post-multiply, so
Read right to left, the same product is a rotation by about the fixed , then about the fixed , then about the fixed . Modern Robotics calls this the XYZ roll-pitch-yaw angles: one matrix, two physical stories. When the angles come back as
with . Other texts use ZYZ, XYZ, or other orders, and libraries encode the difference in a string. In SciPy's Rotation.from_euler, uppercase letters mean intrinsic (body) axes and lowercase letters mean extrinsic (fixed) axes. So 'ZYX' is the convention above, while 'zyx' with the same three numbers is , a different rotation.
Gimbal lock
At the first and third rotation axes line up, and the matrix depends only on (for ) or (for ). Only one combination of the first and third angles matters, so the coordinates lose a dimension. The cleanest way to see the loss is through velocities. The angular velocity in produced by angle rates is
where each column is a rotation axis, written in , at the moment its angle acts. Its determinant is . At the third column is the first, has rank 2, angular velocities outside its two-dimensional range cannot be produced by any angle rates, and near the lock they need very large ones. Nothing happens to the rotation itself: looks the same everywhere, and the singularity belongs to the coordinates, as the poles belong to latitude and longitude rather than to the sphere. Modern Robotics notes that such singularities are unavoidable for any three-parameter representation of rotation, a reason to store orientation as a matrix or a unit quaternion (both treated in Modern Robotics) and to keep Euler angles for input and display.
Worked Examples
Example 1: checking that a matrix is a rotation
evaluates to
In float64, and . For , . The mirror also satisfies , but : it is orthogonal and not a rotation, and it would turn a right-handed frame into a left-handed one.
Example 2: active and passive with the same matrix
Let and .
textactive, R v = ( 0.866, 0.5, 0) the vector turned 30 degrees passive, R^T v = ( 0.866, -0.5, 0) the same vector, in a frame turned 30 degrees dot with b axes = ( 0.866, -0.5, 0) direct check: projections on the columns of R
The second component flips sign. A program that calls R @ v when it needed the coordinates in the new frame produces exactly this error, and the result is still a unit vector, so no length check catches it.
Example 3: the same rotation about a fixed axis and about a body axis
Let , so the body's points along the fixed . Apply both ways:
The two orientations differ. Post-multiplication turned the body about its own , which is the fixed , and the script confirms exactly. Rotating about a body axis equals rotating about wherever that axis currently points in the fixed frame.
Example 4: ZYX versus zyx
With :
textRz Ry Rx (this track) scipy 'zyx' (extrinsic z, then y, then x) [ 0.8138 -0.4410 0.3785] [ 0.8138 -0.4698 0.3420] [ 0.4698 0.8826 0.0180] [ 0.5438 0.8232 -0.1632] [-0.3420 0.1632 0.9254] [-0.2049 0.3188 0.9254]
SciPy's 'ZYX' matches to , and 'xyz' with the angles listed as matches it too, which is the roll-pitch-yaw reading. The lowercase 'zyx' equals and differs by up to 0.181 in an entry. The body axis lands at in one and in the other, apart, and the two orientations differ by a rotation of , from one letter case. The atan2 formulas recover from the first matrix.
Example 5: gimbal lock, run
With , the singular values of , and of the Jacobian of the entries of with respect to at by central differences:
textbeta det E singular values of E rank singular values of d(vec R) rank 0.0 -1.00e+00 1.0000 1.0000 1.0000 3 1.4142 1.4142 1.4142 3 45.0 -7.07e-01 1.3066 1.0000 0.5412 3 1.8478 1.4142 0.7654 3 80.0 -1.74e-01 1.4088 1.0000 0.1233 3 1.9924 1.4142 0.1743 3 89.0 -1.75e-02 1.4142 1.0000 0.0123 3 1.9999 1.4142 0.0175 3 89.9 -1.75e-03 1.4142 1.0000 0.0012 3 2.0000 1.4142 0.0017 3 90.0 -6.12e-17 1.4142 1.0000 0.0000 2 2.0000 1.4142 0.0000 2
The determinant follows and the smallest singular value goes to zero, so the rank falls from 3 to 2 at . For the zero is exact. For the finite-difference Jacobian the smallest singular value at is , difference noise: the rank in the table uses a tolerance of , and the default tolerance of numpy.linalg.matrix_rank would report 3. At the lock, the angles and give matrices that agree to (same ), while differs by 0.766. SciPy's as_euler('ZYX') on that matrix returns with the warning "Gimbal lock detected. Setting third angle to zero since it is not possible to uniquely determine all angles."
Near the lock the coordinates become unstable. Turn the body by about its own and extract the angles again:
textstart (alpha, beta, gamma) change in alpha change in beta change in gamma (30, 30.0, 10) +0.57 -0.09 +0.28 (30, 89.0, 10) +24.38 -0.19 +24.37 (30, 89.9, 10) +69.22 -0.43 +69.22
The physical rotation is in every row, measured as the angle of . A controller that interpolates or differentiates these angles near would command fast, opposite swings of and for a tiny motion.
Common Misconceptions & Pitfalls
- "Any orthogonal matrix is a rotation." in Example 1 is orthogonal with determinant .
- "R rotates the vector, so R also gives its coordinates in the rotated frame." Example 2: the passive reading needs , and the error flips a sign without changing any length.
- "Rotating about x is the same whichever side it multiplies on." Example 3: the left factor uses the fixed , the right factor uses the body , and the results differ.
- "ZYX means the same thing in every library." Example 4: SciPy distinguishes
'ZYX'and'zyx', and the same three numbers produced orientations apart. Write the matrix product next to the angle names. - "Gimbal lock is a physical state the object can get stuck in." The orientation at is an ordinary rotation. Only the three-angle coordinates are singular there, as Example 5's rank drop shows.
Summary
A rotation matrix holds the axes of written in , and it is defined by with ; the determinant excludes reflections. The same matrix rotates a vector actively () or re-expresses a fixed vector passively (), and the two differ in sign. Rotations about fixed axes pre-multiply and rotations about body axes post-multiply. This track's Euler convention is ZYX, , which is also XYZ roll-pitch-yaw about fixed axes, and SciPy's 'zyx' is a different rotation for the same numbers. At the map from angle rates to angular velocity drops from rank 3 to rank 2, and close to it a turn changed two angles by . The orientation is fine; the coordinates are not.