Transformations

The moro.transformations module provides functions for rotations, homogeneous transformations, Euler angles, axis-angle representations, and Denavit-Hartenberg transformations.

Numython R&D, (c) 2026 Moro is a Python library for kinematic and dynamic modeling of serial robots. This library has been designed, mainly, for academic and research purposes, using SymPy as base library.

moro.transformations.axa2rot(k, theta)[source]

Build a rotation matrix from an axis-angle representation.

Parameters:
klist, tuple or sympy Matrix

Rotation axis. Accepted formats are a 3-element list, a 3-element tuple, a column matrix of shape (3, 1), or a row matrix of shape (1, 3). The vector is normalized internally to a column matrix. The zero vector is rejected because it does not define a rotation axis.

thetafloat, int or symbolic

Rotation angle in radians.

Returns:
Rsympy.matrices.dense.MutableDenseMatrix

Rotation matrix of shape (3, 3) computed with Rodrigues’ formula.

moro.transformations.dh(a, alpha, d, theta)[source]

Compute the Denavit-Hartenberg homogeneous transformation matrix.

Parameters:
aint, float or symbolic

Link length (DH parameter).

alphaint, float or symbolic

Link twist (DH parameter).

dint, float or symbolic

Link offset (DH parameter).

thetaint, float or symbolic

Joint angle (DH parameter).

Returns:
sympy.matrices.dense.MutableDenseMatrix

Denavit-Hartenberg homogeneous transformation matrix of shape (4, 4).

Examples

With numerical values:

>>> dh(100, pi/2, 50, pi/2)
⎡0  0  1   0 ⎤
⎢            ⎥
⎢1  0  0  100⎥
⎢            ⎥
⎢0  1  0  50 ⎥
⎢            ⎥
⎣0  0  0   1 ⎦

Using symbolic values:

>>> a = symbols("a")
>>> t = symbols("t")
>>> dh(a, 0, 0, t)
⎡cos(t)  -sin(t)  0  a⋅cos(t)⎤
⎢                            ⎥
⎢sin(t)   cos(t)  0  a⋅sin(t)⎥
⎢                            ⎥
⎢  0        0     1     0    ⎥
⎢                            ⎥
⎣  0        0     0     1    ⎦
moro.transformations.eul2rot(phi, theta, psi, seq='zxz', deg=False)[source]

Build a rotation matrix from proper Euler angles.

Parameters:
phiint, float or symbolic

First Euler angle.

thetaint, float or symbolic

Intermediate Euler angle.

psiint, float or symbolic

Third Euler angle.

seqstr, optional

Proper Euler sequence. Supported sequences are "xyx", "xzx", "yxy", "yzy", "zxz" and "zyz". Matching is case-insensitive. Tait-Bryan sequences such as "xyz" are not supported here.

degbool, optional

If True, the input angles are interpreted as degrees and converted to radians before constructing the matrix.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Rotation matrix.

Notes

This function uses column vectors and active rotations. For a sequence seq="abc", the convention is defined by the matrix product R = R_a(phi) @ R_b(theta) @ R_c(psi), where each elementary rotation is produced by rot(). For proper Euler sequences, a == c.

Examples

>>> eul2rot(pi/2, pi/3, pi/4, seq="zxz")
⎡-√2   -√6         ⎤
⎢────  ────   √3/2 ⎥
⎢ 4     4          ⎥
⎢                  ⎥
⎢-√2    √6         ⎥
⎢────   ──   -1/2  ⎥
⎢ 4     4          ⎥
⎢                  ⎥
⎢ √6    √2         ⎥
⎢ ──    ──    1/2  ⎥
⎣ 4     4          ⎦
>>> eul2rot(pi/6, pi/4, pi/3, seq="xyx")
⎡√2              √2        ⎤
⎢──      √6/4    ──        ⎥
⎢2               4         ⎥
⎢                          ⎥
⎢√2    3/8 + √3  1   3⋅√3 ⎥
⎢──    ────────  ─ - ──── ⎥
⎢4        4      8    8   ⎥
⎢                          ⎥
⎢-√6   1   3⋅√3  √3   3/8⎥
⎢────  ─ + ────  ── - ───⎥
⎣ 4    8    8    4     4 ⎦
moro.transformations.htm2rot(T)[source]

Extract the rotation block from a homogeneous transformation matrix.

Parameters:
Tarray-like or sympy Matrix

Homogeneous transformation matrix. It is converted with Matrix(T) and must have shape (4, 4). No full SE(3) membership validation is performed.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Upper-left rotation block of shape (3, 3).

moro.transformations.htm2tra(T)[source]

Extract the translation vector from a homogeneous transformation matrix.

Parameters:
Tarray-like or sympy Matrix

Homogeneous transformation matrix. It is converted with Matrix(T) and must have shape (4, 4). No full SE(3) membership validation is performed.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Translation column vector of shape (3, 1).

moro.transformations.htmrot(theta, axis='z', deg=False)[source]

Return a homogeneous transformation matrix for a pure rotation.

Parameters:
thetafloat, int or symbolic

Rotation angle. By default, the value is interpreted in radians.

axisstr

Rotation axis, "x", "y" or "z". Matching is case-insensitive. Default is "z".

degbool, optional

If True, theta is interpreted as degrees. Default is False.

Returns:
Hsympy.matrices.dense.MutableDenseMatrix

Homogeneous transformation matrix of shape (4, 4).

Examples

>>> htmrot(pi/2)
⎡0  -1  0  0⎤
⎢           ⎥
⎢1  0   0  0⎥
⎢           ⎥
⎢0  0   1  0⎥
⎢           ⎥
⎣0  0   0  1⎦
>>> htmrot(pi/2, "x")
⎡1  0  0   0⎤
⎢           ⎥
⎢0  0  -1  0⎥
⎢           ⎥
⎢0  1  0   0⎥
⎢           ⎥
⎣0  0  0   1⎦
>>> htmrot(30, "y", True)
⎡0.866025403784439  0         0.5         0⎤
⎢                                          ⎥
⎢        0          1          0          0⎥
⎢                                          ⎥
⎢      -0.5         0  0.866025403784439  0⎥
⎢                                          ⎥
⎣        0          0          0          1⎦
>>> t = symbols("t")
>>> htmrot(t, "x")
⎡1    0        0     0⎤
⎢                     ⎥
⎢0  cos(t)  -sin(t)  0⎥
⎢                     ⎥
⎢0  sin(t)  cos(t)   0⎥
⎢                     ⎥
⎣0    0        0     1⎦
moro.transformations.htmtra(x=0, y=0, z=0)[source]

Calculate the homogeneous transformation matrix of a translation.

Parameters:
xint, float or symbolic, optional

Translation along the x-axis. Default is 0.

yint, float or symbolic, optional

Translation along the y-axis. Default is 0.

zint, float or symbolic, optional

Translation along the z-axis. Default is 0.

Returns:
Hsympy.matrices.dense.MutableDenseMatrix

Homogeneous transformation matrix

Examples

>>> htmtra()
⎡1  0  0  0⎤
⎢          ⎥
⎢0  1  0  0⎥
⎢          ⎥
⎢0  0  1  0⎥
⎢          ⎥
⎣0  0  0  1⎦
>>> htmtra(10,-40,50)
⎡1  0  0  10 ⎤
⎢            ⎥
⎢0  1  0  -40⎥
⎢            ⎥
⎢0  0  1  50 ⎥
⎢            ⎥
⎣0  0  0   1 ⎦
>>> htmtra(z=100)
⎡1  0  0   0 ⎤
⎢            ⎥
⎢0  1  0   0 ⎥
⎢            ⎥
⎢0  0  1  100⎥
⎢            ⎥
⎣0  0  0   1 ⎦
>>> a,b,c = symbols("a,b,c")
>>> htmtra(x=a, y=b, z=c)
⎡1  0  0  a⎤
⎢          ⎥
⎢0  1  0  b⎥
⎢          ⎥
⎢0  0  1  c⎥
⎢          ⎥
⎣0  0  0  1⎦
moro.transformations.invhtm(T)[source]

Compute the structured inverse of a homogeneous transformation matrix.

Parameters:
Tarray-like or sympy Matrix

Homogeneous transformation matrix. It is converted with Matrix(T) and must have shape (4, 4). No full SE(3) membership validation is performed.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Inverse homogeneous transformation matrix computed from the rigid-body structure, using R.T and -R.T*p instead of a general matrix inverse.

moro.transformations.rot(theta, axis='z', deg=False)[source]

Return a rotation matrix that represents a rotation of theta about axis.

Parameters:
thetafloat, int or symbolic

Rotation angle. By default, the value is interpreted in radians.

axisstr

Rotation axis, "x", "y" or "z". Matching is case-insensitive. Default is "z".

degbool, optional

If True, theta is interpreted as degrees. Default is False.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Rotation matrix of shape (3, 3).

moro.transformations.rot2axa(R, deg=False, tol=1e-09)[source]

Return the axis-angle representation of a rotation matrix.

Parameters:
Rsympy Matrix

Rotation matrix in SO(3).

degbool, optional

If True, the angle is returned in degrees. Default is False.

tolfloat, optional

Positive tolerance used to validate numeric rotation matrices, classify angles close to 0, classify angles close to pi, and tolerate small floating-point errors in trigonometric quantities. Default is 1e-9.

Returns:
ksympy.matrices.dense.MutableDenseMatrix

Axis of rotation, a 3D vector.

thetafloat, int or symbolic

Rotation angle in radians by default, or in degrees when deg=True.

moro.transformations.rot2eul(R, seq='zxz', deg=False, tol=1e-09)[source]

Calculate proper Euler angles from a rotation matrix.

Parameters:
Rmatrix-like, shape (3, 3)

Rotation matrix. The function validates only that the input has shape (3, 3); it does not yet perform a full SO(3) membership check.

seqstr, optional

Proper Euler sequence. Supported sequences are "xyx", "xzx", "yxy", "yzy", "zxz" and "zyz". Matching is case-insensitive.

degbool, optional

If True, returned angles are converted from radians to degrees.

tolfloat, optional

Positive numerical tolerance used only for floating-point classification near the singularities theta = 0 and theta = pi and for clipping small numerical excursions of cos(theta) outside [-1, 1].

Returns:
list of tuple

In the general case, returns two equivalent solutions [(phi1, theta1, psi1), (phi2, theta2, psi2)]. In singular cases, returns a single representative solution with psi = 0.

Notes

The convention matches eul2rot(): column vectors, active rotations and R = R_a(phi) @ R_b(theta) @ R_a(psi) for seq="aba". Euler angle representations are not unique; both general-case solutions reconstruct the same matrix, the second solution may contain a negative intermediate angle, and no additional range normalization is applied. At singularities, phi and psi are not independently determined; setting psi = 0 is only a representative convention.

moro.transformations.rot2htm(R)[source]

Build a homogeneous transformation matrix from a rotation matrix.

Parameters:
Rarray-like or sympy Matrix

Rotation block. It is converted with Matrix(R) and must have shape (3, 3). No full SO(3) membership validation is performed.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Homogeneous transformation matrix with zero translation and shape (4, 4).

moro.transformations.rotx(theta, deg=False)[source]

Calculates the rotation matrix about the x-axis

Parameters:
thetafloat, int or symbolic

Rotation angle (given in radians by default)

degbool

If True, theta is interpreted as degrees. Default is False.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Rotation matrix in SO(3).

Examples

>>> rotx(pi)
⎡1  0   0 ⎤
⎢         ⎥
⎢0  -1  0 ⎥
⎢         ⎥
⎣0  0   -1⎦
>>> rotx(60, deg=True)
⎡1          0                  0         ⎤
⎢                                        ⎥
⎢0         0.5         -0.866025403784439⎥
⎢                                        ⎥
⎣0  0.866025403784439         0.5        ⎦
moro.transformations.roty(theta, deg=False)[source]

Calculates the rotation matrix about the y-axis

Parameters:
thetafloat, int or symbolic

Rotation angle (given in radians by default)

degbool

If True, theta is interpreted as degrees. Default is False.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Rotation matrix in SO(3).

Examples

>>> roty(pi/3)
⎡         √3 ⎤
⎢1/2   0  ── ⎥
⎢         2  ⎥
⎢            ⎥
⎢ 0    1   0 ⎥
⎢            ⎥
⎢-√3         ⎥
⎢────  0  1/2⎥
⎣ 2          ⎦
>>> roty(30, deg=True)
⎡0.866025403784439  0         0.5       ⎤
⎢                                       ⎥
⎢        0          1          0        ⎥
⎢                                       ⎥
⎣      -0.5         0  0.866025403784439⎦
moro.transformations.rotz(theta, deg=False)[source]

Calculate the rotation matrix about the z-axis.

Parameters:
thetafloat, int or symbolic

Rotation angle. By default, the value is assumed to be given in radians.

degbool, optional

If True, theta is interpreted as degrees. Default is False.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Rotation matrix in SO(3).

Examples

Using angle in radians:

>>> rotz(pi/2)
⎡0  -1  0⎤
⎢        ⎥
⎢1   0  0⎥
⎢        ⎥
⎣0   0  1⎦

Using symbolic variables:

>>> x = symbols("x")
>>> rotz(x)
⎡cos(x)  -sin(x)  0⎤
⎢                  ⎥
⎢sin(x)   cos(x)  0⎥
⎢                  ⎥
⎣  0        0     1⎦

Using angles in degrees:

>>> rotz(45, deg=True)
⎡0.707106781186548  -0.707106781186547  0⎤
⎢                                        ⎥
⎢0.707106781186547   0.707106781186548  0⎥
⎢                                        ⎥
⎣        0                  0           1⎦
moro.transformations.rt2htm(R, p)[source]

Build a homogeneous transformation matrix from rotation and translation.

Parameters:
Rarray-like or sympy Matrix

Rotation block. It is converted with Matrix(R) and must have shape (3, 3). No full SO(3) membership validation is performed.

plist, tuple or sympy Matrix

Translation vector. Accepted formats are a 3-element list, a 3-element tuple, a column matrix of shape (3, 1), or a row matrix of shape (1, 3). The vector is normalized internally to a column matrix.

Returns:
sympy.matrices.dense.MutableDenseMatrix

Homogeneous transformation matrix of shape (4, 4).

moro.transformations.skew(u)[source]

Return the skew-symmetric matrix associated with a 3D vector.

Parameters:
ulist, tuple or sympy Matrix

Vector. Accepted formats are a 3-element list, a 3-element tuple, a column matrix of shape (3, 1), or a row matrix of shape (1, 3). The vector is normalized internally to a column matrix.

Returns:
Ssympy.matrices.dense.MutableDenseMatrix

Skew-symmetric matrix of shape (3, 3).