Rotation API Reference#
Table of Contents
The rotation portion of the module provides methods for generating rotation matrices, as well as methods for handling the rotations.
The getMatrix* methods return a matrix based on specific rotation types: axis, Euler and from one reference frame to another.
The rotate* methods work similarly to the getMatrix* methods, but they handle deriving the necessary matrices and how to use them internally. This allows the most inexperienced user to safely rotate vectors between reference frames and keeps code clean and concise.
How Rotations Work#
Pure rotations work like a map from a vector space to itself. If the original reference frame is our normal x, y, z coordinate frame, a rotated vector is that original vector expressed with a differenct set of basis vectors.
Basis Vectors#
Simply speaking, basis vectors are the set of vectors that allow us to represent every vector in a vector space. For a Euclidean vector space these are usually the unit vectors pointing towards each positive axis, namely (1, 0, 0), (0, 1, 0) and (0, 0, 1), also called e1, e2 and e3 respectively. Any vector in our vector space then, can be written as a linear combination of our basis vectors: (a, b, c) = e1 * a + e2 * b + e3 * c. Other sets of basis vectors also exist, as well show shortly.
Rotation Matrix#
A rotation matrix is simply a mapping of vectors. When right multiplying a matrix by a vector, we create a new vector that is a linear combination of the columns of our matrix (called the column space). In essence, we can think of these column vectors as a basis for a rotated reference frame in the same vector space.
For a simple example, think of the identity matrix as a rotation. Of course we know this is a rotation of zero radians, since no vector will be changed by multiplying by the identity matrix. This can be demonstrated by looking at the identity matrix’s columns:
>>> Matrix.id
Matrix([1, 0, 0]
[0, 1, 0]
[0, 0, 1])
This first column, which represents where the x-axis is mapped to, is the x-axis (1, 0, 0). The second and third columns show the y and z axes also map to themselves, which is why each vector remains the same after being multiplied by the identity matrix.
A more complex example can be seen using the Euler rotation around the axes X, Y and Z, with angles 1.0, 2.0 and 3.0 radians. This yields the rotation matrix:
>>> getMatrixEuler(XYZ, Angles(1.0, 2.0, 3.0))
Matrix([0.411982, 0.0587266, 0.909297]
[-0.681243, -0.642873, 0.350175]
[0.605127, -0.763718, -0.224845])
Here the x-axis maps to the vector (0.411982, -0.681243, 0.605127). The y and z axes map to the second and third column vectors respectively. Because these vectors are only rotations of our original axis vectors, they remain orthogonal to each other, meaning they are linearly independent, and since there’s three of them in a 3-dimensional vector space, they form a basis.
The significance of this basis is it represents how the three axes of the reference frame defined by the Euler rotation are represented in our original basis. Therefore, by multiplying a vector from the rotated reference frame by our rotation matrix, we get a representation of that vector in the original basis. This is equivalent to rotating the vector from the rotated reference frame, to the original reference frame. Simply put, if we multiply our vectors on the right, the rotation matrix tells us how to move vectors from a rotated reference frame to the unrotated reference frame.
Overly simplifying a few things, the rotation matrix that describes how to move the other direction between reference frames is simply the inverse of the original rotation matrix. Luckily, the inverse of a pure rotation matrix is its transpose, which is simple to compute. Therefore, multiplying a vector from our original reference frame on the right by the transpose of our matrix from above, rotates said vector to the rotated reference frame.
Speeding Things Along#
As you may have already noticed, multiplying the transpose of a matrix on the right generates the same output as if we multiplied the original matrix on the left. This is good for us, because it means we don’t need to transpose our matrices, which otherwise would add more time to our computations. In summary, for an unrotated reference frame A, if we have a pure rotation matrix that describes a mapping to reference frame B, multiplying the matrix by a vector on the right rotates the vector from B to A. Multiplying the matrix by a vector on the left rotates the vector from A to B. Note the opposite is true if you inverse (transpose) the matrix.
If M is a matrix representing a rotation from reference frame A to reference frame B:
Mapping Direction |
Matrix Form |
Operation |
---|---|---|
A -> B |
normal |
vB = vA @ M |
A -> B |
transposed |
vB = transpose(M) @ vA |
B -> A |
normal |
vA = M @ vB |
B -> A |
transposed |
vA = vB @ transpose(M) |
While several reference frame mappings exist, as long as they are pure rotations (no offset origins) a single matrix is enough describe the mapping. This allows us to use the rules above to rotate any vector using the matrix returned by one of the getMatrix* methods. To simplify all of this, PyEVSpace implements a collection of methods to handle all of the above for you. The rotate*To and rotate*From methods remove all of the complexities of rotations, while also eliminating the need for you to create a matrix yourself. While you now know how to rotate vectors yourself, it is advised to use these methods for cleaner code, to reduce errors and faster execution of the rotation.
Generating Rotation Matrices#
The pyevspace module provides the following methods for generating rotation matrices.
Method |
Rotation Type |
Reference |
---|---|---|
Rotation around a single axis |
||
Three axis Euler rotation |
||
From one reference frame to another |
— |
Rotating Vectors#
The following methods are used to rotate vectors without needing to generate a rotation matrix yourself. Each method ‘type’ refers to a rotation type, and has two related methods, a ‘from’ and a ‘to’ method.
Note
An inertial reference frame refers to an un-rotated and constant
reference frame. In theory, this need not be exactly true, only
true relative to the derived reference frame rotating from or to.
In most cases, the corresponding rotation matrix for the inertial
reference frame is the identity matrix: Matrix.id
.
Method |
From Reference Frame |
To Reference Frame |
---|---|---|
The axis and angle specified |
An inertial reference frame |
|
An inertial reference frame |
The axis and angle specified |
|
The frame resulting from the order and angles specified |
An inertial reference frame |
|
An inertial reference frame |
The frame resulting from the order and angles specified |
|
The frame described by the matrix |
An inertial reference frame |
|
An inertial reference frame |
The frame described by the matrix |
|
The offset frame specified |
An inertial reference frame |
|
An inertial reference frame |
The offset frame specified |
Rotation Types#
Enumerated Axes#
A few types are needed to help describe an Euler rotation. An Euler rotation consists of an order of axes about which consecutive axis rotations occur, and the angles by which they’re rotated.
To specify an axis around which a rotation occurs, there are three enumerated constants.
- pyevspace.X_AXIS#
Enumerated constant to specify the X_AXIS.
- Type:
int
- Value:
0
- pyevspace.Y_AXIS#
Enumerated constant to specify the Y_AXIS.
- Type:
int
- Value:
1
- pyevspace.Z_AXIS#
Enumerated constant to specify the Z_AXIS.
- Type:
int
- Value:
2
Order#
There are 12 unique Euler rotation orders, which are already defined, so it
is unlikely to need to instantiate another Order
object, however
the class is still documented below.
- class pyevspace.Order(firstAxis, secondAxis, thirdAxis)#
A class that specifies the order of axes in an Euler rotation. The axis arguments are technically int values, but the enumerated axis values should be used to avoid confusion and made code cleaner and easier to read.
- Parameters:
firstAxis (int) – the first axis of an Euler rotation
secondAxis (int) – the second axis of an Euler rotation
thirdAxis (int) – the third axis of an Euler rotation
Attributes#
- Order.first#
The first axis of the rotation order.
- Type:
int
- Order.second#
The second axis of the rotation order.
- Type:
int
- Order.third#
The third axis of the rotation order.
- Type:
int
Instance Methods#
- Order.__len__()#
Returns the length of the order for sequencing.
- Returns:
always returns 3
- Return type:
int
- Order.__getitem__(index)#
Returns the indexed axis.
- Parameters:
index (int) – the index of the order to get
- Raises:
TypeError – if index is not an int type
IndexError – if index is not in [0, 2]
- Returns:
the indexed axis
- Return type:
int
- Order.__setitem__(index, value)#
to be removed?
- Order.__repr__()#
Converts the order to a string representation, representative of a constructor call.
- Returns:
a string representation of the order
- Return type:
str
- Order.__str__()#
Converts the order to a string representation.
- Returns:
a string representation of the order
- Return type:
str
- Order.__reduce__()#
Returns a tuple of objects capable of reconstructing an order object for copying and pickling.
- Returns:
a tuple with the constructor and rotations
- Return type:
tuple
Angles#
- class pyevspace.Angles(alpha, beta, gamma)#
A class to hold the angles that correspond to the axes in the
Order
type. The angle corresponds to the respective axis in its associated order object.- Parameters:
alpha (float) – the angle in radians around the first axis
beta (float) – the angle in radians around the second axis
gamma (float) – the angle in radians around the third axis
Attributes#
- Angles.alpha#
The first angle of a rotation.
- Angles.beta#
The second angle of a rotation.
- Angles.gamma#
The third angle of a rotation.
Instance Methods#
- Angles.__len__()#
Returns the lengh of the angles for sequencing.
- Returns:
always returns 3
- Return type:
int
- Angles.__getitem__(index)#
Returns the indexed angle.
- Parameters:
index (int) – the index of the angle to get
- Raises:
TypeError – if index is not an int type
IndexError – if index is not in [0, 2]
- Returns:
the indexed angle
- Return type:
float
- Angles.__setitem__(index, value)#
Sets the indexed angle to value.
- Parameters:
index (int) – the index of the angle to get
value (float) – the value to set the angle in radians
- Raises:
TypeError – if index is not an int type or value is not a numeric type
IndexError – if index is not in [0, 2]
- Angles.__repr__()#
Converts the angles to a string representation, representative of a constructor call.
- Returns:
a string representation of the angles
- Return type:
str
- Angles.__str__()#
Converts the angles to a string representation.
- Returns:
a string representation of the angles
- Return type:
str
- Angles.__reduce__()#
Returns a tuple of objects capable of reconstructing an angles object for copying and pickling.
- Returns:
a tuple with the constructor and angles
- Return type:
tuple
Matrix Generator Methods#
- pyevspace.getMatrixAxis(axis, angle)#
Creates a matrix that describes a rotation around an axis by an angle.
- Parameters:
axis (int) – axis of rotation, should be one of the defined enumerated axes
angle (numeric) – angle of rotation in radians
- Raises:
TypeError – if axis is not an int or angle is not a numeric type
ValueError – if axis is not in [0-2]
- Returns:
the rotation matrix
- Return type:
- pyevspace.getMatrixEuler(order, angles)#
Creates a matrix that describes an Euler rotation by its order and the associated angles.
- pyevspace.getMatrixFromTo(orderFrom, anglesFrom, orderTo, anglesTo)#
Creates a matrix that describes a rotation between two reference frames, where each frame is defined as an Euler rotation.
- Parameters:
- Raises:
TypeError – if orderFrom or orderTo are not Order types, or anglesFrom or anglesTo are not Angles types
- Returns:
the rotation matrix
- Return type:
Rotation Methods#
- pyevspace.rotateAxisFrom(axis, angle, vector)#
Rotates a vector from a reference frame defined by an axis rotation.
- Parameters:
axis (int) – axis of rotation, should be one of the defined enumerated axes
angle (float) – angle of rotation in radians
vector (Vector) – vector to rotate
- Raises:
TypeError – if axis is not an int, angle is not a float or vector is not a Vector type
ValueError – if axis is not in [0, 2]
- Returns:
the rotated vector
- Return type:
- pyevspace.rotateAxisTo(axis, angle, vector)#
Rotates a vector to a reference frame defined by an axis rotation.
- Parameters:
axis (int) – axis of rotation, should be one of the defined enumerated axes
angle (float) – angle of rotation in radians
vector (Vector) – vector to rotate
- Raises:
TypeError – if axis is not an int, angle is not a float or vector is not a Vector type
ValueError – if axis is not in [0, 2]
- Returns:
the rotated vector
- Return type:
- pyevspace.rotateEulerFrom(order, angles, vector)#
Rotates a vector from a reference frame defined by an Euler rotation.
- Parameters:
- Raises:
TypeError – if order is not an Order type, angles are not an Angles type or vector is not a Vector type
- Returns:
the rotated vector
- Return type:
- pyevspace.rotateEulerTo(order, angles, vector)#
Rotates a vector to a reference frame defined by an Euler rotation.
- Parameters:
- Raises:
TypeError – if order is not an Order type, angles are not an Angles type or vector is not a Vector type
- Returns:
the rotated vector
- Return type:
- pyevspace.rotateMatrixFrom(matrix, vector)#
Rotates a vector from a reference frame defined by a rotation matrix.
- pyevspace.rotateMatrixTo(matrix, vector)#
Rotates a vector to a reference frame defined by a rotation matrix.
- pyevspace.rotateOffsetFrom(matrix, offset, vector)#
Rotates a vector from an offset reference frame.
- pyevspace.rotateOffsetTo(matrix, offset, vector)#
Rotates a vector to an offset reference frame.