# Transformation Ambiguities and Conventions¶

There are lots of ambiguities in the world of transformations. We try to explain them all here.

## Right-handed vs. Left-handed Coordinate System¶

We typically use a right-handed coordinate system, that is, the x-, y- and z-axis are aligned in a specific way. The name comes from the way how the fingers are attached to the human hand. Try to align your thumb with the imaginary x-axis, your index finger with the y-axis, and your middle finger with the z-axis. It is possible to do this with a right hand in a right-handed system and with the left hand in a left-handed system.

Right-handed | Left-handed |

(Source code, png, hires.png, pdf) |
(Source code, png, hires.png, pdf) |

Note

The default in pytransform3d is a right-handed coordinate system.

## Active (Alibi) vs. Passive (Alias) Transformation¶

An active transformation

changes the physical position of an object

can be defined in the absence of a coordinate system or does not change the current coordinate system

is the only convention used by mathematicians

Another name for active transformation is alibi transformation.

A passive transformation

changes the coordinate system in which the object is described

does not change the object

could be used by physicists and engineers (e.g. roboticists)

Another name for passive transformation is alias transformation.

The following illustration compares the active view with the passive view. The position of the data is interpreted in the frame indicated by solid axes. We use exactly the same transformation matrix in both plots. In the active view, we see that the transformation is applied to the data. The data is physically moved. The dashed basis represents a frame that is moved from the base frame with the same transformation. The data is now interpreted in the old frame. In a passive transformation, we move the frame with the transformation. The data stays at its original position but it is interpreted in the new frame.

Active | Passive |

(Source code, png, hires.png, pdf) |
(Source code, png, hires.png, pdf) |

Using the inverse transformation in the active view gives us exactly the same solution as the original transformation in the passive view and vice versa.

It is usually easy to determine whether the active or the passive convention is used by taking a look at the rotation matrix: when we rotate counter-clockwise by an angle about the z-axis, the following rotation matrix is usually used in an active transformation:

Its transformed version is usually used for a passive transformation:

Warning

The standard in pytransform3d is an active rotation.
Note that there are some functions to generate rotation matrices that
generate passive rotations as well: `matrix_from_angle()`

,
`matrix_from_euler_xyz()`

, and
`matrix_from_euler_zyx()`

. These are kept
for backward compatibility. When in doubt, read the docstring, which
clearly states that a passive convention is used here.

Reference:

Selig, J.M.: Active Versus Passive Transformations in Robotics, 2006, IEEE Robotics and Automation Magazine. PDF: https://openresearch.lsbu.ac.uk/download/641fa36d365e0244b27dd2fc8b881a12061afe1eb5c3952bae15614d3d831710/185181/01598057.pdf.

## Pre-multiply vs. Post-multiply Rotations¶

The same point can be represented by a column vector or a row vector . A rotation matrix can be used to rotate the point by pre-multiplying it to the column vector or by post-multiplying it to the row vector . However, for the same rotation matrix, both approaches are inverse: . Hence, to achieve the same effect we have to use two different rotation matrices depending on how we multiply them to points.

Note

The default in pytransform3d are pre-multiplied rotation matrices.

## Intrinsic vs. Extrinsic Transformations¶

A similar problem occurs when we want to concatenate rotations or transformations: suppose we have a rotation matrix and another matrix and we want to first rotate by and then by . If we want to apply both rotations in global coordinates (global, space-fixed / extrinsic rotation), we have to concatenate them with . We can also express the second rotation in terms of a local, body-fixed coordinates (local, body-fixed / intrinsic rotation) by , which means defines new coordinates in which is applied. Note that this applies to both passive and active rotation matrices. Specifying this convention is particularly relevant when we deal with Euler angles.

Here is a comparison between various conventions of concatenation.

(Source code, png, hires.png, pdf)

Warning

There are two conventions on how to concatenate rotations and
transformations: intrinsic and extrinsic transformation.
There is no default in pytransform3d but usually the function name
should tell you which convention the function uses.
Note that there are two functions to generate rotation matrices that
generate intrinsic rotations without a telling function name:
`matrix_from_euler_xyz()`

and
`matrix_from_euler_zyx()`

. These are kept
for backward compatibility. When in doubt, read the docstring, which
clearly states that they make intrinsic rotations.

## Naming and Frame Conventions¶

In addition to transformation and rotation conventions, there are a lot of different naming and frame conventions. Here are some examples.

## Conventions of Other Software¶

The following is an incomplete list of conventions for representations of rotations, orientations, transformations, or poses and coordinate frames other software packages use. It illustrates the diversity that you will find when you combine different software systems.

Blender user interface (computer graphics)

Active rotations

Euler angles (are actually Tait-Bryan angles): external rotations, angles in degree

Quaternion: scalar first

XSens MVNX format (motion capture)

Active rotations

- Conventions for coordinate frames
Axis orientation in the world (global): x north, y west, z up (NWU)

Axis orientation on body parts: axes are aligned with world axes when subject stands in T pose

Quaternion and rotation matrix rotate from sensor frame to world frame, that is, they represent the orientation of the sensor with respect to the world

Quaternion: scalar first

Euler angles: extrinsic roll-pitch-yaw (xyz) convention

Active rotations

Euler angles: extrinsic roll-pitch-yaw (xyz) convention (getQuaternionFromEuler from pybullet’s API)

Quaternion: scalar last and Hamilton multiplication

Eigen (linear algebra library)

- Quaternion
Scalar first (constructor) and scalar last (internal)

Hamilton multiplication

Peter Corke’s robotics toolbox

Active rotations

- Euler angles
Intrinsic zyz convention

Roll-pitch-yaw angles correspond either to intrinsic zyx convention (default) or intrinsic xyz convention, which can be selected by a parameter

Quaternion: scalar first and Hamilton multiplication

Robot Operating System (ROS) (REP103)

Active transformations

- Conventions for coordinate frames
Axis orientation on body: x forward, y left, z up

Axis orientation in the world: x east, y north, z up (ENU)

Axis orientation of optical camera frame (indicated by suffix in topic name): z forward, x right, y down

- Euler angles
Active, extrinsic roll-pitch-yaw (xyz) convention (as used, e.g., in origin tag of URDF) can be used

In addition, the yaw-pitch-roll (zyx) convention can be used, but is discouraged

A PoseStamped is represented with respect to a frame_id

When interpreted as active transformation, TransformStamped represents a transformation from

*child frame*to its (parent)*frame*Quaternion: scalar last

Universal Robot user interface

- Conventions for coordinate frames
Default axis orientation of tool center point: z forward (approach direction), x and y axes define the orientation with which we approach the target

Euler angles: extrinsic roll-pitch-yaw (xyz) convention